Bug 1308287 part 1. Change [NeedsSubjectPrincipal] to only do the Maybe thing for interfaces that can be exposed to workers. r=baku
authorBoris Zbarsky <bzbarsky@mit.edu>
Mon, 10 Oct 2016 21:07:48 -0400
changeset 423595 3e0c2cad052c8752f84ef746c2b54371971afb1f
parent 423594 67d40adfa5e12f58326a00f27262036edd9386ba
child 423596 0c1078ea4e6de2b8e3b6102d533e5e031f39a60d
push id31945
push users.kaspari@gmail.com
push dateTue, 11 Oct 2016 12:27:19 +0000
reviewersbaku
bugs1308287
milestone52.0a1
Bug 1308287 part 1. Change [NeedsSubjectPrincipal] to only do the Maybe thing for interfaces that can be exposed to workers. r=baku The idea is to not make consumers think about whether the principal exists or not when the caller knows for sure that it does. The substantive changes are in dom/bindings, nsHTMLDocument::SetDesignMode, and around the CanUseStorage bits. Everything else is pretty mechanical.
dom/base/Location.h
dom/base/nsDocument.cpp
dom/base/nsGlobalWindow.cpp
dom/base/nsGlobalWindow.h
dom/base/nsIDocument.h
dom/base/nsObjectLoadingContent.cpp
dom/base/nsObjectLoadingContent.h
dom/bindings/Codegen.py
dom/bindings/test/TestBindingHeader.h
dom/bindings/test/TestCodeGen.webidl
dom/bindings/test/TestJSImplGen.webidl
dom/events/ClipboardEvent.cpp
dom/events/DataTransfer.cpp
dom/events/DataTransfer.h
dom/events/DataTransferItem.cpp
dom/events/DataTransferItem.h
dom/events/DataTransferItemList.cpp
dom/events/DataTransferItemList.h
dom/html/HTMLIFrameElement.h
dom/html/HTMLInputElement.cpp
dom/html/HTMLInputElement.h
dom/html/HTMLObjectElement.cpp
dom/html/HTMLObjectElement.h
dom/html/HTMLSharedObjectElement.h
dom/html/nsGenericHTMLFrameElement.cpp
dom/html/nsGenericHTMLFrameElement.h
dom/html/nsHTMLDocument.cpp
dom/html/nsHTMLDocument.h
dom/storage/DOMStorage.cpp
dom/storage/DOMStorage.h
dom/webidl/Window.webidl
layout/style/CSSStyleSheet.cpp
layout/style/CSSStyleSheet.h
--- a/dom/base/Location.h
+++ b/dom/base/Location.h
@@ -39,184 +39,183 @@ public:
 
   void SetDocShell(nsIDocShell *aDocShell);
   nsIDocShell *GetDocShell();
 
   // nsIDOMLocation
   NS_DECL_NSIDOMLOCATION
 
   #define THROW_AND_RETURN_IF_CALLER_DOESNT_SUBSUME() { \
