Bug 1396449: Part 2 - Use atoms to test WebExtension permissions. r?krizsa draft
authorKris Maglione <maglione.k@gmail.com>
Sun, 03 Sep 2017 18:51:02 -0700
changeset 658392 569a9c310bc72a301b7c37034cec9dede62a1505
parent 658391 4d814343271560be5a5a6f697019b68136735e39
child 729628 7c6ca74ddb9376597f7f53bb812c8a38c754d480
push id77743
push usermaglione.k@gmail.com
push dateMon, 04 Sep 2017 02:46:32 +0000
reviewerskrizsa
bugs1396449
milestone57.0a1
Bug 1396449: Part 2 - Use atoms to test WebExtension permissions. r?krizsa The extension policy services uses atoms internally for permission names, so using them directly rather than strings is considerably cheaper. MozReview-Commit-ID: Io8EuOXHKVy
caps/BasePrincipal.cpp
caps/BasePrincipal.h
caps/ExpandedPrincipal.cpp
caps/ExpandedPrincipal.h
dom/base/nsContentUtils.cpp
dom/base/nsContentUtils.h
dom/base/nsGkAtomList.h
dom/canvas/CanvasRenderingContext2D.cpp
dom/canvas/CanvasUtils.cpp
dom/html/HTMLCanvasElement.cpp
dom/html/HTMLMediaElement.cpp
dom/html/nsHTMLDocument.cpp
toolkit/components/extensions/webrequest/StreamFilter.cpp
--- a/caps/BasePrincipal.cpp
+++ b/caps/BasePrincipal.cpp
@@ -342,17 +342,17 @@ BasePrincipal::AddonPolicy()
 {
   if (Is<ContentPrincipal>()) {
     return As<ContentPrincipal>()->AddonPolicy();
   }
   return nullptr;
 }
 
 bool
-BasePrincipal::AddonHasPermission(const nsAString& aPerm)
+BasePrincipal::AddonHasPermission(const nsIAtom* aPerm)
 {
   auto policy = AddonPolicy();
   if (policy) {
     return policy->HasPermission(aPerm);
   }
   return false;
 }
 
--- a/caps/BasePrincipal.h
+++ b/caps/BasePrincipal.h
@@ -7,16 +7,17 @@
 #ifndef mozilla_BasePrincipal_h
 #define mozilla_BasePrincipal_h
 
 #include "nsJSPrincipals.h"
 
 #include "mozilla/Attributes.h"
 #include "mozilla/OriginAttributes.h"
 
