Bug 1198093 - Part 1: Expose indexedDB to System with [Exposed=System]. r=khuey
authorBevis Tseng <btseng@mozilla.com>
Wed, 30 Mar 2016 11:22:14 +0800
changeset 291215 57f7f132083c4cf6182a5c0aaa9c7ba05e589b5e
parent 291214 5582a25d289de681271efd51a75ce5392f4b1639
child 291216 7fa6eea202cb13eda52766eb0e2c9efa27a21ff6
push id74520
push userryanvm@gmail.com
push dateFri, 01 Apr 2016 17:19:38 +0000
treeherdermozilla-inbound@d9c26f4f5a3b [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerskhuey
bugs1198093
milestone48.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1198093 - Part 1: Expose indexedDB to System with [Exposed=System]. r=khuey
dom/indexedDB/IndexedDatabaseManager.cpp
dom/indexedDB/IndexedDatabaseManager.h
dom/webidl/DOMRequest.webidl
dom/webidl/DOMStringList.webidl
dom/webidl/IDBCursor.webidl
dom/webidl/IDBDatabase.webidl
dom/webidl/IDBFactory.webidl
dom/webidl/IDBFileHandle.webidl
dom/webidl/IDBFileRequest.webidl
dom/webidl/IDBIndex.webidl
dom/webidl/IDBKeyRange.webidl
dom/webidl/IDBMutableFile.webidl
dom/webidl/IDBObjectStore.webidl
dom/webidl/IDBOpenDBRequest.webidl
dom/webidl/IDBRequest.webidl
dom/webidl/IDBTransaction.webidl
dom/webidl/IDBVersionChangeEvent.webidl
js/xpconnect/src/Sandbox.cpp
js/xpconnect/src/XPCComponents.cpp
js/xpconnect/src/xpcprivate.h
--- a/dom/indexedDB/IndexedDatabaseManager.cpp
+++ b/dom/indexedDB/IndexedDatabaseManager.cpp
@@ -548,18 +548,18 @@ IndexedDatabaseManager::CommonPostHandle
                           aFactory->IsChrome(),
                           aFactory->InnerWindowID());
 
   return NS_OK;
 }
 
 // static
 bool
-IndexedDatabaseManager::DefineIndexedDB(JSContext* aCx,
-                                        JS::Handle<JSObject*> aGlobal)
+IndexedDatabaseManager::ResolveSandboxBinding(JSContext* aCx,
+                                              JS::Handle<JSObject*> aGlobal)
 {
   MOZ_ASSERT(NS_IsMainThread());
   MOZ_ASSERT(js::GetObjectClass(aGlobal)->flags & JSCLASS_DOM_GLOBAL,
              "Passed object is not a global object!");
 
   // We need to ensure that the manager has been created already here so that we
   // load preferences that may control which properties are exposed.
   if (NS_WARN_IF(!GetOrCreate())) {
@@ -578,16 +578,28 @@ IndexedDatabaseManager::DefineIndexedDB(
       !IDBOpenDBRequestBinding::GetConstructorObject(aCx, aGlobal) ||
       !IDBRequestBinding::GetConstructorObject(aCx, aGlobal) ||
       !IDBTransactionBinding::GetConstructorObject(aCx, aGlobal) ||
       !IDBVersionChangeEventBinding::GetConstructorObject(aCx, aGlobal))
   {
     return false;
   }
 
+  return true;
+}
+
+// static
+bool
+IndexedDatabaseManager::DefineIndexedDB(JSContext* aCx,
+                                        JS::Handle<JSObject*> aGlobal)
+{
+  MOZ_ASSERT(NS_IsMainThread());
+  MOZ_ASSERT(js::GetObjectClass(aGlobal)->flags & JSCLASS_DOM_GLOBAL,
+             "Passed object is not a global object!");
+
   RefPtr<IDBFactory> factory;
   if (NS_FAILED(IDBFactory::CreateForMainThreadJS(aCx,
                                                   aGlobal,
                                                   getter_AddRefs(factory)))) {
     return false;
   }
 
   MOZ_ASSERT(factory, "This should never fail for chrome!");
@@ -688,16 +700,40 @@ IndexedDatabaseManager::ExperimentalFeat
                "before indexedDB has been initialized!");
   }
 
   return gExperimentalFeaturesEnabled;
 }
 
 // static
 bool
