--- a/dom/base/nsFrameLoader.cpp
+++ b/dom/base/nsFrameLoader.cpp
@@ -53,16 +53,17 @@
#include "nsGlobalWindow.h"
#include "nsPIWindowRoot.h"
#include "nsLayoutUtils.h"
#include "nsMappedAttributes.h"
#include "nsView.h"
#include "nsBaseWidget.h"
#include "GroupedSHistory.h"
#include "PartialSHistory.h"
+#include "nsQueryObject.h"
#include "nsIURI.h"
#include "nsIURL.h"
#include "nsNetUtil.h"
#include "nsGkAtoms.h"
#include "nsNameSpaceManager.h"
@@ -81,16 +82,17 @@
#include "mozilla/GuardObjects.h"
#include "mozilla/HTMLEditor.h"
#include "mozilla/Preferences.h"
#include "mozilla/Unused.h"
#include "mozilla/dom/Element.h"
#include "mozilla/dom/FrameLoaderBinding.h"
#include "mozilla/jsipc/CrossProcessObjectWrappers.h"
#include "mozilla/layout/RenderFrameParent.h"
+#include "nsGenericHTMLFrameElement.h"
#include "GeckoProfiler.h"
#include "jsapi.h"
#include "mozilla/dom/HTMLIFrameElement.h"
#include "nsSandboxFlags.h"
#include "mozilla/layers/CompositorBridgeChild.h"
#include "mozilla/dom/CustomEvent.h"
@@ -242,24 +244,25 @@ nsFrameLoader::LoadFrame(ErrorResult& aR
}
NS_IMETHODIMP
nsFrameLoader::LoadFrame()
{
NS_ENSURE_TRUE(mOwnerContent, NS_ERROR_NOT_INITIALIZED);
nsAutoString src;
+ nsCOMPtr<nsIPrincipal> principal;
bool isSrcdoc = mOwnerContent->IsHTMLElement(nsGkAtoms::iframe) &&
mOwnerContent->HasAttr(kNameSpaceID_None, nsGkAtoms::srcdoc);
if (isSrcdoc) {
src.AssignLiteral("about:srcdoc");
}
else {
- GetURL(src);
+ GetURL(src, getter_AddRefs(principal));
src.Trim(" \t\n\r");
if (src.IsEmpty()) {
// If the frame is a XUL element and has the attribute 'nodefaultsrc=true'
// then we will not use 'about:blank' as fallback but return early without
// starting a load if no 'src' attribute is given (or it's empty).
if (mOwnerContent->IsXULElement() &&
@@ -289,17 +292,17 @@ nsFrameLoader::LoadFrame()
// If the URI was malformed, try to recover by loading about:blank.
if (rv == NS_ERROR_MALFORMED_URI) {
rv = NS_NewURI(getter_AddRefs(uri), NS_LITERAL_STRING("about:blank"),
encoding, base_uri);
}
if (NS_SUCCEEDED(rv)) {
- rv = LoadURI(uri);
+ rv = LoadURI(uri, principal);
}
if (NS_FAILED(rv)) {
FireErrorEvent();
return rv;
}
@@ -326,36 +329,44 @@ nsFrameLoader::LoadURI(nsIURI* aURI, Err
if (NS_FAILED(rv)) {
aRv.Throw(rv);
}
}
NS_IMETHODIMP
nsFrameLoader::LoadURI(nsIURI* aURI)
{
+ return LoadURI(aURI, nullptr);
+}
+
+nsresult
+nsFrameLoader::LoadURI(nsIURI* aURI, nsIPrincipal* aTriggeringPrincipal)
+{
if (!aURI)
return NS_ERROR_INVALID_POINTER;
NS_ENSURE_STATE(!mDestroyCalled && mOwnerContent);
nsCOMPtr<nsIDocument> doc = mOwnerContent->OwnerDoc();
nsresult rv;
// If IsForJSPlugin() returns true then we want to allow the load. We're just
// loading the source for the implementation of the JS plugin from a URI
// that's under our control. We will already have done the security checks for
// loading the plugin content itself in the object/embed loading code.
if (!IsForJSPlugin()) {
- rv = CheckURILoad(aURI);
+ rv = CheckURILoad(aURI, aTriggeringPrincipal);
NS_ENSURE_SUCCESS(rv, rv);
}
mURIToLoad = aURI;
+ mTriggeringPrincipal = aTriggeringPrincipal;
rv = doc->InitializeFrameLoader(this);
if (NS_FAILED(rv)) {
mURIToLoad = nullptr;
+ mTriggeringPrincipal = nullptr;
}
return rv;
}
void
nsFrameLoader::SetIsPrerendered(ErrorResult& aRv)
{
nsresult rv = SetIsPrerendered();
@@ -900,31 +911,35 @@ nsFrameLoader::ReallyStartLoadingInterna
nsresult rv = MaybeCreateDocShell();
if (NS_FAILED(rv)) {
return rv;
}
NS_ASSERTION(mDocShell,
"MaybeCreateDocShell succeeded with a null mDocShell");
// Just to be safe, recheck uri.
- rv = CheckURILoad(mURIToLoad);
+ rv = CheckURILoad(mURIToLoad, mTriggeringPrincipal);
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsIDocShellLoadInfo> loadInfo;
mDocShell->CreateLoadInfo(getter_AddRefs(loadInfo));
NS_ENSURE_TRUE(loadInfo, NS_ERROR_FAILURE);
// If this frame is sandboxed with respect to origin we will set it up with
// a null principal later in nsDocShell::DoURILoad.
// We do it there to correctly sandbox content that was loaded into
// the frame via other methods than the src attribute.
// We'll use our principal, not that of the document loaded inside us. This
// is very important; needed to prevent XSS attacks on documents loaded in
// subframes!
- loadInfo->SetTriggeringPrincipal(mOwnerContent->NodePrincipal());
+ if (mTriggeringPrincipal) {
+ loadInfo->SetTriggeringPrincipal(mTriggeringPrincipal);
+ } else {
+ loadInfo->SetTriggeringPrincipal(mOwnerContent->NodePrincipal());
+ }
nsCOMPtr<nsIURI> referrer;
nsAutoString srcdoc;
bool isSrcdoc = mOwnerContent->IsHTMLElement(nsGkAtoms::iframe) &&
mOwnerContent->GetAttr(kNameSpaceID_None, nsGkAtoms::srcdoc,
srcdoc);
@@ -985,17 +1000,17 @@ nsFrameLoader::ReallyStartLoadingInterna
mNeedsAsyncDestroy = tmpState;
mURIToLoad = nullptr;
NS_ENSURE_SUCCESS(rv, rv);
return NS_OK;
}
nsresult
-nsFrameLoader::CheckURILoad(nsIURI* aURI)
+nsFrameLoader::CheckURILoad(nsIURI* aURI, nsIPrincipal* aPrincipal)
{
// Check for security. The fun part is trying to figure out what principals
// to use. The way I figure it, if we're doing a LoadFrame() accidentally
// (eg someone created a frame/iframe node, we're being parsed, XUL iframes
// are being reframed, etc.) then we definitely want to use the node
// principal of mOwnerContent for security checks. If, on the other hand,
// someone's setting the src on our owner content, or created it via script,
// or whatever, then they can clearly access it... and we should still use
@@ -1004,17 +1019,18 @@ nsFrameLoader::CheckURILoad(nsIURI* aURI
// (since caller can already access mOwnerContent in this case). So just use
// the principal of mOwnerContent no matter what. If script wants to run
// things with its own permissions, which differ from those of mOwnerContent
// (which means the script is privileged in some way) it should set
// window.location instead.
nsIScriptSecurityManager *secMan = nsContentUtils::GetSecurityManager();
// Get our principal
- nsIPrincipal* principal = mOwnerContent->NodePrincipal();
+ nsIPrincipal* principal = aPrincipal ? aPrincipal
+ : mOwnerContent->NodePrincipal();
// Check if we are allowed to load absURL
nsresult rv =
secMan->CheckLoadURIWithPrincipal(principal, aURI,
nsIScriptSecurityManager::STANDARD);
if (NS_FAILED(rv)) {
return rv; // We're not
}
@@ -2728,24 +2744,28 @@ nsFrameLoader::MaybeCreateDocShell()
os->NotifyObservers(NS_ISUPPORTS_CAST(nsIFrameLoader*, this),
"inprocess-browser-shown", nullptr);
}
return NS_OK;
}
void
-nsFrameLoader::GetURL(nsString& aURI)
+nsFrameLoader::GetURL(nsString& aURI, nsIPrincipal** aPrincipal)
{
aURI.Truncate();
if (mOwnerContent->IsHTMLElement(nsGkAtoms::object)) {
mOwnerContent->GetAttr(kNameSpaceID_None, nsGkAtoms::data, aURI);
} else {
mOwnerContent->GetAttr(kNameSpaceID_None, nsGkAtoms::src, aURI);
+ if (RefPtr<nsGenericHTMLFrameElement> frame = do_QueryObject(mOwnerContent)) {
+ nsCOMPtr<nsIPrincipal> prin = frame->GetSrcTriggeringPrincipal();
+ prin.forget(aPrincipal);
+ }
}
}
nsresult
nsFrameLoader::CheckForRecursiveLoad(nsIURI* aURI)
{
nsresult rv;
--- a/dom/base/nsFrameLoader.h
+++ b/dom/base/nsFrameLoader.h
@@ -108,16 +108,18 @@ public:
already_AddRefed<nsITabParent> GetTabParent();
already_AddRefed<nsILoadContext> LoadContext();
void LoadFrame(mozilla::ErrorResult& aRv);
void LoadURI(nsIURI* aURI, mozilla::ErrorResult& aRv);
+ nsresult LoadURI(nsIURI* aURI, nsIPrincipal* aPrincipal);
+
void SetIsPrerendered(mozilla::ErrorResult& aRv);
void MakePrerenderedLoaderActive(mozilla::ErrorResult& aRv);
already_AddRefed<mozilla::dom::Promise>
AppendPartialSHistoryAndSwap(nsIFrameLoader& aOther, mozilla::ErrorResult& aRv);
already_AddRefed<mozilla::dom::Promise>
@@ -319,17 +321,17 @@ public:
/**
* Applies a new set of sandbox flags. These are merged with the sandbox
* flags from our owning content's owning document with a logical OR, this
* ensures that we can only add restrictions and never remove them.
*/
void ApplySandboxFlags(uint32_t sandboxFlags);
- void GetURL(nsString& aURL);
+ void GetURL(nsString& aURL, nsIPrincipal** aPrincipal);
// Properly retrieves documentSize of any subdocument type.
nsresult GetWindowDimensions(nsIntRect& aRect);
virtual nsIMessageSender* GetProcessMessageManager() const override;
// public because a callback needs these.
RefPtr<nsFrameMessageManager> mMessageManager;
@@ -379,17 +381,17 @@ private:
*/
nsresult MaybeCreateDocShell();
nsresult EnsureMessageManager();
nsresult ReallyLoadFrameScripts();
// Updates the subdocument position and size. This gets called only
// when we have our own in-process DocShell.
void UpdateBaseWindowPositionAndSize(nsSubDocumentFrame *aIFrame);
- nsresult CheckURILoad(nsIURI* aURI);
+ nsresult CheckURILoad(nsIURI* aURI, nsIPrincipal* aPrincipal);
void FireErrorEvent();
nsresult ReallyStartLoadingInternal();
// Return true if remote browser created; nothing else to do
bool TryRemoteBrowser();
// Tell the remote browser that it's now "virtually visible"
bool ShowRemoteFrame(const mozilla::ScreenIntSize& size,
@@ -425,16 +427,17 @@ private:
bool SwapBrowsersAndNotify(nsFrameLoader* aOther);
// Returns a promise which will be resolved once all of the blockers have
// resolved which were added during the BrowserWillChangeProcess event.
already_AddRefed<mozilla::dom::Promise> FireWillChangeProcessEvent();
nsCOMPtr<nsIDocShell> mDocShell;
nsCOMPtr<nsIURI> mURIToLoad;
+ nsCOMPtr<nsIPrincipal> mTriggeringPrincipal;
mozilla::dom::Element* mOwnerContent; // WEAK
// After the frameloader has been removed from the DOM but before all of the
// messages from the frame have been received, we keep a strong reference to
// our <browser> element.
RefPtr<mozilla::dom::Element> mOwnerContentStrong;
// Stores the root frame of the subdocument while the subdocument is being
--- a/dom/html/HTMLFrameElement.h
+++ b/dom/html/HTMLFrameElement.h
@@ -94,23 +94,23 @@ public:
{
GetHTMLAttr(nsGkAtoms::scrolling, aScrolling);
}
void SetScrolling(const nsAString& aScrolling, ErrorResult& aError)
{
SetHTMLAttr(nsGkAtoms::scrolling, aScrolling, aError);
}
- void GetSrc(nsAString& aSrc) const
+ void GetSrc(nsString& aSrc, nsIPrincipal&)
{
GetURIAttr(nsGkAtoms::src, nullptr, aSrc);
}
- void SetSrc(const nsAString& aSrc, ErrorResult& aError)
+ void SetSrc(const nsAString& aSrc, nsIPrincipal& aPrincipal, ErrorResult& aError)
{
- SetAttrHelper(nsGkAtoms::src, aSrc);
+ SetHTMLAttr(nsGkAtoms::src, aSrc, aPrincipal, aError);
}
using nsGenericHTMLFrameElement::GetContentDocument;
using nsGenericHTMLFrameElement::GetContentWindow;
protected:
virtual ~HTMLFrameElement();
--- a/dom/html/HTMLIFrameElement.h
+++ b/dom/html/HTMLIFrameElement.h
@@ -45,20 +45,23 @@ public:
virtual nsMapRuleToAttributesFunc GetAttributeMappingFunction() const override;
virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult,
bool aPreallocateChildren) const override;
uint32_t GetSandboxFlags();
// Web IDL binding methods
- // The XPCOM GetSrc is fine for our purposes
- void SetSrc(const nsAString& aSrc, ErrorResult& aError)
+ void GetSrc(nsString& aSrc, nsIPrincipal&)
{
- SetHTMLAttr(nsGkAtoms::src, aSrc, aError);
+ GetSrc(aSrc);
+ }
+ void SetSrc(const nsAString& aSrc, nsIPrincipal& aPrincipal, ErrorResult& aError)
+ {
+ SetHTMLAttr(nsGkAtoms::src, aSrc, aPrincipal, aError);
}
void GetSrcdoc(DOMString& aSrcdoc)
{
GetHTMLAttr(nsGkAtoms::srcdoc, aSrcdoc);
}
void SetSrcdoc(const nsAString& aSrcdoc, ErrorResult& aError)
{
SetHTMLAttr(nsGkAtoms::srcdoc, aSrcdoc, aError);
--- a/dom/html/nsGenericHTMLFrameElement.cpp
+++ b/dom/html/nsGenericHTMLFrameElement.cpp
@@ -48,17 +48,18 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_IN
NS_IMPL_CYCLE_COLLECTION_UNLINK(mOpenerWindow)
NS_IMPL_CYCLE_COLLECTION_UNLINK(mBrowserElementAPI)
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
NS_IMPL_ISUPPORTS_CYCLE_COLLECTION_INHERITED(nsGenericHTMLFrameElement,
nsGenericHTMLElement,
nsIFrameLoaderOwner,
nsIDOMMozBrowserFrame,
- nsIMozBrowserFrame)
+ nsIMozBrowserFrame,
+ nsGenericHTMLFrameElement)
NS_IMPL_BOOL_ATTR(nsGenericHTMLFrameElement, Mozbrowser, mozbrowser)
int32_t
nsGenericHTMLFrameElement::TabIndexDefault()
{
return 0;
}
@@ -332,19 +333,19 @@ PrincipalAllowsBrowserFrame(nsIPrincipal
nsGenericHTMLFrameElement::AfterSetAttr(int32_t aNameSpaceID, nsIAtom* aName,
const nsAttrValue* aValue,
const nsAttrValue* aOldValue,
nsIPrincipal* aSubjectPrincipal,
bool aNotify)
{
if (aValue) {
nsAttrValueOrString value(aValue);
- AfterMaybeChangeAttr(aNameSpaceID, aName, &value, aNotify);
+ AfterMaybeChangeAttr(aNameSpaceID, aName, &value, aSubjectPrincipal, aNotify);
} else {
- AfterMaybeChangeAttr(aNameSpaceID, aName, nullptr, aNotify);
+ AfterMaybeChangeAttr(aNameSpaceID, aName, nullptr, aSubjectPrincipal, aNotify);
}
if (aNameSpaceID == kNameSpaceID_None) {
if (aName == nsGkAtoms::scrolling) {
if (mFrameLoader) {
nsIDocShell* docshell = mFrameLoader->GetExistingDocShell();
nsCOMPtr<nsIScrollable> scrollable = do_QueryInterface(docshell);
if (scrollable) {
@@ -376,30 +377,33 @@ nsGenericHTMLFrameElement::AfterSetAttr(
}
nsresult
nsGenericHTMLFrameElement::OnAttrSetButNotChanged(int32_t aNamespaceID,
nsIAtom* aName,
const nsAttrValueOrString& aValue,
bool aNotify)
{
- AfterMaybeChangeAttr(aNamespaceID, aName, &aValue, aNotify);
+ AfterMaybeChangeAttr(aNamespaceID, aName, &aValue, nullptr, aNotify);
return nsGenericHTMLElement::OnAttrSetButNotChanged(aNamespaceID, aName,
aValue, aNotify);
}
void
nsGenericHTMLFrameElement::AfterMaybeChangeAttr(int32_t aNamespaceID,
nsIAtom* aName,
const nsAttrValueOrString* aValue,
+ nsIPrincipal* aSubjectPrincipal,
bool aNotify)
{
if (aNamespaceID == kNameSpaceID_None) {
if (aName == nsGkAtoms::src) {
+ mSrcTriggeringPrincipal = nsContentUtils::GetAttrTriggeringPrincipal(
+ this, aValue ? aValue->String() : EmptyString(), aSubjectPrincipal);
if (aValue && (!IsHTMLElement(nsGkAtoms::iframe) ||
!HasAttr(kNameSpaceID_None, nsGkAtoms::srcdoc))) {
// Don't propagate error here. The attribute was successfully set,
// that's what we should reflect.
LoadSrc();
}
} else if (aName == nsGkAtoms::name) {
// Propagate "name" to the docshell to make browsing context names live,
--- a/dom/html/nsGenericHTMLFrameElement.h
+++ b/dom/html/nsGenericHTMLFrameElement.h
@@ -14,16 +14,20 @@
#include "nsFrameLoader.h"
#include "nsGenericHTMLElement.h"
#include "nsIDOMEventListener.h"
#include "nsIFrameLoader.h"
#include "nsIMozBrowserFrame.h"
class nsXULElement;
+#define NS_GENERICHTMLFRAMEELEMENT_IID \
+{ 0x8190db72, 0xdab0, 0x4d72, \
+ { 0x94, 0x26, 0x87, 0x5f, 0x5a, 0x8a, 0x2a, 0xe5 } }
+
/**
* A helper class for frame elements
*/
class nsGenericHTMLFrameElement : public nsGenericHTMLElement,
public nsIFrameLoaderOwner,
public mozilla::nsBrowserElement,
public nsIMozBrowserFrame
{
@@ -41,16 +45,18 @@ public:
}
NS_DECL_ISUPPORTS_INHERITED
NS_DECL_NSIFRAMELOADEROWNER
NS_DECL_NSIDOMMOZBROWSERFRAME
NS_DECL_NSIMOZBROWSERFRAME
+ NS_DECLARE_STATIC_IID_ACCESSOR(NS_GENERICHTMLFRAMEELEMENT_IID)
+
// nsIContent
virtual bool IsHTMLFocusable(bool aWithMouse, bool *aIsFocusable, int32_t *aTabIndex) override;
virtual nsresult BindToTree(nsIDocument* aDocument, nsIContent* aParent,
nsIContent* aBindingParent,
bool aCompileEventHandlers) override;
virtual void UnbindFromTree(bool aDeep = true,
bool aNullParent = true) override;
virtual void DestroyContent() override;
@@ -84,16 +90,21 @@ public:
* enum value. scrolling="no" (and its synonyms) maps to
* nsIScrollable::Scrollbar_Never, and anything else (including nullptr) maps
* to nsIScrollable::Scrollbar_Auto.
* @param aValue the attribute value to map or nullptr
* @return nsIScrollable::Scrollbar_Never or nsIScrollable::Scrollbar_Auto
*/
static int32_t MapScrollingAttribute(const nsAttrValue* aValue);
+ nsIPrincipal* GetSrcTriggeringPrincipal() const
+ {
+ return mSrcTriggeringPrincipal;
+ }
+
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(nsIPrincipal& aSubjectPrincipal);
@@ -107,16 +118,18 @@ protected:
bool aNotify) override;
virtual nsresult OnAttrSetButNotChanged(int32_t aNamespaceID, nsIAtom* aName,
const nsAttrValueOrString& aValue,
bool aNotify) override;
RefPtr<nsFrameLoader> mFrameLoader;
nsCOMPtr<nsPIDOMWindowOuter> mOpenerWindow;
+ nsCOMPtr<nsIPrincipal> mSrcTriggeringPrincipal;
+
/**
* True when the element is created by the parser using the
* NS_FROM_PARSER_NETWORK flag.
* If the element is modified, it may lose the flag.
*/
bool mNetworkCreated;
bool mIsPrerendered;
@@ -137,12 +150,17 @@ private:
* It will be called whether the value is being set or unset.
*
* @param aNamespaceID the namespace of the attr being set
* @param aName the localname of the attribute being set
* @param aValue the value being set or null if the value is being unset
* @param aNotify Whether we plan to notify document observers.
*/
void AfterMaybeChangeAttr(int32_t aNamespaceID, nsIAtom* aName,
- const nsAttrValueOrString* aValue, bool aNotify);
+ const nsAttrValueOrString* aValue,
+ nsIPrincipal* aSubjectPrincipal,
+ bool aNotify);
};
+NS_DEFINE_STATIC_IID_ACCESSOR(nsGenericHTMLFrameElement,
+ NS_GENERICHTMLFRAMEELEMENT_IID)
+
#endif // nsGenericHTMLFrameElement_h
--- a/dom/webidl/HTMLFrameElement.webidl
+++ b/dom/webidl/HTMLFrameElement.webidl
@@ -12,17 +12,17 @@
// http://www.whatwg.org/specs/web-apps/current-work/#htmlframeelement
[HTMLConstructor]
interface HTMLFrameElement : HTMLElement {
[CEReactions, SetterThrows]
attribute DOMString name;
[CEReactions, SetterThrows]
attribute DOMString scrolling;
- [CEReactions, SetterThrows]
+ [CEReactions, NeedsSubjectPrincipal, SetterThrows]
attribute DOMString src;
[CEReactions, SetterThrows]
attribute DOMString frameBorder;
[CEReactions, SetterThrows]
attribute DOMString longDesc;
[CEReactions, SetterThrows]
attribute boolean noResize;
[NeedsSubjectPrincipal]
--- a/dom/webidl/HTMLIFrameElement.webidl
+++ b/dom/webidl/HTMLIFrameElement.webidl
@@ -8,17 +8,17 @@
* http://www.whatwg.org/specs/web-apps/current-work/#other-elements,-attributes-and-apis
* © Copyright 2004-2011 Apple Computer, Inc., Mozilla Foundation, and
* Opera Software ASA. You are granted a license to use, reproduce
* and create derivative works of this document.
*/
[HTMLConstructor]
interface HTMLIFrameElement : HTMLElement {
- [CEReactions, SetterThrows, Pure]
+ [CEReactions, NeedsSubjectPrincipal, SetterThrows, Pure]
attribute DOMString src;
[CEReactions, SetterThrows, Pure]
attribute DOMString srcdoc;
[CEReactions, SetterThrows, Pure]
attribute DOMString name;
[PutForwards=value] readonly attribute DOMTokenList sandbox;
// attribute boolean seamless;
[CEReactions, SetterThrows, Pure]
--- a/toolkit/components/extensions/test/mochitest/test_ext_web_accessible_resources.html
+++ b/toolkit/components/extensions/test/mochitest/test_ext_web_accessible_resources.html
@@ -107,17 +107,19 @@ add_task(async function test_web_accessi
browser.test.sendMessage("ready");
}
function contentScript() {
browser.runtime.onMessage.addListener(([msg, url], sender, respond) => {
if (msg == "load-iframe") {
let iframe = document.createElement("iframe");
- iframe.setAttribute("src", url);
+ // Set the src via wrappedJSObject so the load is triggered with the
+ // content page's principal rather than ours.
+ iframe.wrappedJSObject.setAttribute("src", url);
iframe.addEventListener("load", () => { respond(true); });
iframe.addEventListener("error", () => { respond(false); });
document.body.appendChild(iframe);
return true;
}
});
browser.runtime.sendMessage(["content-script-ready"]);
}
--- a/toolkit/components/extensions/test/xpcshell/test_ext_contentscript_triggeringPrincipal.js
+++ b/toolkit/components/extensions/test/xpcshell/test_ext_contentscript_triggeringPrincipal.js
@@ -421,16 +421,21 @@ function awaitLoads(tests, sources, orig
}
add_task(async function test_contentscript_triggeringPrincipals() {
/**
* A list of tests to run in each context, as understood by
* {@see getElementData}.
*/
const TESTS = [
+ // TODO: <frame> element, which requires a frameset document.
+ {
+ element: ["iframe", {}],
+ src: "iframe.html",
+ },
{
element: ["img", {}],
src: "img.png",
},
{
element: ["img", {}],
src: "imgset.png",
srcAttr: "srcset",