Bug 990353 - Flag for discarding where appropriate. r=bent
authorBobby Holley <bobbyholley@gmail.com>
Tue, 22 Apr 2014 14:08:28 -0700
changeset 179661 42aaedb9345585d7c51332a4b6d47a4762a1dac1
parent 179660 26a22df461a295204f77b122230aec0bf00da687
child 179662 6f6abed86df788f06c6567c730505985eddb841f
push id1
push userroot
push dateMon, 20 Oct 2014 17:29:22 +0000
reviewersbent
bugs990353
milestone31.0a1
Bug 990353 - Flag for discarding where appropriate. r=bent
dom/workers/ScriptLoader.cpp
js/xpconnect/src/XPCJSRuntime.cpp
js/xpconnect/src/nsXPConnect.cpp
--- a/dom/workers/ScriptLoader.cpp
+++ b/dom/workers/ScriptLoader.cpp
@@ -694,16 +694,30 @@ ScriptExecutorRunnable::WorkerRun(JSCont
     if (!loadInfo.mExecutionResult) {
       return true;
     }
   }
 
   JS::Rooted<JSObject*> global(aCx, JS::CurrentGlobalOrNull(aCx));
   NS_ASSERTION(global, "Must have a global by now!");
 
+  // Determine whether we want to be discarding source on this global to save
+  // memory. It would make more sense to do this when we create the global, but
+  // the information behind UsesSystemPrincipal() et al isn't finalized until
+  // the call to SetPrincipal during the first script load. After that, however,
+  // it never changes. So we can just idempotently set the bits here.
+  //
+  // Note that we read a pref that is cached on the main thread. This is benignly
+  // racey.
+  if (xpc::ShouldDiscardSystemSource()) {
+    bool discard = aWorkerPrivate->UsesSystemPrincipal() ||
+                   aWorkerPrivate->IsInPrivilegedApp();
+    JS::CompartmentOptionsRef(global).setDiscardSource(discard);
+  }
+
   for (uint32_t index = mFirstIndex; index <= mLastIndex; index++) {
     ScriptLoadInfo& loadInfo = loadInfos.ElementAt(index);
 
     NS_ASSERTION(!loadInfo.mChannel, "Should no longer have a channel!");
     NS_ASSERTION(loadInfo.mExecutionScheduled, "Should be scheduled!");
     NS_ASSERTION(!loadInfo.mExecutionResult, "Should not have executed yet!");
 
     if (NS_FAILED(loadInfo.mLoadResult)) {
--- a/js/xpconnect/src/XPCJSRuntime.cpp
+++ b/js/xpconnect/src/XPCJSRuntime.cpp
@@ -3505,16 +3505,17 @@ XPCJSRuntime::GetCompilationScope()
         SandboxOptions options;
         options.sandboxName.AssignLiteral("XPConnect Compilation Compartment");
         options.invisibleToDebugger = true;
         RootedValue v(cx);
         nsresult rv = CreateSandboxObject(cx, &v, /* principal = */ nullptr, options);
         NS_ENSURE_SUCCESS(rv, nullptr);
 
         mCompilationScope = js::UncheckedUnwrap(&v.toObject());
+        CompartmentOptionsRef(mCompilationScope).setDiscardSource(ShouldDiscardSystemSource());
     }
     return mCompilationScope;
 }
 
 
 void
 XPCJSRuntime::DeleteSingletonScopes()
 {
--- a/js/xpconnect/src/nsXPConnect.cpp
+++ b/js/xpconnect/src/nsXPConnect.cpp
@@ -409,16 +409,27 @@ InitGlobalObject(JSContext* aJSContext, 
     if (!(aFlags & nsIXPConnect::OMIT_COMPONENTS_OBJECT)) {
         // XPCCallContext gives us an active request needed to save/restore.
         if (!GetCompartmentPrivate(aGlobal)->scope->AttachComponentsObject(aJSContext) ||
             !XPCNativeWrapper::AttachNewConstructorObject(aJSContext, aGlobal)) {
             return UnexpectedFailure(false);
         }
     }
 
+    if (ShouldDiscardSystemSource()) {
+        nsIPrincipal *prin = GetObjectPrincipal(aGlobal);
+        bool isSystem = nsContentUtils::IsSystemPrincipal(prin);
+        if (!isSystem) {
+            short status = prin->GetAppStatus();
+            isSystem = status == nsIPrincipal::APP_STATUS_PRIVILEGED ||
+                       status == nsIPrincipal::APP_STATUS_CERTIFIED;
+        }
+        JS::CompartmentOptionsRef(aGlobal).setDiscardSource(isSystem);
+    }
+
     // Stuff coming through this path always ends up as a DOM global.
     MOZ_ASSERT(js::GetObjectClass(aGlobal)->flags & JSCLASS_DOM_GLOBAL);
 
     // Init WebIDL binding constructors wanted on all XPConnect globals.
     //
     // XXX Please do not add any additional classes here without the approval of
     //     the XPConnect module owner.
     if (!PromiseBinding::GetConstructorObject(aJSContext, aGlobal) ||