+IndexedDatabaseManager::ExperimentalFeaturesEnabled(JSContext* aCx, JSObject* aGlobal)
+{
+  // If, in the child process, properties of the global object are enumerated
+  // before the chrome registry (and thus the value of |intl.accept_languages|)
+  // is ready, calling IndexedDatabaseManager::Init will permanently break
+  // that preference. We can retrieve gExperimentalFeaturesEnabled without
+  // actually going through IndexedDatabaseManager.
+  // See Bug 1198093 comment 14 for detailed explanation.
+  if (IsNonExposedGlobal(aCx, js::GetGlobalForObjectCrossCompartment(aGlobal),
+                         GlobalNames::BackstagePass)) {
+    MOZ_ASSERT(NS_IsMainThread());
+    static bool featureRetrieved = false;
+    if (!featureRetrieved) {
+      gExperimentalFeaturesEnabled = Preferences::GetBool(kPrefExperimental);
+      featureRetrieved = true;
+    }
+    return gExperimentalFeaturesEnabled;
+  }
+
+  return ExperimentalFeaturesEnabled();
+}
+
+// static
+bool
 IndexedDatabaseManager::IsFileHandleEnabled()
 {
   MOZ_ASSERT(gDBManager,
              "IsFileHandleEnabled() called before indexedDB has been "
              "initialized!");
 
   return gFileHandleEnabled;
 }
--- a/dom/indexedDB/IndexedDatabaseManager.h
+++ b/dom/indexedDB/IndexedDatabaseManager.h
@@ -114,20 +114,17 @@ public:
     return sLoggingModule;
   }
 #endif
 
   static bool
   ExperimentalFeaturesEnabled();
 
   static bool
-  ExperimentalFeaturesEnabled(JSContext* /* aCx */, JSObject* /* aGlobal */)
-  {
-    return ExperimentalFeaturesEnabled();
-  }
+  ExperimentalFeaturesEnabled(JSContext* aCx, JSObject* aGlobal);
 
   static bool
   IsFileHandleEnabled();
 
   void
   ClearBackgroundActor();
 
   void
@@ -186,16 +183,19 @@ public:
 
     return mgr->mFileMutex;
   }
 
   static nsresult
   CommonPostHandleEvent(EventChainPostVisitor& aVisitor, IDBFactory* aFactory);
 
   static bool
+  ResolveSandboxBinding(JSContext* aCx, JS::Handle<JSObject*> aGlobal);
+
+  static bool
   DefineIndexedDB(JSContext* aCx, JS::Handle<JSObject*> aGlobal);
 
 private:
   IndexedDatabaseManager();
   ~IndexedDatabaseManager();
 
   nsresult
   Init();
--- a/dom/webidl/DOMRequest.webidl
+++ b/dom/webidl/DOMRequest.webidl
@@ -1,27 +1,27 @@
 /* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 enum DOMRequestReadyState { "pending", "done" };
 
-[Exposed=(Window,Worker), NoInterfaceObject]
+[Exposed=(Window,Worker,System), NoInterfaceObject]
 interface DOMRequestShared {
   readonly attribute DOMRequestReadyState readyState;
 
   readonly attribute any result;
   readonly attribute DOMError? error;
 
   attribute EventHandler onsuccess;
   attribute EventHandler onerror;
 };
 
-[Exposed=(Window,Worker)]
+[Exposed=(Window,Worker,System)]
 interface DOMRequest : EventTarget {
   // The [TreatNonCallableAsNull] annotation is required since then() should do
   // nothing instead of throwing errors when non-callable arguments are passed.
   // See documentation for Promise.then to see why we return "any".
   [NewObject, Throws]
   any then([TreatNonCallableAsNull] optional AnyCallback? fulfillCallback = null,
            [TreatNonCallableAsNull] optional AnyCallback? rejectCallback = null);
 };
--- a/dom/webidl/DOMStringList.webidl
+++ b/dom/webidl/DOMStringList.webidl
@@ -5,14 +5,14 @@
  *
  * The origin of this IDL file is
  * http://www.w3.org/TR/2012/WD-dom-20120105/
  *
  * Copyright © 2012 W3C® (MIT, ERCIM, Keio), All Rights Reserved. W3C
  * liability, trademark and document use rules apply.
  */
 
