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
--- 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);
}