Sat, 03 Jan 2015 20:18:00 +0100
Conditionally enable double key logic according to:
private browsing mode or privacy.thirdparty.isolate preference and
implement in GetCookieStringCommon and FindCookie where it counts...
With some reservations of how to convince FindCookie users to test
condition and pass a nullptr when disabling double key logic.
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /* vim: set ts=8 sts=4 et sw=4 tw=99: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
7 #ifndef xpcpublic_h
8 #define xpcpublic_h
10 #include "jsapi.h"
11 #include "jsproxy.h"
12 #include "js/HeapAPI.h"
13 #include "js/GCAPI.h"
15 #include "nsISupports.h"
16 #include "nsIURI.h"
17 #include "nsIPrincipal.h"
18 #include "nsWrapperCache.h"
19 #include "nsStringGlue.h"
20 #include "nsTArray.h"
21 #include "mozilla/dom/JSSlots.h"
22 #include "nsMathUtils.h"
23 #include "nsStringBuffer.h"
24 #include "mozilla/dom/BindingDeclarations.h"
26 class nsGlobalWindow;
27 class nsIPrincipal;
28 class nsScriptNameSpaceManager;
29 class nsIGlobalObject;
30 class nsIMemoryReporterCallback;
32 #ifndef BAD_TLS_INDEX
33 #define BAD_TLS_INDEX ((uint32_t) -1)
34 #endif
36 namespace xpc {
38 class Scriptability {
39 public:
40 Scriptability(JSCompartment *c);
41 bool Allowed();
42 bool IsImmuneToScriptPolicy();
44 void Block();
45 void Unblock();
46 void SetDocShellAllowsScript(bool aAllowed);
48 static Scriptability& Get(JSObject *aScope);
50 private:
51 // Whenever a consumer wishes to prevent script from running on a global,
52 // it increments this value with a call to Block(). When it wishes to
53 // re-enable it (if ever), it decrements this value with a call to Unblock().
54 // Script may not run if this value is non-zero.
55 uint32_t mScriptBlocks;
57 // Whether the docshell allows javascript in this scope. If this scope
58 // doesn't have a docshell, this value is always true.
59 bool mDocShellAllowsScript;
61 // Whether this scope is immune to user-defined or addon-defined script
62 // policy.
63 bool mImmuneToScriptPolicy;
65 // Whether the new-style domain policy when this compartment was created
66 // forbids script execution.
67 bool mScriptBlockedByPolicy;
68 };
70 JSObject *
71 TransplantObject(JSContext *cx, JS::HandleObject origobj, JS::HandleObject target);
73 bool IsXBLScope(JSCompartment *compartment);
74 bool IsInXBLScope(JSObject *obj);
76 // Return a raw XBL scope object corresponding to contentScope, which must
77 // be an object whose global is a DOM window.
78 //
79 // The return value is not wrapped into cx->compartment, so be sure to enter
80 // its compartment before doing anything meaningful.
81 //
82 // Also note that XBL scopes are lazily created, so the return-value should be
83 // null-checked unless the caller can ensure that the scope must already
84 // exist.
85 //
86 // This function asserts if |contentScope| is itself in an XBL scope to catch
87 // sloppy consumers. Conversely, GetXBLScopeOrGlobal will handle objects that
88 // are in XBL scope (by just returning the global).
89 JSObject *
90 GetXBLScope(JSContext *cx, JSObject *contentScope);
92 inline JSObject *
93 GetXBLScopeOrGlobal(JSContext *cx, JSObject *obj) {
94 if (IsInXBLScope(obj))
95 return js::GetGlobalForObjectCrossCompartment(obj);
96 return GetXBLScope(cx, obj);
97 }
99 // Returns whether XBL scopes have been explicitly disabled for code running
100 // in this compartment. See the comment around mAllowXBLScope.
101 bool
102 AllowXBLScope(JSCompartment *c);
104 // Returns whether we will use an XBL scope for this compartment. This is
105 // semantically equivalent to comparing global != GetXBLScope(global), but it
106 // does not have the side-effect of eagerly creating the XBL scope if it does
107 // not already exist.
108 bool
109 UseXBLScope(JSCompartment *c);
111 bool
112 IsSandboxPrototypeProxy(JSObject *obj);
114 bool
115 IsReflector(JSObject *obj);
117 bool
118 IsXrayWrapper(JSObject *obj);
120 // If this function was created for a given XrayWrapper, returns the global of
121 // the Xrayed object. Otherwise, returns the global of the function.
122 //
123 // To emphasize the obvious: the return value here is not necessarily same-
124 // compartment with the argument.
125 JSObject *
126 XrayAwareCalleeGlobal(JSObject *fun);
128 void
129 TraceXPCGlobal(JSTracer *trc, JSObject *obj);
131 } /* namespace xpc */
133 namespace JS {
135 struct RuntimeStats;
137 }
139 #define XPCONNECT_GLOBAL_FLAGS_WITH_EXTRA_SLOTS(n) \
140 JSCLASS_DOM_GLOBAL | JSCLASS_HAS_PRIVATE | \
141 JSCLASS_PRIVATE_IS_NSISUPPORTS | JSCLASS_IMPLEMENTS_BARRIERS | \
142 JSCLASS_GLOBAL_FLAGS_WITH_SLOTS(DOM_GLOBAL_SLOTS + n)
144 #define XPCONNECT_GLOBAL_EXTRA_SLOT_OFFSET (JSCLASS_GLOBAL_SLOT_COUNT + DOM_GLOBAL_SLOTS)
146 #define XPCONNECT_GLOBAL_FLAGS XPCONNECT_GLOBAL_FLAGS_WITH_EXTRA_SLOTS(0)
148 inline JSObject*
149 xpc_FastGetCachedWrapper(JSContext *cx, nsWrapperCache *cache, JS::MutableHandleValue vp)
150 {
151 if (cache) {
152 JSObject* wrapper = cache->GetWrapper();
153 if (wrapper &&
154 js::GetObjectCompartment(wrapper) == js::GetContextCompartment(cx))
155 {
156 vp.setObject(*wrapper);
157 return wrapper;
158 }
159 }
161 return nullptr;
162 }
164 // The JS GC marks objects gray that are held alive directly or
165 // indirectly by an XPConnect root. The cycle collector explores only
166 // this subset of the JS heap.
167 inline bool
168 xpc_IsGrayGCThing(void *thing)
169 {
170 return JS::GCThingIsMarkedGray(thing);
171 }
173 // The cycle collector only cares about some kinds of GCthings that are
174 // reachable from an XPConnect root. Implemented in nsXPConnect.cpp.
175 extern bool
176 xpc_GCThingIsGrayCCThing(void *thing);
178 inline JSScript *
179 xpc_UnmarkGrayScript(JSScript *script)
180 {
181 if (script)
182 JS::ExposeGCThingToActiveJS(script, JSTRACE_SCRIPT);
184 return script;
185 }
187 // If aVariant is an XPCVariant, this marks the object to be in aGeneration.
188 // This also unmarks the gray JSObject.
189 extern void
190 xpc_MarkInCCGeneration(nsISupports* aVariant, uint32_t aGeneration);
192 // If aWrappedJS is a JS wrapper, unmark its JSObject.
193 extern void
194 xpc_TryUnmarkWrappedGrayObject(nsISupports* aWrappedJS);
196 extern void
197 xpc_UnmarkSkippableJSHolders();
199 // No JS can be on the stack when this is called. Probably only useful from
200 // xpcshell.
201 void
202 xpc_ActivateDebugMode();
204 // readable string conversions, static methods and members only
205 class XPCStringConvert
206 {
207 // One-slot cache, because it turns out it's common for web pages to
208 // get the same string a few times in a row. We get about a 40% cache
209 // hit rate on this cache last it was measured. We'd get about 70%
210 // hit rate with a hashtable with removal on finalization, but that
211 // would take a lot more machinery.
212 struct ZoneStringCache
213 {
214 nsStringBuffer* mBuffer;
215 JSString* mString;
216 };
218 public:
220 // If the string shares the readable's buffer, that buffer will
221 // get assigned to *sharedBuffer. Otherwise null will be
222 // assigned.
223 static bool ReadableToJSVal(JSContext *cx, const nsAString &readable,
224 nsStringBuffer** sharedBuffer,
225 JS::MutableHandleValue vp);
227 // Convert the given stringbuffer/length pair to a jsval
228 static MOZ_ALWAYS_INLINE bool
229 StringBufferToJSVal(JSContext* cx, nsStringBuffer* buf, uint32_t length,
230 JS::MutableHandleValue rval, bool* sharedBuffer)
231 {
232 JS::Zone *zone = js::GetContextZone(cx);
233 ZoneStringCache *cache = static_cast<ZoneStringCache*>(JS_GetZoneUserData(zone));
234 if (cache && buf == cache->mBuffer) {
235 MOZ_ASSERT(JS::GetGCThingZone(cache->mString) == zone);
236 JS::MarkStringAsLive(zone, cache->mString);
237 rval.setString(cache->mString);
238 *sharedBuffer = false;
239 return true;
240 }
242 JSString *str = JS_NewExternalString(cx,
243 static_cast<jschar*>(buf->Data()),
244 length, &sDOMStringFinalizer);
245 if (!str) {
246 return false;
247 }
248 rval.setString(str);
249 if (!cache) {
250 cache = new ZoneStringCache();
251 JS_SetZoneUserData(zone, cache);
252 }
253 cache->mBuffer = buf;
254 cache->mString = str;
255 *sharedBuffer = true;
256 return true;
257 }
259 static void FreeZoneCache(JS::Zone *zone);
260 static void ClearZoneCache(JS::Zone *zone);
262 static MOZ_ALWAYS_INLINE bool IsLiteral(JSString *str)
263 {
264 return JS_IsExternalString(str) &&
265 JS_GetExternalStringFinalizer(str) == &sLiteralFinalizer;
266 }
268 static MOZ_ALWAYS_INLINE bool IsDOMString(JSString *str)
269 {
270 return JS_IsExternalString(str) &&
271 JS_GetExternalStringFinalizer(str) == &sDOMStringFinalizer;
272 }
274 private:
275 static const JSStringFinalizer sLiteralFinalizer, sDOMStringFinalizer;
277 static void FinalizeLiteral(const JSStringFinalizer *fin, jschar *chars);
279 static void FinalizeDOMString(const JSStringFinalizer *fin, jschar *chars);
281 XPCStringConvert(); // not implemented
282 };
284 namespace xpc {
286 // If these functions return false, then an exception will be set on cx.
287 bool Base64Encode(JSContext *cx, JS::HandleValue val, JS::MutableHandleValue out);
288 bool Base64Decode(JSContext *cx, JS::HandleValue val, JS::MutableHandleValue out);
290 /**
291 * Convert an nsString to jsval, returning true on success.
292 * Note, the ownership of the string buffer may be moved from str to rval.
293 * If that happens, str will point to an empty string after this call.
294 */
295 bool NonVoidStringToJsval(JSContext *cx, nsAString &str, JS::MutableHandleValue rval);
296 inline bool StringToJsval(JSContext *cx, nsAString &str, JS::MutableHandleValue rval)
297 {
298 // From the T_DOMSTRING case in XPCConvert::NativeData2JS.
299 if (str.IsVoid()) {
300 rval.setNull();
301 return true;
302 }
303 return NonVoidStringToJsval(cx, str, rval);
304 }
306 inline bool
307 NonVoidStringToJsval(JSContext* cx, const nsAString& str, JS::MutableHandleValue rval)
308 {
309 nsString mutableCopy(str);
310 return NonVoidStringToJsval(cx, mutableCopy, rval);
311 }
313 inline bool
314 StringToJsval(JSContext* cx, const nsAString& str, JS::MutableHandleValue rval)
315 {
316 nsString mutableCopy(str);
317 return StringToJsval(cx, mutableCopy, rval);
318 }
320 /**
321 * As above, but for mozilla::dom::DOMString.
322 */
323 MOZ_ALWAYS_INLINE
324 bool NonVoidStringToJsval(JSContext* cx, mozilla::dom::DOMString& str,
325 JS::MutableHandleValue rval)
326 {
327 if (!str.HasStringBuffer()) {
328 // It's an actual XPCOM string
329 return NonVoidStringToJsval(cx, str.AsAString(), rval);
330 }
332 uint32_t length = str.StringBufferLength();
333 if (length == 0) {
334 rval.set(JS_GetEmptyStringValue(cx));
335 return true;
336 }
338 nsStringBuffer* buf = str.StringBuffer();
339 bool shared;
340 if (!XPCStringConvert::StringBufferToJSVal(cx, buf, length, rval,
341 &shared)) {
342 return false;
343 }
344 if (shared) {
345 // JS now needs to hold a reference to the buffer
346 buf->AddRef();
347 }
348 return true;
349 }
351 MOZ_ALWAYS_INLINE
352 bool StringToJsval(JSContext* cx, mozilla::dom::DOMString& str,
353 JS::MutableHandleValue rval)
354 {
355 if (str.IsNull()) {
356 rval.setNull();
357 return true;
358 }
359 return NonVoidStringToJsval(cx, str, rval);
360 }
362 nsIPrincipal *GetCompartmentPrincipal(JSCompartment *compartment);
364 void SetLocationForGlobal(JSObject *global, const nsACString& location);
365 void SetLocationForGlobal(JSObject *global, nsIURI *locationURI);
367 // ReportJSRuntimeExplicitTreeStats will expect this in the |extra| member
368 // of JS::ZoneStats.
369 class ZoneStatsExtras {
370 public:
371 ZoneStatsExtras()
372 {}
374 nsAutoCString pathPrefix;
376 private:
377 ZoneStatsExtras(const ZoneStatsExtras &other) MOZ_DELETE;
378 ZoneStatsExtras& operator=(const ZoneStatsExtras &other) MOZ_DELETE;
379 };
381 // ReportJSRuntimeExplicitTreeStats will expect this in the |extra| member
382 // of JS::CompartmentStats.
383 class CompartmentStatsExtras {
384 public:
385 CompartmentStatsExtras()
386 {}
388 nsAutoCString jsPathPrefix;
389 nsAutoCString domPathPrefix;
390 nsCOMPtr<nsIURI> location;
392 private:
393 CompartmentStatsExtras(const CompartmentStatsExtras &other) MOZ_DELETE;
394 CompartmentStatsExtras& operator=(const CompartmentStatsExtras &other) MOZ_DELETE;
395 };
397 // This reports all the stats in |rtStats| that belong in the "explicit" tree,
398 // (which isn't all of them).
399 // @see ZoneStatsExtras
400 // @see CompartmentStatsExtras
401 nsresult
402 ReportJSRuntimeExplicitTreeStats(const JS::RuntimeStats &rtStats,
403 const nsACString &rtPath,
404 nsIMemoryReporterCallback *cb,
405 nsISupports *closure, size_t *rtTotal = nullptr);
407 /**
408 * Throws an exception on cx and returns false.
409 */
410 bool
411 Throw(JSContext *cx, nsresult rv);
413 /**
414 * Every global should hold a native that implements the nsIGlobalObject interface.
415 */
416 nsIGlobalObject *
417 GetNativeForGlobal(JSObject *global);
419 /**
420 * In some cases a native object does not really belong to any compartment (XBL,
421 * document created from by XHR of a worker, etc.). But when for some reason we
422 * have to wrap these natives (because of an event for example) instead of just
423 * wrapping them into some random compartment we find on the context stack (like
424 * we did previously) a default compartment is used. This function returns that
425 * compartment's global. It is a singleton on the runtime.
426 * If you find yourself wanting to use this compartment, you're probably doing
427 * something wrong. Callers MUST consult with the XPConnect module owner before
428 * using this compartment. If you don't, bholley will hunt you down.
429 */
430 JSObject *
431 GetJunkScope();
433 /**
434 * Returns the native global of the junk scope. See comment of GetJunkScope
435 * about the conditions of using it.
436 */
437 nsIGlobalObject *
438 GetJunkScopeGlobal();
440 /**
441 * Shared compilation scope for XUL prototype documents and XBL
442 * precompilation. This compartment has a null principal. No code may run, and
443 * it is invisible to the debugger.
444 */
445 JSObject *
446 GetCompilationScope();
448 /**
449 * If |aObj| is a window, returns the associated nsGlobalWindow.
450 * Otherwise, returns null.
451 */
452 nsGlobalWindow*
453 WindowOrNull(JSObject *aObj);
455 /*
456 * Returns the dummy global associated with the SafeJSContext. Callers MUST
457 * consult with the XPConnect module owner before using this function.
458 */
459 JSObject *
460 GetSafeJSContextGlobal();
462 /**
463 * If |aObj| has a window for a global, returns the associated nsGlobalWindow.
464 * Otherwise, returns null.
465 */
466 nsGlobalWindow*
467 WindowGlobalOrNull(JSObject *aObj);
469 // Error reporter used when there is no associated DOM window on to which to
470 // report errors and warnings.
471 void
472 SystemErrorReporter(JSContext *cx, const char *message, JSErrorReport *rep);
474 void
475 SimulateActivityCallback(bool aActive);
477 void
478 RecordAdoptedNode(JSCompartment *c);
480 void
481 RecordDonatedNode(JSCompartment *c);
483 // This function may be used off-main-thread, in which case it is benignly
484 // racey.
485 bool
486 ShouldDiscardSystemSource();
488 } // namespace xpc
490 namespace mozilla {
491 namespace dom {
493 typedef JSObject*
494 (*DefineInterface)(JSContext *cx, JS::Handle<JSObject*> global,
495 JS::Handle<jsid> id, bool defineOnGlobal);
497 typedef JSObject*
498 (*ConstructNavigatorProperty)(JSContext *cx, JS::Handle<JSObject*> naviObj);
500 // Check whether a constructor should be enabled for the given object.
501 // Note that the object should NOT be an Xray, since Xrays will end up
502 // defining constructors on the underlying object.
503 // This is a typedef for the function type itself, not the function
504 // pointer, so it's more obvious that pointers to a ConstructorEnabled
505 // can be null.
506 typedef bool
507 (ConstructorEnabled)(JSContext* cx, JS::Handle<JSObject*> obj);
509 void
510 Register(nsScriptNameSpaceManager* aNameSpaceManager);
512 /**
513 * A test for whether WebIDL methods that should only be visible to
514 * chrome or XBL scopes should be exposed.
515 */
516 bool IsChromeOrXBL(JSContext* cx, JSObject* /* unused */);
518 } // namespace dom
519 } // namespace mozilla
521 #endif