-[Exposed=(Window,Worker)]
+[Exposed=(Window,Worker,System)]
 interface DOMStringList {
   readonly attribute unsigned long length;
   getter DOMString? item(unsigned long index);
   boolean contains(DOMString string);
 };
--- a/dom/webidl/IDBCursor.webidl
+++ b/dom/webidl/IDBCursor.webidl
@@ -9,17 +9,17 @@
 
 enum IDBCursorDirection {
     "next",
     "nextunique",
     "prev",
     "prevunique"
 };
 
-[Exposed=(Window,Worker)]
+[Exposed=(Window,Worker,System)]
 interface IDBCursor {
     readonly    attribute (IDBObjectStore or IDBIndex) source;
 
     readonly    attribute IDBCursorDirection           direction;
 
     [Throws]
     readonly    attribute any                          key;
 
@@ -34,13 +34,13 @@ interface IDBCursor {
 
     [Throws]
     void       continue (optional any key);
 
     [Throws]
     IDBRequest delete ();
 };
 
-[Exposed=(Window,Worker)]
+[Exposed=(Window,Worker,System)]
 interface IDBCursorWithValue : IDBCursor {
     [Throws]
     readonly    attribute any value;
 };
--- a/dom/webidl/IDBDatabase.webidl
+++ b/dom/webidl/IDBDatabase.webidl
@@ -5,17 +5,17 @@
  *
  * The origin of this IDL file is
  * https://dvcs.w3.org/hg/IndexedDB/raw-file/tip/Overview.html#idl-def-IDBObjectStoreParameters
  *
  * Copyright © 2012 W3C® (MIT, ERCIM, Keio), All Rights Reserved. W3C
  * liability, trademark and document use rules apply.
  */
 
-[Exposed=(Window,Worker)]
+[Exposed=(Window,Worker,System)]
 interface IDBDatabase : EventTarget {
     readonly    attribute DOMString          name;
     readonly    attribute unsigned long long version;
 
     readonly    attribute DOMStringList      objectStoreNames;
 
     [Throws]
     IDBObjectStore createObjectStore (DOMString name, optional IDBObjectStoreParameters optionalParameters);
--- a/dom/webidl/IDBFactory.webidl
+++ b/dom/webidl/IDBFactory.webidl
@@ -18,17 +18,17 @@ dictionary IDBOpenDBOptions
   StorageType storage;
 };
 
 /**
  * Interface that defines the indexedDB property on a window.  See
  * http://dvcs.w3.org/hg/IndexedDB/raw-file/tip/Overview.html#idl-def-IDBFactory
  * for more information.
  */
-[Exposed=(Window,Worker)]
+[Exposed=(Window,Worker,System)]
 interface IDBFactory {
   [Throws]
   IDBOpenDBRequest
   open(DOMString name,
        [EnforceRange] unsigned long long version);
 
   [Throws]
   IDBOpenDBRequest
--- a/dom/webidl/IDBFileHandle.webidl
+++ b/dom/webidl/IDBFileHandle.webidl
@@ -3,16 +3,17 @@
  * You can obtaone at http://mozilla.org/MPL/2.0/. */
 
 dictionary IDBFileMetadataParameters
 {
   boolean size = true;
   boolean lastModified = true;
 };
 
+[Exposed=(Window,System)]
 interface IDBFileHandle : EventTarget
 {
   readonly attribute IDBMutableFile? mutableFile;
   // this is deprecated due to renaming in the spec
   readonly attribute IDBMutableFile? fileHandle; // now mutableFile
   readonly attribute FileMode mode;
   readonly attribute boolean active;
   attribute unsigned long long? location;
--- a/dom/webidl/IDBFileRequest.webidl
+++ b/dom/webidl/IDBFileRequest.webidl
@@ -1,13 +1,14 @@
 /* -*- Mode: IDL; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* vim: set ts=2 et sw=2 tw=80: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
+[Exposed=(Window,System)]
 interface IDBFileRequest : DOMRequest {
   readonly attribute IDBFileHandle? fileHandle;
   // this is deprecated due to renaming in the spec
   readonly attribute IDBFileHandle? lockedFile; // now fileHandle
 
   attribute EventHandler onprogress;
 };
--- a/dom/webidl/IDBIndex.webidl
+++ b/dom/webidl/IDBIndex.webidl
@@ -13,17 +13,17 @@ dictionary IDBIndexParameters {
     // <null>:   Not locale-aware, uses normal JS sorting.
     // <string>: Always sorted based on the rules of the specified
     //           locale (e.g. "en-US", etc.).
     // "auto":   Sorted by the platform default, may change based on
     //           user agent options.
     DOMString? locale = null;
 };
 
-[Exposed=(Window,Worker)]
+[Exposed=(Window,Worker,System)]
 interface IDBIndex {
     readonly    attribute DOMString      name;
     readonly    attribute IDBObjectStore objectStore;
 
     [Throws]
     readonly    attribute any            keyPath;
 
     readonly    attribute boolean        multiEntry;
--- a/dom/webidl/IDBKeyRange.webidl
+++ b/dom/webidl/IDBKeyRange.webidl
@@ -4,17 +4,17 @@
 /*
  * The origin of this IDL file is
  * https://dvcs.w3.org/hg/IndexedDB/raw-file/tip/Overview.html
  *
  * Copyright © 2012 W3C® (MIT, ERCIM, Keio), All Rights Reserved. W3C
  * liability, trademark and document use rules apply.
  */
 
-[Exposed=(Window,Worker)]
+[Exposed=(Window,Worker,System)]
 interface IDBKeyRange {
   [Throws]
   readonly attribute any     lower;
   [Throws]
   readonly attribute any     upper;
   [Constant]
   readonly attribute boolean lowerOpen;
   [Constant]
@@ -28,14 +28,14 @@ interface IDBKeyRange {
   [NewObject, Throws]
   static IDBKeyRange lowerBound (any lower, optional boolean open = false);
   [NewObject, Throws]
   static IDBKeyRange upperBound (any upper, optional boolean open = false);
   [NewObject, Throws]
   static IDBKeyRange bound (any lower, any upper, optional boolean lowerOpen = false, optional boolean upperOpen = false);
 };
 
-[Exposed=(Window,Worker),
+[Exposed=(Window,Worker,System),
  Func="mozilla::dom::IndexedDatabaseManager::ExperimentalFeaturesEnabled"]
 interface IDBLocaleAwareKeyRange : IDBKeyRange {
   [NewObject, Throws]
   static IDBLocaleAwareKeyRange bound (any lower, any upper, optional boolean lowerOpen = false, optional boolean upperOpen = false);
 };
--- a/dom/webidl/IDBMutableFile.webidl
+++ b/dom/webidl/IDBMutableFile.webidl
@@ -1,13 +1,14 @@
 /* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
+[Exposed=(Window,System)]
 interface IDBMutableFile : EventTarget {
   readonly attribute DOMString name;
   readonly attribute DOMString type;
 
   readonly attribute IDBDatabase database;
 
   [Throws]
   IDBFileHandle open(optional FileMode mode = "readonly");
--- a/dom/webidl/IDBObjectStore.webidl
+++ b/dom/webidl/IDBObjectStore.webidl
@@ -7,17 +7,17 @@
  * https://dvcs.w3.org/hg/IndexedDB/raw-file/tip/Overview.html#idl-def-IDBObjectStore
  */
 
 dictionary IDBObjectStoreParameters {
     (DOMString or sequence<DOMString>)? keyPath = null;
     boolean                             autoIncrement = false;
 };
 
-[Exposed=(Window,Worker)]
+[Exposed=(Window,Worker,System)]
 interface IDBObjectStore {
     readonly    attribute DOMString      name;
 
     [Throws]
     readonly    attribute any            keyPath;
 
     readonly    attribute DOMStringList  indexNames;
     readonly    attribute IDBTransaction transaction;
--- a/dom/webidl/IDBOpenDBRequest.webidl
+++ b/dom/webidl/IDBOpenDBRequest.webidl
@@ -2,14 +2,14 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this file,
  * You can obtain one at http://mozilla.org/MPL/2.0/.
  *
  * The origin of this IDL file is
  * https://dvcs.w3.org/hg/IndexedDB/raw-file/tip/Overview.html#idl-def-IDBOpenDBRequest
  */
 
-[Exposed=(Window,Worker)]
+[Exposed=(Window,Worker,System)]
 interface IDBOpenDBRequest : IDBRequest {
                 attribute EventHandler onblocked;
 
                 attribute EventHandler onupgradeneeded;
 };
--- a/dom/webidl/IDBRequest.webidl
+++ b/dom/webidl/IDBRequest.webidl
@@ -8,17 +8,17 @@
  * https://dvcs.w3.org/hg/IndexedDB/raw-file/tip/Overview.html#idl-def-IDBRequestReadyState
  */
 
 enum IDBRequestReadyState {
     "pending",
     "done"
 };
 
-[Exposed=(Window,Worker)]
+[Exposed=(Window,Worker,System)]
 interface IDBRequest : EventTarget {
     [Throws]
     readonly    attribute any                  result;
 
     [Throws]
     readonly    attribute DOMError?            error;
 
     readonly    attribute (IDBObjectStore or IDBIndex or IDBCursor)? source;
--- a/dom/webidl/IDBTransaction.webidl
+++ b/dom/webidl/IDBTransaction.webidl
@@ -14,17 +14,17 @@ enum IDBTransactionMode {
     // The "readwriteflush" mode is only available when the
     // |IndexedDatabaseManager::ExperimentalFeaturesEnabled()| function returns
     // true. This mode is not yet part of the standard.
     "readwriteflush",
     "cleanup",
     "versionchange"
 };
 
-[Exposed=(Window,Worker)]
+[Exposed=(Window,Worker,System)]
 interface IDBTransaction : EventTarget {
     [Throws]
     readonly    attribute IDBTransactionMode mode;
     readonly    attribute IDBDatabase        db;
 
     readonly    attribute DOMError?          error;
 
     [Throws]
--- a/dom/webidl/IDBVersionChangeEvent.webidl
+++ b/dom/webidl/IDBVersionChangeEvent.webidl
@@ -11,14 +11,14 @@
  */
 
 dictionary IDBVersionChangeEventInit : EventInit {
     unsigned long long  oldVersion = 0;
     unsigned long long? newVersion = null;
 };
 
 [Constructor(DOMString type, optional IDBVersionChangeEventInit eventInitDict),
- Exposed=(Window,Worker)]
+ Exposed=(Window,Worker,System)]
 interface IDBVersionChangeEvent : Event {
     readonly    attribute unsigned long long  oldVersion;
     readonly    attribute unsigned long long? newVersion;
 };
 
--- a/js/xpconnect/src/Sandbox.cpp
+++ b/js/xpconnect/src/Sandbox.cpp
@@ -936,23 +936,24 @@ xpc::GlobalProperties::Parse(JSContext* 
         }
     }
     return true;
 }
 
 bool
 xpc::GlobalProperties::Define(JSContext* cx, JS::HandleObject obj)
 {
+    // Properties will be exposed to System automatically but not to Sandboxes
+    // if |[Exposed=System]| is specified.
+    // This function holds common properties not exposed automatically but able
+    // to be requested either in |Cu.importGlobalProperties| or
+    // |wantGlobalProperties| of a sandbox.
     if (CSS && !dom::CSSBinding::GetConstructorObject(cx, obj))
         return false;
 
-    if (indexedDB &&
-        !IndexedDatabaseManager::DefineIndexedDB(cx, obj))
-        return false;
-
     if (XMLHttpRequest &&
         !dom::XMLHttpRequestBinding::GetConstructorObject(cx, obj))
         return false;
 
     if (TextEncoder &&
         !dom::TextEncoderBinding::GetConstructorObject(cx, obj))
         return false;
 
@@ -999,16 +1000,39 @@ xpc::GlobalProperties::Define(JSContext*
         return false;
 
     if (fileReader && !dom::FileReaderBinding::GetConstructorObject(cx, obj))
         return false;
 
     return true;
 }
 
+bool
+xpc::GlobalProperties::DefineInXPCComponents(JSContext* cx, JS::HandleObject obj)
+{
+    if (indexedDB &&
+        !IndexedDatabaseManager::DefineIndexedDB(cx, obj))
+        return false;
+
+    return Define(cx, obj);
+}
+
+bool
+xpc::GlobalProperties::DefineInSandbox(JSContext* cx, JS::HandleObject obj)
+{
+    MOZ_ASSERT(IsSandbox(obj));
+
+    if (indexedDB &&
+        !(IndexedDatabaseManager::ResolveSandboxBinding(cx, obj) &&
+          IndexedDatabaseManager::DefineIndexedDB(cx, obj)))
+        return false;
+
+    return Define(cx, obj);
+}
+
 nsresult
 xpc::CreateSandboxObject(JSContext* cx, MutableHandleValue vp, nsISupports* prinOrSop,
                          SandboxOptions& options)
 {
     // Create the sandbox global object
     nsCOMPtr<nsIPrincipal> principal = do_QueryInterface(prinOrSop);
     if (!principal) {
         nsCOMPtr<nsIScriptObjectPrincipal> sop = do_QueryInterface(prinOrSop);
@@ -1165,17 +1189,17 @@ xpc::CreateSandboxObject(JSContext* cx, 
 
         if (options.wantExportHelpers &&
             (!JS_DefineFunction(cx, sandbox, "exportFunction", SandboxExportFunction, 3, 0) ||
              !JS_DefineFunction(cx, sandbox, "createObjectIn", SandboxCreateObjectIn, 2, 0) ||
              !JS_DefineFunction(cx, sandbox, "cloneInto", SandboxCloneInto, 3, 0) ||
              !JS_DefineFunction(cx, sandbox, "isProxy", SandboxIsProxy, 1, 0)))
             return NS_ERROR_XPC_UNEXPECTED;
 
-        if (!options.globalProperties.Define(cx, sandbox))
+        if (!options.globalProperties.DefineInSandbox(cx, sandbox))
             return NS_ERROR_XPC_UNEXPECTED;
 
 #ifndef SPIDERMONKEY_PROMISE
         // Promise is supposed to be part of ES, and therefore should appear on
         // every global.
         if (!dom::PromiseBinding::GetConstructorObject(cx, sandbox))
             return NS_ERROR_XPC_UNEXPECTED;
 #endif // SPIDERMONKEY_PROMISE
--- a/js/xpconnect/src/XPCComponents.cpp
+++ b/js/xpconnect/src/XPCComponents.cpp
@@ -2543,17 +2543,17 @@ nsXPCComponents_Utils::ImportGlobalPrope
     if (NS_WARN_IF(!JS_IsArrayObject(cx, propertyList, &isArray))) {
         return NS_ERROR_FAILURE;
     }
     if (NS_WARN_IF(!isArray)) {
         return NS_ERROR_INVALID_ARG;
     }
 
     if (!options.Parse(cx, propertyList) ||
-        !options.Define(cx, global))
+        !options.DefineInXPCComponents(cx, global))
     {
         return NS_ERROR_FAILURE;
     }
 
     return NS_OK;
 }
 
 NS_IMETHODIMP
--- a/js/xpconnect/src/xpcprivate.h
+++ b/js/xpconnect/src/xpcprivate.h
@@ -3354,33 +3354,36 @@ nsresult
 ThrowAndFail(nsresult errNum, JSContext* cx, bool* retval);
 
 struct GlobalProperties {
     GlobalProperties() {
       mozilla::PodZero(this);
 
     }
     bool Parse(JSContext* cx, JS::HandleObject obj);
-    bool Define(JSContext* cx, JS::HandleObject obj);
+    bool DefineInXPCComponents(JSContext* cx, JS::HandleObject obj);
+    bool DefineInSandbox(JSContext* cx, JS::HandleObject obj);
     bool CSS : 1;
     bool indexedDB : 1;
     bool XMLHttpRequest : 1;
     bool TextDecoder : 1;
     bool TextEncoder : 1;
     bool URL : 1;
     bool URLSearchParams : 1;
     bool atob : 1;
     bool btoa : 1;
     bool Blob : 1;
     bool File : 1;
     bool crypto : 1;
     bool rtcIdentityProvider : 1;
     bool fetch : 1;
     bool caches : 1;
     bool fileReader: 1;
+private:
+    bool Define(JSContext* cx, JS::HandleObject obj);
 };
 
 // Infallible.
 already_AddRefed<nsIXPCComponents_utils_Sandbox>
 NewSandboxConstructor();
 
 // Returns true if class of 'obj' is SandboxClass.
 bool