+class nsIAtom;
 class nsIContentSecurityPolicy;
 class nsIObjectOutputStream;
 class nsIObjectInputStream;
 class nsIURI;
 
 class ExpandedPrincipal;
 
 namespace mozilla {
@@ -77,17 +78,17 @@ public:
   NS_IMETHOD GetIsSystemPrincipal(bool* aResult) override;
   NS_IMETHOD GetOriginAttributes(JSContext* aCx, JS::MutableHandle<JS::Value> aVal) final;
   NS_IMETHOD GetOriginSuffix(nsACString& aOriginSuffix) final;
   NS_IMETHOD GetAppId(uint32_t* aAppId) final;
   NS_IMETHOD GetIsInIsolatedMozBrowserElement(bool* aIsInIsolatedMozBrowserElement) final;
   NS_IMETHOD GetUserContextId(uint32_t* aUserContextId) final;
   NS_IMETHOD GetPrivateBrowsingId(uint32_t* aPrivateBrowsingId) final;
 
-  virtual bool AddonHasPermission(const nsAString& aPerm);
+  virtual bool AddonHasPermission(const nsIAtom* aPerm);
 
   virtual bool IsCodebasePrincipal() const { return false; };
 
   static BasePrincipal* Cast(nsIPrincipal* aPrin) { return static_cast<BasePrincipal*>(aPrin); }
 
   static already_AddRefed<BasePrincipal>
   CreateCodebasePrincipal(const nsACString& aOrigin);
 
--- a/caps/ExpandedPrincipal.cpp
+++ b/caps/ExpandedPrincipal.cpp
@@ -167,17 +167,17 @@ ExpandedPrincipal::GetBaseDomain(nsACStr
 NS_IMETHODIMP
 ExpandedPrincipal::GetAddonId(nsAString& aAddonId)
 {
   aAddonId.Truncate();
   return NS_OK;
 };
 
 bool
-ExpandedPrincipal::AddonHasPermission(const nsAString& aPerm)
+ExpandedPrincipal::AddonHasPermission(const nsIAtom* aPerm)
 {
   for (size_t i = 0; i < mPrincipals.Length(); ++i) {
     if (BasePrincipal::Cast(mPrincipals[i])->AddonHasPermission(aPerm)) {
       return true;
     }
   }
   return false;
 }
--- a/caps/ExpandedPrincipal.h
+++ b/caps/ExpandedPrincipal.h
@@ -29,17 +29,17 @@ public:
   NS_IMETHOD_(MozExternalRefCountType) Release() override { return nsJSPrincipals::Release(); };
   NS_IMETHOD QueryInterface(REFNSIID aIID, void** aInstancePtr) override;
   NS_IMETHOD GetHashValue(uint32_t* aHashValue) override;
   NS_IMETHOD GetURI(nsIURI** aURI) override;
   NS_IMETHOD GetDomain(nsIURI** aDomain) override;
   NS_IMETHOD SetDomain(nsIURI* aDomain) override;
   NS_IMETHOD GetBaseDomain(nsACString& aBaseDomain) override;
   NS_IMETHOD GetAddonId(nsAString& aAddonId) override;
-  virtual bool AddonHasPermission(const nsAString& aPerm) override;
+  virtual bool AddonHasPermission(const nsIAtom* aPerm) override;
   virtual nsresult GetScriptLocation(nsACString &aStr) override;
 
 protected:
   explicit ExpandedPrincipal(nsTArray<nsCOMPtr<nsIPrincipal>> &aWhiteList);
 
   virtual ~ExpandedPrincipal();
 
   bool SubsumesInternal(nsIPrincipal* aOther,
--- a/dom/base/nsContentUtils.cpp
+++ b/dom/base/nsContentUtils.cpp
@@ -2326,30 +2326,30 @@ nsContentUtils::CanCallerAccess(nsPIDOMW
   nsCOMPtr<nsIScriptObjectPrincipal> scriptObject = do_QueryInterface(aWindow);
   NS_ENSURE_TRUE(scriptObject, false);
 
   return CanCallerAccess(SubjectPrincipal(), scriptObject->GetPrincipal());
 }
 
 // static
 bool
-nsContentUtils::PrincipalHasPermission(nsIPrincipal* aPrincipal, const nsAString& aPerm)
+nsContentUtils::PrincipalHasPermission(nsIPrincipal* aPrincipal, const nsIAtom* aPerm)
 {
   // Chrome gets access by default.
   if (IsSystemPrincipal(aPrincipal)) {
     return true;
   }
 
   // Otherwise, only allow if caller is an addon with the permission.
   return BasePrincipal::Cast(aPrincipal)->AddonHasPermission(aPerm);
 }
 
 // static
 bool
-nsContentUtils::CallerHasPermission(JSContext* aCx, const nsAString& aPerm)
+nsContentUtils::CallerHasPermission(JSContext* aCx, const nsIAtom* aPerm)
 {
   return PrincipalHasPermission(SubjectPrincipal(aCx), aPerm);
 }
 
 //static
 bool
 nsContentUtils::InProlog(nsINode *aNode)
 {
@@ -7345,17 +7345,17 @@ nsContentUtils::IsRequestFullScreenAllow
 /* static */
 bool
 nsContentUtils::IsCutCopyAllowed(nsIPrincipal* aSubjectPrincipal)
 {
   if (!IsCutCopyRestricted() && EventStateManager::IsHandlingUserInput()) {
     return true;
   }
 
-  return PrincipalHasPermission(aSubjectPrincipal, NS_LITERAL_STRING("clipboardWrite"));
+  return PrincipalHasPermission(aSubjectPrincipal, nsGkAtoms::clipboardWrite);
 }
 
 /* static */
 bool
 nsContentUtils::IsFrameTimingEnabled()
 {
   return sIsFrameTimingPrefEnabled;
 }
--- a/dom/base/nsContentUtils.h
+++ b/dom/base/nsContentUtils.h
@@ -52,16 +52,17 @@ class imgICache;
 class imgIContainer;
 class imgINotificationObserver;
 class imgIRequest;
 class imgLoader;
 class imgRequestProxy;
 class nsAutoScriptBlockerSuppressNodeRemoved;
 class nsCacheableFuncStringHTMLCollection;
 class nsHtml5StringParser;
+class nsIAtom;
 class nsIChannel;
 class nsIConsoleService;
 class nsIContent;
 class nsIContentPolicy;
 class nsIContentSecurityPolicy;
 class nsIDocShellTreeItem;
 class nsIDocumentLoaderFactory;
 class nsIDOMDocument;
@@ -585,20 +586,20 @@ public:
   static bool CanCallerAccess(nsIDOMNode *aNode);
   static bool CanCallerAccess(nsINode* aNode);
 
   // Check if the (JS) caller can access aWindow.
   // aWindow can be either outer or inner window.
   static bool CanCallerAccess(nsPIDOMWindowInner* aWindow);
 
   // Check if the principal is chrome or an addon with the permission.
-  static bool PrincipalHasPermission(nsIPrincipal* aPrincipal, const nsAString& aPerm);
+  static bool PrincipalHasPermission(nsIPrincipal* aPrincipal, const nsIAtom* aPerm);
 
   // Check if the JS caller is chrome or an addon with the permission.
-  static bool CallerHasPermission(JSContext* aCx, const nsAString& aPerm);
+  static bool CallerHasPermission(JSContext* aCx, const nsIAtom* aPerm);
 
   /**
    * GetDocumentFromCaller gets its document by looking at the last called
    * function and finding the document that the function itself relates to.
    * For example, consider two windows A and B in the same origin. B has a
    * function which does something that ends up needing the current document.
    * If a script in window A were to call B's function, GetDocumentFromCaller
    * would find that function (in B) and return B's document.
--- a/dom/base/nsGkAtomList.h
+++ b/dom/base/nsGkAtomList.h
@@ -2064,16 +2064,21 @@ GK_ATOM(ondevicelight, "ondevicelight")
 GK_ATOM(ondevicechange, "ondevicechange")
 
 // HTML element attributes that only exposed to XBL and chrome content
 GK_ATOM(mozinputrangeignorepreventdefault, "mozinputrangeignorepreventdefault")
 
 // WebExtensions
 GK_ATOM(moz_extension, "moz-extension")
 GK_ATOM(all_urlsPermission, "<all_urls>")
+GK_ATOM(clipboardRead, "clipboardRead")
+GK_ATOM(clipboardWrite, "clipboardWrite")
+GK_ATOM(debugger, "debugger")
+GK_ATOM(tabs, "tabs")
+GK_ATOM(webRequestBlocking, "webRequestBlocking")
 GK_ATOM(http, "http")
 GK_ATOM(https, "https")
 
 //---------------------------------------------------------------------------
 // Special atoms
 //---------------------------------------------------------------------------
 
 // Node types
--- a/dom/canvas/CanvasRenderingContext2D.cpp
+++ b/dom/canvas/CanvasRenderingContext2D.cpp
@@ -5682,17 +5682,17 @@ CanvasRenderingContext2D::GetImageData(J
 
   // Check only if we have a canvas element; if we were created with a docshell,
   // then it's special internal use.
   if (mCanvasElement && mCanvasElement->IsWriteOnly() &&
       // We could ask bindings for the caller type, but they already hand us a
       // JSContext, and we're at least _somewhat_ perf-sensitive (so may not
       // want to compute the caller type in the common non-write-only case), so
       // let's just use what we have.
-      !nsContentUtils::CallerHasPermission(aCx, NS_LITERAL_STRING("<all_urls>")))
+      !nsContentUtils::CallerHasPermission(aCx, nsGkAtoms::all_urlsPermission))
   {
     // XXX ERRMSG we need to report an error to developers here! (bug 329026)
     aError.Throw(NS_ERROR_DOM_SECURITY_ERR);
     return nullptr;
   }
 
   if (!IsFinite(aSx) || !IsFinite(aSy) ||
       !IsFinite(aSw) || !IsFinite(aSh)) {
--- a/dom/canvas/CanvasUtils.cpp
+++ b/dom/canvas/CanvasUtils.cpp
@@ -113,13 +113,13 @@ CoerceDouble(const JS::Value& v, double*
         return false;
     }
     return true;
 }
 
 bool
 HasDrawWindowPrivilege(JSContext* aCx, JSObject* /* unused */)
 {
-  return nsContentUtils::CallerHasPermission(aCx, NS_LITERAL_STRING("<all_urls>"));
+  return nsContentUtils::CallerHasPermission(aCx, nsGkAtoms::all_urlsPermission);
 }
 
 } // namespace CanvasUtils
 } // namespace mozilla
--- a/dom/html/HTMLCanvasElement.cpp
+++ b/dom/html/HTMLCanvasElement.cpp
@@ -650,17 +650,17 @@ HTMLCanvasElement::ParseAttribute(int32_
 void
 HTMLCanvasElement::ToDataURL(JSContext* aCx, const nsAString& aType,
                              JS::Handle<JS::Value> aParams,
                              nsAString& aDataURL,
                              ErrorResult& aRv)
 {
   // do a trust check if this is a write-only canvas
   if (mWriteOnly &&
-      !nsContentUtils::CallerHasPermission(aCx, NS_LITERAL_STRING("<all_urls>"))) {
+      !nsContentUtils::CallerHasPermission(aCx, nsGkAtoms::all_urlsPermission)) {
     aRv.Throw(NS_ERROR_DOM_SECURITY_ERR);
     return;
   }
 
   aRv = ToDataURLImpl(aCx, aType, aParams, aDataURL);
 }
 
 void
@@ -833,17 +833,17 @@ void
 HTMLCanvasElement::ToBlob(JSContext* aCx,
                           BlobCallback& aCallback,
                           const nsAString& aType,
                           JS::Handle<JS::Value> aParams,
                           ErrorResult& aRv)
 {
   // do a trust check if this is a write-only canvas
   if (mWriteOnly &&
-      !nsContentUtils::CallerHasPermission(aCx, NS_LITERAL_STRING("<all_urls>"))) {
+      !nsContentUtils::CallerHasPermission(aCx, nsGkAtoms::all_urlsPermission)) {
     aRv.Throw(NS_ERROR_DOM_SECURITY_ERR);
     return;
   }
 
   nsCOMPtr<nsIGlobalObject> global = OwnerDoc()->GetScopeObject();
   MOZ_ASSERT(global);
 
   nsIntSize elemSize = GetWidthHeight();
--- a/dom/html/HTMLMediaElement.cpp
+++ b/dom/html/HTMLMediaElement.cpp
@@ -7568,19 +7568,18 @@ HTMLMediaElement::MarkAsTainted()
   if (mDecoder) {
     mDecoder->SetSuspendTaint(true);
   }
 }
 
 bool
 HasDebuggerOrTabsPrivilege(JSContext* aCx, JSObject* aObj)
 {
-  return nsContentUtils::CallerHasPermission(aCx,
-                                             NS_LITERAL_STRING("debugger")) ||
-         nsContentUtils::CallerHasPermission(aCx, NS_LITERAL_STRING("tabs"));
+  return nsContentUtils::CallerHasPermission(aCx, nsGkAtoms::debugger) ||
+         nsContentUtils::CallerHasPermission(aCx, nsGkAtoms::tabs);
  }
 
 void
 HTMLMediaElement::AsyncResolveSeekDOMPromiseIfExists()
 {
   MOZ_ASSERT(NS_IsMainThread());
   if (mSeekDOMPromise) {
     RefPtr<dom::Promise> promise = mSeekDOMPromise.forget();
--- a/dom/html/nsHTMLDocument.cpp
+++ b/dom/html/nsHTMLDocument.cpp
@@ -3285,17 +3285,17 @@ nsHTMLDocument::ExecCommand(const nsAStr
 
   if (commandID.LowerCaseEqualsLiteral("gethtml")) {
     rv.Throw(NS_ERROR_FAILURE);
     return false;
   }
 
   bool restricted = commandID.LowerCaseEqualsLiteral("paste");
   if (restricted && !nsContentUtils::PrincipalHasPermission(&aSubjectPrincipal,
-                                                            NS_LITERAL_STRING("clipboardRead"))) {
+                                                            nsGkAtoms::clipboardRead)) {
     return false;
   }
 
   // get command manager and dispatch command to our window if it's acceptable
   nsCOMPtr<nsICommandManager> cmdMgr;
   GetMidasCommandManager(getter_AddRefs(cmdMgr));
   if (!cmdMgr) {
     rv.Throw(NS_ERROR_FAILURE);
--- a/toolkit/components/extensions/webrequest/StreamFilter.cpp
+++ b/toolkit/components/extensions/webrequest/StreamFilter.cpp
@@ -256,17 +256,17 @@ StreamFilter::FireErrorEvent(const nsASt
 
 /*****************************************************************************
  * Glue
  *****************************************************************************/
 
 /* static */ bool
 StreamFilter::IsAllowedInContext(JSContext* aCx, JSObject* /* unused */)
 {
-  return nsContentUtils::CallerHasPermission(aCx, NS_LITERAL_STRING("webRequestBlocking"));
+  return nsContentUtils::CallerHasPermission(aCx, nsGkAtoms::webRequestBlocking);
 }
 
 JSObject*
 StreamFilter::WrapObject(JSContext* aCx, HandleObject aGivenProto)
 {
   return StreamFilterBinding::Wrap(aCx, this, aGivenProto);
 }