-    MOZ_ASSERT(aSubjectPrincipal.isSome()); \
-    if (!CallerSubsumes(aSubjectPrincipal.value())) { \
+    if (!CallerSubsumes(&aSubjectPrincipal)) { \
       aError.Throw(NS_ERROR_DOM_SECURITY_ERR); \
       return; \
     } \
   }
 
   // WebIDL API:
   void Assign(const nsAString& aUrl,
-              const Maybe<nsIPrincipal*>& aSubjectPrincipal,
+              nsIPrincipal& aSubjectPrincipal,
               ErrorResult& aError)
   {
     THROW_AND_RETURN_IF_CALLER_DOESNT_SUBSUME();
     aError = Assign(aUrl);
   }
 
   void Replace(const nsAString& aUrl,
-               const Maybe<nsIPrincipal*>& aSubjectPrincipal,
+               nsIPrincipal& aSubjectPrincipal,
                ErrorResult& aError)
   {
     aError = Replace(aUrl);
   }
 
   void Reload(bool aForceget,
-              const Maybe<nsIPrincipal*>& aSubjectPrincipal,
+              nsIPrincipal& aSubjectPrincipal,
               ErrorResult& aError)
   {
     THROW_AND_RETURN_IF_CALLER_DOESNT_SUBSUME();
     aError = Reload(aForceget);
   }
 
   void GetHref(nsAString& aHref,
-               const Maybe<nsIPrincipal*>& aSubjectPrincipal,
+               nsIPrincipal& aSubjectPrincipal,
                ErrorResult& aError)
   {
     THROW_AND_RETURN_IF_CALLER_DOESNT_SUBSUME();
     aError = GetHref(aHref);
   }
 
   void SetHref(const nsAString& aHref,
-               const Maybe<nsIPrincipal*>& aSubjectPrincipal,
+               nsIPrincipal& aSubjectPrincipal,
                ErrorResult& aError)
   {
     aError = SetHref(aHref);
   }
 
   void GetOrigin(nsAString& aOrigin,
-                 const Maybe<nsIPrincipal*>& aSubjectPrincipal,
+                 nsIPrincipal& aSubjectPrincipal,
                  ErrorResult& aError)
   {
     THROW_AND_RETURN_IF_CALLER_DOESNT_SUBSUME();
     aError = GetOrigin(aOrigin);
   }
 
   void GetProtocol(nsAString& aProtocol,
-                   const Maybe<nsIPrincipal*>& aSubjectPrincipal,
+                   nsIPrincipal& aSubjectPrincipal,
                    ErrorResult& aError)
   {
     THROW_AND_RETURN_IF_CALLER_DOESNT_SUBSUME();
     aError = GetProtocol(aProtocol);
   }
 
   void SetProtocol(const nsAString& aProtocol,
-                   const Maybe<nsIPrincipal*>& aSubjectPrincipal,
+                   nsIPrincipal& aSubjectPrincipal,
                    ErrorResult& aError)
   {
     THROW_AND_RETURN_IF_CALLER_DOESNT_SUBSUME();
     aError = SetProtocol(aProtocol);
   }
 
   void GetHost(nsAString& aHost,
-               const Maybe<nsIPrincipal*>& aSubjectPrincipal,
+               nsIPrincipal& aSubjectPrincipal,
                ErrorResult& aError)
   {
     THROW_AND_RETURN_IF_CALLER_DOESNT_SUBSUME();
     aError = GetHost(aHost);
   }
 
   void SetHost(const nsAString& aHost,
-               const Maybe<nsIPrincipal*>& aSubjectPrincipal,
+               nsIPrincipal& aSubjectPrincipal,
                ErrorResult& aError)
   {
     THROW_AND_RETURN_IF_CALLER_DOESNT_SUBSUME();
     aError = SetHost(aHost);
   }
 
   void GetHostname(nsAString& aHostname,
-                   const Maybe<nsIPrincipal*>& aSubjectPrincipal,
+                   nsIPrincipal& aSubjectPrincipal,
                    ErrorResult& aError)
   {
     THROW_AND_RETURN_IF_CALLER_DOESNT_SUBSUME();
     aError = GetHostname(aHostname);
   }
 
   void SetHostname(const nsAString& aHostname,
-                   const Maybe<nsIPrincipal*>& aSubjectPrincipal,
+                   nsIPrincipal& aSubjectPrincipal,
                    ErrorResult& aError)
   {
     THROW_AND_RETURN_IF_CALLER_DOESNT_SUBSUME();
     aError = SetHostname(aHostname);
   }
 
   void GetPort(nsAString& aPort,
-               const Maybe<nsIPrincipal*>& aSubjectPrincipal,
+               nsIPrincipal& aSubjectPrincipal,
                ErrorResult& aError)
   {
     THROW_AND_RETURN_IF_CALLER_DOESNT_SUBSUME();
     aError = GetPort(aPort);
   }
 
   void SetPort(const nsAString& aPort,
-               const Maybe<nsIPrincipal*>& aSubjectPrincipal,
+               nsIPrincipal& aSubjectPrincipal,
                ErrorResult& aError)
   {
     THROW_AND_RETURN_IF_CALLER_DOESNT_SUBSUME();
     aError = SetPort(aPort);
   }
 
   void GetPathname(nsAString& aPathname,
-                   const Maybe<nsIPrincipal*>& aSubjectPrincipal,
+                   nsIPrincipal& aSubjectPrincipal,
                    ErrorResult& aError)
   {
     THROW_AND_RETURN_IF_CALLER_DOESNT_SUBSUME();
     aError = GetPathname(aPathname);
   }
 
   void SetPathname(const nsAString& aPathname,
-                   const Maybe<nsIPrincipal*>& aSubjectPrincipal,
+                   nsIPrincipal& aSubjectPrincipal,
                    ErrorResult& aError)
   {
     THROW_AND_RETURN_IF_CALLER_DOESNT_SUBSUME();
     aError = SetPathname(aPathname);
   }
 
   void GetSearch(nsAString& aSeach,
-                 const Maybe<nsIPrincipal*>& aSubjectPrincipal,
+                 nsIPrincipal& aSubjectPrincipal,
                  ErrorResult& aError)
   {
     THROW_AND_RETURN_IF_CALLER_DOESNT_SUBSUME();
     aError = GetSearch(aSeach);
   }
 
   void SetSearch(const nsAString& aSeach,
-                 const Maybe<nsIPrincipal*>& aSubjectPrincipal,
+                 nsIPrincipal& aSubjectPrincipal,
                  ErrorResult& aError)
   {
     THROW_AND_RETURN_IF_CALLER_DOESNT_SUBSUME();
     aError = SetSearch(aSeach);
   }
 
   void GetHash(nsAString& aHash,
-               const Maybe<nsIPrincipal*>& aSubjectPrincipal,
+               nsIPrincipal& aSubjectPrincipal,
                ErrorResult& aError)
   {
     THROW_AND_RETURN_IF_CALLER_DOESNT_SUBSUME();
     aError = GetHash(aHash);
   }
 
   void SetHash(const nsAString& aHash,
-               const Maybe<nsIPrincipal*>& aSubjectPrincipal,
+               nsIPrincipal& aSubjectPrincipal,
                ErrorResult& aError)
   {
     THROW_AND_RETURN_IF_CALLER_DOESNT_SUBSUME();
     aError = SetHash(aHash);
   }
 
   void Stringify(nsAString& aRetval,
-                 const Maybe<nsIPrincipal*>& aSubjectPrincipal,
+                 nsIPrincipal& aSubjectPrincipal,
                  ErrorResult& aError)
   {
     // GetHref checks CallerSubsumes.
     GetHref(aRetval, aSubjectPrincipal, aError);
   }
 
   nsPIDOMWindowInner* GetParentObject() const
   {
--- a/dom/base/nsDocument.cpp
+++ b/dom/base/nsDocument.cpp
@@ -6238,16 +6238,24 @@ nsDocument::LoadBindingDocument(const ns
                                      ? Some(nsContentUtils::SubjectPrincipal())
                                      : Nothing(),
                                    rv);
   return rv.StealNSResult();
 }
 
 void
 nsIDocument::LoadBindingDocument(const nsAString& aURI,
+                                 nsIPrincipal& aSubjectPrincipal,
+                                 ErrorResult& rv)
+{
+  LoadBindingDocument(aURI, Some(&aSubjectPrincipal), rv);
+}
+
+void
+nsIDocument::LoadBindingDocument(const nsAString& aURI,
                                  const Maybe<nsIPrincipal*>& aSubjectPrincipal,
                                  ErrorResult& rv)
 {
   nsCOMPtr<nsIURI> uri;
   rv = NS_NewURI(getter_AddRefs(uri), aURI,
                  mCharacterSet.get(),
                  GetDocBaseURI());
   if (rv.Failed()) {
--- a/dom/base/nsGlobalWindow.cpp
+++ b/dom/base/nsGlobalWindow.cpp
@@ -6812,23 +6812,22 @@ nsGlobalWindow::CanMoveResizeWindows(boo
     }
   }
   return true;
 }
 
 bool
 nsGlobalWindow::AlertOrConfirm(bool aAlert,
                                const nsAString& aMessage,
-                               const Maybe<nsIPrincipal*>& aSubjectPrincipal,
+                               nsIPrincipal& aSubjectPrincipal,
                                ErrorResult& aError)
 {
   // XXX This method is very similar to nsGlobalWindow::Prompt, make
   // sure any modifications here don't need to happen over there!
   MOZ_ASSERT(IsOuterWindow());
-  MOZ_ASSERT(aSubjectPrincipal.isSome());
 
   if (!AreDialogsEnabled()) {
     // Just silently return.  In the case of alert(), the return value is
     // ignored.  In the case of confirm(), returning false is the same thing as
     // would happen if the user cancels.
     return false;
   }
 
@@ -6837,17 +6836,17 @@ nsGlobalWindow::AlertOrConfirm(bool aAle
   // the whole time a modal dialog is open.
   nsAutoPopupStatePusher popupStatePusher(openAbused, true);
 
   // Before bringing up the window, unsuppress painting and flush
   // pending reflows.
   EnsureReflowFlushAndPaint();
 
   nsAutoString title;
-  MakeScriptDialogTitle(title, aSubjectPrincipal.value());
+  MakeScriptDialogTitle(title, &aSubjectPrincipal);
 
   // Remove non-terminating null characters from the
   // string. See bug #310037.
   nsAutoString final;
   nsContentUtils::StripNullChars(aMessage, final);
 
   nsresult rv;
   nsCOMPtr<nsIPromptFactory> promptFac =
@@ -6890,55 +6889,55 @@ nsGlobalWindow::AlertOrConfirm(bool aAle
                prompt->Alert(title.get(), final.get()) :
                prompt->Confirm(title.get(), final.get(), &result);
   }
 
   return result;
 }
 
 void
-nsGlobalWindow::Alert(const Maybe<nsIPrincipal*>& aSubjectPrincipal,
+nsGlobalWindow::Alert(nsIPrincipal& aSubjectPrincipal,
                       ErrorResult& aError)
 {
   MOZ_ASSERT(IsInnerWindow());
   Alert(EmptyString(), aSubjectPrincipal, aError);
 }
 
 void
 nsGlobalWindow::AlertOuter(const nsAString& aMessage,
-                           const Maybe<nsIPrincipal*>& aSubjectPrincipal,
+                           nsIPrincipal& aSubjectPrincipal,
                            ErrorResult& aError)
 {
   MOZ_RELEASE_ASSERT(IsOuterWindow());
   AlertOrConfirm(/* aAlert = */ true, aMessage, aSubjectPrincipal, aError);
 }
 
 void
 nsGlobalWindow::Alert(const nsAString& aMessage,
-                      const Maybe<nsIPrincipal*>& aSubjectPrincipal,
+                      nsIPrincipal& aSubjectPrincipal,
                       ErrorResult& aError)
 {
   FORWARD_TO_OUTER_OR_THROW(AlertOuter, (aMessage, aSubjectPrincipal, aError),
                             aError, );
 }
 
 bool
 nsGlobalWindow::ConfirmOuter(const nsAString& aMessage,
-                             const Maybe<nsIPrincipal*>& aSubjectPrincipal,
+                             nsIPrincipal& aSubjectPrincipal,
                              ErrorResult& aError)
 {
   MOZ_RELEASE_ASSERT(IsOuterWindow());
 
   return AlertOrConfirm(/* aAlert = */ false, aMessage, aSubjectPrincipal,
                         aError);
 }
 
 bool
 nsGlobalWindow::Confirm(const nsAString& aMessage,
-                        const Maybe<nsIPrincipal*>& aSubjectPrincipal,
+                        nsIPrincipal& aSubjectPrincipal,
                         ErrorResult& aError)
 {
   FORWARD_TO_OUTER_OR_THROW(ConfirmOuter, (aMessage, aSubjectPrincipal, aError),
                             aError, false);
 }
 
 already_AddRefed<Promise>
 nsGlobalWindow::Fetch(const RequestOrUSVString& aInput,
@@ -6946,23 +6945,22 @@ nsGlobalWindow::Fetch(const RequestOrUSV
 {
   return FetchRequest(this, aInput, aInit, aRv);
 }
 
 void
 nsGlobalWindow::PromptOuter(const nsAString& aMessage,
                             const nsAString& aInitial,
                             nsAString& aReturn,
-                            const Maybe<nsIPrincipal*>& aSubjectPrincipal,
+                            nsIPrincipal& aSubjectPrincipal,
                             ErrorResult& aError)
 {
   // XXX This method is very similar to nsGlobalWindow::AlertOrConfirm, make
   // sure any modifications here don't need to happen over there!
   MOZ_RELEASE_ASSERT(IsOuterWindow());
-  MOZ_ASSERT(aSubjectPrincipal.isSome());
 
   SetDOMStringToNull(aReturn);
 
   if (!AreDialogsEnabled()) {
     // Return null, as if the user just canceled the prompt.
     return;
   }
 
@@ -6971,17 +6969,17 @@ nsGlobalWindow::PromptOuter(const nsAStr
   // the whole time a modal dialog is open.
   nsAutoPopupStatePusher popupStatePusher(openAbused, true);
 
   // Before bringing up the window, unsuppress painting and flush
   // pending reflows.
   EnsureReflowFlushAndPaint();
 
   nsAutoString title;
-  MakeScriptDialogTitle(title, aSubjectPrincipal.value());
+  MakeScriptDialogTitle(title, &aSubjectPrincipal);
 
   // Remove non-terminating null characters from the
   // string. See bug #310037.
   nsAutoString fixedMessage, fixedInitial;
   nsContentUtils::StripNullChars(aMessage, fixedMessage);
   nsContentUtils::StripNullChars(aInitial, fixedInitial);
 
   nsresult rv;
@@ -7032,17 +7030,17 @@ nsGlobalWindow::PromptOuter(const nsAStr
   if (ok && outValue) {
     aReturn.Assign(outValue);
   }
 }
 
 void
 nsGlobalWindow::Prompt(const nsAString& aMessage, const nsAString& aInitial,
                        nsAString& aReturn,
-                       const Maybe<nsIPrincipal*>& aSubjectPrincipal,
+                       nsIPrincipal& aSubjectPrincipal,
                        ErrorResult& aError)
 {
   FORWARD_TO_OUTER_OR_THROW(PromptOuter,
                             (aMessage, aInitial, aReturn, aSubjectPrincipal,
                              aError),
                             aError, );
 }
 
@@ -8278,21 +8276,20 @@ nsGlobalWindow::CallerInnerWindow()
   nsCOMPtr<nsPIDOMWindowInner> win = do_QueryInterface(global);
   return nsGlobalWindow::Cast(win);
 }
 
 void
 nsGlobalWindow::PostMessageMozOuter(JSContext* aCx, JS::Handle<JS::Value> aMessage,
                                     const nsAString& aTargetOrigin,
                                     JS::Handle<JS::Value> aTransfer,
-                                    const Maybe<nsIPrincipal*>& aSubjectPrincipal,
+                                    nsIPrincipal& aSubjectPrincipal,
                                     ErrorResult& aError)
 {
   MOZ_RELEASE_ASSERT(IsOuterWindow());
-  MOZ_ASSERT(aSubjectPrincipal.isSome());
 
   //
   // Window.postMessage is an intentional subversion of the same-origin policy.
   // As such, this code must be particularly careful in the information it
   // exposes to calling code.
   //
   // http://www.whatwg.org/specs/web-apps/current-work/multipage/section-crossDocumentMessages.html
   //
@@ -8365,17 +8362,17 @@ nsGlobalWindow::PostMessageMozOuter(JSCo
     }
 
     if (NS_FAILED(originURI->SetUserPass(EmptyCString())) ||
         NS_FAILED(originURI->SetPath(EmptyCString()))) {
       return;
     }
 
     PrincipalOriginAttributes attrs =
-      BasePrincipal::Cast(aSubjectPrincipal.value())->OriginAttributesRef();
+      BasePrincipal::Cast(&aSubjectPrincipal)->OriginAttributesRef();
     // Create a nsIPrincipal inheriting the app/browser attributes from the
     // caller.
     providedPrincipal = BasePrincipal::CreateCodebasePrincipal(originURI, attrs);
     if (NS_WARN_IF(!providedPrincipal)) {
       return;
     }
   }
 
@@ -8403,30 +8400,30 @@ nsGlobalWindow::PostMessageMozOuter(JSCo
 
   aError = NS_DispatchToCurrentThread(event);
 }
 
 void
 nsGlobalWindow::PostMessageMoz(JSContext* aCx, JS::Handle<JS::Value> aMessage,
                                const nsAString& aTargetOrigin,
                                JS::Handle<JS::Value> aTransfer,
-                               const Maybe<nsIPrincipal*>& aSubjectPrincipal,
+                               nsIPrincipal& aSubjectPrincipal,
                                ErrorResult& aError)
 {
   FORWARD_TO_OUTER_OR_THROW(PostMessageMozOuter,
                             (aCx, aMessage, aTargetOrigin, aTransfer,
                              aSubjectPrincipal, aError),
                             aError, );
 }
 
 void
 nsGlobalWindow::PostMessageMoz(JSContext* aCx, JS::Handle<JS::Value> aMessage,
                                const nsAString& aTargetOrigin,
                                const Optional<Sequence<JS::Value>>& aTransfer,
-                               const Maybe<nsIPrincipal*>& aSubjectPrincipal,
+                               nsIPrincipal& aSubjectPrincipal,
                                ErrorResult& aError)
 {
   JS::Rooted<JS::Value> transferArray(aCx, JS::UndefinedValue());
   if (aTransfer.WasPassed()) {
     const Sequence<JS::Value >& values = aTransfer.Value();
 
     // The input sequence only comes from the generated bindings code, which
     // ensures it is rooted.
@@ -9044,41 +9041,39 @@ nsGlobalWindow::CacheXBLPrototypeHandler
     mCachedXBLPrototypeHandlers = new nsJSThingHashtable<nsPtrHashKey<nsXBLPrototypeHandler>, JSObject*>();
     PreserveWrapper(ToSupports(this));
   }
 
   mCachedXBLPrototypeHandlers->Put(aKey, aHandler);
 }
 
 Element*
-nsGlobalWindow::GetFrameElementOuter(const Maybe<nsIPrincipal*>& aSubjectPrincipal)
+nsGlobalWindow::GetFrameElementOuter(nsIPrincipal& aSubjectPrincipal)
 {
   MOZ_RELEASE_ASSERT(IsOuterWindow());
-  MOZ_ASSERT(aSubjectPrincipal.isSome());
 
   if (!mDocShell || mDocShell->GetIsMozBrowserOrApp()) {
     return nullptr;
   }
 
   // Per HTML5, the frameElement getter returns null in cross-origin situations.
   Element* element = GetRealFrameElementOuter();
   if (!element) {
     return nullptr;
   }
 
-  if (!aSubjectPrincipal.value()->
-         SubsumesConsideringDomain(element->NodePrincipal())) {
+  if (!aSubjectPrincipal.SubsumesConsideringDomain(element->NodePrincipal())) {
     return nullptr;
   }
 
   return element;
 }
 
 Element*
-nsGlobalWindow::GetFrameElement(const Maybe<nsIPrincipal*>& aSubjectPrincipal,
+nsGlobalWindow::GetFrameElement(nsIPrincipal& aSubjectPrincipal,
                                 ErrorResult& aError)
 {
   FORWARD_TO_OUTER_OR_THROW(GetFrameElementOuter, (aSubjectPrincipal), aError,
                             nullptr);
 }
 
 Element*
 nsGlobalWindow::GetRealFrameElementOuter()
@@ -9247,33 +9242,32 @@ nsGlobalWindow::ConvertDialogOptions(con
     }
   }
 }
 
 already_AddRefed<nsIVariant>
 nsGlobalWindow::ShowModalDialogOuter(const nsAString& aUrl,
                                      nsIVariant* aArgument,
                                      const nsAString& aOptions,
-                                     const Maybe<nsIPrincipal*>& aSubjectPrincipal,
+                                     nsIPrincipal& aSubjectPrincipal,
                                      ErrorResult& aError)
 {
   MOZ_RELEASE_ASSERT(IsOuterWindow());
-  MOZ_ASSERT(aSubjectPrincipal.isSome());
 
   if (mDoc) {
     mDoc->WarnOnceAbout(nsIDocument::eShowModalDialog);
   }
 
   if (!IsShowModalDialogEnabled()) {
     aError.Throw(NS_ERROR_NOT_AVAILABLE);
     return nullptr;
   }
 
   RefPtr<DialogValueHolder> argHolder =
-    new DialogValueHolder(aSubjectPrincipal.value(), aArgument);
+    new DialogValueHolder(&aSubjectPrincipal, aArgument);
 
   // Before bringing up the window/dialog, unsuppress painting and flush
   // pending reflows.
   EnsureReflowFlushAndPaint();
 
   if (!AreDialogsEnabled()) {
     // We probably want to keep throwing here; silently doing nothing is a bit
     // weird given the typical use cases of showModalDialog().
@@ -9320,30 +9314,30 @@ nsGlobalWindow::ShowModalDialogOuter(con
   MOZ_ASSERT(!aError.Failed());
 
   return retVal.forget();
 }
 
 already_AddRefed<nsIVariant>
 nsGlobalWindow::ShowModalDialog(const nsAString& aUrl, nsIVariant* aArgument,
                                 const nsAString& aOptions,
-                                const Maybe<nsIPrincipal*>& aSubjectPrincipal,
+                                nsIPrincipal& aSubjectPrincipal,
                                 ErrorResult& aError)
 {
   FORWARD_TO_OUTER_OR_THROW(ShowModalDialogOuter,
                             (aUrl, aArgument, aOptions, aSubjectPrincipal,
                              aError), aError, nullptr);
 }
 
 void
 nsGlobalWindow::ShowModalDialog(JSContext* aCx, const nsAString& aUrl,
                                 JS::Handle<JS::Value> aArgument,
                                 const nsAString& aOptions,
                                 JS::MutableHandle<JS::Value> aRetval,
-                                const Maybe<nsIPrincipal*>& aSubjectPrincipal,
+                                nsIPrincipal& aSubjectPrincipal,
                                 ErrorResult& aError)
 {
   MOZ_ASSERT(IsInnerWindow());
 
   nsCOMPtr<nsIVariant> args;
   aError = nsContentUtils::XPConnect()->JSToVariant(aCx,
                                                     aArgument,
                                                     getter_AddRefs(args));
@@ -10582,27 +10576,27 @@ nsGlobalWindow::GetSessionStorage(ErrorR
   if (MOZ_LOG_TEST(gDOMLeakPRLog, LogLevel::Debug)) {
     PR_LogPrint("nsGlobalWindow %p returns %p sessionStorage", this, mSessionStorage.get());
   }
 
   return mSessionStorage;
 }
 
 DOMStorage*
-nsGlobalWindow::GetLocalStorage(const Maybe<nsIPrincipal*>& aSubjectPrincipal,
-                                ErrorResult& aError)
+nsGlobalWindow::GetLocalStorage(ErrorResult& aError)
 {
   MOZ_RELEASE_ASSERT(IsInnerWindow());
 
   if (!Preferences::GetBool(kStorageEnabled)) {
     return nullptr;
   }
 
   if (!mLocalStorage) {
-    if (!DOMStorage::CanUseStorage(AsInner(), aSubjectPrincipal)) {
+    if (nsContentUtils::StorageAllowedForWindow(AsInner()) ==
+          nsContentUtils::StorageAccess::eDeny) {
       aError.Throw(NS_ERROR_DOM_SECURITY_ERR);
       return nullptr;
     }
 
     nsIPrincipal *principal = GetPrincipal();
     if (!principal) {
       return nullptr;
     }
@@ -11658,20 +11652,17 @@ nsGlobalWindow::CloneStorageEvent(const 
   aEvent->GetNewValue(dict.mNewValue);
   aEvent->GetUrl(dict.mUrl);
 
   RefPtr<DOMStorage> storageArea = aEvent->GetStorageArea();
   MOZ_ASSERT(storageArea);
 
   RefPtr<DOMStorage> storage;
   if (storageArea->GetType() == DOMStorage::LocalStorage) {
-    storage = GetLocalStorage(nsContentUtils::GetCurrentJSContext()
-                                ? Some(nsContentUtils::SubjectPrincipal())
-                                : Nothing(),
-                              aRv);
+    storage = GetLocalStorage(aRv);
   } else {
     MOZ_ASSERT(storageArea->GetType() == DOMStorage::SessionStorage);
     storage = GetSessionStorage(aRv);
   }
 
   if (aRv.Failed() || !storage) {
     return nullptr;
   }
@@ -13996,42 +13987,40 @@ NS_INTERFACE_MAP_END_INHERITING(nsGlobal
 
 NS_IMPL_ADDREF_INHERITED(nsGlobalModalWindow, nsGlobalWindow)
 NS_IMPL_RELEASE_INHERITED(nsGlobalModalWindow, nsGlobalWindow)
 
 
 void
 nsGlobalWindow::GetDialogArgumentsOuter(JSContext* aCx,
                                         JS::MutableHandle<JS::Value> aRetval,
-                                        const Maybe<nsIPrincipal*>& aSubjectPrincipal,
+                                        nsIPrincipal& aSubjectPrincipal,
                                         ErrorResult& aError)
 {
   MOZ_RELEASE_ASSERT(IsOuterWindow());
-  MOZ_ASSERT(aSubjectPrincipal.isSome());
   MOZ_ASSERT(IsModalContentWindow(),
              "This should only be called on modal windows!");
 
   if (!mDialogArguments) {
     MOZ_ASSERT(mIsClosed, "This window should be closed!");
     aRetval.setUndefined();
     return;
   }
 
   // This does an internal origin check, and returns undefined if the subject
   // does not subsumes the origin of the arguments.
   JS::Rooted<JSObject*> wrapper(aCx, GetWrapper());
   JSAutoCompartment ac(aCx, wrapper);
-  mDialogArguments->Get(aCx, wrapper, aSubjectPrincipal.value(),
-                        aRetval, aError);
+  mDialogArguments->Get(aCx, wrapper, &aSubjectPrincipal, aRetval, aError);
 }
 
 void
 nsGlobalWindow::GetDialogArguments(JSContext* aCx,
                                    JS::MutableHandle<JS::Value> aRetval,
-                                   const Maybe<nsIPrincipal*>& aSubjectPrincipal,
+                                   nsIPrincipal& aSubjectPrincipal,
                                    ErrorResult& aError)
 {
   FORWARD_TO_OUTER_OR_THROW(GetDialogArgumentsOuter,
                             (aCx, aRetval, aSubjectPrincipal, aError),
                             aError, );
 }
 
 /* static */ already_AddRefed<nsGlobalModalWindow>
@@ -14065,38 +14054,36 @@ void
 nsGlobalWindow::InitWasOffline()
 {
   mWasOffline = NS_IsOffline() || NS_IsAppOffline(GetPrincipal());
 }
 
 void
 nsGlobalWindow::GetReturnValueOuter(JSContext* aCx,
                                     JS::MutableHandle<JS::Value> aReturnValue,
-                                    const Maybe<nsIPrincipal*>& aSubjectPrincipal,
+                                    nsIPrincipal& aSubjectPrincipal,
                                     ErrorResult& aError)
 {
   MOZ_RELEASE_ASSERT(IsOuterWindow());
-  MOZ_ASSERT(aSubjectPrincipal.isSome());
   MOZ_ASSERT(IsModalContentWindow(),
              "This should only be called on modal windows!");
 
   if (mReturnValue) {
     JS::Rooted<JSObject*> wrapper(aCx, GetWrapper());
     JSAutoCompartment ac(aCx, wrapper);
-    mReturnValue->Get(aCx, wrapper, aSubjectPrincipal.value(),
-                      aReturnValue, aError);
+    mReturnValue->Get(aCx, wrapper, &aSubjectPrincipal, aReturnValue, aError);
   } else {
     aReturnValue.setUndefined();
   }
 }
 
 void
 nsGlobalWindow::GetReturnValue(JSContext* aCx,
                                JS::MutableHandle<JS::Value> aReturnValue,
-                               const Maybe<nsIPrincipal*>& aSubjectPrincipal,
+                               nsIPrincipal& aSubjectPrincipal,
                                ErrorResult& aError)
 {
   FORWARD_TO_OUTER_OR_THROW(GetReturnValueOuter,
                             (aCx, aReturnValue, aSubjectPrincipal, aError),
                             aError, );
 }
 
 NS_IMETHODIMP
@@ -14110,38 +14097,36 @@ nsGlobalModalWindow::GetReturnValue(nsIV
     return NS_OK;
   }
   return mReturnValue->Get(nsContentUtils::SubjectPrincipal(), aRetVal);
 }
 
 void
 nsGlobalWindow::SetReturnValueOuter(JSContext* aCx,
                                     JS::Handle<JS::Value> aReturnValue,
-                                    const Maybe<nsIPrincipal*>& aSubjectPrincipal,
+                                    nsIPrincipal& aSubjectPrincipal,
                                     ErrorResult& aError)
 {
   MOZ_RELEASE_ASSERT(IsOuterWindow());
-  MOZ_ASSERT(aSubjectPrincipal.isSome());
   MOZ_ASSERT(IsModalContentWindow(),
              "This should only be called on modal windows!");
 
   nsCOMPtr<nsIVariant> returnValue;
   aError =
     nsContentUtils::XPConnect()->JSToVariant(aCx, aReturnValue,
                                              getter_AddRefs(returnValue));
   if (!aError.Failed()) {
-    mReturnValue = new DialogValueHolder(aSubjectPrincipal.value(),
-                                         returnValue);
+    mReturnValue = new DialogValueHolder(&aSubjectPrincipal, returnValue);
   }
 }
 
 void
 nsGlobalWindow::SetReturnValue(JSContext* aCx,
                                JS::Handle<JS::Value> aReturnValue,
-                               const Maybe<nsIPrincipal*>& aSubjectPrincipal,
+                               nsIPrincipal& aSubjectPrincipal,
                                ErrorResult& aError)
 {
   FORWARD_TO_OUTER_OR_THROW(SetReturnValueOuter,
                             (aCx, aReturnValue, aSubjectPrincipal, aError),
                             aError, );
 }
 
 NS_IMETHODIMP
--- a/dom/base/nsGlobalWindow.h
+++ b/dom/base/nsGlobalWindow.h
@@ -932,19 +932,19 @@ public:
   void SetOpener(JSContext* aCx, JS::Handle<JS::Value> aOpener,
                  mozilla::ErrorResult& aError);
   already_AddRefed<nsPIDOMWindowOuter> GetParentOuter();
   already_AddRefed<nsPIDOMWindowOuter> GetParent(mozilla::ErrorResult& aError);
   already_AddRefed<nsPIDOMWindowOuter> GetParent() override;
   nsPIDOMWindowOuter* GetScriptableParent() override;
   nsPIDOMWindowOuter* GetScriptableParentOrNull() override;
   mozilla::dom::Element*
-  GetFrameElementOuter(const mozilla::Maybe<nsIPrincipal*>& aSubjectPrincipal);
+  GetFrameElementOuter(nsIPrincipal& aSubjectPrincipal);
   mozilla::dom::Element*
-  GetFrameElement(const mozilla::Maybe<nsIPrincipal*>& aSubjectPrincipal,
+  GetFrameElement(nsIPrincipal& aSubjectPrincipal,
                   mozilla::ErrorResult& aError);
   already_AddRefed<nsIDOMElement> GetFrameElement() override;
   already_AddRefed<nsPIDOMWindowOuter>
   OpenOuter(const nsAString& aUrl,
             const nsAString& aName,
             const nsAString& aOptions,
             mozilla::ErrorResult& aError);
   already_AddRefed<nsPIDOMWindowOuter>
@@ -977,58 +977,58 @@ public:
   static bool
   TokenizeDialogOptions(nsAString& aToken, nsAString::const_iterator& aIter,
                         nsAString::const_iterator aEnd);
   static void
   ConvertDialogOptions(const nsAString& aOptions, nsAString& aResult);
 
 protected:
   bool AlertOrConfirm(bool aAlert, const nsAString& aMessage,
-                      const mozilla::Maybe<nsIPrincipal*>& aSubjectPrincipal,
+                      nsIPrincipal& aSubjectPrincipal,
                       mozilla::ErrorResult& aError);
 
 public:
-  void Alert(const mozilla::Maybe<nsIPrincipal*>& aSubjectPrincipal,
+  void Alert(nsIPrincipal& aSubjectPrincipal,
              mozilla::ErrorResult& aError);
   void AlertOuter(const nsAString& aMessage,
-                  const mozilla::Maybe<nsIPrincipal*>& aSubjectPrincipal,
+                  nsIPrincipal& aSubjectPrincipal,
                   mozilla::ErrorResult& aError);
   void Alert(const nsAString& aMessage,
-             const mozilla::Maybe<nsIPrincipal*>& aSubjectPrincipal,
+             nsIPrincipal& aSubjectPrincipal,
              mozilla::ErrorResult& aError);
   bool ConfirmOuter(const nsAString& aMessage,
-                    const mozilla::Maybe<nsIPrincipal*>& aSubjectPrincipal,
+                    nsIPrincipal& aSubjectPrincipal,
                     mozilla::ErrorResult& aError);
   bool Confirm(const nsAString& aMessage,
-               const mozilla::Maybe<nsIPrincipal*>& aSubjectPrincipal,
+               nsIPrincipal& aSubjectPrincipal,
                mozilla::ErrorResult& aError);
   void PromptOuter(const nsAString& aMessage, const nsAString& aInitial,
                    nsAString& aReturn,
-                   const mozilla::Maybe<nsIPrincipal*>& aSubjectPrincipal,
+                   nsIPrincipal& aSubjectPrincipal,
                    mozilla::ErrorResult& aError);
   void Prompt(const nsAString& aMessage, const nsAString& aInitial,
               nsAString& aReturn,
-              const mozilla::Maybe<nsIPrincipal*>& aSubjectPrincipal,
+              nsIPrincipal& aSubjectPrincipal,
               mozilla::ErrorResult& aError);
   already_AddRefed<mozilla::dom::cache::CacheStorage> GetCaches(mozilla::ErrorResult& aRv);
   already_AddRefed<mozilla::dom::Promise> Fetch(const mozilla::dom::RequestOrUSVString& aInput,
                                                 const mozilla::dom::RequestInit& aInit,
                                                 mozilla::ErrorResult& aRv);
   void PrintOuter(mozilla::ErrorResult& aError);
   void Print(mozilla::ErrorResult& aError);
   void ShowModalDialog(JSContext* aCx, const nsAString& aUrl,
                        JS::Handle<JS::Value> aArgument,
                        const nsAString& aOptions,
                        JS::MutableHandle<JS::Value> aRetval,
-                       const mozilla::Maybe<nsIPrincipal*>& aSubjectPrincipal,
+                       nsIPrincipal& aSubjectPrincipal,
                        mozilla::ErrorResult& aError);
   void PostMessageMoz(JSContext* aCx, JS::Handle<JS::Value> aMessage,
                       const nsAString& aTargetOrigin,
                       const mozilla::dom::Optional<mozilla::dom::Sequence<JS::Value > >& aTransfer,
-                      const mozilla::Maybe<nsIPrincipal*>& aSubjectPrincipal,
+                      nsIPrincipal& aSubjectPrincipal,
                       mozilla::ErrorResult& aError);
   int32_t SetTimeout(JSContext* aCx, mozilla::dom::Function& aFunction,
                      int32_t aTimeout,
                      const mozilla::dom::Sequence<JS::Value>& aArguments,
                      mozilla::ErrorResult& aError);
   int32_t SetTimeout(JSContext* aCx, const nsAString& aHandler,
                      int32_t aTimeout,
                      const mozilla::dom::Sequence<JS::Value>& /* unused */,
@@ -1044,18 +1044,17 @@ public:
                       mozilla::ErrorResult& aError);
   void ClearInterval(int32_t aHandle);
   void Atob(const nsAString& aAsciiBase64String, nsAString& aBinaryData,
             mozilla::ErrorResult& aError);
   void Btoa(const nsAString& aBinaryData, nsAString& aAsciiBase64String,
             mozilla::ErrorResult& aError);
   mozilla::dom::DOMStorage* GetSessionStorage(mozilla::ErrorResult& aError);
   mozilla::dom::DOMStorage*
-  GetLocalStorage(const mozilla::Maybe<nsIPrincipal*>& aSubjectPrincipal,
-                  mozilla::ErrorResult& aError);
+  GetLocalStorage(mozilla::ErrorResult& aError);
   mozilla::dom::Selection* GetSelectionOuter();
   mozilla::dom::Selection* GetSelection(mozilla::ErrorResult& aError);
   already_AddRefed<nsISelection> GetSelection() override;
   mozilla::dom::IDBFactory* GetIndexedDB(mozilla::ErrorResult& aError);
   already_AddRefed<nsICSSDeclaration>
     GetComputedStyle(mozilla::dom::Element& aElt, const nsAString& aPseudoElt,
                      mozilla::ErrorResult& aError) override;
   already_AddRefed<mozilla::dom::MediaQueryList> MatchMediaOuter(const nsAString& aQuery);
@@ -1265,32 +1264,32 @@ public:
   nsIMessageBroadcaster* GetMessageManager(mozilla::ErrorResult& aError);
   nsIMessageBroadcaster* GetGroupMessageManager(const nsAString& aGroup,
                                                 mozilla::ErrorResult& aError);
   void BeginWindowMove(mozilla::dom::Event& aMouseDownEvent,
                        mozilla::dom::Element* aPanel,
                        mozilla::ErrorResult& aError);
 
   void GetDialogArgumentsOuter(JSContext* aCx, JS::MutableHandle<JS::Value> aRetval,
-                               const mozilla::Maybe<nsIPrincipal*>& aSubjectPrincipal,
+                               nsIPrincipal& aSubjectPrincipal,
                                mozilla::ErrorResult& aError);
   void GetDialogArguments(JSContext* aCx, JS::MutableHandle<JS::Value> aRetval,
-                          const mozilla::Maybe<nsIPrincipal*>& aSubjectPrincipal,
+                          nsIPrincipal& aSubjectPrincipal,
                           mozilla::ErrorResult& aError);
   void GetReturnValueOuter(JSContext* aCx, JS::MutableHandle<JS::Value> aReturnValue,
-                           const mozilla::Maybe<nsIPrincipal*>& aSubjectPrincipal,
+                           nsIPrincipal& aSubjectPrincipal,
                            mozilla::ErrorResult& aError);
   void GetReturnValue(JSContext* aCx, JS::MutableHandle<JS::Value> aReturnValue,
-                      const mozilla::Maybe<nsIPrincipal*>& aSubjectPrincipal,
+                      nsIPrincipal& aSubjectPrincipal,
                       mozilla::ErrorResult& aError);
   void SetReturnValueOuter(JSContext* aCx, JS::Handle<JS::Value> aReturnValue,
-                           const mozilla::Maybe<nsIPrincipal*>& aSubjectPrincipal,
+                           nsIPrincipal& aSubjectPrincipal,
                            mozilla::ErrorResult& aError);
   void SetReturnValue(JSContext* aCx, JS::Handle<JS::Value> aReturnValue,
-                      const mozilla::Maybe<nsIPrincipal*>& aSubjectPrincipal,
+                      nsIPrincipal& aSubjectPrincipal,
                       mozilla::ErrorResult& aError);
 
   void GetInterface(JSContext* aCx, nsIJSID* aIID,
                     JS::MutableHandle<JS::Value> aRetval,
                     mozilla::ErrorResult& aError);
 
   already_AddRefed<nsWindowRoot> GetWindowRootOuter();
   already_AddRefed<nsWindowRoot> GetWindowRoot(mozilla::ErrorResult& aError);
@@ -1703,34 +1702,34 @@ protected:
   // Returns CSS pixels based on primary screen.  Outer windows only.
   mozilla::CSSIntPoint GetScreenXY(mozilla::ErrorResult& aError);
 
   nsGlobalWindow* InnerForSetTimeoutOrInterval(mozilla::ErrorResult& aError);
 
   void PostMessageMozOuter(JSContext* aCx, JS::Handle<JS::Value> aMessage,
                            const nsAString& aTargetOrigin,
                            JS::Handle<JS::Value> aTransfer,
-                           const mozilla::Maybe<nsIPrincipal*>& aSubjectPrincipal,
+                           nsIPrincipal& aSubjectPrincipal,
                            mozilla::ErrorResult& aError);
   void PostMessageMoz(JSContext* aCx, JS::Handle<JS::Value> aMessage,
                       const nsAString& aTargetOrigin,
                       JS::Handle<JS::Value> aTransfer,
-                      const mozilla::Maybe<nsIPrincipal*>& aSubjectPrincipal,
+                      nsIPrincipal& aSubjectPrincipal,
                       mozilla::ErrorResult& aError);
 
   already_AddRefed<nsIVariant>
     ShowModalDialogOuter(const nsAString& aUrl, nsIVariant* aArgument,
                          const nsAString& aOptions,
-                         const mozilla::Maybe<nsIPrincipal*>& aSubjectPrincipal,
+                         nsIPrincipal& aSubjectPrincipal,
                          mozilla::ErrorResult& aError);
 
   already_AddRefed<nsIVariant>
     ShowModalDialog(const nsAString& aUrl, nsIVariant* aArgument,
                     const nsAString& aOptions,
-                    const mozilla::Maybe<nsIPrincipal*>& aSubjectPrincipal,
+                    nsIPrincipal& aSubjectPrincipal,
                     mozilla::ErrorResult& aError);
 
   // Ask the user if further dialogs should be blocked, if dialogs are currently
   // being abused. This is used in the cases where we have no modifiable UI to
   // show, in that case we show a separate dialog to ask this question.
   bool ConfirmDialogIfNeeded();
 
   // Helper called after moving/resizing, to update docShell's presContext
--- a/dom/base/nsIDocument.h
+++ b/dom/base/nsIDocument.h
@@ -2683,16 +2683,19 @@ public:
 
   // QuerySelector and QuerySelectorAll already defined on nsINode
   nsINodeList* GetAnonymousNodes(Element& aElement);
   Element* GetAnonymousElementByAttribute(Element& aElement,
                                           const nsAString& aAttrName,
                                           const nsAString& aAttrValue);
   Element* GetBindingParent(nsINode& aNode);
   void LoadBindingDocument(const nsAString& aURI,
+                           nsIPrincipal& aSubjectPrincipal,
+                           mozilla::ErrorResult& rv);
+  void LoadBindingDocument(const nsAString& aURI,
                            const mozilla::Maybe<nsIPrincipal*>& aSubjectPrincipal,
                            mozilla::ErrorResult& rv);
   mozilla::dom::XPathExpression*
     CreateExpression(const nsAString& aExpression,
                      mozilla::dom::XPathNSResolver* aResolver,
                      mozilla::ErrorResult& rv);
   nsINode* CreateNSResolver(nsINode& aNodeResolver);
   already_AddRefed<mozilla::dom::XPathResult>
--- a/dom/base/nsObjectLoadingContent.cpp
+++ b/dom/base/nsObjectLoadingContent.cpp
@@ -3532,34 +3532,32 @@ nsObjectLoadingContent::ShouldPlay(Fallb
     return true;
   case nsIPluginTag::STATE_CLICKTOPLAY:
     return false;
   }
   MOZ_CRASH("Unexpected enabledState");
 }
 
 nsIDocument*
-nsObjectLoadingContent::GetContentDocument(const mozilla::Maybe<nsIPrincipal*>& aSubjectPrincipal)
+nsObjectLoadingContent::GetContentDocument(nsIPrincipal& aSubjectPrincipal)
 {
-  MOZ_ASSERT(aSubjectPrincipal.isSome());
-
   nsCOMPtr<nsIContent> thisContent =
     do_QueryInterface(static_cast<nsIImageLoadingContent*>(this));
 
   if (!thisContent->IsInComposedDoc()) {
     return nullptr;
   }
 
   nsIDocument *sub_doc = thisContent->OwnerDoc()->GetSubDocumentFor(thisContent);
   if (!sub_doc) {
     return nullptr;
   }
 
   // Return null for cross-origin contentDocument.
-  if (!aSubjectPrincipal.value()->SubsumesConsideringDomain(sub_doc->NodePrincipal())) {
+  if (!aSubjectPrincipal.SubsumesConsideringDomain(sub_doc->NodePrincipal())) {
     return nullptr;
   }
 
   return sub_doc;
 }
 
 void
 nsObjectLoadingContent::LegacyCall(JSContext* aCx,
--- a/dom/base/nsObjectLoadingContent.h
+++ b/dom/base/nsObjectLoadingContent.h
@@ -175,17 +175,17 @@ class nsObjectLoadingContent : public ns
     // id.  If in doubt, return true.
     static bool MayResolve(jsid aId);
 
     // Helper for WebIDL enumeration
     void GetOwnPropertyNames(JSContext* aCx, nsTArray<nsString>& /* unused */,
                              mozilla::ErrorResult& aRv);
 
     // WebIDL API
-    nsIDocument* GetContentDocument(const mozilla::Maybe<nsIPrincipal*>& aSubjectPrincipal);
+    nsIDocument* GetContentDocument(nsIPrincipal& aSubjectPrincipal);
     void GetActualType(nsAString& aType) const
     {
       CopyUTF8toUTF16(mContentType, aType);
     }
     uint32_t DisplayedType() const
     {
       return mType;
     }
--- a/dom/bindings/Codegen.py
+++ b/dom/bindings/Codegen.py
@@ -6902,23 +6902,23 @@ class CGCallGenerator(CGThing):
     isFallible is a boolean indicating whether the call should be fallible.
 
     resultVar: If the returnType is not void, then the result of the call is
     stored in a C++ variable named by resultVar. The caller is responsible for
     declaring the result variable. If the caller doesn't care about the result
     value, resultVar can be omitted.
     """
     def __init__(self, isFallible, needsSubjectPrincipal, arguments, argsPre,
-                 returnType, extendedAttributes, descriptorProvider,
+                 returnType, extendedAttributes, descriptor,
                  nativeMethodName, static, object="self", argsPost=[],
                  resultVar=None):
         CGThing.__init__(self)
 
         result, resultOutParam, resultRooter, resultArgs, resultConversion = \
-            getRetvalDeclarationForType(returnType, descriptorProvider)
+            getRetvalDeclarationForType(returnType, descriptor)
 
         args = CGList([CGGeneric(arg) for arg in argsPre], ", ")
         for a, name in arguments:
             arg = CGGeneric(name)
 
             # Now constify the things that need it
             def needsConst(a):
                 if a.type.isDictionary():
@@ -7003,26 +7003,42 @@ class CGCallGenerator(CGThing):
         elif result is not None:
             assert resultOutParam is None
             call = CGWrapper(call, pre=resultVar + " = ")
 
         call = CGWrapper(call, post=";\n")
         self.cgRoot.append(call)
 
         if needsSubjectPrincipal:
-            self.cgRoot.prepend(CGGeneric(dedent(
-               """
-               Maybe<nsIPrincipal*> subjectPrincipal;
-               if (NS_IsMainThread()) {
-                 JSCompartment* compartment = js::GetContextCompartment(cx);
-                 MOZ_ASSERT(compartment);
-                 JSPrincipals* principals = JS_GetCompartmentPrincipals(compartment);
-                 subjectPrincipal.emplace(nsJSPrincipals::get(principals));
-               }
-               """)))
+            getPrincipal = dedent(
+                """
+                JSCompartment* compartment = js::GetContextCompartment(cx);
+                MOZ_ASSERT(compartment);
+                JSPrincipals* principals = JS_GetCompartmentPrincipals(compartment);
+                """)
+
+            if descriptor.interface.isExposedInAnyWorker():
+                self.cgRoot.prepend(CGGeneric(fill(
+                    """
+                    Maybe<nsIPrincipal*> subjectPrincipal;
+                    if (NS_IsMainThread()) {
+                      $*{getPrincipal}
+                      subjectPrincipal.emplace(nsJSPrincipals::get(principals));
+                    }
+                    """,
+                    getPrincipal=getPrincipal)))
+            else:
+                self.cgRoot.prepend(CGGeneric(fill(
+                    """
+                    $*{getPrincipal}
+                    // Initializing a nonnull is pretty darn annoying...
+                    NonNull<nsIPrincipal> subjectPrincipal;
+                    subjectPrincipal = static_cast<nsIPrincipal*>(nsJSPrincipals::get(principals));
+                    """,
+                    getPrincipal=getPrincipal)))
 
         if isFallible:
             self.cgRoot.prepend(CGGeneric("binding_detail::FastErrorResult rv;\n"))
             self.cgRoot.append(CGGeneric(dedent(
                 """
                 if (MOZ_UNLIKELY(rv.MaybeSetPendingException(cx))) {
                   return false;
                 }
@@ -13988,17 +14004,17 @@ class CGNativeMember(ClassMethod):
                                  "aRetVal"))
         elif returnType.isAny():
             args.append(Argument("JS::MutableHandle<JS::Value>", "aRetVal"))
         elif returnType.isObject() or returnType.isSpiderMonkeyInterface():
             args.append(Argument("JS::MutableHandle<JSObject*>", "aRetVal"))
 
         # And the nsIPrincipal
         if self.member.getExtendedAttribute('NeedsSubjectPrincipal'):
-            args.append(Argument("const Maybe<nsIPrincipal*>&", "aPrincipal"))
+            args.append(Argument("nsIPrincipal&", "aPrincipal"))
         # And the ErrorResult
         if 'infallible' not in self.extendedAttrs:
             # Use aRv so it won't conflict with local vars named "rv"
             args.append(Argument("ErrorResult&", "aRv"))
         # The legacycaller thisval
         if self.member.isMethod() and self.member.isLegacycaller():
             # If it has an identifier, we can't deal with it yet
             assert self.member.isIdentifierLess()
--- a/dom/bindings/test/TestBindingHeader.h
+++ b/dom/bindings/test/TestBindingHeader.h
@@ -928,16 +928,19 @@ public:
   void SetJsonifierShouldSkipThis3(TestCallbackInterface&);
   void ThrowingMethod(ErrorResult& aRv);
   bool GetThrowingAttr(ErrorResult& aRv) const;
   void SetThrowingAttr(bool arg, ErrorResult& aRv);
   bool GetThrowingGetterAttr(ErrorResult& aRv) const;
   void SetThrowingGetterAttr(bool arg);
   bool ThrowingSetterAttr() const;
   void SetThrowingSetterAttr(bool arg, ErrorResult& aRv);
+  void NeedsSubjectPrincipalMethod(nsIPrincipal&);
+  bool NeedsSubjectPrincipalAttr(nsIPrincipal&);
+  void SetNeedsSubjectPrincipalAttr(bool, nsIPrincipal&);
   int16_t LegacyCall(const JS::Value&, uint32_t, TestInterface&);
   void PassArgsWithDefaults(JSContext*, const Optional<int32_t>&,
                             TestInterface*, const Dict&, double,
                             const Optional<float>&);
 
   void SetDashed_attribute(int8_t);
   int8_t Dashed_attribute();
   void Dashed_method();
--- a/dom/bindings/test/TestCodeGen.webidl
+++ b/dom/bindings/test/TestCodeGen.webidl
@@ -938,16 +938,18 @@ interface TestInterface {
   void passRenamedInterface(TestRenamedInterface arg);
   [PutForwards=writableByte] readonly attribute TestInterface putForwardsAttr;
   [PutForwards=writableByte, LenientThis] readonly attribute TestInterface putForwardsAttr2;
   [PutForwards=writableByte, ChromeOnly] readonly attribute TestInterface putForwardsAttr3;
   [Throws] void throwingMethod();
   [Throws] attribute boolean throwingAttr;
   [GetterThrows] attribute boolean throwingGetterAttr;
   [SetterThrows] attribute boolean throwingSetterAttr;
+  [NeedsSubjectPrincipal] void needsSubjectPrincipalMethod();
+  [NeedsSubjectPrincipal] attribute boolean needsSubjectPrincipalAttr;
   legacycaller short(unsigned long arg1, TestInterface arg2);
   void passArgsWithDefaults(optional long arg1,
                             optional TestInterface? arg2 = null,
                             optional Dict arg3, optional double arg4 = 5.0,
                             optional float arg5);
 
   attribute any jsonifierShouldSkipThis;
   attribute TestParentInterface jsonifierShouldSkipThis2;
--- a/dom/bindings/test/TestJSImplGen.webidl
+++ b/dom/bindings/test/TestJSImplGen.webidl
@@ -789,16 +789,20 @@ interface TestJSImplInterface {
   void passRenamedInterface(TestRenamedInterface arg);
   [PutForwards=writableByte] readonly attribute TestJSImplInterface putForwardsAttr;
   [PutForwards=writableByte, LenientThis] readonly attribute TestJSImplInterface putForwardsAttr2;
   [PutForwards=writableByte, ChromeOnly] readonly attribute TestJSImplInterface putForwardsAttr3;
   [Throws] void throwingMethod();
   [Throws] attribute boolean throwingAttr;
   [GetterThrows] attribute boolean throwingGetterAttr;
   [SetterThrows] attribute boolean throwingSetterAttr;
+  // NeedsSubjectPrincipal not supported on JS-implemented things for
+  // now, because we always pass in the caller principal anyway.
+  //  [NeedsSubjectPrincipal] void needsSubjectPrincipalMethod();
+  //  [NeedsSubjectPrincipal] attribute boolean needsSubjectPrincipalAttr;
   // legacycaller short(unsigned long arg1, TestInterface arg2);
   void passArgsWithDefaults(optional long arg1,
                             optional TestInterface? arg2 = null,
                             optional Dict arg3, optional double arg4 = 5.0,
                             optional float arg5);
   attribute any jsonifierShouldSkipThis;
   attribute TestParentInterface jsonifierShouldSkipThis2;
   attribute TestCallbackInterface jsonifierShouldSkipThis3;
--- a/dom/events/ClipboardEvent.cpp
+++ b/dom/events/ClipboardEvent.cpp
@@ -71,17 +71,17 @@ ClipboardEvent::Constructor(const Global
   if (e->mEventIsInternal) {
     InternalClipboardEvent* event = e->mEvent->AsClipboardEvent();
     if (event) {
       // Always create a clipboardData for the copy event. If this is changed to
       // support other types of events, make sure that read/write privileges are
       // checked properly within DataTransfer.
       clipboardData = new DataTransfer(ToSupports(e), eCopy, false, -1);
       clipboardData->SetData(aParam.mDataType, aParam.mData,
-                             Some(aGlobal.GetSubjectPrincipal()), aRv);
+                             *aGlobal.GetSubjectPrincipal(), aRv);
       NS_ENSURE_TRUE(!aRv.Failed(), nullptr);
     }
   }
 
   e->InitClipboardEvent(aType, aParam.mBubbles, aParam.mCancelable,
                         clipboardData);
   e->SetTrusted(trusted);
   e->SetComposed(aParam.mComposed);
--- a/dom/events/DataTransfer.cpp
+++ b/dom/events/DataTransfer.cpp
@@ -279,21 +279,20 @@ DataTransfer::SetEffectAllowedInt(uint32
 NS_IMETHODIMP
 DataTransfer::GetMozUserCancelled(bool* aUserCancelled)
 {
   *aUserCancelled = MozUserCancelled();
   return NS_OK;
 }
 
 already_AddRefed<FileList>
-DataTransfer::GetFiles(const Maybe<nsIPrincipal*>& aSubjectPrincipal,
+DataTransfer::GetFiles(nsIPrincipal& aSubjectPrincipal,
                        ErrorResult& aRv)
 {
-  MOZ_ASSERT(aSubjectPrincipal.isSome());
-  return mItems->Files(aSubjectPrincipal.value());
+  return mItems->Files(&aSubjectPrincipal);
 }
 
 NS_IMETHODIMP
 DataTransfer::GetFiles(nsIDOMFileList** aFileList)
 {
   if (!aFileList) {
     return NS_ERROR_FAILURE;
   }
@@ -347,27 +346,25 @@ DataTransfer::GetTypes(nsTArray<nsString
     }
     aTypes.AppendElement(NS_LITERAL_STRING("Files"));
     break;
   }
 }
 
 void
 DataTransfer::GetData(const nsAString& aFormat, nsAString& aData,
-                      const Maybe<nsIPrincipal*>& aSubjectPrincipal,
+                      nsIPrincipal& aSubjectPrincipal,
                       ErrorResult& aRv)
 {
-  MOZ_ASSERT(aSubjectPrincipal.isSome());
-
   // return an empty string if data for the format was not found
   aData.Truncate();
 
   nsCOMPtr<nsIVariant> data;
   nsresult rv =
-    GetDataAtInternal(aFormat, 0, aSubjectPrincipal.value(),
+    GetDataAtInternal(aFormat, 0, &aSubjectPrincipal,
                       getter_AddRefs(data));
   if (NS_FAILED(rv)) {
     if (rv != NS_ERROR_DOM_INDEX_SIZE_ERR) {
       aRv.Throw(rv);
     }
     return;
   }
 
@@ -407,34 +404,30 @@ DataTransfer::GetData(const nsAString& a
     else {
       aData = stringdata;
     }
   }
 }
 
 void
 DataTransfer::SetData(const nsAString& aFormat, const nsAString& aData,
-                      const Maybe<nsIPrincipal*>& aSubjectPrincipal,
+                      nsIPrincipal& aSubjectPrincipal,
                       ErrorResult& aRv)
 {
-  MOZ_ASSERT(aSubjectPrincipal.isSome());
-
   RefPtr<nsVariantCC> variant = new nsVariantCC();
   variant->SetAsAString(aData);
 
-  aRv = SetDataAtInternal(aFormat, variant, 0, aSubjectPrincipal.value());
+  aRv = SetDataAtInternal(aFormat, variant, 0, &aSubjectPrincipal);
 }
 
 void
 DataTransfer::ClearData(const Optional<nsAString>& aFormat,
-                        const Maybe<nsIPrincipal*>& aSubjectPrincipal,
+                        nsIPrincipal& aSubjectPrincipal,
                         ErrorResult& aRv)
 {
-  MOZ_ASSERT(aSubjectPrincipal.isSome());
-
   if (mReadOnly) {
     aRv.Throw(NS_ERROR_DOM_NO_MODIFICATION_ALLOWED_ERR);
     return;
   }
 
   if (MozItemCount() == 0) {
     return;
   }
@@ -611,23 +604,21 @@ DataTransfer::GetDataAtInternal(const ns
   data.forget(aData);
   return NS_OK;
 }
 
 void
 DataTransfer::MozGetDataAt(JSContext* aCx, const nsAString& aFormat,
                            uint32_t aIndex,
                            JS::MutableHandle<JS::Value> aRetval,
-                           const Maybe<nsIPrincipal*>& aSubjectPrincipal,
+                           nsIPrincipal& aSubjectPrincipal,
                            mozilla::ErrorResult& aRv)
 {
-  MOZ_ASSERT(aSubjectPrincipal.isSome());
-
   nsCOMPtr<nsIVariant> data;
-  aRv = GetDataAtInternal(aFormat, aIndex, aSubjectPrincipal.value(),
+  aRv = GetDataAtInternal(aFormat, aIndex, &aSubjectPrincipal,
                           getter_AddRefs(data));
   if (aRv.Failed()) {
     return;
   }
 
   if (!data) {
     aRetval.setNull();
     return;
@@ -703,36 +694,32 @@ DataTransfer::SetDataAtInternal(const ns
   }
 
   return SetDataWithPrincipal(aFormat, aData, aIndex, aSubjectPrincipal);
 }
 
 void
 DataTransfer::MozSetDataAt(JSContext* aCx, const nsAString& aFormat,
                            JS::Handle<JS::Value> aData, uint32_t aIndex,
-                           const Maybe<nsIPrincipal*>& aSubjectPrincipal,
+                           nsIPrincipal& aSubjectPrincipal,
                            ErrorResult& aRv)
 {
-  MOZ_ASSERT(aSubjectPrincipal.isSome());
-
   nsCOMPtr<nsIVariant> data;
   aRv = nsContentUtils::XPConnect()->JSValToVariant(aCx, aData,
                                                     getter_AddRefs(data));
   if (!aRv.Failed()) {
-    aRv = SetDataAtInternal(aFormat, data, aIndex, aSubjectPrincipal.value());
+    aRv = SetDataAtInternal(aFormat, data, aIndex, &aSubjectPrincipal);
   }
 }
 
 void
 DataTransfer::MozClearDataAt(const nsAString& aFormat, uint32_t aIndex,
-                             const Maybe<nsIPrincipal*>& aSubjectPrincipal,
+                             nsIPrincipal& aSubjectPrincipal,
                              ErrorResult& aRv)
 {
-  MOZ_ASSERT(aSubjectPrincipal.isSome());
-
   if (mReadOnly) {
     aRv.Throw(NS_ERROR_DOM_NO_MODIFICATION_ALLOWED_ERR);
     return;
   }
 
   if (aIndex >= MozItemCount()) {
     aRv.Throw(NS_ERROR_DOM_INDEX_SIZE_ERR);
     return;
@@ -757,25 +744,24 @@ DataTransfer::MozClearDataAt(const nsASt
   if (aIndex == 0 && mItems->MozItemCount() > 1 &&
       mItems->MozItemsAt(0)->Length() == 0) {
     mItems->PopIndexZero();
   }
 }
 
 void
 DataTransfer::MozClearDataAtHelper(const nsAString& aFormat, uint32_t aIndex,
-                                   const Maybe<nsIPrincipal*>& aSubjectPrincipal,
+                                   nsIPrincipal& aSubjectPrincipal,
                                    ErrorResult& aRv)
 {
   MOZ_ASSERT(!mReadOnly);
   MOZ_ASSERT(aIndex < MozItemCount());
   MOZ_ASSERT(aIndex == 0 ||
              (mEventMessage != eCut && mEventMessage != eCopy &&
               mEventMessage != ePaste));
-  MOZ_ASSERT(aSubjectPrincipal.isSome());
 
   nsAutoString format;
   GetRealFormat(aFormat, format);
 
   mItems->MozRemoveByTypeAt(format, aIndex, aSubjectPrincipal, aRv);
 }
 
 void
@@ -799,21 +785,19 @@ DataTransfer::SetDragImage(nsIDOMElement
   nsCOMPtr<Element> image = do_QueryInterface(aImage);
   if (image) {
     SetDragImage(*image, aX, aY, rv);
   }
   return rv.StealNSResult();
 }
 
 already_AddRefed<Promise>
-DataTransfer::GetFilesAndDirectories(const Maybe<nsIPrincipal*>& aSubjectPrincipal,
+DataTransfer::GetFilesAndDirectories(nsIPrincipal& aSubjectPrincipal,
                                      ErrorResult& aRv)
 {
-  MOZ_ASSERT(aSubjectPrincipal.isSome());
-
   nsCOMPtr<nsINode> parentNode = do_QueryInterface(mParent);
   if (!parentNode) {
     aRv.Throw(NS_ERROR_FAILURE);
     return nullptr;
   }
 
   nsCOMPtr<nsIGlobalObject> global = parentNode->OwnerDoc()->GetScopeObject();
   MOZ_ASSERT(global);
@@ -822,17 +806,17 @@ DataTransfer::GetFilesAndDirectories(con
     return nullptr;
   }
 
   RefPtr<Promise> p = Promise::Create(global, aRv);
   if (NS_WARN_IF(aRv.Failed())) {
     return nullptr;
   }
 
-  RefPtr<FileList> files = mItems->Files(aSubjectPrincipal.value());
+  RefPtr<FileList> files = mItems->Files(&aSubjectPrincipal);
   if (NS_WARN_IF(!files)) {
     return nullptr;
   }
 
   Sequence<RefPtr<File>> filesSeq;
   files->ToSequence(filesSeq, aRv);
   if (NS_WARN_IF(aRv.Failed())) {
     return nullptr;
@@ -840,17 +824,17 @@ DataTransfer::GetFilesAndDirectories(con
 
   p->MaybeResolve(filesSeq);
 
   return p.forget();
 }
 
 already_AddRefed<Promise>
 DataTransfer::GetFiles(bool aRecursiveFlag,
-                       const Maybe<nsIPrincipal*>& aSubjectPrincipal,
+                       nsIPrincipal& aSubjectPrincipal,
                        ErrorResult& aRv)
 {
   // Currently we don't support directories.
   return GetFilesAndDirectories(aSubjectPrincipal, aRv);
 }
 
 void
 DataTransfer::AddElement(Element& aElement, ErrorResult& aRv)
--- a/dom/events/DataTransfer.h
+++ b/dom/events/DataTransfer.h
@@ -134,38 +134,38 @@ public:
   }
 
   void SetDragImage(Element& aElement, int32_t aX, int32_t aY,
                     ErrorResult& aRv);
 
   void GetTypes(nsTArray<nsString>& aTypes) const;
 
   void GetData(const nsAString& aFormat, nsAString& aData,
-               const Maybe<nsIPrincipal*>& aSubjectPrincipal,
+               nsIPrincipal& aSubjectPrincipal,
                ErrorResult& aRv);
 
   void SetData(const nsAString& aFormat, const nsAString& aData,
-               const Maybe<nsIPrincipal*>& aSubjectPrincipal,
+               nsIPrincipal& aSubjectPrincipal,
                ErrorResult& aRv);
 
   void ClearData(const mozilla::dom::Optional<nsAString>& aFormat,
-                 const Maybe<nsIPrincipal*>& aSubjectPrincipal,
+                 nsIPrincipal& aSubjectPrincipal,
                  mozilla::ErrorResult& aRv);
 
   already_AddRefed<FileList>
-  GetFiles(const Maybe<nsIPrincipal*>& aSubjectPrincipal,
+  GetFiles(nsIPrincipal& aSubjectPrincipal,
            mozilla::ErrorResult& aRv);
 
   already_AddRefed<Promise>
-  GetFilesAndDirectories(const Maybe<nsIPrincipal*>& aSubjectPrincipal,
+  GetFilesAndDirectories(nsIPrincipal& aSubjectPrincipal,
                          mozilla::ErrorResult& aRv);
 
   already_AddRefed<Promise>
   GetFiles(bool aRecursiveFlag,
-           const Maybe<nsIPrincipal*>& aSubjectPrincipal,
+           nsIPrincipal& aSubjectPrincipal,
            ErrorResult& aRv);
 
 
   void AddElement(Element& aElement, mozilla::ErrorResult& aRv);
 
   uint32_t MozItemCount() const;
 
   void GetMozCursor(nsString& aCursor)
@@ -176,27 +176,27 @@ public:
       aCursor.AssignLiteral("auto");
     }
   }
 
   already_AddRefed<DOMStringList> MozTypesAt(uint32_t aIndex,
                                              mozilla::ErrorResult& aRv) const;
 
   void MozClearDataAt(const nsAString& aFormat, uint32_t aIndex,
-                      const Maybe<nsIPrincipal*>& aSubjectPrincipal,
+                      nsIPrincipal& aSubjectPrincipal,
                       mozilla::ErrorResult& aRv);
 
   void MozSetDataAt(JSContext* aCx, const nsAString& aFormat,
                     JS::Handle<JS::Value> aData, uint32_t aIndex,
-                    const Maybe<nsIPrincipal*>& aSubjectPrincipal,
+                    nsIPrincipal& aSubjectPrincipal,
                     mozilla::ErrorResult& aRv);
 
   void MozGetDataAt(JSContext* aCx, const nsAString& aFormat,
                     uint32_t aIndex, JS::MutableHandle<JS::Value> aRetval,
-                    const Maybe<nsIPrincipal*>& aSubjectPrincipal,
+                    nsIPrincipal& aSubjectPrincipal,
                     mozilla::ErrorResult& aRv);
 
   bool MozUserCancelled() const
   {
     return mUserCancelled;
   }
 
   already_AddRefed<nsINode> GetMozSourceNode();
@@ -321,17 +321,17 @@ protected:
   void FillAllExternalData();
 
   void FillInExternalCustomTypes(uint32_t aIndex, nsIPrincipal* aPrincipal);
 
   void FillInExternalCustomTypes(nsIVariant* aData, uint32_t aIndex,
                                  nsIPrincipal* aPrincipal);
 
   void MozClearDataAtHelper(const nsAString& aFormat, uint32_t aIndex,
-                            const Maybe<nsIPrincipal*>& aSubjectPrincipal,
+                            nsIPrincipal& aSubjectPrincipal,
                             mozilla::ErrorResult& aRv);
 
   nsCOMPtr<nsISupports> mParent;
 
   // the drop effect and effect allowed
   uint32_t mDropEffect;
   uint32_t mEffectAllowed;
 
--- a/dom/events/DataTransferItem.cpp
+++ b/dom/events/DataTransferItem.cpp
@@ -226,28 +226,26 @@ DataTransferItem::FillInExternalData()
 
   if (oldKind != Kind()) {
     NS_WARNING("Clipboard data provided by the OS does not match predicted kind");
     mDataTransfer->TypesListMayHaveChanged();
   }
 }
 
 already_AddRefed<File>
-DataTransferItem::GetAsFile(const Maybe<nsIPrincipal*>& aSubjectPrincipal,
+DataTransferItem::GetAsFile(nsIPrincipal& aSubjectPrincipal,
                             ErrorResult& aRv)
 {
-  MOZ_ASSERT(aSubjectPrincipal.isSome());
-
   if (mKind != KIND_FILE) {
     return nullptr;
   }
 
   // This is done even if we have an mCachedFile, as it performs the necessary
   // permissions checks to ensure that we are allowed to access this type.
-  nsCOMPtr<nsIVariant> data = Data(aSubjectPrincipal.value(), aRv);
+  nsCOMPtr<nsIVariant> data = Data(&aSubjectPrincipal, aRv);
   if (NS_WARN_IF(!data || aRv.Failed())) {
     return nullptr;
   }
 
   // Generate the dom::File from the stored data, caching it so that the
   // same object is returned in the future.
   if (!mCachedFile) {
     nsCOMPtr<nsISupports> supports;
@@ -271,21 +269,19 @@ DataTransferItem::GetAsFile(const Maybe<
     }
   }
 
   RefPtr<File> file = mCachedFile;
   return file.forget();
 }
 
 already_AddRefed<FileSystemEntry>
-DataTransferItem::GetAsEntry(const Maybe<nsIPrincipal*>& aSubjectPrincipal,
+DataTransferItem::GetAsEntry(nsIPrincipal& aSubjectPrincipal,
                              ErrorResult& aRv)
 {
-  MOZ_ASSERT(aSubjectPrincipal.isSome());
-
   RefPtr<File> file = GetAsFile(aSubjectPrincipal, aRv);
   if (NS_WARN_IF(aRv.Failed()) || !file) {
     return nullptr;
   }
 
   nsCOMPtr<nsIGlobalObject> global;
   // This is annoying, but DataTransfer may have various things as parent.
   nsCOMPtr<EventTarget> target =
@@ -374,29 +370,27 @@ DataTransferItem::CreateFileFromInputStr
   }
 
   return File::CreateMemoryFile(mDataTransfer, data, available, fileName,
                                 mType, PR_Now());
 }
 
 void
 DataTransferItem::GetAsString(FunctionStringCallback* aCallback,
-                              const Maybe<nsIPrincipal*>& aSubjectPrincipal,
+                              nsIPrincipal& aSubjectPrincipal,
                               ErrorResult& aRv)
 {
-  MOZ_ASSERT(aSubjectPrincipal.isSome());
-
   if (!aCallback || mKind != KIND_STRING) {
     return;
   }
 
   // Theoretically this should be done inside of the runnable, as it might be an
   // expensive operation on some systems, however we wouldn't get access to the
   // NS_ERROR_DOM_SECURITY_ERROR messages which may be raised by this method.
-  nsCOMPtr<nsIVariant> data = Data(aSubjectPrincipal.value(), aRv);
+  nsCOMPtr<nsIVariant> data = Data(&aSubjectPrincipal, aRv);
   if (NS_WARN_IF(!data || aRv.Failed())) {
     return;
   }
 
   nsAutoString stringData;
   nsresult rv = data->GetAsAString(stringData);
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return;
--- a/dom/events/DataTransferItem.h
+++ b/dom/events/DataTransferItem.h
@@ -45,19 +45,18 @@ public:
   {
     MOZ_ASSERT(mDataTransfer, "Must be associated with a DataTransfer");
   }
 
   already_AddRefed<DataTransferItem> Clone(DataTransfer* aDataTransfer) const;
 
   virtual JSObject* WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) override;
 
-  // NOTE: This accesses the subject principal, and should not be called from C++
   void GetAsString(FunctionStringCallback* aCallback,
-                   const Maybe<nsIPrincipal*>& aPrincipal,
+                   nsIPrincipal& aSubjectPrincipal,
                    ErrorResult& aRv);
 
   void GetKind(nsAString& aKind) const
   {
     switch (mKind) {
     case KIND_FILE:
       aKind = NS_LITERAL_STRING("file");
       return;
@@ -76,20 +75,20 @@ public:
   }
 
   eKind Kind() const
   {
     return mKind;
   }
 
   already_AddRefed<File>
-  GetAsFile(const Maybe<nsIPrincipal*>& aSubjectPrincipal, ErrorResult& aRv);
+  GetAsFile(nsIPrincipal& aSubjectPrincipal, ErrorResult& aRv);
 
   already_AddRefed<FileSystemEntry>
-  GetAsEntry(const Maybe<nsIPrincipal*>& aSubjectPrincipal, ErrorResult& aRv);
+  GetAsEntry(nsIPrincipal& aSubjectPrincipal, ErrorResult& aRv);
 
   DataTransfer* GetParentObject() const
   {
     return mDataTransfer;
   }
 
   nsIPrincipal* Principal() const
   {
--- a/dom/events/DataTransferItemList.cpp
+++ b/dom/events/DataTransferItemList.cpp
@@ -77,21 +77,19 @@ DataTransferItemList::Clone(DataTransfer
     list->mItems[i] = list->mIndexedItems[index][subIndex];
   }
 
   return list.forget();
 }
 
 void
 DataTransferItemList::Remove(uint32_t aIndex,
-                             const Maybe<nsIPrincipal*>& aSubjectPrincipal,
+                             nsIPrincipal& aSubjectPrincipal,
                              ErrorResult& aRv)
 {
-  MOZ_ASSERT(aSubjectPrincipal.isSome());
-
   if (mDataTransfer->IsReadOnly()) {
     aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
     return;
   }
 
   if (aIndex >= Length()) {
     aRv.Throw(NS_ERROR_DOM_INDEX_SIZE_ERR);
     return;
@@ -121,21 +119,19 @@ DataTransferItemList::MozItemCount() con
   // if it is empty, scripts using the moz* APIs should see it as not existing.
   if (length == 1 && mIndexedItems[0].IsEmpty()) {
     return 0;
   }
   return length;
 }
 
 void
-DataTransferItemList::Clear(const Maybe<nsIPrincipal*>& aSubjectPrincipal,
+DataTransferItemList::Clear(nsIPrincipal& aSubjectPrincipal,
                             ErrorResult& aRv)
 {
-  MOZ_ASSERT(aSubjectPrincipal.isSome());
-
   if (NS_WARN_IF(mDataTransfer->IsReadOnly())) {
     return;
   }
 
   uint32_t count = Length();
   for (uint32_t i = 0; i < count; i++) {
     // We always remove the last item first, to avoid moving items around in
     // memory as much
@@ -144,81 +140,75 @@ DataTransferItemList::Clear(const Maybe<
   }
 
   MOZ_ASSERT(Length() == 0);
 }
 
 DataTransferItem*
 DataTransferItemList::Add(const nsAString& aData,
                           const nsAString& aType,
-                          const Maybe<nsIPrincipal*>& aSubjectPrincipal,
+                          nsIPrincipal& aSubjectPrincipal,
                           ErrorResult& aRv)
 {
-  MOZ_ASSERT(aSubjectPrincipal.isSome());
-
   if (NS_WARN_IF(mDataTransfer->IsReadOnly())) {
     return nullptr;
   }
 
   nsCOMPtr<nsIVariant> data(new storage::TextVariant(aData));
 
   nsAutoString format;
   mDataTransfer->GetRealFormat(aType, format);
 
-  if (!DataTransfer::PrincipalMaySetData(format, data,
-                                         aSubjectPrincipal.value())) {
+  if (!DataTransfer::PrincipalMaySetData(format, data, &aSubjectPrincipal)) {
     aRv.Throw(NS_ERROR_DOM_SECURITY_ERR);
     return nullptr;
   }
 
   // We add the textual data to index 0. We set aInsertOnly to true, as we don't
   // want to update an existing entry if it is already present, as per the spec.
   RefPtr<DataTransferItem> item =
-    SetDataWithPrincipal(format, data, 0, aSubjectPrincipal.value(),
+    SetDataWithPrincipal(format, data, 0, &aSubjectPrincipal,
                          /* aInsertOnly = */ true,
                          /* aHidden = */ false,
                          aRv);
   if (NS_WARN_IF(aRv.Failed())) {
     return nullptr;
   }
   MOZ_ASSERT(item->Kind() != DataTransferItem::KIND_FILE);
 
   return item;
 }
 
 DataTransferItem*
 DataTransferItemList::Add(File& aData,
-                          const Maybe<nsIPrincipal*>& aSubjectPrincipal,
+                          nsIPrincipal& aSubjectPrincipal,
                           ErrorResult& aRv)
 {
-  MOZ_ASSERT(aSubjectPrincipal.isSome());
-
   if (mDataTransfer->IsReadOnly()) {
     return nullptr;
   }
 
   nsCOMPtr<nsISupports> supports = do_QueryObject(&aData);
   nsCOMPtr<nsIWritableVariant> data = new nsVariant();
   data->SetAsISupports(supports);
 
   nsAutoString type;
   aData.GetType(type);
 
-  if (!DataTransfer::PrincipalMaySetData(type, data,
-                                         aSubjectPrincipal.value())) {
+  if (!DataTransfer::PrincipalMaySetData(type, data, &aSubjectPrincipal)) {
     aRv.Throw(NS_ERROR_DOM_SECURITY_ERR);
     return nullptr;
   }
 
   // We need to add this as a new item, as multiple files can't exist in the
   // same item in the Moz DataTransfer layout. It will be appended at the end of
   // the internal specced layout.
   uint32_t index = mIndexedItems.Length();
   RefPtr<DataTransferItem> item =
-    SetDataWithPrincipal(type, data, index, aSubjectPrincipal.value(),
+    SetDataWithPrincipal(type, data, index, &aSubjectPrincipal,
                          /* aInsertOnly = */ true,
                          /* aHidden = */ false,
                          aRv);
   if (NS_WARN_IF(aRv.Failed())) {
     return nullptr;
   }
   MOZ_ASSERT(item->Kind() == DataTransferItem::KIND_FILE);
 
@@ -267,21 +257,19 @@ DataTransferItemList::Files(nsIPrincipal
 
   files = mFiles;
   return files.forget();
 }
 
 void
 DataTransferItemList::MozRemoveByTypeAt(const nsAString& aType,
                                         uint32_t aIndex,
-                                        const Maybe<nsIPrincipal*>& aSubjectPrincipal,
+                                        nsIPrincipal& aSubjectPrincipal,
                                         ErrorResult& aRv)
 {
-  MOZ_ASSERT(aSubjectPrincipal.isSome());
-
   if (NS_WARN_IF(mDataTransfer->IsReadOnly() ||
                  aIndex >= mIndexedItems.Length())) {
     return;
   }
 
   bool removeAll = aType.IsEmpty();
 
   nsTArray<RefPtr<DataTransferItem>>& items = mIndexedItems[aIndex];
@@ -490,26 +478,25 @@ DataTransferItemList::ClearAllItems()
   // Re-generate files (into an empty list)
   RegenerateFiles();
 }
 
 void
 DataTransferItemList::ClearDataHelper(DataTransferItem* aItem,
                                       uint32_t aIndexHint,
                                       uint32_t aMozOffsetHint,
-                                      const Maybe<nsIPrincipal*>& aSubjectPrincipal,
+                                      nsIPrincipal& aSubjectPrincipal,
                                       ErrorResult& aRv)
 {
   MOZ_ASSERT(aItem);
   if (NS_WARN_IF(mDataTransfer->IsReadOnly())) {
     return;
   }
 
-  if (aItem->Principal() && aSubjectPrincipal.isSome() &&
-      !aSubjectPrincipal.value()->Subsumes(aItem->Principal())) {
+  if (aItem->Principal() && !aSubjectPrincipal.Subsumes(aItem->Principal())) {
     aRv.Throw(NS_ERROR_DOM_SECURITY_ERR);
     return;
   }
 
   // Check if the aIndexHint is actually the index, and then remove the item
   // from aItems
   bool found;
   if (IndexedGetter(aIndexHint, found) == aItem) {
@@ -576,17 +563,17 @@ DataTransferItemList::GenerateFiles(File
   uint32_t count = Length();
   for (uint32_t i = 0; i < count; i++) {
     bool found;
     RefPtr<DataTransferItem> item = IndexedGetter(i, found);
     MOZ_ASSERT(found);
 
     if (item->Kind() == DataTransferItem::KIND_FILE) {
       IgnoredErrorResult rv;
-      RefPtr<File> file = item->GetAsFile(Some(aFilesPrincipal), rv);
+      RefPtr<File> file = item->GetAsFile(*aFilesPrincipal, rv);
       if (NS_WARN_IF(rv.Failed() || !file)) {
         continue;
       }
       aFiles->Append(file);
     }
   }
 }
 
--- a/dom/events/DataTransferItemList.h
+++ b/dom/events/DataTransferItemList.h
@@ -46,61 +46,61 @@ public:
                                JS::Handle<JSObject*> aGivenProto) override;
 
   uint32_t Length() const
   {
     return mItems.Length();
   };
 
   DataTransferItem* Add(const nsAString& aData, const nsAString& aType,
-                        const Maybe<nsIPrincipal*>& aSubjectPrincipal,
+                        nsIPrincipal& aSubjectPrincipal,
                         ErrorResult& rv);
   DataTransferItem* Add(File& aData,
-                        const Maybe<nsIPrincipal*>& aSubjectPrincipal,
+                        nsIPrincipal& aSubjectPrincipal,
                         ErrorResult& aRv);
 
   void Remove(uint32_t aIndex,
-              const Maybe<nsIPrincipal*>& aSubjectPrincipal,
+              nsIPrincipal& aSubjectPrincipal,
               ErrorResult& aRv);
 
   DataTransferItem* IndexedGetter(uint32_t aIndex, bool& aFound) const;
 
   DataTransfer* GetParentObject() const
   {
     return mDataTransfer;
   }
 
-  void Clear(const Maybe<nsIPrincipal*>& aSubjectPrincipal, ErrorResult& aRv);
+  void Clear(nsIPrincipal& aSubjectPrincipal, ErrorResult& aRv);
 
   already_AddRefed<DataTransferItem>
   SetDataWithPrincipal(const nsAString& aType, nsIVariant* aData,
                        uint32_t aIndex, nsIPrincipal* aPrincipal,
                        bool aInsertOnly, bool aHidden, ErrorResult& aRv);
 
   already_AddRefed<FileList> Files(nsIPrincipal* aPrincipal);
 
   // Moz-style helper methods for interacting with the stored data
   void MozRemoveByTypeAt(const nsAString& aType, uint32_t aIndex,
-                         const Maybe<nsIPrincipal*>& aSubjectPrincipal,
+                         nsIPrincipal& aSubjectPrincipal,
                          ErrorResult& aRv);
   DataTransferItem* MozItemByTypeAt(const nsAString& aType, uint32_t aIndex);
   const nsTArray<RefPtr<DataTransferItem>>* MozItemsAt(uint32_t aIndex);
   uint32_t MozItemCount() const;
 
   // Causes everything in indexes above 0 to shift down one index.
   void PopIndexZero();
 
   // Delete every item in the DataTransferItemList, without checking for
   // permissions or read-only status (for internal use only).
   void ClearAllItems();
 
 private:
   void ClearDataHelper(DataTransferItem* aItem, uint32_t aIndexHint,
                        uint32_t aMozOffsetHint,
-                       const Maybe<nsIPrincipal*>& aSubjectPrincipal,
+                       nsIPrincipal& aSubjectPrincipal,
                        ErrorResult& aRv);
   DataTransferItem* AppendNewItem(uint32_t aIndex, const nsAString& aType,
                                   nsIVariant* aData, nsIPrincipal* aPrincipal,
                                   bool aHidden);
   void RegenerateFiles();
   void GenerateFiles(FileList* aFiles, nsIPrincipal* aFilesPrincipal);
 
   ~DataTransferItemList() {}
--- a/dom/html/HTMLIFrameElement.h
+++ b/dom/html/HTMLIFrameElement.h
@@ -163,17 +163,17 @@ public:
   {
     SetHTMLAttr(nsGkAtoms::referrerpolicy, aReferrer, aError);
   }
   void GetReferrerPolicy(nsAString& aReferrer)
   {
     GetEnumAttr(nsGkAtoms::referrerpolicy, EmptyCString().get(), aReferrer);
   }
   nsIDocument*
-  GetSVGDocument(const mozilla::Maybe<nsIPrincipal*>& aSubjectPrincipal)
+  GetSVGDocument(nsIPrincipal& aSubjectPrincipal)
   {
     return GetContentDocument(aSubjectPrincipal);
   }
   bool Mozbrowser() const
   {
     return GetBoolAttr(nsGkAtoms::mozbrowser);
   }
   void SetMozbrowser(bool aAllow, ErrorResult& aError)
--- a/dom/html/HTMLInputElement.cpp
+++ b/dom/html/HTMLInputElement.cpp
@@ -2836,21 +2836,19 @@ NS_IMETHODIMP
 HTMLInputElement::MozIsTextField(bool aExcludePassword, bool* aResult)
 {
   *aResult = MozIsTextField(aExcludePassword);
   return NS_OK;
 }
 
 void
 HTMLInputElement::SetUserInput(const nsAString& aInput,
-                               const mozilla::Maybe<nsIPrincipal*>& aPrincipal) {
-  MOZ_ASSERT(aPrincipal.isSome());
-
+                               nsIPrincipal& aSubjectPrincipal) {
   if (mType == NS_FORM_INPUT_FILE &&
-      !nsContentUtils::IsSystemPrincipal(aPrincipal.value())) {
+      !nsContentUtils::IsSystemPrincipal(&aSubjectPrincipal)) {
     return;
   }
 
   SetUserInput(aInput);
 }
 
 NS_IMETHODIMP
 HTMLInputElement::SetUserInput(const nsAString& aValue)
--- a/dom/html/HTMLInputElement.h
+++ b/dom/html/HTMLInputElement.h
@@ -816,17 +816,17 @@ public:
     return mNumberControlSpinnerIsSpinning && !mNumberControlSpinnerSpinsUp;
   }
 
   bool MozIsTextField(bool aExcludePassword);
 
   nsIEditor* GetEditor();
 
   void SetUserInput(const nsAString& aInput,
-                    const mozilla::Maybe<nsIPrincipal*>& aPrincipal);
+                    nsIPrincipal& aSubjectPrincipal);
 
   // XPCOM GetPhonetic() is OK
 
   /**
    * If aValue contains a valid floating-point number in the format specified
    * by the HTML 5 spec:
    *
    *   http://www.whatwg.org/specs/web-apps/current-work/multipage/common-microsyntaxes.html#floating-point-numbers
--- a/dom/html/HTMLObjectElement.cpp
+++ b/dom/html/HTMLObjectElement.cpp
@@ -461,23 +461,23 @@ HTMLObjectElement::TabIndexDefault()
 }
 
 NS_IMETHODIMP
 HTMLObjectElement::GetContentDocument(nsIDOMDocument **aContentDocument)
 {
   NS_ENSURE_ARG_POINTER(aContentDocument);
 
   nsCOMPtr<nsIDOMDocument> domDoc =
-    do_QueryInterface(GetContentDocument(Some(nsContentUtils::SubjectPrincipal())));
+    do_QueryInterface(GetContentDocument(*nsContentUtils::SubjectPrincipal()));
   domDoc.forget(aContentDocument);
   return NS_OK;
 }
 
 nsPIDOMWindowOuter*
-HTMLObjectElement::GetContentWindow(const mozilla::Maybe<nsIPrincipal*>& aSubjectPrincipal)
+HTMLObjectElement::GetContentWindow(nsIPrincipal& aSubjectPrincipal)
 {
   nsIDocument* doc = GetContentDocument(aSubjectPrincipal);
   if (doc) {
     return doc->GetWindow();
   }
 
   return nullptr;
 }
--- a/dom/html/HTMLObjectElement.h
+++ b/dom/html/HTMLObjectElement.h
@@ -153,17 +153,17 @@ public:
   }
   void SetHeight(const nsAString& aValue, ErrorResult& aRv)
   {
     SetHTMLAttr(nsGkAtoms::height, aValue, aRv);
   }
   using nsObjectLoadingContent::GetContentDocument;
 
   nsPIDOMWindowOuter*
-  GetContentWindow(const mozilla::Maybe<nsIPrincipal*>& aSubjectPrincipal);
+  GetContentWindow(nsIPrincipal& aSubjectPrincipal);
 
   using nsIConstraintValidation::CheckValidity;
   using nsIConstraintValidation::ReportValidity;
   using nsIConstraintValidation::GetValidationMessage;
   void GetAlign(DOMString& aValue)
   {
     GetHTMLAttr(nsGkAtoms::align, aValue);
   }
@@ -234,17 +234,17 @@ public:
     GetHTMLAttr(nsGkAtoms::border, aValue);
   }
   void SetBorder(const nsAString& aValue, ErrorResult& aRv)
   {
     SetHTMLAttr(nsGkAtoms::border, aValue, aRv);
   }
 
   nsIDocument*
-  GetSVGDocument(const mozilla::Maybe<nsIPrincipal*>& aSubjectPrincipal)
+  GetSVGDocument(nsIPrincipal& aSubjectPrincipal)
   {
     return GetContentDocument(aSubjectPrincipal);
   }
 
 private:
   /**
    * Calls LoadObject with the correct arguments to start the plugin load.
    */
--- a/dom/html/HTMLSharedObjectElement.h
+++ b/dom/html/HTMLSharedObjectElement.h
@@ -183,17 +183,17 @@ public:
   {
     SetHTMLAttr(nsGkAtoms::type, aValue, aRv);
   }
   // width covered by <applet>
   // height covered by <applet>
   // align covered by <applet>
   // name covered by <applet>
   nsIDocument*
-  GetSVGDocument(const mozilla::Maybe<nsIPrincipal*>& aSubjectPrincipal)
+  GetSVGDocument(nsIPrincipal& aSubjectPrincipal)
   {
     return GetContentDocument(aSubjectPrincipal);
   }
 
   /**
    * Calls LoadObject with the correct arguments to start the plugin load.
    */
   void StartObjectLoad(bool aNotify, bool aForceLoad);
--- a/dom/html/nsGenericHTMLFrameElement.cpp
+++ b/dom/html/nsGenericHTMLFrameElement.cpp
@@ -75,37 +75,36 @@ nsGenericHTMLFrameElement::~nsGenericHTM
   }
 }
 
 nsresult
 nsGenericHTMLFrameElement::GetContentDocument(nsIDOMDocument** aContentDocument)
 {
   NS_PRECONDITION(aContentDocument, "Null out param");
   nsCOMPtr<nsIDOMDocument> document =
-    do_QueryInterface(GetContentDocument(Some(nsContentUtils::SubjectPrincipal())));
+    do_QueryInterface(GetContentDocument(*nsContentUtils::SubjectPrincipal()));
   document.forget(aContentDocument);
   return NS_OK;
 }
 
 nsIDocument*
-nsGenericHTMLFrameElement::GetContentDocument(const Maybe<nsIPrincipal*>& aSubjectPrincipal)
+nsGenericHTMLFrameElement::GetContentDocument(nsIPrincipal& aSubjectPrincipal)
 {
   nsCOMPtr<nsPIDOMWindowOuter> win = GetContentWindow();
   if (!win) {
     return nullptr;
   }
 
   nsIDocument *doc = win->GetDoc();
   if (!doc) {
     return nullptr;
   }
 
   // Return null for cross-origin contentDocument.
-  if (!aSubjectPrincipal.value()
-        ->SubsumesConsideringDomain(doc->NodePrincipal())) {
+  if (!aSubjectPrincipal.SubsumesConsideringDomain(doc->NodePrincipal())) {
     return nullptr;
   }
   return doc;
 }
 
 already_AddRefed<nsPIDOMWindowOuter>
 nsGenericHTMLFrameElement::GetContentWindow()
 {
--- a/dom/html/nsGenericHTMLFrameElement.h
+++ b/dom/html/nsGenericHTMLFrameElement.h
@@ -97,18 +97,17 @@ public:
 
 protected:
   virtual ~nsGenericHTMLFrameElement();
 
   // This doesn't really ensure a frame loader in all cases, only when
   // it makes sense.
   void EnsureFrameLoader();
   nsresult LoadSrc();
-  nsIDocument*
-  GetContentDocument(const mozilla::Maybe<nsIPrincipal*>& aSubjectPrincipal);
+  nsIDocument* GetContentDocument(nsIPrincipal& aSubjectPrincipal);
   nsresult GetContentDocument(nsIDOMDocument** aContentDocument);
   already_AddRefed<nsPIDOMWindowOuter> GetContentWindow();
 
   RefPtr<nsFrameLoader> mFrameLoader;
 
   /**
    * True when the element is created by the parser using the
    * NS_FROM_PARSER_NETWORK flag.
--- a/dom/html/nsHTMLDocument.cpp
+++ b/dom/html/nsHTMLDocument.cpp
@@ -2838,20 +2838,28 @@ nsHTMLDocument::SetDesignMode(const nsAS
   SetDesignMode(aDesignMode, nsContentUtils::GetCurrentJSContext()
                                ? Some(nsContentUtils::SubjectPrincipal())
                                : Nothing(), rv);
   return rv.StealNSResult();
 }
 
 void
 nsHTMLDocument::SetDesignMode(const nsAString& aDesignMode,
+                              nsIPrincipal& aSubjectPrincipal,
+                              ErrorResult& rv)
+{
+  SetDesignMode(aDesignMode, Some(&aSubjectPrincipal), rv);
+}
+
+void
+nsHTMLDocument::SetDesignMode(const nsAString& aDesignMode,
                               const Maybe<nsIPrincipal*>& aSubjectPrincipal,
                               ErrorResult& rv)
 {
-  if (!nsContentUtils::LegacyIsCallerNativeCode() &&
+  if (aSubjectPrincipal.isSome() &&
       !aSubjectPrincipal.value()->Subsumes(NodePrincipal())) {
     rv.Throw(NS_ERROR_DOM_PROP_ACCESS_DENIED);
     return;
   }
   bool editableMode = HasFlag(NODE_IS_EDITABLE);
   if (aDesignMode.LowerCaseEqualsASCII(editableMode ? "off" : "on")) {
     SetEditableFlag(!editableMode);
 
--- a/dom/html/nsHTMLDocument.h
+++ b/dom/html/nsHTMLDocument.h
@@ -206,21 +206,24 @@ public:
        bool aReplace,
        mozilla::ErrorResult& rv);
   void Close(mozilla::ErrorResult& rv);
   void Write(JSContext* cx, const mozilla::dom::Sequence<nsString>& aText,
              mozilla::ErrorResult& rv);
   void Writeln(JSContext* cx, const mozilla::dom::Sequence<nsString>& aText,
                mozilla::ErrorResult& rv);
   void GetDesignMode(nsAString& aDesignMode,
-                     const mozilla::Maybe<nsIPrincipal*>& aSubjectPrincipal)
+                     nsIPrincipal& aSubjectPrincipal)
   {
     GetDesignMode(aDesignMode);
   }
   void SetDesignMode(const nsAString& aDesignMode,
+                     nsIPrincipal& aSubjectPrincipal,
+                     mozilla::ErrorResult& rv);
+  void SetDesignMode(const nsAString& aDesignMode,
                      const mozilla::Maybe<nsIPrincipal*>& aSubjectPrincipal,
                      mozilla::ErrorResult& rv);
   bool ExecCommand(const nsAString& aCommandID, bool aDoShowUI,
                    const nsAString& aValue, mozilla::ErrorResult& rv);
   bool QueryCommandEnabled(const nsAString& aCommandID,
                            mozilla::ErrorResult& rv);
   bool QueryCommandIndeterm(const nsAString& aCommandID,
                             mozilla::ErrorResult& rv);
--- a/dom/storage/DOMStorage.cpp
+++ b/dom/storage/DOMStorage.cpp
@@ -62,69 +62,61 @@ DOMStorage::~DOMStorage()
 
 /* virtual */ JSObject*
 DOMStorage::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto)
 {
   return StorageBinding::Wrap(aCx, this, aGivenProto);
 }
 
 uint32_t
-DOMStorage::GetLength(const Maybe<nsIPrincipal*>& aSubjectPrincipal,
+DOMStorage::GetLength(nsIPrincipal& aSubjectPrincipal,
                       ErrorResult& aRv)
 {
-  MOZ_ASSERT(aSubjectPrincipal.isSome());
-
-  if (!CanUseStorage(nullptr, aSubjectPrincipal, this)) {
+  if (!CanUseStorage(aSubjectPrincipal)) {
     aRv.Throw(NS_ERROR_DOM_SECURITY_ERR);
     return 0;
   }
 
   uint32_t length;
   aRv = mCache->GetLength(this, &length);
   return length;
 }
 
 void
 DOMStorage::Key(uint32_t aIndex, nsAString& aResult,
-                const Maybe<nsIPrincipal*>& aSubjectPrincipal,
+                nsIPrincipal& aSubjectPrincipal,
                 ErrorResult& aRv)
 {
-  MOZ_ASSERT(aSubjectPrincipal.isSome());
-
-  if (!CanUseStorage(nullptr, aSubjectPrincipal, this)) {
+  if (!CanUseStorage(aSubjectPrincipal)) {
     aRv.Throw(NS_ERROR_DOM_SECURITY_ERR);
     return;
   }
 
   aRv = mCache->GetKey(this, aIndex, aResult);
 }
 
 void
 DOMStorage::GetItem(const nsAString& aKey, nsAString& aResult,
-                    const Maybe<nsIPrincipal*>& aSubjectPrincipal,
+                    nsIPrincipal& aSubjectPrincipal,
                     ErrorResult& aRv)
 {
-  MOZ_ASSERT(aSubjectPrincipal.isSome());
-
-  if (!CanUseStorage(nullptr, aSubjectPrincipal, this)) {
+  if (!CanUseStorage(aSubjectPrincipal)) {
     aRv.Throw(NS_ERROR_DOM_SECURITY_ERR);
     return;
   }
 
   aRv = mCache->GetItem(this, aKey, aResult);
 }
 
 void
 DOMStorage::SetItem(const nsAString& aKey, const nsAString& aData,
-                    const Maybe<nsIPrincipal*>& aSubjectPrincipal,
+                    nsIPrincipal& aSubjectPrincipal,
                     ErrorResult& aRv)
 {
-  MOZ_ASSERT(aSubjectPrincipal.isSome());
-
-  if (!CanUseStorage(nullptr, aSubjectPrincipal, this)) {
+  if (!CanUseStorage(aSubjectPrincipal)) {
     aRv.Throw(NS_ERROR_DOM_SECURITY_ERR);
     return;
   }
 
   nsString data;
   bool ok = data.Assign(aData, fallible);
   if (!ok) {
     aRv.Throw(NS_ERROR_OUT_OF_MEMORY);
@@ -139,44 +131,40 @@ DOMStorage::SetItem(const nsAString& aKe
 
   if (!aRv.ErrorCodeIs(NS_SUCCESS_DOM_NO_OPERATION)) {
     BroadcastChangeNotification(aKey, old, aData);
   }
 }
 
 void
 DOMStorage::RemoveItem(const nsAString& aKey,
-                       const Maybe<nsIPrincipal*>& aSubjectPrincipal,
+                       nsIPrincipal& aSubjectPrincipal,
                        ErrorResult& aRv)
 {
-  MOZ_ASSERT(aSubjectPrincipal.isSome());
-
-  if (!CanUseStorage(nullptr, aSubjectPrincipal, this)) {
+  if (!CanUseStorage(aSubjectPrincipal)) {
     aRv.Throw(NS_ERROR_DOM_SECURITY_ERR);
     return;
   }
 
   nsAutoString old;
   aRv = mCache->RemoveItem(this, aKey, old);
   if (aRv.Failed()) {
     return;
   }
 
   if (!aRv.ErrorCodeIs(NS_SUCCESS_DOM_NO_OPERATION)) {
     BroadcastChangeNotification(aKey, old, NullString());
   }
 }
 
 void
-DOMStorage::Clear(const Maybe<nsIPrincipal*>& aSubjectPrincipal,
+DOMStorage::Clear(nsIPrincipal& aSubjectPrincipal,
                   ErrorResult& aRv)
 {
-  MOZ_ASSERT(aSubjectPrincipal.isSome());
-
-  if (!CanUseStorage(nullptr, aSubjectPrincipal, this)) {
+  if (!CanUseStorage(aSubjectPrincipal)) {
     aRv.Throw(NS_ERROR_DOM_SECURITY_ERR);
     return;
   }
 
   aRv = mCache->Clear(this);
   if (NS_WARN_IF(aRv.Failed())) {
     return;
   }
@@ -240,47 +228,34 @@ DOMStorage::BroadcastChangeNotification(
                                   ? u"localStorage"
                                   : u"sessionStorage");
   NS_DispatchToMainThread(r);
 }
 
 static const char kPermissionType[] = "cookie";
 static const char kStorageEnabled[] = "dom.storage.enabled";
 
-// static, public
 bool
-DOMStorage::CanUseStorage(nsPIDOMWindowInner* aWindow,
-                          const Maybe<nsIPrincipal*>& aSubjectPrincipal,
-                          DOMStorage* aStorage)
+DOMStorage::CanUseStorage(nsIPrincipal& aSubjectPrincipal)
 {
   // This method is responsible for correct setting of mIsSessionOnly.
 
   if (!mozilla::Preferences::GetBool(kStorageEnabled)) {
     return false;
   }
 
-  nsContentUtils::StorageAccess access = nsContentUtils::StorageAccess::eDeny;
-  if (aWindow) {
-    access = nsContentUtils::StorageAllowedForWindow(aWindow);
-  } else if (aStorage) {
-    access = nsContentUtils::StorageAllowedForPrincipal(aStorage->mPrincipal);
-  }
+  nsContentUtils::StorageAccess access =
+    nsContentUtils::StorageAllowedForPrincipal(mPrincipal);
 
   if (access == nsContentUtils::StorageAccess::eDeny) {
     return false;
   }
 
-  if (aStorage) {
-    aStorage->mIsSessionOnly = access <= nsContentUtils::StorageAccess::eSessionScoped;
-
-    MOZ_ASSERT(aSubjectPrincipal.isSome());
-    return aStorage->CanAccess(aSubjectPrincipal.value());
-  }
-
-  return true;
+  mIsSessionOnly = access <= nsContentUtils::StorageAccess::eSessionScoped;
+  return CanAccess(&aSubjectPrincipal);
 }
 
 DOMStorage::StorageType
 DOMStorage::GetType() const
 {
   return mManager->Type();
 }
 
@@ -315,18 +290,17 @@ bool
 DOMStorage::CanAccess(nsIPrincipal* aPrincipal)
 {
   return !aPrincipal || aPrincipal->Subsumes(mPrincipal);
 }
 
 void
 DOMStorage::GetSupportedNames(nsTArray<nsString>& aKeys)
 {
-  if (!CanUseStorage(nullptr, Some(nsContentUtils::SubjectPrincipal()),
-                     this)) {
+  if (!CanUseStorage(*nsContentUtils::SubjectPrincipal())) {
     // return just an empty array
     aKeys.Clear();
     return;
   }
 
   mCache->GetKeys(this, aKeys);
 }
 
--- a/dom/storage/DOMStorage.h
+++ b/dom/storage/DOMStorage.h
@@ -65,84 +65,83 @@ public:
   // WebIDL
   JSObject* WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) override;
 
   nsPIDOMWindowInner* GetParentObject() const
   {
     return mWindow;
   }
 
-  uint32_t GetLength(const Maybe<nsIPrincipal*>& aSubjectPrincipal,
+  uint32_t GetLength(nsIPrincipal& aSubjectPrincipal,
                      ErrorResult& aRv);
 
   void Key(uint32_t aIndex, nsAString& aResult,
-           const Maybe<nsIPrincipal*>& aSubjectPrincipal,
+           nsIPrincipal& aSubjectPrincipal,
            ErrorResult& aRv);
 
   void GetItem(const nsAString& aKey, nsAString& aResult,
-               const Maybe<nsIPrincipal*>& aSubjectPrincipal,
+               nsIPrincipal& aSubjectPrincipal,
                ErrorResult& aRv);
 
   void GetSupportedNames(nsTArray<nsString>& aKeys);
 
   void NamedGetter(const nsAString& aKey, bool& aFound, nsAString& aResult,
-                   const Maybe<nsIPrincipal*>& aSubjectPrincipal,
+                   nsIPrincipal& aSubjectPrincipal,
                    ErrorResult& aRv)
   {
     GetItem(aKey, aResult, aSubjectPrincipal, aRv);
     aFound = !aResult.IsVoid();
   }
 
   void SetItem(const nsAString& aKey, const nsAString& aValue,
-               const Maybe<nsIPrincipal*>& aSubjectPrincipal,
+               nsIPrincipal& aSubjectPrincipal,
                ErrorResult& aRv);
 
   void NamedSetter(const nsAString& aKey, const nsAString& aValue,
-                   const Maybe<nsIPrincipal*>& aSubjectPrincipal,
+                   nsIPrincipal& aSubjectPrincipal,
                    ErrorResult& aRv)
   {
     SetItem(aKey, aValue, aSubjectPrincipal, aRv);
   }
 
   void RemoveItem(const nsAString& aKey,
-                  const Maybe<nsIPrincipal*>& aSubjectPrincipal,
+                  nsIPrincipal& aSubjectPrincipal,
                   ErrorResult& aRv);
 
   void NamedDeleter(const nsAString& aKey, bool& aFound,
-                    const Maybe<nsIPrincipal*>& aSubjectPrincipal,
+                    nsIPrincipal& aSubjectPrincipal,
                     ErrorResult& aRv)
   {
     RemoveItem(aKey, aSubjectPrincipal, aRv);
 
     aFound = !aRv.ErrorCodeIs(NS_SUCCESS_DOM_NO_OPERATION);
   }
 
-  void Clear(const Maybe<nsIPrincipal*>& aSubjectPrincipal,
+  void Clear(nsIPrincipal& aSubjectPrincipal,
              ErrorResult& aRv);
 
-  // The method checks whether the caller can use a storage.
-  // CanUseStorage is called before any DOM initiated operation
-  // on a storage is about to happen and ensures that the storage's
-  // session-only flag is properly set according the current settings.
-  // It is an optimization since the privileges check and session only
-  // state determination are complex and share the code (comes hand in
-  // hand together).
-  static bool CanUseStorage(nsPIDOMWindowInner* aWindow,
-                            const Maybe<nsIPrincipal*>& aSubjectPrincipal,
-                            DOMStorage* aStorage = nullptr);
-
   bool IsPrivate() const;
   bool IsSessionOnly() const { return mIsSessionOnly; }
 
   bool IsForkOf(const DOMStorage* aOther) const
   {
     MOZ_ASSERT(aOther);
     return mCache == aOther->mCache;
   }
 
+protected:
+  // The method checks whether the caller can use a storage.
+  // CanUseStorage is called before any DOM initiated operation
+  // on a storage is about to happen and ensures that the storage's
+  // session-only flag is properly set according the current settings.
+  // It is an optimization since the privileges check and session only
+  // state determination are complex and share the code (comes hand in
+  // hand together).
+  bool CanUseStorage(nsIPrincipal& aSubjectPrincipal);
+
 private:
   ~DOMStorage();
 
   friend class DOMStorageManager;
   friend class DOMStorageCache;
 
   nsCOMPtr<nsPIDOMWindowInner> mWindow;
   RefPtr<DOMStorageManager> mManager;
--- a/dom/webidl/Window.webidl
+++ b/dom/webidl/Window.webidl
@@ -104,17 +104,17 @@ interface WindowSessionStorage {
   //[Throws] readonly attribute Storage sessionStorage;
   [Throws] readonly attribute Storage? sessionStorage;
 };
 Window implements WindowSessionStorage;
 
 // http://www.whatwg.org/specs/web-apps/current-work/
 [NoInterfaceObject]
 interface WindowLocalStorage {
-  [Throws, NeedsSubjectPrincipal] readonly attribute Storage? localStorage;
+  [Throws] readonly attribute Storage? localStorage;
 };
 Window implements WindowLocalStorage;
 
 // http://www.whatwg.org/specs/web-apps/current-work/
 partial interface Window {
   void captureEvents();
   void releaseEvents();
 };
--- a/layout/style/CSSStyleSheet.cpp
+++ b/layout/style/CSSStyleSheet.cpp
@@ -1621,22 +1621,20 @@ void
 CSSStyleSheet::DidDirty()
 {
   MOZ_ASSERT(!mInner->mComplete || mDirty,
              "caller must have called WillDirty()");
   ClearRuleCascades();
 }
 
 void
-CSSStyleSheet::SubjectSubsumesInnerPrincipal(const Maybe<nsIPrincipal*>& aSubjectPrincipal,
+CSSStyleSheet::SubjectSubsumesInnerPrincipal(nsIPrincipal& aSubjectPrincipal,
                                              ErrorResult& aRv)
 {
-  MOZ_ASSERT(aSubjectPrincipal.isSome());
-
-  if (aSubjectPrincipal.value()->Subsumes(mInner->mPrincipal)) {
+  if (aSubjectPrincipal.Subsumes(mInner->mPrincipal)) {
     return;
   }
 
   // Allow access only if CORS mode is not NONE
   if (GetCORSMode() == CORS_NONE) {
     aRv.Throw(NS_ERROR_DOM_SECURITY_ERR);
     return;
   }
@@ -1654,17 +1652,17 @@ CSSStyleSheet::SubjectSubsumesInnerPrinc
   // anyway if not complete, so we can just do that here too.
   if (!mInner->mComplete) {
     aRv.Throw(NS_ERROR_DOM_INVALID_ACCESS_ERR);
     return;
   }
 
   WillDirty();
 
-  mInner->mPrincipal = aSubjectPrincipal.value();
+  mInner->mPrincipal = &aSubjectPrincipal;
 
   DidDirty();
 }
 
 nsresult
 CSSStyleSheet::RegisterNamespaceRule(css::Rule* aRule)
 {
   if (!mInner->mNameSpaceMap) {
@@ -1777,23 +1775,23 @@ CSSStyleSheet::GetDOMOwnerRule() const
   return mOwnerRule ? mOwnerRule->GetDOMRule() : nullptr;
 }
 
 NS_IMETHODIMP    
 CSSStyleSheet::GetCssRules(nsIDOMCSSRuleList** aCssRules)
 {
   ErrorResult rv;
   nsCOMPtr<nsIDOMCSSRuleList> rules =
-    GetCssRules(Some(nsContentUtils::SubjectPrincipal()), rv);
+    GetCssRules(*nsContentUtils::SubjectPrincipal(), rv);
   rules.forget(aCssRules);
   return rv.StealNSResult();
 }
 
 CSSRuleList*
-CSSStyleSheet::GetCssRules(const Maybe<nsIPrincipal*>& aSubjectPrincipal,
+CSSStyleSheet::GetCssRules(nsIPrincipal& aSubjectPrincipal,
                            ErrorResult& aRv)
 {
   // No doing this on incomplete sheets!
   if (!mInner->mComplete) {
     aRv.Throw(NS_ERROR_DOM_INVALID_ACCESS_ERR);
     return nullptr;
   }
   
@@ -1814,23 +1812,23 @@ CSSStyleSheet::GetCssRules(const Maybe<n
 
 NS_IMETHODIMP    
 CSSStyleSheet::InsertRule(const nsAString& aRule,
                           uint32_t aIndex,
                           uint32_t* aReturn)
 {
   ErrorResult rv;
   *aReturn =
-    InsertRule(aRule, aIndex, Some(nsContentUtils::SubjectPrincipal()), rv);
+    InsertRule(aRule, aIndex, *nsContentUtils::SubjectPrincipal(), rv);
   return rv.StealNSResult();
 }
 
 uint32_t
 CSSStyleSheet::InsertRule(const nsAString& aRule, uint32_t aIndex,
-                          const Maybe<nsIPrincipal*>& aSubjectPrincipal,
+                          nsIPrincipal& aSubjectPrincipal,
                           ErrorResult& aRv)
 {
   //-- Security check: Only scripts whose principal subsumes that of the
   //   style sheet can modify rule collections.
   SubjectSubsumesInnerPrincipal(aSubjectPrincipal, aRv);
   if (NS_WARN_IF(aRv.Failed())) {
     return 0;
   }
@@ -1972,23 +1970,23 @@ CSSStyleSheet::InsertRuleInternal(const 
 
   return aIndex;
 }
 
 NS_IMETHODIMP    
 CSSStyleSheet::DeleteRule(uint32_t aIndex)
 {
   ErrorResult rv;
-  DeleteRule(aIndex, Some(nsContentUtils::SubjectPrincipal()), rv);
+  DeleteRule(aIndex, *nsContentUtils::SubjectPrincipal(), rv);
   return rv.StealNSResult();
 }
 
 void
 CSSStyleSheet::DeleteRule(uint32_t aIndex,
-                          const Maybe<nsIPrincipal*>& aSubjectPrincipal,
+                          nsIPrincipal& aSubjectPrincipal,
                           ErrorResult& aRv)
 {
   // No doing this if the sheet is not complete!
   if (!mInner->mComplete) {
     aRv.Throw(NS_ERROR_DOM_INVALID_ACCESS_ERR);
     return;
   }
 
--- a/layout/style/CSSStyleSheet.h
+++ b/layout/style/CSSStyleSheet.h
@@ -241,24 +241,24 @@ public:
   bool Disabled() const { return mDisabled; }
   // The XPCOM SetDisabled is fine for WebIDL
 
   // WebIDL CSSStyleSheet API
   // Can't be inline because we can't include ImportRule here.  And can't be
   // called GetOwnerRule because that would be ambiguous with the ImportRule
   // version.
   nsIDOMCSSRule* GetDOMOwnerRule() const;
-  dom::CSSRuleList* GetCssRules(const Maybe<nsIPrincipal*>& aSubjectPrincipal,
+  dom::CSSRuleList* GetCssRules(nsIPrincipal& aSubjectPrincipal,
                                 ErrorResult& aRv);
   uint32_t InsertRule(const nsAString& aRule, uint32_t aIndex,
-                      const Maybe<nsIPrincipal*>& aSubjectPrincipal,
+                      nsIPrincipal& aSubjectPrincipal,
                       ErrorResult& aRv);
 
   void DeleteRule(uint32_t aIndex,
-                  const Maybe<nsIPrincipal*>& aSubjectPrincipal,
+                  nsIPrincipal& aSubjectPrincipal,
                   ErrorResult& aRv);
 
   // WebIDL miscellaneous bits
   dom::ParentObject GetParentObject() const {
     if (mOwningNode) {
       return dom::ParentObject(mOwningNode);
     }
 
@@ -286,17 +286,17 @@ protected:
   virtual ~CSSStyleSheet();
 
   void ClearRuleCascades();
 
   // Return success if the subject principal subsumes the principal of our
   // inner, error otherwise.  This will also succeed if the subject has
   // UniversalXPConnect or if access is allowed by CORS.  In the latter case,
   // it will set the principal of the inner to the subject principal.
-  void SubjectSubsumesInnerPrincipal(const Maybe<nsIPrincipal*>& aSubjectPrincipal,
+  void SubjectSubsumesInnerPrincipal(nsIPrincipal& aSubjectPrincipal,
                                      ErrorResult& aRv);
 
   // Add the namespace mapping from this @namespace rule to our namespace map
   nsresult RegisterNamespaceRule(css::Rule* aRule);
 
   // Drop our reference to mRuleCollection
   void DropRuleCollection();