--- a/dom/base/nsFrameLoader.cpp
+++ b/dom/base/nsFrameLoader.cpp
@@ -894,16 +894,53 @@ nsFrameLoader::SwapWithOtherRemoteLoader
}
nsIPresShell* ourShell = ourDoc->GetShell();
nsIPresShell* otherShell = otherDoc->GetShell();
if (!ourShell || !otherShell) {
return NS_ERROR_NOT_IMPLEMENTED;
}
+ if (mRemoteBrowser->IsIsolatedMozBrowserElement() !=
+ aOther->mRemoteBrowser->IsIsolatedMozBrowserElement() ||
+ mRemoteBrowser->HasOwnApp() != aOther->mRemoteBrowser->HasOwnApp()) {
+ return NS_ERROR_NOT_IMPLEMENTED;
+ }
+
+ if (mRemoteBrowser->OriginAttributesRef() !=
+ aOther->mRemoteBrowser->OriginAttributesRef()) {
+ return NS_ERROR_NOT_IMPLEMENTED;
+ }
+
+ bool ourFullscreenAllowed =
+ ourContent->IsXULElement(nsGkAtoms::browser) ||
+ (OwnerIsMozBrowserOrAppFrame() &&
+ (ourContent->HasAttr(kNameSpaceID_None, nsGkAtoms::allowfullscreen) ||
+ ourContent->HasAttr(kNameSpaceID_None, nsGkAtoms::mozallowfullscreen)));
+ bool otherFullscreenAllowed =
+ otherContent->IsXULElement(nsGkAtoms::browser) ||
+ (aOther->OwnerIsMozBrowserOrAppFrame() &&
+ (otherContent->HasAttr(kNameSpaceID_None, nsGkAtoms::allowfullscreen) ||
+ otherContent->HasAttr(kNameSpaceID_None, nsGkAtoms::mozallowfullscreen)));
+ if (ourFullscreenAllowed != otherFullscreenAllowed) {
+ return NS_ERROR_NOT_IMPLEMENTED;
+ }
+
+ bool ourHasHistory =
+ mIsTopLevelContent &&
+ ourContent->IsXULElement(nsGkAtoms::browser) &&
+ !ourContent->HasAttr(kNameSpaceID_None, nsGkAtoms::disablehistory);
+ bool otherHasHistory =
+ aOther->mIsTopLevelContent &&
+ otherContent->IsXULElement(nsGkAtoms::browser) &&
+ !otherContent->HasAttr(kNameSpaceID_None, nsGkAtoms::disablehistory);
+ if (ourHasHistory != otherHasHistory) {
+ return NS_ERROR_NOT_IMPLEMENTED;
+ }
+
if (mInSwap || aOther->mInSwap) {
return NS_ERROR_NOT_IMPLEMENTED;
}
mInSwap = aOther->mInSwap = true;
nsIFrame* ourFrame = ourContent->GetPrimaryFrame();
nsIFrame* otherFrame = otherContent->GetPrimaryFrame();
if (!ourFrame || !otherFrame) {
@@ -1046,33 +1083,57 @@ nsFrameLoader::SwapWithOtherLoader(nsFra
RefPtr<nsFrameLoader>& aFirstToSwap,
RefPtr<nsFrameLoader>& aSecondToSwap)
{
NS_PRECONDITION((aFirstToSwap == this && aSecondToSwap == aOther) ||
(aFirstToSwap == aOther && aSecondToSwap == this),
"Swapping some sort of random loaders?");
NS_ENSURE_STATE(!mInShow && !aOther->mInShow);
- if (IsRemoteFrame() && aOther->IsRemoteFrame()) {
- return SwapWithOtherRemoteLoader(aOther, aFirstToSwap, aSecondToSwap);
- }
-
- if (IsRemoteFrame() || aOther->IsRemoteFrame()) {
+ if (IsRemoteFrame() != aOther->IsRemoteFrame()) {
NS_WARNING("Swapping remote and non-remote frames is not currently supported");
return NS_ERROR_NOT_IMPLEMENTED;
}
Element* ourContent = mOwnerContent;
Element* otherContent = aOther->mOwnerContent;
if (!ourContent || !otherContent) {
// Can't handle this
return NS_ERROR_NOT_IMPLEMENTED;
}
+ bool ourHasSrcdoc = ourContent->IsHTMLElement(nsGkAtoms::iframe) &&
+ ourContent->HasAttr(kNameSpaceID_None, nsGkAtoms::srcdoc);
+ bool otherHasSrcdoc = otherContent->IsHTMLElement(nsGkAtoms::iframe) &&
+ otherContent->HasAttr(kNameSpaceID_None, nsGkAtoms::srcdoc);
+ if (ourHasSrcdoc || otherHasSrcdoc) {
+ // Ignore this case entirely for now, since we support XUL <-> HTML swapping
+ return NS_ERROR_NOT_IMPLEMENTED;
+ }
+
+ bool ourPassPointerEvents =
+ ourContent->AttrValueIs(kNameSpaceID_None,
+ nsGkAtoms::mozpasspointerevents,
+ nsGkAtoms::_true,
+ eCaseMatters);
+ bool otherPassPointerEvents =
+ otherContent->AttrValueIs(kNameSpaceID_None,
+ nsGkAtoms::mozpasspointerevents,
+ nsGkAtoms::_true,
+ eCaseMatters);
+ if (ourPassPointerEvents != otherPassPointerEvents) {
+ return NS_ERROR_NOT_IMPLEMENTED;
+ }
+
+ // Divert to a separate path for the remaining steps in the remote case
+ if (IsRemoteFrame() && aOther->IsRemoteFrame()) {
+ return SwapWithOtherRemoteLoader(aOther, aFirstToSwap, aSecondToSwap);
+ }
+
// Make sure there are no same-origin issues
bool equal;
nsresult rv =
ourContent->NodePrincipal()->Equals(otherContent->NodePrincipal(), &equal);
if (NS_FAILED(rv) || !equal) {
// Security problems loom. Just bail on it all
return NS_ERROR_DOM_SECURITY_ERR;
}
@@ -1198,17 +1259,30 @@ nsFrameLoader::SwapWithOtherLoader(nsFra
nsIPresShell* otherShell = otherDoc->GetShell();
if (!ourShell || !otherShell) {
return NS_ERROR_NOT_IMPLEMENTED;
}
if (ourDocshell->GetIsIsolatedMozBrowserElement() !=
otherDocshell->GetIsIsolatedMozBrowserElement() ||
ourDocshell->GetIsApp() != otherDocshell->GetIsApp()) {
- return NS_ERROR_NOT_IMPLEMENTED;
+ return NS_ERROR_NOT_IMPLEMENTED;
+ }
+
+ if (ourDocshell->GetOriginAttributes() !=
+ otherDocshell->GetOriginAttributes()) {
+ return NS_ERROR_NOT_IMPLEMENTED;
+ }
+
+ bool ourFullscreenAllowed;
+ bool otherFullscreenAllowed;
+ ourDocshell->GetFullscreenAllowed(&ourFullscreenAllowed);
+ otherDocshell->GetFullscreenAllowed(&otherFullscreenAllowed);
+ if (ourFullscreenAllowed != otherFullscreenAllowed) {
+ return NS_ERROR_NOT_IMPLEMENTED;
}
if (mInSwap || aOther->mInSwap) {
return NS_ERROR_NOT_IMPLEMENTED;
}
AutoResetInFrameSwap autoFrameSwap(this, aOther, ourDocshell, otherDocshell,
ourEventTarget, otherEventTarget);
--- a/dom/base/nsIFrameLoader.idl
+++ b/dom/base/nsIFrameLoader.idl
@@ -230,21 +230,9 @@ interface nsIFrameLoaderOwner : nsISuppo
* iframes.
*/
readonly attribute mozIApplication parentApplication;
/**
* Puts the FrameLoaderOwner in prerendering mode.
*/
void setIsPrerendered();
-
- /**
- * Swap frame loaders with the given nsIFrameLoaderOwner. This may
- * only be posible in a very limited range of circumstances, or
- * never, depending on the object implementing this interface.
- *
- * @throws NS_ERROR_NOT_IMPLEMENTED if the swapping logic is not
- * implemented for the two given frame loader owners.
- * @throws NS_ERROR_DOM_SECURITY_ERR if the swap is not allowed on
- * security grounds.
- */
- void swapFrameLoaders(in nsIFrameLoaderOwner aOtherOwner);
};
--- a/dom/base/nsObjectLoadingContent.cpp
+++ b/dom/base/nsObjectLoadingContent.cpp
@@ -1230,22 +1230,16 @@ nsObjectLoadingContent::GetParentApplica
NS_IMETHODIMP
nsObjectLoadingContent::SetIsPrerendered()
{
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
-nsObjectLoadingContent::SwapFrameLoaders(nsIFrameLoaderOwner* aOtherLoader)
-{
- return NS_ERROR_NOT_IMPLEMENTED;
-}
-
-NS_IMETHODIMP
nsObjectLoadingContent::GetActualType(nsACString& aType)
{
aType = mContentType;
return NS_OK;
}
NS_IMETHODIMP
nsObjectLoadingContent::GetDisplayedType(uint32_t* aType)
@@ -1647,17 +1641,17 @@ nsObjectLoadingContent::CheckProcessPoli
return false;
}
nsCOMPtr<nsIContent> thisContent =
do_QueryInterface(static_cast<nsIImageLoadingContent*>(this));
NS_ASSERTION(thisContent, "Must be an instance of content");
nsIDocument* doc = thisContent->OwnerDoc();
-
+
int32_t objectType;
switch (mType) {
case eType_Image:
objectType = nsIContentPolicy::TYPE_INTERNAL_IMAGE;
break;
case eType_Document:
objectType = nsIContentPolicy::TYPE_DOCUMENT;
break;
@@ -2914,17 +2908,17 @@ nsObjectLoadingContent::PluginCrashed(ns
PluginDestroyed();
// Switch to fallback/crashed state, notify
LoadFallback(eFallbackCrashed, true);
// send nsPluginCrashedEvent
- // Note that aPluginTag in invalidated after we're called, so copy
+ // Note that aPluginTag in invalidated after we're called, so copy
// out any data we need now.
nsAutoCString pluginName;
aPluginTag->GetName(pluginName);
nsAutoCString pluginFilename;
aPluginTag->GetFilename(pluginFilename);
nsCOMPtr<nsIRunnable> ev =
new nsPluginCrashedEvent(thisContent,
@@ -3822,9 +3816,8 @@ nsObjectLoadingContent::SetupProtoChainR
}
nsObjectLoadingContent* objectLoadingContent =
static_cast<nsObjectLoadingContent*>(mContent.get());
objectLoadingContent->SetupProtoChain(cx, obj);
return NS_OK;
}
NS_IMPL_ISUPPORTS(nsObjectLoadingContent::SetupProtoChainRunner, nsIRunnable)
-
--- a/dom/base/nsObjectLoadingContent.h
+++ b/dom/base/nsObjectLoadingContent.h
@@ -22,25 +22,26 @@
#include "nsIRunnable.h"
#include "nsIThreadInternal.h"
#include "nsIFrame.h"
#include "nsIFrameLoader.h"
class nsAsyncInstantiateEvent;
class nsStopPluginRunnable;
class AutoSetInstantiatingToFalse;
+class nsFrameLoader;
class nsPluginFrame;
-class nsFrameLoader;
class nsXULElement;
class nsPluginInstanceOwner;
namespace mozilla {
namespace dom {
template<typename T> class Sequence;
struct MozPluginParameter;
+class HTMLIFrameElement;
} // namespace dom
} // namespace mozilla
class nsObjectLoadingContent : public nsImageLoadingContent
, public nsIStreamListener
, public nsIFrameLoaderOwner
, public nsIObjectLoadingContent
, public nsIChannelEventSink
@@ -202,32 +203,38 @@ class nsObjectLoadingContent : public ns
bool Activated() const
{
return mActivated;
}
nsIURI* GetSrcURI() const
{
return mURI;
}
-
+
/**
* The default state that this plugin would be without manual activation.
* @returns PLUGIN_ACTIVE if the default state would be active.
*/
uint32_t DefaultFallbackType();
uint32_t PluginFallbackType() const
{
return mFallbackType;
}
bool HasRunningPlugin() const
{
return !!mInstanceOwner;
}
- void SwapFrameLoaders(nsXULElement& aOtherOwner, mozilla::ErrorResult& aRv)
+ void SwapFrameLoaders(mozilla::dom::HTMLIFrameElement& aOtherLoaderOwner,
+ mozilla::ErrorResult& aRv)
+ {
+ aRv.Throw(NS_ERROR_NOT_IMPLEMENTED);
+ }
+ void SwapFrameLoaders(nsXULElement& aOtherLoaderOwner,
+ mozilla::ErrorResult& aRv)
{
aRv.Throw(NS_ERROR_NOT_IMPLEMENTED);
}
void LegacyCall(JSContext* aCx, JS::Handle<JS::Value> aThisVal,
const mozilla::dom::Sequence<JS::Value>& aArguments,
JS::MutableHandle<JS::Value> aRetval,
mozilla::ErrorResult& aRv);
@@ -395,21 +402,21 @@ class nsObjectLoadingContent : public ns
* - mURI : The final URI, considering mChannel if
* mChannelLoaded is set
* - mContentType : The final content type, considering mChannel if
* mChannelLoaded is set
* - mBaseURI : The object's base URI, which may be set by the
* object (codebase attribute)
* - mType : The type the object is determined to be based
* on the above
- *
+ *
* NOTE The class assumes that mType is the currently loaded type at various
* points, so the caller of this function must take the appropriate
* actions to ensure this
- *
+ *
* NOTE This function does not perform security checks, only determining the
* requested type and parameters of the object.
*
* @param aJavaURI Specify that the URI will be consumed by java, which
* changes codebase parsing and URI construction. Used
* internally.
*
* @return Returns a bitmask of ParameterUpdateFlags values
@@ -501,17 +508,17 @@ class nsObjectLoadingContent : public ns
void NotifyStateChanged(ObjectType aOldType,
mozilla::EventStates aOldState,
bool aSync, bool aNotify);
/**
* Returns a ObjectType value corresponding to the type of content we would
* support the given MIME type as, taking capabilities and plugin state
* into account
- *
+ *
* NOTE this does not consider whether the content would be suppressed by
* click-to-play or other content policy checks
*/
ObjectType GetTypeOfContent(const nsCString& aMIMEType);
/**
* Gets the frame that's associated with this content node.
* Does not flush.
--- a/dom/base/test/chrome/chrome.ini
+++ b/dom/base/test/chrome/chrome.ini
@@ -20,16 +20,17 @@ support-files =
file_bug1209621.xul
fileconstructor_file.png
frame_bug814638.xul
frame_registerElement_content.html
registerElement_ep.js
host_bug814638.xul
window_nsITextInputProcessor.xul
title_window.xul
+ window_swapFrameLoaders.xul
[test_bug120684.xul]
[test_bug206691.xul]
[test_bug339494.xul]
[test_bug357450.xul]
[test_bug380418.html]
[test_bug380418.html^headers^]
[test_bug383430.html]
@@ -72,8 +73,9 @@ skip-if = buildapp == 'mulet'
[test_registerElement_content.xul]
[test_registerElement_ep.xul]
[test_domparsing.xul]
[test_fileconstructor.xul]
[test_fileconstructor_tempfile.xul]
[test_nsITextInputProcessor.xul]
[test_title.xul]
[test_windowroot.xul]
+[test_swapFrameLoaders.xul]
new file mode 100644
--- /dev/null
+++ b/dom/base/test/chrome/test_swapFrameLoaders.xul
@@ -0,0 +1,26 @@
+<?xml version="1.0"?>
+<?xml-stylesheet type="text/css" href="chrome://global/skin"?>
+<?xml-stylesheet type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"?>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=1242644
+Test swapFrameLoaders with different frame types and remoteness
+-->
+<window title="Mozilla Bug 1242644"
+ xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
+ <script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"/>
+
+ <!-- test results are displayed in the html:body -->
+ <body xmlns="http://www.w3.org/1999/xhtml">
+ <a href="https://bugzilla.mozilla.org/show_bug.cgi?id=1242644"
+ target="_blank">Mozilla Bug 1242644</a>
+ </body>
+
+ <!-- test code goes here -->
+ <script type="application/javascript"><![CDATA[
+ SimpleTest.waitForExplicitFinish();
+ SimpleTest.requestLongerTimeout(100);
+
+ window.open("window_swapFrameLoaders.xul", "bug1242644",
+ "chrome,width=600,height=600");
+ ]]></script>
+</window>
new file mode 100644
--- /dev/null
+++ b/dom/base/test/chrome/window_swapFrameLoaders.xul
@@ -0,0 +1,177 @@
+<?xml version="1.0"?>
+<?xml-stylesheet type="text/css" href="chrome://global/skin"?>
+<?xml-stylesheet type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"?>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=1242644
+Test swapFrameLoaders with different frame types and remoteness
+-->
+<window title="Mozilla Bug 1242644"
+ xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
+ <script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SpawnTask.js"></script>
+
+ <script type="application/javascript"><![CDATA[
+ ["SimpleTest", "SpecialPowers", "info", "is"].forEach(key => {
+ window[key] = window.opener[key];
+ })
+ const { interfaces: Ci } = Components;
+
+ const NS = {
+ xul: "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul",
+ html: "http://www.w3.org/1999/xhtml",
+ }
+
+ const TAG = {
+ xul: "browser",
+ html: "iframe", // mozbrowser
+ }
+
+ const SCENARIOS = [
+ ["xul", "xul"],
+ ["xul", "html"],
+ ["html", "xul"],
+ ["html", "html"],
+ ["xul", "xul", "remote"],
+ ["xul", "html", "remote"],
+ ["html", "xul", "remote"],
+ ["html", "html", "remote"],
+ ];
+
+ function once(target, eventName, useCapture = false) {
+ info("Waiting for event: '" + eventName + "' on " + target + ".");
+
+ return new Promise(resolve => {
+ for (let [add, remove] of [
+ ["addEventListener", "removeEventListener"],
+ ["addMessageListener", "removeMessageListener"],
+ ]) {
+ if ((add in target) && (remove in target)) {
+ target[add](eventName, function onEvent(...aArgs) {
+ info("Got event: '" + eventName + "' on " + target + ".");
+ target[remove](eventName, onEvent, useCapture);
+ resolve(aArgs);
+ }, useCapture);
+ break;
+ }
+ }
+ });
+ }
+
+ function* addFrame(type, remote) {
+ let frame = document.createElementNS(NS[type], TAG[type]);
+ frame.setAttribute("remote", remote);
+ if (remote && type == "xul") {
+ frame.setAttribute("style", "-moz-binding: none;");
+ }
+ if (type == "html") {
+ frame.setAttribute("mozbrowser", "true");
+ frame.setAttribute("noisolation", "true");
+ frame.setAttribute("allowfullscreen", "true");
+ } else if (type == "xul") {
+ frame.setAttribute("type", "content");
+ }
+ frame.setAttribute("src", "about:blank");
+ document.documentElement.appendChild(frame);
+ return frame;
+ }
+
+ add_task(function*() {
+ yield new Promise(resolve => {
+ SpecialPowers.pushPrefEnv(
+ { "set": [["dom.mozBrowserFramesEnabled", true]] },
+ resolve);
+ });
+ });
+
+ add_task(function*() {
+ for (let scenario of SCENARIOS) {
+ let [ typeA, typeB, remote ] = scenario;
+ remote = !!remote;
+ info(`Adding frame A, type ${typeA}, remote ${remote}`);
+ let frameA = yield addFrame(typeA, remote);
+
+ info(`Adding frame B, type ${typeB}, remote ${remote}`);
+ let frameB = yield addFrame(typeB, remote);
+
+ let frameScriptFactory = function(name) {
+ return `function() {
+ addMessageListener("ping", function() {
+ sendAsyncMessage("pong", "${name}");
+ });
+ }`;
+ }
+
+ // Load frame script into each frame
+ {
+ let mmA = frameA.frameLoader.messageManager;
+ let mmB = frameB.frameLoader.messageManager;
+
+ mmA.loadFrameScript("data:,(" + frameScriptFactory("A") + ")()", false);
+ mmB.loadFrameScript("data:,(" + frameScriptFactory("B") + ")()", false);
+ }
+
+ // Ping before swap
+ {
+ let mmA = frameA.frameLoader.messageManager;
+ let mmB = frameB.frameLoader.messageManager;
+
+ let inflightA = once(mmA, "pong");
+ let inflightB = once(mmB, "pong");
+
+ info("Ping message manager for frame A");
+ mmA.sendAsyncMessage("ping");
+ let [ { data: pongA } ] = yield inflightA;
+ is(pongA, "A", "Frame A message manager gets reply A before swap");
+
+ info("Ping message manager for frame B");
+ mmB.sendAsyncMessage("ping");
+ let [ { data: pongB } ] = yield inflightB;
+ is(pongB, "B", "Frame B message manager gets reply B before swap");
+ }
+
+ // Ping after swap using message managers acquired before
+ {
+ let mmA = frameA.frameLoader.messageManager;
+ let mmB = frameB.frameLoader.messageManager;
+
+ info("swapFrameLoaders");
+ frameA.swapFrameLoaders(frameB);
+
+ let inflightA = once(mmA, "pong");
+ let inflightB = once(mmB, "pong");
+
+ info("Ping message manager for frame A");
+ mmA.sendAsyncMessage("ping");
+ let [ { data: pongA } ] = yield inflightA;
+ is(pongA, "B", "Frame A message manager acquired before swap gets reply B after swap");
+
+ info("Ping message manager for frame B");
+ mmB.sendAsyncMessage("ping");
+ let [ { data: pongB } ] = yield inflightB;
+ is(pongB, "A", "Frame B message manager acquired before swap gets reply A after swap");
+ }
+
+ // Ping after swap using message managers acquired after
+ {
+ let mmA = frameA.frameLoader.messageManager;
+ let mmB = frameB.frameLoader.messageManager;
+
+ let inflightA = once(mmA, "pong");
+ let inflightB = once(mmB, "pong");
+
+ info("Ping message manager for frame A");
+ mmA.sendAsyncMessage("ping");
+ let [ { data: pongA } ] = yield inflightA;
+ is(pongA, "B", "Frame A message manager acquired after swap gets reply B after swap");
+
+ info("Ping message manager for frame B");
+ mmB.sendAsyncMessage("ping");
+ let [ { data: pongB } ] = yield inflightB;
+ is(pongB, "A", "Frame B message manager acquired after swap gets reply A after swap");
+ }
+
+ frameA.remove();
+ frameB.remove();
+ }
+ });
+ ]]></script>
+</window>
--- a/dom/html/nsGenericHTMLFrameElement.cpp
+++ b/dom/html/nsGenericHTMLFrameElement.cpp
@@ -3,16 +3,17 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "nsGenericHTMLFrameElement.h"
#include "mozilla/dom/BrowserElementAudioChannel.h"
#include "mozilla/dom/ContentChild.h"
+#include "mozilla/dom/HTMLIFrameElement.h"
#include "mozilla/Preferences.h"
#include "mozilla/ErrorResult.h"
#include "GeckoProfiler.h"
#include "mozIApplication.h"
#include "nsAttrValueInlines.h"
#include "nsContentUtils.h"
#include "nsIAppsService.h"
#include "nsIDocShell.h"
@@ -20,16 +21,17 @@
#include "nsIFrame.h"
#include "nsIInterfaceRequestorUtils.h"
#include "nsIPermissionManager.h"
#include "nsIPresShell.h"
#include "nsIScrollable.h"
#include "nsPresContext.h"
#include "nsServiceManagerUtils.h"
#include "nsSubDocumentFrame.h"
+#include "nsXULElement.h"
using namespace mozilla;
using namespace mozilla::dom;
NS_IMPL_CYCLE_COLLECTION_CLASS(nsGenericHTMLFrameElement)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(nsGenericHTMLFrameElement,
nsGenericHTMLElement)
@@ -206,21 +208,57 @@ nsGenericHTMLFrameElement::GetParentAppl
rv = appsService->GetAppByLocalId(appId, aApplication);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
return NS_OK;
}
-NS_IMETHODIMP
-nsGenericHTMLFrameElement::SwapFrameLoaders(nsIFrameLoaderOwner* aOtherOwner)
+void
+nsGenericHTMLFrameElement::SwapFrameLoaders(HTMLIFrameElement& aOtherLoaderOwner,
+ ErrorResult& rv)
+{
+ if (&aOtherLoaderOwner == this) {
+ // nothing to do
+ return;
+ }
+
+ if (!aOtherLoaderOwner.mFrameLoader) {
+ rv.Throw(NS_ERROR_NOT_IMPLEMENTED);
+ return;
+ }
+
+ SwapFrameLoaders(aOtherLoaderOwner.mFrameLoader, rv);
+}
+
+void
+nsGenericHTMLFrameElement::SwapFrameLoaders(nsXULElement& aOtherLoaderOwner,
+ ErrorResult& rv)
{
- // We don't support this yet
- return NS_ERROR_NOT_IMPLEMENTED;
+ if (!mFrameLoader) {
+ rv.Throw(NS_ERROR_NOT_IMPLEMENTED);
+ return;
+ }
+
+ aOtherLoaderOwner.SwapFrameLoaders(mFrameLoader, rv);
+}
+
+void
+nsGenericHTMLFrameElement::SwapFrameLoaders(RefPtr<nsFrameLoader>& aOtherLoader,
+ mozilla::ErrorResult& rv)
+{
+ if (!mFrameLoader || !aOtherLoader) {
+ rv.Throw(NS_ERROR_NOT_IMPLEMENTED);
+ return;
+ }
+
+ rv = mFrameLoader->SwapWithOtherLoader(aOtherLoader,
+ mFrameLoader,
+ aOtherLoader);
}
NS_IMETHODIMP
nsGenericHTMLFrameElement::SetIsPrerendered()
{
MOZ_ASSERT(!mFrameLoader, "Please call SetIsPrerendered before frameLoader is created");
mIsPrerendered = true;
return NS_OK;
@@ -707,15 +745,8 @@ nsGenericHTMLFrameElement::AllowCreateFr
NS_IMETHODIMP
nsGenericHTMLFrameElement::InitializeBrowserAPI()
{
MOZ_ASSERT(mFrameLoader);
InitBrowserElementAPI();
return NS_OK;
}
-
-void
-nsGenericHTMLFrameElement::SwapFrameLoaders(nsXULElement& aOtherOwner,
- ErrorResult& aError)
-{
- aError.Throw(NS_ERROR_NOT_IMPLEMENTED);
-}
--- a/dom/html/nsGenericHTMLFrameElement.h
+++ b/dom/html/nsGenericHTMLFrameElement.h
@@ -69,17 +69,24 @@ public:
nsresult CopyInnerTo(mozilla::dom::Element* aDest);
virtual int32_t TabIndexDefault() override;
NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(nsGenericHTMLFrameElement,
nsGenericHTMLElement)
- void SwapFrameLoaders(nsXULElement& aOtherOwner, mozilla::ErrorResult& aError);
+ void SwapFrameLoaders(mozilla::dom::HTMLIFrameElement& aOtherLoaderOwner,
+ mozilla::ErrorResult& aError);
+
+ void SwapFrameLoaders(nsXULElement& aOtherLoaderOwner,
+ mozilla::ErrorResult& aError);
+
+ void SwapFrameLoaders(RefPtr<nsFrameLoader>& aOtherLoader,
+ mozilla::ErrorResult& rv);
static bool BrowserFramesEnabled();
/**
* Helper method to map a HTML 'scrolling' attribute value to a nsIScrollable
* enum value. scrolling="no" (and its synonyms) maps to
* nsIScrollable::Scrollbar_Never, and anything else (including nullptr) maps
* to nsIScrollable::Scrollbar_Auto.
--- a/dom/webidl/XULElement.webidl
+++ b/dom/webidl/XULElement.webidl
@@ -121,15 +121,18 @@ interface XULElement : Element {
interface MozFrameLoaderOwner {
[ChromeOnly]
readonly attribute MozFrameLoader? frameLoader;
[ChromeOnly]
void setIsPrerendered();
[ChromeOnly, Throws]
- void swapFrameLoaders(XULElement aOtherOwner);
+ void swapFrameLoaders(XULElement aOtherLoaderOwner);
+
+ [ChromeOnly, Throws]
+ void swapFrameLoaders(HTMLIFrameElement aOtherLoaderOwner);
};
XULElement implements GlobalEventHandlers;
XULElement implements TouchEventHandlers;
XULElement implements MozFrameLoaderOwner;
XULElement implements OnErrorEventHandlerForNodes;
--- a/dom/xul/nsXULElement.cpp
+++ b/dom/xul/nsXULElement.cpp
@@ -106,16 +106,17 @@
#include "mozilla/EventDispatcher.h"
#include "mozAutoDocUpdate.h"
#include "nsIDOMXULCommandEvent.h"
#include "nsCCUncollectableMarker.h"
#include "nsICSSDeclaration.h"
#include "mozilla/dom/XULElementBinding.h"
#include "mozilla/dom/BoxObject.h"
+#include "mozilla/dom/HTMLIFrameElement.h"
using namespace mozilla;
using namespace mozilla::dom;
#ifdef XUL_PROTOTYPE_ATTRIBUTE_METERING
uint32_t nsXULPrototypeAttribute::gNumElements;
uint32_t nsXULPrototypeAttribute::gNumAttributes;
uint32_t nsXULPrototypeAttribute::gNumCacheTests;
@@ -1631,51 +1632,61 @@ nsXULElement::GetParentApplication(mozIA
nsresult
nsXULElement::SetIsPrerendered()
{
return SetAttr(kNameSpaceID_None, nsGkAtoms::prerendered, nullptr,
NS_LITERAL_STRING("true"), true);
}
-nsresult
-nsXULElement::SwapFrameLoaders(nsIFrameLoaderOwner* aOtherOwner)
+void
+nsXULElement::SwapFrameLoaders(HTMLIFrameElement& aOtherLoaderOwner,
+ ErrorResult& rv)
{
- nsCOMPtr<nsIContent> otherContent(do_QueryInterface(aOtherOwner));
- NS_ENSURE_TRUE(otherContent, NS_ERROR_NOT_IMPLEMENTED);
-
- nsXULElement* otherEl = FromContent(otherContent);
- NS_ENSURE_TRUE(otherEl, NS_ERROR_NOT_IMPLEMENTED);
-
- ErrorResult rv;
- SwapFrameLoaders(*otherEl, rv);
- return rv.StealNSResult();
+ nsXULSlots *ourSlots = static_cast<nsXULSlots*>(GetExistingDOMSlots());
+ if (!ourSlots || !ourSlots->mFrameLoader) {
+ rv.Throw(NS_ERROR_NOT_IMPLEMENTED);
+ return;
+ }
+
+ aOtherLoaderOwner.SwapFrameLoaders(ourSlots->mFrameLoader, rv);
}
void
-nsXULElement::SwapFrameLoaders(nsXULElement& aOtherElement, ErrorResult& rv)
+nsXULElement::SwapFrameLoaders(nsXULElement& aOtherLoaderOwner,
+ ErrorResult& rv)
{
- if (&aOtherElement == this) {
+ if (&aOtherLoaderOwner == this) {
// nothing to do
return;
}
- nsXULSlots *ourSlots = static_cast<nsXULSlots*>(GetExistingDOMSlots());
nsXULSlots *otherSlots =
- static_cast<nsXULSlots*>(aOtherElement.GetExistingDOMSlots());
- if (!ourSlots || !ourSlots->mFrameLoader ||
- !otherSlots || !otherSlots->mFrameLoader) {
- // Can't handle swapping when there is nothing to swap... yet.
+ static_cast<nsXULSlots*>(aOtherLoaderOwner.GetExistingDOMSlots());
+ if (!otherSlots || !otherSlots->mFrameLoader) {
rv.Throw(NS_ERROR_NOT_IMPLEMENTED);
return;
}
- rv = ourSlots->mFrameLoader->SwapWithOtherLoader(otherSlots->mFrameLoader,
+ SwapFrameLoaders(otherSlots->mFrameLoader, rv);
+}
+
+void
+nsXULElement::SwapFrameLoaders(RefPtr<nsFrameLoader>& aOtherLoader,
+ mozilla::ErrorResult& rv)
+{
+ nsXULSlots *ourSlots = static_cast<nsXULSlots*>(GetExistingDOMSlots());
+ if (!ourSlots || !ourSlots->mFrameLoader || !aOtherLoader) {
+ rv.Throw(NS_ERROR_NOT_IMPLEMENTED);
+ return;
+ }
+
+ rv = ourSlots->mFrameLoader->SwapWithOtherLoader(aOtherLoader,
ourSlots->mFrameLoader,
- otherSlots->mFrameLoader);
+ aOtherLoader);
}
NS_IMETHODIMP
nsXULElement::GetParentTree(nsIDOMXULMultiSelectControlElement** aTreeElement)
{
for (nsIContent* current = GetParent(); current;
current = current->GetParent()) {
if (current->NodeInfo()->Equals(nsGkAtoms::listbox,
--- a/dom/xul/nsXULElement.h
+++ b/dom/xul/nsXULElement.h
@@ -49,16 +49,17 @@ typedef nsTArray<RefPtr<nsXULPrototypeNo
namespace mozilla {
class EventChainPreVisitor;
class EventListenerManager;
namespace css {
class StyleRule;
} // namespace css
namespace dom {
class BoxObject;
+class HTMLIFrameElement;
} // namespace dom
} // namespace mozilla
namespace JS {
class SourceBufferHolder;
} // namespace JS
////////////////////////////////////////////////////////////////////////
@@ -407,17 +408,16 @@ public:
NS_DECL_NSIDOMXULELEMENT
virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult) const override;
virtual mozilla::EventStates IntrinsicState() const override;
nsresult GetFrameLoader(nsIFrameLoader** aFrameLoader);
nsresult GetParentApplication(mozIApplication** aApplication);
nsresult SetIsPrerendered();
- nsresult SwapFrameLoaders(nsIFrameLoaderOwner* aOtherOwner);
virtual void RecompileScriptEventListeners() override;
// This function should ONLY be used by BindToTree implementations.
// The function exists solely because XUL elements store the binding
// parent as a member instead of in the slots, as Element does.
void SetXULBindingParent(nsIContent* aBindingParent)
{
@@ -571,17 +571,22 @@ public:
const nsAString& aValue);
already_AddRefed<nsINodeList>
GetElementsByAttributeNS(const nsAString& aNamespaceURI,
const nsAString& aAttribute,
const nsAString& aValue,
mozilla::ErrorResult& rv);
// Style() inherited from nsStyledElement
already_AddRefed<nsFrameLoader> GetFrameLoader();
- void SwapFrameLoaders(nsXULElement& aOtherOwner, mozilla::ErrorResult& rv);
+ void SwapFrameLoaders(mozilla::dom::HTMLIFrameElement& aOtherLoaderOwner,
+ mozilla::ErrorResult& rv);
+ void SwapFrameLoaders(nsXULElement& aOtherLoaderOwner,
+ mozilla::ErrorResult& rv);
+ void SwapFrameLoaders(RefPtr<nsFrameLoader>& aOtherLoader,
+ mozilla::ErrorResult& rv);
nsINode* GetScopeChainParent() const override
{
// For XUL, the parent is the parent element, if any
Element* parent = GetParentElement();
return parent ? parent : nsStyledElement::GetScopeChainParent();
}
@@ -641,17 +646,17 @@ protected:
virtual bool ParseAttribute(int32_t aNamespaceID,
nsIAtom* aAttribute,
const nsAString& aValue,
nsAttrValue& aResult) override;
virtual mozilla::EventListenerManager*
GetEventListenerManagerForAttr(nsIAtom* aAttrName,
bool* aDefer) override;
-
+
/**
* Add a listener for the specified attribute, if appropriate.
*/
void AddListenerFor(const nsAttrName& aName,
bool aCompileEventHandlers);
void MaybeAddPopupListener(nsIAtom* aLocalName);
nsIWidget* GetWindowWidget();
@@ -668,17 +673,17 @@ protected:
void RemoveBroadcaster(const nsAString & broadcasterId);
protected:
// Internal accessor. This shadows the 'Slots', and returns
// appropriate value.
nsIControllers *Controllers() {
nsDOMSlots* slots = GetExistingDOMSlots();
- return slots ? slots->mControllers : nullptr;
+ return slots ? slots->mControllers : nullptr;
}
void UnregisterAccessKey(const nsAString& aOldValue);
bool BoolAttrIsTrue(nsIAtom* aName) const;
friend nsresult
NS_NewXULElement(mozilla::dom::Element** aResult, mozilla::dom::NodeInfo *aNodeInfo);
friend void