Bug 989528 - Rename AutoSystemCaller to AutoNoJSAPI, and assert against pre-existing exceptions. r=bz
authorBobby Holley <bobbyholley@gmail.com>
Mon, 14 Apr 2014 20:27:00 -0700
changeset 196940 bcd2cf9e9bdf261b2f3d214742bcdbd31c6441b8
parent 196939 b59ad321f19eac4377bf859925b25b74d64f61b4
child 196941 bdccb863d2de0ec48d5291948a2caf2c0ef7dd1e
push id3624
push userasasaki@mozilla.com
push dateMon, 09 Jun 2014 21:49:01 +0000
treeherdermozilla-beta@b1a5da15899a [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbz
bugs989528
milestone31.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 989528 - Rename AutoSystemCaller to AutoNoJSAPI, and assert against pre-existing exceptions. r=bz
accessible/src/html/HTMLFormControlAccessible.cpp
content/html/content/src/nsTextEditorState.cpp
dom/base/ScriptSettings.cpp
dom/base/ScriptSettings.h
dom/base/nsGlobalWindow.cpp
dom/bindings/BindingUtils.cpp
js/jsd/jsd_xpc.cpp
layout/base/nsRefreshDriver.cpp
layout/forms/nsTextControlFrame.cpp
security/manager/pki/src/nsNSSDialogHelper.cpp
toolkit/devtools/server/nsJSInspector.cpp
xpfe/appshell/src/nsContentTreeOwner.cpp
xpfe/appshell/src/nsXULWindow.cpp
--- a/accessible/src/html/HTMLFormControlAccessible.cpp
+++ b/accessible/src/html/HTMLFormControlAccessible.cpp
@@ -469,17 +469,17 @@ HTMLTextFieldAccessible::GetEditor() con
 {
   nsCOMPtr<nsIDOMNSEditableElement> editableElt(do_QueryInterface(mContent));
   if (!editableElt)
     return nullptr;
 
   // nsGenericHTMLElement::GetEditor has a security check.
   // Make sure we're not restricted by the permissions of
   // whatever script is currently running.
-  mozilla::dom::AutoSystemCaller asc;
+  mozilla::dom::AutoNoJSAPI nojsapi;
 
   nsCOMPtr<nsIEditor> editor;
   editableElt->GetEditor(getter_AddRefs(editor));
 
   return editor.forget();
 }
 
 ////////////////////////////////////////////////////////////////////////////////
--- a/content/html/content/src/nsTextEditorState.cpp
+++ b/content/html/content/src/nsTextEditorState.cpp
@@ -1247,17 +1247,17 @@ nsTextEditorState::PrepareEditor(const n
 
     // What follows is a bit of a hack.  The editor uses the public DOM APIs
     // for its content manipulations, and it causes it to fail some security
     // checks deep inside when initializing. So we explictly make it clear that
     // we're native code.
     // Note that any script that's directly trying to access our value
     // has to be going through some scriptable object to do that and that
     // already does the relevant security checks.
-    AutoSystemCaller asc;
+    AutoNoJSAPI nojsapi;
 
     rv = newEditor->Init(domdoc, GetRootNode(), mSelCon, editorFlags);
     NS_ENSURE_SUCCESS(rv, rv);
   }
 
   // Initialize the controller for the editor
 
   if (!SuppressEventHandlers(presContext)) {
@@ -1735,18 +1735,18 @@ nsTextEditorState::GetValue(nsAString& a
     // access its own DOM nodes!  Let's try to deal with that by pushing a null
     // JSContext on the JSContext stack to make it clear that we're native
     // code.  Note that any script that's directly trying to access our value
     // has to be going through some scriptable object to do that and that
     // already does the relevant security checks.
     // XXXbz if we could just get the textContent of our anonymous content (eg
     // if plaintext editor didn't create <br> nodes all over), we wouldn't need
     // this.
-    { /* Scope for AutoSystemCaller. */
-      AutoSystemCaller asc;
+    { /* Scope for AutoNoJSAPI. */
+      AutoNoJSAPI nojsapi;
 
       mEditor->OutputToString(NS_LITERAL_STRING("text/plain"), flags,
                               aValue);
     }
     if (canCache) {
       mCachedValue = aValue;
     } else {
       mCachedValue.Truncate();
@@ -1815,17 +1815,17 @@ nsTextEditorState::SetValue(const nsAStr
         NS_WARNING("Why don't we have a document?");
         return;
       }
 
       // Time to mess with our security context... See comments in GetValue()
       // for why this is needed.  Note that we have to do this up here, because
       // otherwise SelectAll() will fail.
       {
-        AutoSystemCaller asc;
+        AutoNoJSAPI nojsapi;
 
         nsCOMPtr<nsISelection> domSel;
         nsCOMPtr<nsISelectionPrivate> selPriv;
         mSelCon->GetSelection(nsISelectionController::SELECTION_NORMAL,
                               getter_AddRefs(domSel));
         if (domSel)
         {
           selPriv = do_QueryInterface(domSel);
--- a/dom/base/ScriptSettings.cpp
+++ b/dom/base/ScriptSettings.cpp
@@ -18,34 +18,34 @@
 #include "nsJSUtils.h"
 
 namespace mozilla {
 namespace dom {
 
 class ScriptSettingsStack;
 static mozilla::ThreadLocal<ScriptSettingsStack*> sScriptSettingsTLS;
 
-ScriptSettingsStackEntry ScriptSettingsStackEntry::SystemSingleton;
+ScriptSettingsStackEntry ScriptSettingsStackEntry::NoJSAPISingleton;
 
 class ScriptSettingsStack {
 public:
   static ScriptSettingsStack& Ref() {
     return *sScriptSettingsTLS.get();
   }
   ScriptSettingsStack() {};
 
   void Push(ScriptSettingsStackEntry* aSettings) {
     // The bottom-most entry must always be a candidate entry point.
-    MOZ_ASSERT_IF(mStack.Length() == 0 || mStack.LastElement()->IsSystemSingleton(),
+    MOZ_ASSERT_IF(mStack.Length() == 0 || mStack.LastElement()->NoJSAPI(),
                   aSettings->mIsCandidateEntryPoint);
     mStack.AppendElement(aSettings);
   }
 
-  void PushSystem() {
-    mStack.AppendElement(&ScriptSettingsStackEntry::SystemSingleton);
+  void PushNoJSAPI() {
+    mStack.AppendElement(&ScriptSettingsStackEntry::NoJSAPISingleton);
   }
 
   void Pop() {
     MOZ_ASSERT(mStack.Length() > 0);
     mStack.RemoveElementAt(mStack.Length() - 1);
   }
 
   ScriptSettingsStackEntry* Incumbent() {
@@ -153,19 +153,19 @@ GetIncumbentGlobal()
 }
 
 nsIPrincipal*
 GetWebIDLCallerPrincipal()
 {
   MOZ_ASSERT(NS_IsMainThread());
   ScriptSettingsStackEntry *entry = ScriptSettingsStack::Ref().EntryPoint();
 
-  // If we have an entry point that is not the system singleton, we know it
+  // If we have an entry point that is not the NoJSAPI singleton, we know it
   // must be an AutoEntryScript.
-  if (!entry || entry->IsSystemSingleton()) {
+  if (!entry || entry->NoJSAPI()) {
     return nullptr;
   }
   AutoEntryScript* aes = static_cast<AutoEntryScript*>(entry);
 
   // We can't yet rely on the Script Settings Stack to properly determine the
   // entry script, because there are still lots of places in the tree where we
   // don't yet use an AutoEntryScript (bug 951991 tracks this work). In the
   // mean time though, we can make some observations to hack around the
@@ -266,25 +266,27 @@ AutoIncumbentScript::AutoIncumbentScript
 }
 
 AutoIncumbentScript::~AutoIncumbentScript()
 {
   MOZ_ASSERT(mStack.Incumbent() == this);
   mStack.Pop();
 }
 
-AutoSystemCaller::AutoSystemCaller(bool aIsMainThread)
+AutoNoJSAPI::AutoNoJSAPI(bool aIsMainThread)
   : mStack(ScriptSettingsStack::Ref())
 {
+  MOZ_ASSERT_IF(nsContentUtils::GetCurrentJSContextForThread(),
+                !JS_IsExceptionPending(nsContentUtils::GetCurrentJSContextForThread()));
   if (aIsMainThread) {
     mCxPusher.construct(static_cast<JSContext*>(nullptr),
                         /* aAllowNull = */ true);
   }
-  mStack.PushSystem();
+  mStack.PushNoJSAPI();
 }
 
-AutoSystemCaller::~AutoSystemCaller()
+AutoNoJSAPI::~AutoNoJSAPI()
 {
   mStack.Pop();
 }
 
 } // namespace dom
 } // namespace mozilla
--- a/dom/base/ScriptSettings.h
+++ b/dom/base/ScriptSettings.h
@@ -81,18 +81,18 @@ struct ScriptSettingsStackEntry {
                "No outer windows allowed");
   }
 
   ~ScriptSettingsStackEntry() {
     // We must have an actual JS global for the entire time this is on the stack.
     MOZ_ASSERT_IF(mGlobalObject, mGlobalObject->GetGlobalJSObject());
   }
 
-  bool IsSystemSingleton() { return this == &SystemSingleton; }
-  static ScriptSettingsStackEntry SystemSingleton;
+  bool NoJSAPI() { return this == &NoJSAPISingleton; }
+  static ScriptSettingsStackEntry NoJSAPISingleton;
 
 private:
   ScriptSettingsStackEntry() : mGlobalObject(nullptr)
                              , mIsCandidateEntryPoint(true)
   {}
 };
 
 /*
@@ -191,24 +191,27 @@ public:
   AutoIncumbentScript(nsIGlobalObject* aGlobalObject);
   ~AutoIncumbentScript();
 private:
   dom::ScriptSettingsStack& mStack;
   JS::AutoHideScriptedCaller mCallerOverride;
 };
 
 /*
- * A class used for C++ to indicate that existing entry and incumbent scripts
- * should not apply to anything in scope, and that callees should act as if
- * they were invoked "from C++".
+ * A class to put the JS engine in an unusable state. The subject principal
+ * will become System, the information on the script settings stack is
+ * rendered inaccessible, and JSAPI may not be manipulated until the class is
+ * either popped or an AutoJSAPI instance is subsequently pushed.
+ *
+ * This class may not be instantiated if an exception is pending.
  */
-class AutoSystemCaller {
+class AutoNoJSAPI {
 public:
-  AutoSystemCaller(bool aIsMainThread = NS_IsMainThread());
-  ~AutoSystemCaller();
+  AutoNoJSAPI(bool aIsMainThread = NS_IsMainThread());
+  ~AutoNoJSAPI();
 private:
   dom::ScriptSettingsStack& mStack;
   mozilla::Maybe<AutoCxPusher> mCxPusher;
 };
 
 } // namespace dom
 } // namespace mozilla
 
--- a/dom/base/nsGlobalWindow.cpp
+++ b/dom/base/nsGlobalWindow.cpp
@@ -11467,19 +11467,19 @@ nsGlobalWindow::OpenInternal(const nsASt
       // up.  We do NOT want this case looking at the JS context on the stack
       // when searching.  Compare comments on
       // nsIDOMWindow::OpenWindow and nsIWindowWatcher::OpenWindow.
 
       // Note: Because nsWindowWatcher is so broken, it's actually important
       // that we don't force a system caller here, because that screws it up
       // when it tries to compute the caller principal to associate with dialog
       // arguments. That whole setup just really needs to be rewritten. :-(
-      Maybe<AutoSystemCaller> asc;
+      Maybe<AutoNoJSAPI> nojsapi;
       if (!aContentModal) {
-        asc.construct();
+        nojsapi.construct();
       }
 
 
       rv = pwwatch->OpenWindow2(this, url.get(), name_ptr, options_ptr,
                                 /* aCalledFromScript = */ false,
                                 aDialog, aNavigate, aExtraArgument,
                                 getter_AddRefs(domReturn));
 
--- a/dom/bindings/BindingUtils.cpp
+++ b/dom/bindings/BindingUtils.cpp
@@ -2032,17 +2032,17 @@ ConstructJSImplementation(JSContext* aCx
                           nsPIDOMWindow* aWindow,
                           JS::MutableHandle<JSObject*> aObject,
                           ErrorResult& aRv)
 {
   // Make sure to divorce ourselves from the calling JS while creating and
   // initializing the object, so exceptions from that will get reported
   // properly, since those are never exceptions that a spec wants to be thrown.
   {
-    AutoSystemCaller asc;
+    AutoNoJSAPI nojsapi;
 
     // Get the XPCOM component containing the JS implementation.
     nsCOMPtr<nsISupports> implISupports = do_CreateInstance(aContractId);
     if (!implISupports) {
       NS_WARNING("Failed to get JS implementation for contract");
       aRv.Throw(NS_ERROR_FAILURE);
       return;
     }
--- a/js/jsd/jsd_xpc.cpp
+++ b/js/jsd/jsd_xpc.cpp
@@ -36,17 +36,17 @@
 #include "nsDOMJSUtils.h"
 #include "SandboxPrivate.h"
 #include "nsJSPrincipals.h"
 #include "nsContentUtils.h"
 #include "mozilla/dom/ScriptSettings.h"
 
 using mozilla::AutoSafeJSContext;
 using mozilla::AutoPushJSContext;
-using mozilla::dom::AutoSystemCaller;
+using mozilla::dom::AutoNoJSAPI;
 
 /*
  * defining CAUTIOUS_SCRIPTHOOK makes jsds disable GC while calling out to the
  * script hook.  This was a hack to avoid some js engine problems that should
  * be fixed now (see Mozilla bug 77636).
  */
 #undef CAUTIOUS_SCRIPTHOOK
 
@@ -3006,17 +3006,17 @@ jsdService::WrapValue(JS::Handle<JS::Val
 
 
 NS_IMETHODIMP
 jsdService::EnterNestedEventLoop (jsdINestCallback *callback, uint32_t *_rval)
 {
     // Nesting event queues is a thing of the past.  Now, we just spin the
     // current event loop.
     nsresult rv = NS_OK;
-    AutoSystemCaller asc;
+    AutoNoJSAPI nojsapi;
     uint32_t nestLevel = ++mNestedLoopLevel;
     nsCOMPtr<nsIThread> thread = do_GetCurrentThread();
 
     if (callback) {
         DoPause(nullptr, true);
         rv = callback->OnNest();
         DoUnPause(nullptr, true);
     }
--- a/layout/base/nsRefreshDriver.cpp
+++ b/layout/base/nsRefreshDriver.cpp
@@ -717,17 +717,17 @@ nsRefreshDriver::AdvanceTimeAndRefresh(i
     mMostRecentRefresh = TimeStamp::Now();
 
     mTestControllingRefreshes = true;
   }
 
   mMostRecentRefreshEpochTime += aMilliseconds * 1000;
   mMostRecentRefresh += TimeDuration::FromMilliseconds((double) aMilliseconds);
 
-  mozilla::dom::AutoSystemCaller asc;
+  mozilla::dom::AutoNoJSAPI nojsapi;
   DoTick();
 }
 
 void
 nsRefreshDriver::RestoreNormalRefresh()
 {
   mTestControllingRefreshes = false;
   EnsureTimerStarted(false);
--- a/layout/forms/nsTextControlFrame.cpp
+++ b/layout/forms/nsTextControlFrame.cpp
@@ -258,17 +258,17 @@ nsTextControlFrame::EnsureEditorInitiali
 
   // Make sure that editor init doesn't do things that would kill us off
   // (especially off the script blockers it'll create for its DOM mutations).
   {
     nsAutoScriptBlocker scriptBlocker;
 
     // Time to mess with our security context... See comments in GetValue()
     // for why this is needed.
-    mozilla::dom::AutoSystemCaller asc;
+    mozilla::dom::AutoNoJSAPI nojsapi;
 
     // Make sure that we try to focus the content even if the method fails
     class EnsureSetFocus {
     public:
       explicit EnsureSetFocus(nsTextControlFrame* aFrame)
         : mFrame(aFrame) {}
       ~EnsureSetFocus() {
         if (nsContentUtils::IsFocusedContent(mFrame->GetContent()))
--- a/security/manager/pki/src/nsNSSDialogHelper.cpp
+++ b/security/manager/pki/src/nsNSSDialogHelper.cpp
@@ -34,17 +34,17 @@ nsNSSDialogHelper::openDialog(
     windowWatcher->GetActiveWindow(getter_AddRefs(parent));
   }
 
   // We're loading XUL into this window, and it's happening on behalf of the
   // system, not on behalf of content. Make sure the initial about:blank window
   // gets a system principal, otherwise we'll bork when trying to wrap the
   // nsIKeyGenThread |arguments| property into the unprivileged scoope.
   MOZ_ASSERT(!strncmp("chrome://", url, strlen("chrome://")));
-  mozilla::dom::AutoSystemCaller asc;
+  mozilla::dom::AutoNoJSAPI nojsapi;
 
   nsCOMPtr<nsIDOMWindow> newWindow;
   rv = windowWatcher->OpenWindow(parent,
                                  url,
                                  "_blank",
                                  modal
                                  ? kOpenDialogParam
                                  : kOpenWindowParam,
--- a/toolkit/devtools/server/nsJSInspector.cpp
+++ b/toolkit/devtools/server/nsJSInspector.cpp
@@ -68,17 +68,17 @@ NS_IMETHODIMP
 nsJSInspector::EnterNestedEventLoop(JS::Handle<JS::Value> requestor, uint32_t *out)
 {
   nsresult rv = NS_OK;
 
   mLastRequestor = requestor;
   mRequestors.AppendElement(requestor);
   mozilla::HoldJSObjects(this);
 
-  mozilla::dom::AutoSystemCaller asc;
+  mozilla::dom::AutoNoJSAPI nojsapi;
 
   uint32_t nestLevel = ++mNestedLoopLevel;
   while (NS_SUCCEEDED(rv) && mNestedLoopLevel >= nestLevel) {
     if (!NS_ProcessNextEvent())
       rv = NS_ERROR_UNEXPECTED;
   }
 
   NS_ASSERTION(mNestedLoopLevel <= nestLevel,
--- a/xpfe/appshell/src/nsContentTreeOwner.cpp
+++ b/xpfe/appshell/src/nsContentTreeOwner.cpp
@@ -941,17 +941,17 @@ nsContentTreeOwner::ProvideWindow(nsIDOM
   chromeWin->GetBrowserDOMWindow(getter_AddRefs(browserDOMWin));
   if (!browserDOMWin) {
     return NS_OK;
   }
 
   *aWindowIsNew = (containerPref != nsIBrowserDOMWindow::OPEN_CURRENTWINDOW);
 
   {
-    dom::AutoSystemCaller asc;
+    dom::AutoNoJSAPI nojsapi;
 
     // Get a new rendering area from the browserDOMWin.  We don't want
     // to be starting any loads here, so get it with a null URI.
     return browserDOMWin->OpenURI(nullptr, aParent, containerPref,
                                   nsIBrowserDOMWindow::OPEN_NEW, aReturn);
   }
 }
 
--- a/xpfe/appshell/src/nsXULWindow.cpp
+++ b/xpfe/appshell/src/nsXULWindow.cpp
@@ -57,17 +57,17 @@
 #include "mozilla/AutoRestore.h"
 #include "mozilla/Preferences.h"
 #include "mozilla/dom/BarProps.h"
 #include "mozilla/dom/Element.h"
 #include "mozilla/dom/Event.h"
 #include "mozilla/dom/ScriptSettings.h"
 
 using namespace mozilla;
-using dom::AutoSystemCaller;
+using dom::AutoNoJSAPI;
 
 #define SIZEMODE_NORMAL     NS_LITERAL_STRING("normal")
 #define SIZEMODE_MAXIMIZED  NS_LITERAL_STRING("maximized")
 #define SIZEMODE_MINIMIZED  NS_LITERAL_STRING("minimized")
 #define SIZEMODE_FULLSCREEN NS_LITERAL_STRING("fullscreen")
 
 #define WINDOWTYPE_ATTRIBUTE NS_LITERAL_STRING("windowtype")
 
@@ -355,17 +355,17 @@ NS_IMETHODIMP nsXULWindow::ShowModal()
   nsCOMPtr<nsIWidget> window = mWindow;
   nsCOMPtr<nsIXULWindow> tempRef = this;  
 
   window->SetModal(true);
   mContinueModalLoop = true;
   EnableParent(false);
 
   {
-    AutoSystemCaller asc;
+    AutoNoJSAPI nojsapi;
     nsIThread *thread = NS_GetCurrentThread();
     while (mContinueModalLoop) {
       if (!NS_ProcessNextEvent(thread))
         break;
     }
   }
 
   mContinueModalLoop = false;
@@ -1771,32 +1771,32 @@ NS_IMETHODIMP nsXULWindow::CreateNewCont
   NS_ENSURE_TRUE(uri, NS_ERROR_FAILURE);
 
   // We need to create a chrome window to contain the content window we're about
   // to pass back. The subject principal needs to be system while we're creating
   // it to make things work right, so force a system caller. See bug 799348
   // comment 13 for a description of what happens when we don't.
   nsCOMPtr<nsIXULWindow> newWindow;
   {
-    AutoSystemCaller asc;
+    AutoNoJSAPI nojsapi;
     appShell->CreateTopLevelWindow(this, uri,
                                    aChromeFlags, 615, 480,
                                    getter_AddRefs(newWindow));
     NS_ENSURE_TRUE(newWindow, NS_ERROR_FAILURE);
   }
 
   // Specify that we want the window to remain locked until the chrome has loaded.
   nsXULWindow *xulWin = static_cast<nsXULWindow*>
                                    (static_cast<nsIXULWindow*>
                                                (newWindow));
 
   xulWin->LockUntilChromeLoad();
 
   {
-    AutoSystemCaller asc;
+    AutoNoJSAPI nojsapi;
     nsIThread *thread = NS_GetCurrentThread();
     while (xulWin->IsLocked()) {
       if (!NS_ProcessNextEvent(thread))
         break;
     }
  }
 
   NS_ENSURE_STATE(xulWin->mPrimaryContentShell);