2015-05-03 22:32:37 +03:00
|
|
|
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
|
|
|
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
2012-05-21 15:12:37 +04:00
|
|
|
/* 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/. */
|
2002-01-29 09:27:27 +03:00
|
|
|
|
2006-03-30 12:03:04 +04:00
|
|
|
/*
|
|
|
|
* Class for managing loading of a subframe (creation of the docshell,
|
|
|
|
* handling of loads in it, recursion-checking).
|
|
|
|
*/
|
|
|
|
|
2011-04-03 06:14:00 +04:00
|
|
|
#include "base/basictypes.h"
|
2009-10-30 15:58:07 +03:00
|
|
|
|
2009-07-02 20:54:22 +04:00
|
|
|
#include "prenv.h"
|
|
|
|
|
2015-09-29 07:31:56 +03:00
|
|
|
#include "nsDocShell.h"
|
2002-01-29 09:27:27 +03:00
|
|
|
#include "nsIDOMHTMLIFrameElement.h"
|
|
|
|
#include "nsIDOMHTMLFrameElement.h"
|
2012-06-20 23:25:22 +04:00
|
|
|
#include "nsIDOMMozBrowserFrame.h"
|
2002-01-29 09:27:27 +03:00
|
|
|
#include "nsIDOMWindow.h"
|
|
|
|
#include "nsIPresShell.h"
|
2013-10-02 15:40:07 +04:00
|
|
|
#include "nsIContentInlines.h"
|
2009-10-16 23:42:29 +04:00
|
|
|
#include "nsIContentViewer.h"
|
2002-01-29 09:27:27 +03:00
|
|
|
#include "nsIDocument.h"
|
|
|
|
#include "nsIDOMDocument.h"
|
2002-04-17 08:17:16 +04:00
|
|
|
#include "nsPIDOMWindow.h"
|
2002-01-29 09:27:27 +03:00
|
|
|
#include "nsIWebNavigation.h"
|
2010-03-26 21:39:39 +03:00
|
|
|
#include "nsIWebProgress.h"
|
2002-01-29 09:27:27 +03:00
|
|
|
#include "nsIDocShell.h"
|
|
|
|
#include "nsIDocShellTreeOwner.h"
|
|
|
|
#include "nsIDocShellLoadInfo.h"
|
|
|
|
#include "nsIBaseWindow.h"
|
2016-08-16 04:04:04 +03:00
|
|
|
#include "nsIBrowser.h"
|
2003-10-30 06:01:25 +03:00
|
|
|
#include "nsContentUtils.h"
|
2009-11-06 23:43:39 +03:00
|
|
|
#include "nsIXPConnect.h"
|
2004-02-19 05:44:03 +03:00
|
|
|
#include "nsUnicharUtils.h"
|
2004-05-31 20:31:15 +04:00
|
|
|
#include "nsIScriptGlobalObject.h"
|
2002-01-29 09:27:27 +03:00
|
|
|
#include "nsIScriptSecurityManager.h"
|
2009-10-16 23:42:29 +04:00
|
|
|
#include "nsIScrollable.h"
|
2005-02-08 02:53:47 +03:00
|
|
|
#include "nsFrameLoader.h"
|
2007-02-16 02:04:33 +03:00
|
|
|
#include "nsIDOMEventTarget.h"
|
2008-08-08 03:15:40 +04:00
|
|
|
#include "nsIFrame.h"
|
2012-02-18 03:41:13 +04:00
|
|
|
#include "nsIScrollableFrame.h"
|
2010-08-31 04:49:07 +04:00
|
|
|
#include "nsSubDocumentFrame.h"
|
2012-07-27 18:03:27 +04:00
|
|
|
#include "nsError.h"
|
2008-10-08 17:04:32 +04:00
|
|
|
#include "nsISHistory.h"
|
2009-01-13 22:32:30 +03:00
|
|
|
#include "nsISHistoryInternal.h"
|
2011-05-28 11:43:57 +04:00
|
|
|
#include "nsIDOMHTMLDocument.h"
|
2010-07-19 22:33:33 +04:00
|
|
|
#include "nsIXULWindow.h"
|
2010-11-19 00:01:12 +03:00
|
|
|
#include "nsIEditor.h"
|
2012-03-04 20:02:00 +04:00
|
|
|
#include "nsIMozBrowserFrame.h"
|
2014-02-12 23:07:19 +04:00
|
|
|
#include "nsISHistory.h"
|
2014-03-29 23:10:27 +04:00
|
|
|
#include "nsNullPrincipal.h"
|
2014-11-24 22:05:35 +03:00
|
|
|
#include "nsIScriptError.h"
|
2015-02-06 19:26:29 +03:00
|
|
|
#include "nsGlobalWindow.h"
|
|
|
|
#include "nsPIWindowRoot.h"
|
2009-10-28 23:41:46 +03:00
|
|
|
#include "nsLayoutUtils.h"
|
2013-01-03 17:23:11 +04:00
|
|
|
#include "nsView.h"
|
2016-10-14 10:31:02 +03:00
|
|
|
#include "GroupedSHistory.h"
|
|
|
|
#include "PartialSHistory.h"
|
2002-01-29 09:27:27 +03:00
|
|
|
|
2003-08-08 17:14:06 +04:00
|
|
|
#include "nsIURI.h"
|
2003-08-09 00:32:22 +04:00
|
|
|
#include "nsIURL.h"
|
2002-01-29 09:27:27 +03:00
|
|
|
#include "nsNetUtil.h"
|
|
|
|
|
2006-12-26 20:47:52 +03:00
|
|
|
#include "nsGkAtoms.h"
|
2014-02-28 03:04:46 +04:00
|
|
|
#include "nsNameSpaceManager.h"
|
2002-04-17 08:17:16 +04:00
|
|
|
|
2008-02-26 17:47:51 +03:00
|
|
|
#include "nsThreadUtils.h"
|
2009-07-01 00:39:22 +04:00
|
|
|
|
2010-01-01 04:35:55 +03:00
|
|
|
#include "nsIDOMChromeWindow.h"
|
2010-05-18 16:28:37 +04:00
|
|
|
#include "nsInProcessTabChildGlobal.h"
|
2010-01-01 04:35:55 +03:00
|
|
|
|
2011-01-13 20:45:14 +03:00
|
|
|
#include "Layers.h"
|
2014-10-07 06:30:42 +04:00
|
|
|
#include "ClientLayerManager.h"
|
2011-01-13 20:45:14 +03:00
|
|
|
|
2010-07-19 22:33:33 +04:00
|
|
|
#include "ContentParent.h"
|
2009-11-05 08:11:33 +03:00
|
|
|
#include "TabParent.h"
|
2015-02-09 02:50:01 +03:00
|
|
|
#include "mozilla/plugins/PPluginWidgetParent.h"
|
|
|
|
#include "../plugins/ipc/PluginWidgetParent.h"
|
2014-03-17 10:56:54 +04:00
|
|
|
#include "mozilla/AsyncEventDispatcher.h"
|
2015-10-07 06:47:46 +03:00
|
|
|
#include "mozilla/BasePrincipal.h"
|
2011-11-16 11:50:19 +04:00
|
|
|
#include "mozilla/GuardObjects.h"
|
2011-05-25 10:31:59 +04:00
|
|
|
#include "mozilla/Preferences.h"
|
2016-08-23 07:09:32 +03:00
|
|
|
#include "mozilla/Unused.h"
|
2011-11-16 11:50:19 +04:00
|
|
|
#include "mozilla/dom/Element.h"
|
2015-01-27 00:32:18 +03:00
|
|
|
#include "mozilla/jsipc/CrossProcessObjectWrappers.h"
|
2011-11-16 11:50:19 +04:00
|
|
|
#include "mozilla/layout/RenderFrameParent.h"
|
2013-03-18 18:25:50 +04:00
|
|
|
#include "GeckoProfiler.h"
|
2011-05-25 10:31:59 +04:00
|
|
|
|
2011-10-01 21:14:35 +04:00
|
|
|
#include "jsapi.h"
|
2013-02-23 04:59:26 +04:00
|
|
|
#include "mozilla/dom/HTMLIFrameElement.h"
|
2012-08-20 22:34:32 +04:00
|
|
|
#include "nsSandboxFlags.h"
|
2016-03-22 21:08:38 +03:00
|
|
|
#include "mozilla/layers/CompositorBridgeChild.h"
|
2016-11-09 22:51:02 +03:00
|
|
|
#include "mozilla/dom/CustomEvent.h"
|
2012-08-20 22:34:32 +04:00
|
|
|
|
2015-09-10 23:50:58 +03:00
|
|
|
#include "mozilla/dom/ipc/StructuredCloneData.h"
|
2015-08-06 00:25:39 +03:00
|
|
|
#include "mozilla/WebBrowserPersistLocalDocument.h"
|
2016-11-09 22:51:02 +03:00
|
|
|
#include "mozilla/dom/GroupedHistoryEvent.h"
|
|
|
|
#include "mozilla/dom/Promise.h"
|
|
|
|
#include "mozilla/dom/PromiseNativeHandler.h"
|
2011-10-01 21:14:35 +04:00
|
|
|
|
2015-10-22 06:44:00 +03:00
|
|
|
#include "nsPrincipal.h"
|
|
|
|
|
2012-09-05 07:00:26 +04:00
|
|
|
#ifdef MOZ_XUL
|
|
|
|
#include "nsXULPopupManager.h"
|
|
|
|
#endif
|
|
|
|
|
2016-05-16 12:40:54 +03:00
|
|
|
#ifdef NS_PRINTING
|
|
|
|
#include "mozilla/embedding/printingui/PrintingParent.h"
|
|
|
|
#include "nsIWebBrowserPrint.h"
|
|
|
|
#endif
|
|
|
|
|
2009-11-05 08:11:33 +03:00
|
|
|
using namespace mozilla;
|
2013-02-15 00:41:30 +04:00
|
|
|
using namespace mozilla::hal;
|
2009-11-05 08:11:33 +03:00
|
|
|
using namespace mozilla::dom;
|
2012-09-28 09:43:12 +04:00
|
|
|
using namespace mozilla::dom::ipc;
|
2011-01-13 20:45:14 +03:00
|
|
|
using namespace mozilla::layers;
|
2011-07-18 22:04:47 +04:00
|
|
|
using namespace mozilla::layout;
|
2011-01-13 20:45:14 +03:00
|
|
|
typedef FrameMetrics::ViewID ViewID;
|
2011-01-13 20:45:14 +03:00
|
|
|
|
2003-08-09 00:32:22 +04:00
|
|
|
// Bug 136580: Limit to the number of nested content frames that can have the
|
|
|
|
// same URL. This is to stop content that is recursively loading
|
|
|
|
// itself. Note that "#foo" on the end of URL doesn't affect
|
|
|
|
// whether it's considered identical, but "?foo" or ";foo" are
|
|
|
|
// considered and compared.
|
2005-03-10 00:59:18 +03:00
|
|
|
// Bug 228829: Limit this to 1, like IE does.
|
|
|
|
#define MAX_SAME_URL_CONTENT_FRAMES 1
|
2003-08-09 00:32:22 +04:00
|
|
|
|
|
|
|
// Bug 8065: Limit content frame depth to some reasonable level. This
|
|
|
|
// does not count chrome frames when determining depth, nor does it
|
|
|
|
// prevent chrome recursion. Number is fairly arbitrary, but meant to
|
|
|
|
// keep number of shells to a reasonable number on accidental recursion with a
|
|
|
|
// small (but not 1) branching factor. With large branching factors the number
|
|
|
|
// of shells can rapidly become huge and run us out of memory. To solve that,
|
|
|
|
// we'd need to re-institute a fixed version of bug 98158.
|
|
|
|
#define MAX_DEPTH_CONTENT_FRAMES 10
|
|
|
|
|
2016-10-14 10:31:02 +03:00
|
|
|
NS_IMPL_CYCLE_COLLECTION(nsFrameLoader,
|
|
|
|
mDocShell,
|
|
|
|
mMessageManager,
|
|
|
|
mChildMessageManager,
|
2016-10-28 06:36:38 +03:00
|
|
|
mOpener,
|
2016-12-22 11:06:50 +03:00
|
|
|
mPartialSHistory)
|
2011-03-06 14:11:31 +03:00
|
|
|
NS_IMPL_CYCLE_COLLECTING_ADDREF(nsFrameLoader)
|
|
|
|
NS_IMPL_CYCLE_COLLECTING_RELEASE(nsFrameLoader)
|
2007-03-08 14:17:16 +03:00
|
|
|
|
2007-04-25 20:35:27 +04:00
|
|
|
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsFrameLoader)
|
2007-03-08 14:17:16 +03:00
|
|
|
NS_INTERFACE_MAP_ENTRY(nsIFrameLoader)
|
2011-01-12 00:34:31 +03:00
|
|
|
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIFrameLoader)
|
2015-08-06 00:25:39 +03:00
|
|
|
NS_INTERFACE_MAP_ENTRY(nsIWebBrowserPersistable)
|
2007-03-08 14:17:16 +03:00
|
|
|
NS_INTERFACE_MAP_END
|
2002-01-29 09:27:27 +03:00
|
|
|
|
2016-10-17 17:37:50 +03:00
|
|
|
nsFrameLoader::nsFrameLoader(Element* aOwner, nsPIDOMWindowOuter* aOpener, bool aNetworkCreated)
|
2011-01-13 20:45:14 +03:00
|
|
|
: mOwnerContent(aOwner)
|
2016-05-05 00:12:48 +03:00
|
|
|
, mDetachedSubdocFrame(nullptr)
|
2016-10-17 17:37:50 +03:00
|
|
|
, mOpener(aOpener)
|
2015-06-09 13:49:17 +03:00
|
|
|
, mRemoteBrowser(nullptr)
|
|
|
|
, mChildID(0)
|
|
|
|
, mEventMode(EVENT_MODE_NORMAL_DISPATCH)
|
2016-11-09 22:51:02 +03:00
|
|
|
, mBrowserChangingProcessBlockers(nullptr)
|
2015-01-05 22:16:09 +03:00
|
|
|
, mIsPrerendered(false)
|
2011-10-17 18:59:28 +04:00
|
|
|
, mDepthTooGreat(false)
|
|
|
|
, mIsTopLevelContent(false)
|
|
|
|
, mDestroyCalled(false)
|
|
|
|
, mNeedsAsyncDestroy(false)
|
|
|
|
, mInSwap(false)
|
|
|
|
, mInShow(false)
|
|
|
|
, mHideCalled(false)
|
2011-01-13 20:45:14 +03:00
|
|
|
, mNetworkCreated(aNetworkCreated)
|
2011-10-17 18:59:28 +04:00
|
|
|
, mRemoteBrowserShown(false)
|
2011-01-13 20:45:14 +03:00
|
|
|
, mRemoteFrame(false)
|
2011-12-05 16:38:46 +04:00
|
|
|
, mClipSubdocument(true)
|
2012-02-18 03:41:13 +04:00
|
|
|
, mClampScrollPosition(true)
|
2012-09-05 07:00:26 +04:00
|
|
|
, mObservingOwnerContent(false)
|
2013-04-26 04:53:26 +04:00
|
|
|
, mVisible(true)
|
2011-01-13 20:45:14 +03:00
|
|
|
{
|
2015-07-31 12:28:36 +03:00
|
|
|
mRemoteFrame = ShouldUseRemoteProcess();
|
2016-10-17 17:37:50 +03:00
|
|
|
MOZ_ASSERT(!mRemoteFrame || !aOpener,
|
|
|
|
"Cannot pass aOpener for a remote frame!");
|
2011-01-13 20:45:14 +03:00
|
|
|
}
|
|
|
|
|
2013-07-18 03:34:57 +04:00
|
|
|
nsFrameLoader::~nsFrameLoader()
|
|
|
|
{
|
|
|
|
if (mMessageManager) {
|
|
|
|
mMessageManager->Disconnect();
|
|
|
|
}
|
2015-03-06 06:21:51 +03:00
|
|
|
MOZ_RELEASE_ASSERT(mDestroyCalled);
|
2013-07-18 03:34:57 +04:00
|
|
|
}
|
|
|
|
|
2009-08-19 13:09:26 +04:00
|
|
|
nsFrameLoader*
|
2016-10-17 17:37:50 +03:00
|
|
|
nsFrameLoader::Create(Element* aOwner, nsPIDOMWindowOuter* aOpener, bool aNetworkCreated)
|
2009-08-19 13:09:26 +04:00
|
|
|
{
|
2012-07-30 18:20:58 +04:00
|
|
|
NS_ENSURE_TRUE(aOwner, nullptr);
|
2011-10-18 14:53:36 +04:00
|
|
|
nsIDocument* doc = aOwner->OwnerDoc();
|
2016-05-17 16:18:22 +03:00
|
|
|
|
|
|
|
// We never create nsFrameLoaders for elements in resource documents.
|
|
|
|
//
|
|
|
|
// We never create nsFrameLoaders for elements in data documents, unless the
|
|
|
|
// document is a static document.
|
|
|
|
// Static documents are an exception because any sub-documents need an
|
|
|
|
// nsFrameLoader to keep the relevant docShell alive, even though the
|
|
|
|
// nsFrameLoader isn't used to load anything (the sub-document is created by
|
|
|
|
// the static clone process).
|
|
|
|
//
|
|
|
|
// We never create nsFrameLoaders for elements that are not
|
|
|
|
// in-composed-document, unless the element belongs to a static document.
|
|
|
|
// Static documents are an exception because this method is called at a point
|
|
|
|
// in the static clone process before aOwner has been inserted into its
|
|
|
|
// document. For other types of documents this wouldn't be a problem since
|
|
|
|
// we'd create the nsFrameLoader as necessary after aOwner is inserted into a
|
|
|
|
// document, but the mechanisms that take care of that don't apply for static
|
|
|
|
// documents so we need to create the nsFrameLoader now. (This isn't wasteful
|
|
|
|
// since for a static document we know aOwner will end up in a document and
|
|
|
|
// the nsFrameLoader will be used for its docShell.)
|
|
|
|
//
|
2013-06-19 01:25:50 +04:00
|
|
|
NS_ENSURE_TRUE(!doc->IsResourceDoc() &&
|
2016-05-17 16:18:22 +03:00
|
|
|
((!doc->IsLoadedAsData() && aOwner->IsInComposedDoc()) ||
|
|
|
|
doc->IsStaticDocument()),
|
2012-07-30 18:20:58 +04:00
|
|
|
nullptr);
|
2009-08-19 13:09:26 +04:00
|
|
|
|
2016-10-17 17:37:50 +03:00
|
|
|
return new nsFrameLoader(aOwner, aOpener, aNetworkCreated);
|
2009-08-19 13:09:26 +04:00
|
|
|
}
|
|
|
|
|
2005-02-09 00:30:47 +03:00
|
|
|
NS_IMETHODIMP
|
2002-04-17 08:17:16 +04:00
|
|
|
nsFrameLoader::LoadFrame()
|
2002-01-29 09:27:27 +03:00
|
|
|
{
|
2002-04-17 08:17:16 +04:00
|
|
|
NS_ENSURE_TRUE(mOwnerContent, NS_ERROR_NOT_INITIALIZED);
|
2002-01-29 09:27:27 +03:00
|
|
|
|
2002-04-17 08:17:16 +04:00
|
|
|
nsAutoString src;
|
2002-01-29 09:27:27 +03:00
|
|
|
|
2015-03-03 14:08:59 +03:00
|
|
|
bool isSrcdoc = mOwnerContent->IsHTMLElement(nsGkAtoms::iframe) &&
|
2013-06-29 07:13:23 +04:00
|
|
|
mOwnerContent->HasAttr(kNameSpaceID_None, nsGkAtoms::srcdoc);
|
|
|
|
if (isSrcdoc) {
|
|
|
|
src.AssignLiteral("about:srcdoc");
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
GetURL(src);
|
|
|
|
|
|
|
|
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).
|
2015-03-03 14:08:59 +03:00
|
|
|
if (mOwnerContent->IsXULElement() &&
|
2013-06-29 07:13:23 +04:00
|
|
|
mOwnerContent->AttrValueIs(kNameSpaceID_None, nsGkAtoms::nodefaultsrc,
|
|
|
|
nsGkAtoms::_true, eCaseMatters)) {
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
src.AssignLiteral("about:blank");
|
2013-06-06 23:05:21 +04:00
|
|
|
}
|
2002-04-17 08:17:16 +04:00
|
|
|
}
|
2002-01-29 09:27:27 +03:00
|
|
|
|
2011-10-18 14:53:36 +04:00
|
|
|
nsIDocument* doc = mOwnerContent->OwnerDoc();
|
2011-10-18 15:19:44 +04:00
|
|
|
if (doc->IsStaticDocument()) {
|
2005-09-21 23:14:30 +04:00
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2016-05-12 19:22:25 +03:00
|
|
|
if (doc->IsLoadedAsInteractiveData()) {
|
|
|
|
// XBL bindings doc shouldn't load sub-documents.
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2005-05-01 17:06:48 +04:00
|
|
|
nsCOMPtr<nsIURI> base_uri = mOwnerContent->GetBaseURI();
|
|
|
|
const nsAFlatCString &doc_charset = doc->GetDocumentCharacterSet();
|
2012-07-30 18:20:58 +04:00
|
|
|
const char *charset = doc_charset.IsEmpty() ? nullptr : doc_charset.get();
|
2002-04-17 08:17:16 +04:00
|
|
|
|
|
|
|
nsCOMPtr<nsIURI> uri;
|
2006-01-17 21:13:31 +03:00
|
|
|
nsresult rv = NS_NewURI(getter_AddRefs(uri), src, charset, base_uri);
|
|
|
|
|
|
|
|
// 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"),
|
2009-03-17 03:59:33 +03:00
|
|
|
charset, base_uri);
|
2006-01-17 21:13:31 +03:00
|
|
|
}
|
|
|
|
|
2010-02-25 05:45:43 +03:00
|
|
|
if (NS_SUCCEEDED(rv)) {
|
|
|
|
rv = LoadURI(uri);
|
|
|
|
}
|
2015-11-24 04:40:02 +03:00
|
|
|
|
2010-02-25 05:45:43 +03:00
|
|
|
if (NS_FAILED(rv)) {
|
|
|
|
FireErrorEvent();
|
|
|
|
|
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
nsFrameLoader::FireErrorEvent()
|
|
|
|
{
|
2014-03-17 10:56:54 +04:00
|
|
|
if (!mOwnerContent) {
|
|
|
|
return;
|
2010-02-25 05:45:43 +03:00
|
|
|
}
|
2015-10-18 08:24:48 +03:00
|
|
|
RefPtr<AsyncEventDispatcher > loadBlockingAsyncDispatcher =
|
2014-03-17 10:56:54 +04:00
|
|
|
new LoadBlockingAsyncEventDispatcher(mOwnerContent,
|
|
|
|
NS_LITERAL_STRING("error"),
|
|
|
|
false, false);
|
|
|
|
loadBlockingAsyncDispatcher->PostDOMEvent();
|
2005-09-21 23:14:30 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
nsFrameLoader::LoadURI(nsIURI* aURI)
|
|
|
|
{
|
|
|
|
if (!aURI)
|
|
|
|
return NS_ERROR_INVALID_POINTER;
|
2008-03-21 14:44:09 +03:00
|
|
|
NS_ENSURE_STATE(!mDestroyCalled && mOwnerContent);
|
2005-09-21 23:14:30 +04:00
|
|
|
|
2011-10-18 14:53:36 +04:00
|
|
|
nsCOMPtr<nsIDocument> doc = mOwnerContent->OwnerDoc();
|
2005-09-21 23:14:30 +04:00
|
|
|
|
2008-03-21 14:44:09 +03:00
|
|
|
nsresult rv = CheckURILoad(aURI);
|
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
|
|
|
|
mURIToLoad = aURI;
|
|
|
|
rv = doc->InitializeFrameLoader(this);
|
|
|
|
if (NS_FAILED(rv)) {
|
2012-07-30 18:20:58 +04:00
|
|
|
mURIToLoad = nullptr;
|
2008-03-21 14:44:09 +03:00
|
|
|
}
|
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
|
2015-01-05 22:16:09 +03:00
|
|
|
NS_IMETHODIMP
|
|
|
|
nsFrameLoader::SetIsPrerendered()
|
|
|
|
{
|
|
|
|
MOZ_ASSERT(!mDocShell, "Please call SetIsPrerendered before docShell is created");
|
|
|
|
mIsPrerendered = true;
|
|
|
|
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2016-05-20 06:36:27 +03:00
|
|
|
NS_IMETHODIMP
|
|
|
|
nsFrameLoader::MakePrerenderedLoaderActive()
|
|
|
|
{
|
|
|
|
MOZ_ASSERT(mIsPrerendered, "This frameloader was not in prerendered mode.");
|
|
|
|
|
|
|
|
mIsPrerendered = false;
|
|
|
|
if (IsRemoteFrame()) {
|
|
|
|
if (!mRemoteBrowser) {
|
|
|
|
NS_WARNING("Missing remote browser.");
|
|
|
|
return NS_ERROR_FAILURE;
|
|
|
|
}
|
|
|
|
|
|
|
|
mRemoteBrowser->SetDocShellIsActive(true);
|
|
|
|
} else {
|
|
|
|
if (!mDocShell) {
|
|
|
|
NS_WARNING("Missing docshell.");
|
|
|
|
return NS_ERROR_FAILURE;
|
|
|
|
}
|
|
|
|
|
|
|
|
nsresult rv = mDocShell->SetIsActive(true);
|
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
}
|
|
|
|
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2016-10-14 10:31:02 +03:00
|
|
|
NS_IMETHODIMP
|
2016-12-22 11:06:50 +03:00
|
|
|
nsFrameLoader::GetPartialSHistory(nsIPartialSHistory** aResult)
|
2016-10-14 10:31:02 +03:00
|
|
|
{
|
2016-12-22 11:06:50 +03:00
|
|
|
if (mRemoteBrowser && !mPartialSHistory) {
|
2016-10-14 10:31:02 +03:00
|
|
|
// For remote case we can lazy initialize PartialSHistory since
|
|
|
|
// it doens't need to be registered as a listener to nsISHistory directly.
|
2016-12-22 11:06:50 +03:00
|
|
|
mPartialSHistory = new PartialSHistory(this);
|
2016-10-14 10:31:02 +03:00
|
|
|
}
|
|
|
|
|
2016-12-22 11:06:50 +03:00
|
|
|
nsCOMPtr<nsIPartialSHistory> partialHistory(mPartialSHistory);
|
2016-10-14 10:31:02 +03:00
|
|
|
partialHistory.forget(aResult);
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2016-12-19 10:03:17 +03:00
|
|
|
NS_IMETHODIMP
|
|
|
|
nsFrameLoader::EnsureGroupedSHistory(nsIGroupedSHistory** aResult)
|
|
|
|
{
|
|
|
|
nsCOMPtr<nsIPartialSHistory> partialHistory;
|
2016-12-22 11:06:50 +03:00
|
|
|
GetPartialSHistory(getter_AddRefs(partialHistory));
|
2016-12-19 10:03:17 +03:00
|
|
|
MOZ_ASSERT(partialHistory);
|
|
|
|
|
|
|
|
nsCOMPtr<nsIGroupedSHistory> groupedHistory;
|
|
|
|
partialHistory->GetGroupedSHistory(getter_AddRefs(groupedHistory));
|
|
|
|
if (!groupedHistory) {
|
|
|
|
groupedHistory = new GroupedSHistory();
|
2016-12-22 11:06:50 +03:00
|
|
|
groupedHistory->AppendPartialSHistory(partialHistory);
|
2016-12-19 10:03:17 +03:00
|
|
|
|
|
|
|
#ifdef DEBUG
|
|
|
|
nsCOMPtr<nsIGroupedSHistory> test;
|
2016-12-22 11:06:50 +03:00
|
|
|
GetGroupedSHistory(getter_AddRefs(test));
|
2016-12-19 10:03:17 +03:00
|
|
|
MOZ_ASSERT(test == groupedHistory, "GroupedHistory must match");
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
groupedHistory.forget(aResult);
|
|
|
|
return NS_OK;
|
|
|
|
}
|
2016-10-14 10:31:02 +03:00
|
|
|
|
|
|
|
NS_IMETHODIMP
|
2016-12-22 11:06:50 +03:00
|
|
|
nsFrameLoader::GetGroupedSHistory(nsIGroupedSHistory** aResult)
|
2016-10-14 10:31:02 +03:00
|
|
|
{
|
2016-12-19 10:03:17 +03:00
|
|
|
nsCOMPtr<nsIGroupedSHistory> groupedSHistory;
|
2016-12-22 11:06:50 +03:00
|
|
|
if (mPartialSHistory) {
|
|
|
|
mPartialSHistory->GetGroupedSHistory(getter_AddRefs(groupedSHistory));
|
2016-12-19 10:03:17 +03:00
|
|
|
}
|
|
|
|
groupedSHistory.forget(aResult);
|
2016-10-14 10:31:02 +03:00
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2016-11-09 22:51:02 +03:00
|
|
|
bool
|
|
|
|
nsFrameLoader::SwapBrowsersAndNotify(nsFrameLoader* aOther)
|
2016-10-14 10:31:02 +03:00
|
|
|
{
|
2016-11-09 22:51:02 +03:00
|
|
|
// Cache the owner content before calling SwapBrowsers, which will change
|
|
|
|
// these member variables.
|
|
|
|
RefPtr<mozilla::dom::Element> primaryContent = mOwnerContent;
|
|
|
|
RefPtr<mozilla::dom::Element> secondaryContent = aOther->mOwnerContent;
|
|
|
|
|
|
|
|
// Swap loaders through our owner, so the owner's listeners will be correctly
|
|
|
|
// setup.
|
|
|
|
nsCOMPtr<nsIBrowser> ourBrowser = do_QueryInterface(primaryContent);
|
|
|
|
nsCOMPtr<nsIBrowser> otherBrowser = do_QueryInterface(secondaryContent);
|
|
|
|
if (NS_WARN_IF(!ourBrowser || !otherBrowser)) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
nsresult rv = ourBrowser->SwapBrowsers(otherBrowser, nsIBrowser::SWAP_KEEP_PERMANENT_KEY);
|
|
|
|
if (NS_WARN_IF(NS_FAILED(rv))) {
|
|
|
|
return false;
|
2016-10-14 10:31:02 +03:00
|
|
|
}
|
|
|
|
|
2016-11-09 22:51:02 +03:00
|
|
|
// Dispatch the BrowserChangedProcess event to tell JS that the process swap
|
|
|
|
// has occurred.
|
|
|
|
GroupedHistoryEventInit eventInit;
|
|
|
|
eventInit.mBubbles = true;
|
|
|
|
eventInit.mCancelable= false;
|
|
|
|
eventInit.mOtherBrowser = secondaryContent;
|
|
|
|
RefPtr<GroupedHistoryEvent> event =
|
|
|
|
GroupedHistoryEvent::Constructor(primaryContent,
|
|
|
|
NS_LITERAL_STRING("BrowserChangedProcess"),
|
|
|
|
eventInit);
|
|
|
|
event->SetTrusted(true);
|
|
|
|
bool dummy;
|
|
|
|
primaryContent->DispatchEvent(event, &dummy);
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2016-12-22 11:06:50 +03:00
|
|
|
class AppendPartialSHistoryAndSwapHelper : public PromiseNativeHandler
|
2016-11-09 22:51:02 +03:00
|
|
|
{
|
|
|
|
public:
|
|
|
|
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
|
2016-12-22 11:06:50 +03:00
|
|
|
NS_DECL_CYCLE_COLLECTION_CLASS(AppendPartialSHistoryAndSwapHelper)
|
2016-11-09 22:51:02 +03:00
|
|
|
|
2016-12-22 11:06:50 +03:00
|
|
|
AppendPartialSHistoryAndSwapHelper(nsFrameLoader* aThis,
|
|
|
|
nsFrameLoader* aOther,
|
|
|
|
Promise* aPromise)
|
2016-11-09 22:51:02 +03:00
|
|
|
: mThis(aThis), mOther(aOther), mPromise(aPromise) {}
|
|
|
|
|
|
|
|
void
|
|
|
|
ResolvedCallback(JSContext* aCx, JS::Handle<JS::Value> aValue) override
|
|
|
|
{
|
|
|
|
nsCOMPtr<nsIGroupedSHistory> otherGroupedHistory;
|
2016-12-22 11:06:50 +03:00
|
|
|
mOther->GetGroupedSHistory(getter_AddRefs(otherGroupedHistory));
|
2016-11-09 22:51:02 +03:00
|
|
|
MOZ_ASSERT(!otherGroupedHistory,
|
|
|
|
"Cannot append a GroupedSHistory owner to another.");
|
|
|
|
if (otherGroupedHistory) {
|
|
|
|
mPromise->MaybeRejectWithUndefined();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Append ourselves.
|
|
|
|
nsresult rv;
|
2016-12-19 10:03:17 +03:00
|
|
|
nsCOMPtr<nsIGroupedSHistory> groupedSHistory;
|
|
|
|
rv = mThis->EnsureGroupedSHistory(getter_AddRefs(groupedSHistory));
|
|
|
|
if (NS_WARN_IF(NS_FAILED(rv))) {
|
|
|
|
mPromise->MaybeRejectWithUndefined();
|
|
|
|
return;
|
2016-11-09 22:51:02 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
// Append the other.
|
|
|
|
nsCOMPtr<nsIPartialSHistory> otherPartialSHistory;
|
2016-12-22 11:06:50 +03:00
|
|
|
MOZ_ALWAYS_SUCCEEDS(mOther->GetPartialSHistory(getter_AddRefs(otherPartialSHistory)));
|
|
|
|
rv = groupedSHistory->AppendPartialSHistory(otherPartialSHistory);
|
2016-11-09 22:51:02 +03:00
|
|
|
if (NS_WARN_IF(NS_FAILED(rv))) {
|
|
|
|
mPromise->MaybeRejectWithUndefined();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Swap the browsers and fire the BrowserChangedProcess event.
|
|
|
|
if (mThis->SwapBrowsersAndNotify(mOther)) {
|
|
|
|
mPromise->MaybeResolveWithUndefined();
|
|
|
|
} else {
|
|
|
|
mPromise->MaybeRejectWithUndefined();
|
|
|
|
}
|
2016-10-14 10:31:02 +03:00
|
|
|
}
|
|
|
|
|
2016-11-09 22:51:02 +03:00
|
|
|
void
|
|
|
|
RejectedCallback(JSContext* aCx, JS::Handle<JS::Value> aValue) override
|
|
|
|
{
|
|
|
|
mPromise->MaybeRejectWithUndefined();
|
|
|
|
}
|
|
|
|
|
|
|
|
private:
|
2016-12-22 11:06:50 +03:00
|
|
|
~AppendPartialSHistoryAndSwapHelper() {}
|
2016-11-09 22:51:02 +03:00
|
|
|
RefPtr<nsFrameLoader> mThis;
|
|
|
|
RefPtr<nsFrameLoader> mOther;
|
|
|
|
RefPtr<Promise> mPromise;
|
|
|
|
};
|
|
|
|
|
2016-12-22 11:06:50 +03:00
|
|
|
NS_IMPL_CYCLE_COLLECTING_ADDREF(AppendPartialSHistoryAndSwapHelper)
|
|
|
|
NS_IMPL_CYCLE_COLLECTING_RELEASE(AppendPartialSHistoryAndSwapHelper)
|
|
|
|
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(AppendPartialSHistoryAndSwapHelper)
|
2016-11-09 22:51:02 +03:00
|
|
|
NS_INTERFACE_MAP_ENTRY(nsISupports)
|
|
|
|
NS_INTERFACE_MAP_END
|
2016-12-22 11:06:50 +03:00
|
|
|
NS_IMPL_CYCLE_COLLECTION(AppendPartialSHistoryAndSwapHelper,
|
2016-11-09 22:51:02 +03:00
|
|
|
mThis, mPromise)
|
|
|
|
|
|
|
|
class RequestGroupedHistoryNavigationHelper : public PromiseNativeHandler
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
|
|
|
|
NS_DECL_CYCLE_COLLECTION_CLASS(RequestGroupedHistoryNavigationHelper)
|
|
|
|
|
|
|
|
RequestGroupedHistoryNavigationHelper(nsFrameLoader* aThis,
|
|
|
|
uint32_t aGlobalIndex,
|
|
|
|
Promise* aPromise)
|
|
|
|
: mThis(aThis), mGlobalIndex(aGlobalIndex), mPromise(aPromise) {}
|
|
|
|
|
|
|
|
void
|
|
|
|
ResolvedCallback(JSContext* aCx, JS::Handle<JS::Value> aValue) override
|
|
|
|
{
|
2016-12-13 11:32:54 +03:00
|
|
|
if (NS_WARN_IF(!mThis->mOwnerContent)) {
|
|
|
|
mPromise->MaybeRejectWithUndefined();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2016-12-19 10:03:17 +03:00
|
|
|
nsCOMPtr<nsIGroupedSHistory> groupedSHistory;
|
2016-12-22 11:06:50 +03:00
|
|
|
mThis->GetGroupedSHistory(getter_AddRefs(groupedSHistory));
|
2016-12-19 10:03:17 +03:00
|
|
|
if (NS_WARN_IF(!groupedSHistory)) {
|
|
|
|
mPromise->MaybeRejectWithUndefined();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2016-11-09 22:51:02 +03:00
|
|
|
// Navigate the loader to the new index
|
|
|
|
nsCOMPtr<nsIFrameLoader> otherLoader;
|
2016-12-19 10:03:17 +03:00
|
|
|
nsresult rv = groupedSHistory->GotoIndex(mGlobalIndex, getter_AddRefs(otherLoader));
|
2016-12-13 11:32:54 +03:00
|
|
|
|
|
|
|
// Check if the gotoIndex failed because the target frameloader is dead. We
|
|
|
|
// need to perform a navigateAndRestoreByIndex and then return to recover.
|
|
|
|
if (rv == NS_ERROR_NOT_AVAILABLE) {
|
|
|
|
// Get the nsIXULBrowserWindow so that we can call NavigateAndRestoreByIndex on it.
|
|
|
|
nsCOMPtr<nsIDocShell> docShell = mThis->mOwnerContent->OwnerDoc()->GetDocShell();
|
|
|
|
if (NS_WARN_IF(!docShell)) {
|
|
|
|
mPromise->MaybeRejectWithUndefined();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
nsCOMPtr<nsIDocShellTreeOwner> treeOwner;
|
|
|
|
docShell->GetTreeOwner(getter_AddRefs(treeOwner));
|
|
|
|
if (NS_WARN_IF(!treeOwner)) {
|
|
|
|
mPromise->MaybeRejectWithUndefined();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
nsCOMPtr<nsIXULWindow> window = do_GetInterface(treeOwner);
|
|
|
|
if (NS_WARN_IF(!window)) {
|
|
|
|
mPromise->MaybeRejectWithUndefined();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
nsCOMPtr<nsIXULBrowserWindow> xbw;
|
|
|
|
window->GetXULBrowserWindow(getter_AddRefs(xbw));
|
|
|
|
if (NS_WARN_IF(!xbw)) {
|
|
|
|
mPromise->MaybeRejectWithUndefined();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
nsCOMPtr<nsIBrowser> ourBrowser = do_QueryInterface(mThis->mOwnerContent);
|
|
|
|
if (NS_WARN_IF(!ourBrowser)) {
|
|
|
|
mPromise->MaybeRejectWithUndefined();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
rv = xbw->NavigateAndRestoreByIndex(ourBrowser, mGlobalIndex);
|
|
|
|
if (NS_WARN_IF(NS_FAILED(rv))) {
|
|
|
|
mPromise->MaybeRejectWithUndefined();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
mPromise->MaybeResolveWithUndefined();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Check for any other type of failure
|
|
|
|
if (NS_WARN_IF(NS_FAILED(rv))) {
|
2016-11-09 22:51:02 +03:00
|
|
|
mPromise->MaybeRejectWithUndefined();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2016-12-13 11:32:54 +03:00
|
|
|
// Perform the swap.
|
|
|
|
nsFrameLoader* other = static_cast<nsFrameLoader*>(otherLoader.get());
|
|
|
|
if (!other || other == mThis) {
|
2016-11-09 22:51:02 +03:00
|
|
|
mPromise->MaybeRejectWithUndefined();
|
|
|
|
return;
|
2016-10-14 10:31:02 +03:00
|
|
|
}
|
2016-11-09 22:51:02 +03:00
|
|
|
|
|
|
|
// Swap the browsers and fire the BrowserChangedProcess event.
|
|
|
|
if (mThis->SwapBrowsersAndNotify(other)) {
|
|
|
|
mPromise->MaybeResolveWithUndefined();
|
|
|
|
} else {
|
|
|
|
mPromise->MaybeRejectWithUndefined();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
RejectedCallback(JSContext* aCx, JS::Handle<JS::Value> aValue) override
|
|
|
|
{
|
|
|
|
mPromise->MaybeRejectWithUndefined();
|
|
|
|
}
|
|
|
|
|
|
|
|
private:
|
|
|
|
~RequestGroupedHistoryNavigationHelper() {}
|
|
|
|
RefPtr<nsFrameLoader> mThis;
|
|
|
|
uint32_t mGlobalIndex;
|
|
|
|
RefPtr<Promise> mPromise;
|
|
|
|
};
|
|
|
|
|
|
|
|
NS_IMPL_CYCLE_COLLECTING_ADDREF(RequestGroupedHistoryNavigationHelper)
|
|
|
|
NS_IMPL_CYCLE_COLLECTING_RELEASE(RequestGroupedHistoryNavigationHelper)
|
|
|
|
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(RequestGroupedHistoryNavigationHelper)
|
|
|
|
NS_INTERFACE_MAP_ENTRY(nsISupports)
|
|
|
|
NS_INTERFACE_MAP_END
|
|
|
|
NS_IMPL_CYCLE_COLLECTION(RequestGroupedHistoryNavigationHelper,
|
|
|
|
mThis, mPromise)
|
|
|
|
|
|
|
|
already_AddRefed<Promise>
|
|
|
|
nsFrameLoader::FireWillChangeProcessEvent()
|
|
|
|
{
|
|
|
|
AutoJSAPI jsapi;
|
|
|
|
if (NS_WARN_IF(!jsapi.Init(mOwnerContent->GetOwnerGlobal()))) {
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
JSContext* cx = jsapi.cx();
|
|
|
|
GlobalObject global(cx, mOwnerContent->GetOwnerGlobal()->GetGlobalJSObject());
|
|
|
|
MOZ_ASSERT(!global.Failed());
|
|
|
|
|
|
|
|
// Set our mBrowserChangingProcessBlockers property to refer to the blockers
|
|
|
|
// list. We will synchronously dispatch a DOM event to collect this list of
|
|
|
|
// blockers.
|
|
|
|
nsTArray<RefPtr<Promise>> blockers;
|
|
|
|
mBrowserChangingProcessBlockers = &blockers;
|
|
|
|
|
|
|
|
GroupedHistoryEventInit eventInit;
|
|
|
|
eventInit.mBubbles = true;
|
|
|
|
eventInit.mCancelable = false;
|
|
|
|
eventInit.mOtherBrowser = nullptr;
|
|
|
|
RefPtr<GroupedHistoryEvent> event =
|
|
|
|
GroupedHistoryEvent::Constructor(mOwnerContent,
|
|
|
|
NS_LITERAL_STRING("BrowserWillChangeProcess"),
|
|
|
|
eventInit);
|
|
|
|
event->SetTrusted(true);
|
|
|
|
bool dummy;
|
|
|
|
mOwnerContent->DispatchEvent(event, &dummy);
|
|
|
|
|
|
|
|
mBrowserChangingProcessBlockers = nullptr;
|
|
|
|
|
|
|
|
ErrorResult rv;
|
|
|
|
RefPtr<Promise> allPromise = Promise::All(global, blockers, rv);
|
|
|
|
return allPromise.forget();
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
2016-12-22 11:06:50 +03:00
|
|
|
nsFrameLoader::AppendPartialSHistoryAndSwap(nsIFrameLoader* aOther, nsISupports** aPromise)
|
2016-11-09 22:51:02 +03:00
|
|
|
{
|
|
|
|
if (!aOther) {
|
|
|
|
return NS_ERROR_INVALID_POINTER;
|
2016-10-14 10:31:02 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
if (aOther == this) {
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
RefPtr<nsFrameLoader> otherLoader = static_cast<nsFrameLoader*>(aOther);
|
|
|
|
|
2016-11-09 22:51:02 +03:00
|
|
|
RefPtr<Promise> ready = FireWillChangeProcessEvent();
|
|
|
|
if (NS_WARN_IF(!ready)) {
|
2016-10-14 10:31:02 +03:00
|
|
|
return NS_ERROR_FAILURE;
|
|
|
|
}
|
2016-11-09 22:51:02 +03:00
|
|
|
|
|
|
|
// This promise will be resolved when the swap has finished, we return it now
|
|
|
|
// and pass it to our helper so our helper can resolve it.
|
|
|
|
ErrorResult rv;
|
|
|
|
RefPtr<Promise> complete = Promise::Create(mOwnerContent->GetOwnerGlobal(), rv);
|
|
|
|
if (NS_WARN_IF(rv.Failed())) {
|
|
|
|
return rv.StealNSResult();
|
2016-10-14 10:31:02 +03:00
|
|
|
}
|
|
|
|
|
2016-11-09 22:51:02 +03:00
|
|
|
// Attach our handler to the ready promise, and make it fulfil the complete
|
|
|
|
// promise when we are done.
|
2016-12-22 11:06:50 +03:00
|
|
|
RefPtr<AppendPartialSHistoryAndSwapHelper> helper =
|
|
|
|
new AppendPartialSHistoryAndSwapHelper(this, otherLoader, complete);
|
2016-11-09 22:51:02 +03:00
|
|
|
ready->AppendNativeHandler(helper);
|
|
|
|
complete.forget(aPromise);
|
2016-10-14 10:31:02 +03:00
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
2016-11-09 22:51:02 +03:00
|
|
|
nsFrameLoader::RequestGroupedHistoryNavigation(uint32_t aGlobalIndex, nsISupports** aPromise)
|
2016-10-14 10:31:02 +03:00
|
|
|
{
|
|
|
|
|
2016-11-09 22:51:02 +03:00
|
|
|
RefPtr<Promise> ready = FireWillChangeProcessEvent();
|
|
|
|
if (NS_WARN_IF(!ready)) {
|
2016-10-14 10:31:02 +03:00
|
|
|
return NS_ERROR_FAILURE;
|
|
|
|
}
|
|
|
|
|
2016-11-09 22:51:02 +03:00
|
|
|
// This promise will be resolved when the swap has finished, we return it now
|
|
|
|
// and pass it to our helper so our helper can resolve it.
|
|
|
|
ErrorResult rv;
|
|
|
|
RefPtr<Promise> complete = Promise::Create(mOwnerContent->GetOwnerGlobal(), rv);
|
|
|
|
if (NS_WARN_IF(rv.Failed())) {
|
|
|
|
return rv.StealNSResult();
|
2016-10-14 10:31:02 +03:00
|
|
|
}
|
|
|
|
|
2016-11-09 22:51:02 +03:00
|
|
|
// Attach our handler to the ready promise, and make it fulfil the complete
|
|
|
|
// promise when we are done.
|
|
|
|
RefPtr<RequestGroupedHistoryNavigationHelper> helper =
|
|
|
|
new RequestGroupedHistoryNavigationHelper(this, aGlobalIndex, complete);
|
|
|
|
ready->AppendNativeHandler(helper);
|
|
|
|
complete.forget(aPromise);
|
|
|
|
return NS_OK;
|
|
|
|
}
|
2016-10-14 10:31:02 +03:00
|
|
|
|
2016-11-09 22:51:02 +03:00
|
|
|
NS_IMETHODIMP
|
|
|
|
nsFrameLoader::AddProcessChangeBlockingPromise(js::Handle<js::Value> aPromise,
|
|
|
|
JSContext* aCx)
|
|
|
|
{
|
|
|
|
nsCOMPtr<nsIGlobalObject> go = xpc::NativeGlobal(JS::CurrentGlobalOrNull(aCx));
|
|
|
|
if (!go) {
|
2016-10-14 10:31:02 +03:00
|
|
|
return NS_ERROR_FAILURE;
|
|
|
|
}
|
2016-11-09 22:51:02 +03:00
|
|
|
ErrorResult rv;
|
|
|
|
RefPtr<Promise> promise = Promise::Resolve(go, aCx, aPromise, rv);
|
|
|
|
if (NS_WARN_IF(rv.Failed())) {
|
|
|
|
return rv.StealNSResult();
|
|
|
|
}
|
|
|
|
|
|
|
|
if (NS_WARN_IF(!mBrowserChangingProcessBlockers)) {
|
|
|
|
return NS_ERROR_DOM_INVALID_STATE_ERR;
|
2016-10-14 10:31:02 +03:00
|
|
|
}
|
|
|
|
|
2016-11-09 22:51:02 +03:00
|
|
|
mBrowserChangingProcessBlockers->AppendElement(promise);
|
2016-10-14 10:31:02 +03:00
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2008-03-21 14:44:09 +03:00
|
|
|
nsresult
|
|
|
|
nsFrameLoader::ReallyStartLoading()
|
2010-02-25 05:45:43 +03:00
|
|
|
{
|
|
|
|
nsresult rv = ReallyStartLoadingInternal();
|
|
|
|
if (NS_FAILED(rv)) {
|
|
|
|
FireErrorEvent();
|
|
|
|
}
|
2015-11-24 04:40:02 +03:00
|
|
|
|
2010-02-25 05:45:43 +03:00
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
|
|
|
|
nsresult
|
|
|
|
nsFrameLoader::ReallyStartLoadingInternal()
|
2008-03-21 14:44:09 +03:00
|
|
|
{
|
2015-02-24 17:41:43 +03:00
|
|
|
NS_ENSURE_STATE(mURIToLoad && mOwnerContent && mOwnerContent->IsInComposedDoc());
|
2009-07-01 00:39:22 +04:00
|
|
|
|
2014-05-24 01:12:29 +04:00
|
|
|
PROFILER_LABEL("nsFrameLoader", "ReallyStartLoading",
|
|
|
|
js::ProfileEntry::Category::OTHER);
|
2013-01-31 10:40:43 +04:00
|
|
|
|
2015-07-31 12:28:36 +03:00
|
|
|
if (IsRemoteFrame()) {
|
2015-04-07 05:56:10 +03:00
|
|
|
if (!mRemoteBrowser && !TryRemoteBrowser()) {
|
2010-10-20 15:44:50 +04:00
|
|
|
NS_WARNING("Couldn't create child process for iframe.");
|
|
|
|
return NS_ERROR_FAILURE;
|
2009-10-16 23:42:27 +04:00
|
|
|
}
|
|
|
|
|
2015-04-07 05:56:10 +03:00
|
|
|
// FIXME get error codes from child
|
|
|
|
mRemoteBrowser->LoadURL(mURIToLoad);
|
2015-11-24 04:40:02 +03:00
|
|
|
|
2015-04-07 05:56:10 +03:00
|
|
|
if (!mRemoteBrowserShown && !ShowRemoteFrame(ScreenIntSize(0, 0))) {
|
2012-04-25 20:35:58 +04:00
|
|
|
NS_WARNING("[nsFrameLoader] ReallyStartLoadingInternal tried but couldn't show remote browser.\n");
|
|
|
|
}
|
|
|
|
|
2009-07-01 00:39:22 +04:00
|
|
|
return NS_OK;
|
|
|
|
}
|
2008-03-21 14:44:09 +03:00
|
|
|
|
2015-07-31 12:28:36 +03:00
|
|
|
nsresult rv = MaybeCreateDocShell();
|
|
|
|
if (NS_FAILED(rv)) {
|
|
|
|
return rv;
|
|
|
|
}
|
2009-10-16 23:42:27 +04:00
|
|
|
NS_ASSERTION(mDocShell,
|
|
|
|
"MaybeCreateDocShell succeeded with a null mDocShell");
|
|
|
|
|
|
|
|
// Just to be safe, recheck uri.
|
|
|
|
rv = CheckURILoad(mURIToLoad);
|
2002-04-17 08:17:16 +04:00
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
2002-01-29 09:27:27 +03:00
|
|
|
|
|
|
|
nsCOMPtr<nsIDocShellLoadInfo> loadInfo;
|
|
|
|
mDocShell->CreateLoadInfo(getter_AddRefs(loadInfo));
|
|
|
|
NS_ENSURE_TRUE(loadInfo, NS_ERROR_FAILURE);
|
|
|
|
|
2013-03-15 21:25:31 +04:00
|
|
|
// If this frame is sandboxed with respect to origin we will set it up with
|
|
|
|
// a null principal later in nsDocShell::DoURILoad.
|
2012-08-20 22:34:32 +04:00
|
|
|
// We do it there to correctly sandbox content that was loaded into
|
2013-03-15 21:25:31 +04:00
|
|
|
// the frame via other methods than the src attribute.
|
2012-06-22 14:04:47 +04:00
|
|
|
// 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!
|
2016-07-28 10:20:41 +03:00
|
|
|
loadInfo->SetTriggeringPrincipal(mOwnerContent->NodePrincipal());
|
2008-03-21 14:44:09 +03:00
|
|
|
|
|
|
|
nsCOMPtr<nsIURI> referrer;
|
2015-11-24 04:40:02 +03:00
|
|
|
|
2013-06-29 07:13:23 +04:00
|
|
|
nsAutoString srcdoc;
|
2015-03-03 14:08:59 +03:00
|
|
|
bool isSrcdoc = mOwnerContent->IsHTMLElement(nsGkAtoms::iframe) &&
|
2013-06-29 07:13:23 +04:00
|
|
|
mOwnerContent->GetAttr(kNameSpaceID_None, nsGkAtoms::srcdoc,
|
|
|
|
srcdoc);
|
|
|
|
|
|
|
|
if (isSrcdoc) {
|
|
|
|
nsAutoString referrerStr;
|
|
|
|
mOwnerContent->OwnerDoc()->GetReferrer(referrerStr);
|
|
|
|
rv = NS_NewURI(getter_AddRefs(referrer), referrerStr);
|
|
|
|
|
|
|
|
loadInfo->SetSrcdocData(srcdoc);
|
2014-02-06 18:46:29 +04:00
|
|
|
nsCOMPtr<nsIURI> baseURI = mOwnerContent->GetBaseURI();
|
|
|
|
loadInfo->SetBaseURI(baseURI);
|
2013-06-29 07:13:23 +04:00
|
|
|
}
|
|
|
|
else {
|
|
|
|
rv = mOwnerContent->NodePrincipal()->GetURI(getter_AddRefs(referrer));
|
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
}
|
2008-03-21 14:44:09 +03:00
|
|
|
|
2014-03-29 23:10:27 +04:00
|
|
|
// Use referrer as long as it is not an nsNullPrincipalURI.
|
|
|
|
// We could add a method such as GetReferrerURI to principals to make this
|
|
|
|
// cleaner, but given that we need to start using Source Browsing Context for
|
|
|
|
// referrer (see Bug 960639) this may be wasted effort at this stage.
|
|
|
|
if (referrer) {
|
|
|
|
bool isNullPrincipalScheme;
|
|
|
|
rv = referrer->SchemeIs(NS_NULLPRINCIPAL_SCHEME, &isNullPrincipalScheme);
|
|
|
|
if (NS_SUCCEEDED(rv) && !isNullPrincipalScheme) {
|
|
|
|
loadInfo->SetReferrer(referrer);
|
|
|
|
}
|
|
|
|
}
|
2008-03-21 14:44:09 +03:00
|
|
|
|
2015-07-17 20:46:19 +03:00
|
|
|
// get referrer policy for this iframe:
|
|
|
|
// first load document wide policy, then
|
|
|
|
// load iframe referrer attribute if enabled in preferences
|
|
|
|
// per element referrer overrules document wide referrer if enabled
|
|
|
|
net::ReferrerPolicy referrerPolicy = mOwnerContent->OwnerDoc()->GetReferrerPolicy();
|
|
|
|
HTMLIFrameElement* iframe = HTMLIFrameElement::FromContent(mOwnerContent);
|
|
|
|
if (iframe) {
|
2015-12-01 03:13:03 +03:00
|
|
|
net::ReferrerPolicy iframeReferrerPolicy = iframe->GetReferrerPolicyAsEnum();
|
2015-07-17 20:46:19 +03:00
|
|
|
if (iframeReferrerPolicy != net::RP_Unset) {
|
|
|
|
referrerPolicy = iframeReferrerPolicy;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
loadInfo->SetReferrerPolicy(referrerPolicy);
|
2014-11-18 16:46:29 +03:00
|
|
|
|
2012-10-26 12:46:27 +04:00
|
|
|
// Default flags:
|
|
|
|
int32_t flags = nsIWebNavigation::LOAD_FLAGS_NONE;
|
|
|
|
|
|
|
|
// Flags for browser frame:
|
2016-02-18 06:31:29 +03:00
|
|
|
if (OwnerIsMozBrowserFrame()) {
|
2012-10-26 12:46:27 +04:00
|
|
|
flags = nsIWebNavigation::LOAD_FLAGS_ALLOW_THIRD_PARTY_FIXUP |
|
2016-07-28 10:20:41 +03:00
|
|
|
nsIWebNavigation::LOAD_FLAGS_DISALLOW_INHERIT_PRINCIPAL;
|
2012-10-26 12:46:27 +04:00
|
|
|
}
|
|
|
|
|
2008-03-21 14:44:09 +03:00
|
|
|
// Kick off the load...
|
2011-09-29 10:19:26 +04:00
|
|
|
bool tmpState = mNeedsAsyncDestroy;
|
2011-10-17 18:59:28 +04:00
|
|
|
mNeedsAsyncDestroy = true;
|
2013-10-11 00:28:07 +04:00
|
|
|
nsCOMPtr<nsIURI> uriToLoad = mURIToLoad;
|
|
|
|
rv = mDocShell->LoadURI(uriToLoad, loadInfo, flags, false);
|
2009-01-14 14:01:46 +03:00
|
|
|
mNeedsAsyncDestroy = tmpState;
|
2012-07-30 18:20:58 +04:00
|
|
|
mURIToLoad = nullptr;
|
2010-02-25 05:45:43 +03:00
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
|
2008-03-21 14:44:09 +03:00
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
nsresult
|
|
|
|
nsFrameLoader::CheckURILoad(nsIURI* aURI)
|
|
|
|
{
|
2006-02-27 22:14:51 +03:00
|
|
|
// 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
|
|
|
|
// the principal of mOwnerContent. I don't think that leads to privilege
|
|
|
|
// escalation, and it's reasonably guaranteed to not lead to XSS issues
|
2006-02-28 08:21:17 +03:00
|
|
|
// (since caller can already access mOwnerContent in this case). So just use
|
2006-02-27 22:14:51 +03:00
|
|
|
// 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.
|
2005-10-14 13:07:29 +04:00
|
|
|
nsIScriptSecurityManager *secMan = nsContentUtils::GetSecurityManager();
|
2003-10-30 06:01:25 +03:00
|
|
|
|
2006-02-27 22:14:51 +03:00
|
|
|
// Get our principal
|
2006-04-27 22:21:11 +04:00
|
|
|
nsIPrincipal* principal = mOwnerContent->NodePrincipal();
|
2002-01-29 09:27:27 +03:00
|
|
|
|
|
|
|
// Check if we are allowed to load absURL
|
2008-03-21 14:44:09 +03:00
|
|
|
nsresult rv =
|
|
|
|
secMan->CheckLoadURIWithPrincipal(principal, aURI,
|
|
|
|
nsIScriptSecurityManager::STANDARD);
|
2002-01-29 09:27:27 +03:00
|
|
|
if (NS_FAILED(rv)) {
|
|
|
|
return rv; // We're not
|
|
|
|
}
|
|
|
|
|
2005-03-08 03:02:55 +03:00
|
|
|
// Bail out if this is an infinite recursion scenario
|
2015-07-31 12:28:36 +03:00
|
|
|
if (IsRemoteFrame()) {
|
2009-10-16 23:42:27 +04:00
|
|
|
return NS_OK;
|
|
|
|
}
|
2008-03-21 14:44:09 +03:00
|
|
|
return CheckForRecursiveLoad(aURI);
|
2002-01-29 09:27:27 +03:00
|
|
|
}
|
|
|
|
|
2005-02-09 00:30:47 +03:00
|
|
|
NS_IMETHODIMP
|
2002-01-29 09:27:27 +03:00
|
|
|
nsFrameLoader::GetDocShell(nsIDocShell **aDocShell)
|
|
|
|
{
|
2012-07-30 18:20:58 +04:00
|
|
|
*aDocShell = nullptr;
|
2011-06-15 04:29:10 +04:00
|
|
|
nsresult rv = NS_OK;
|
2002-04-26 02:06:49 +04:00
|
|
|
|
2015-07-31 12:28:36 +03:00
|
|
|
if (IsRemoteFrame()) {
|
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
|
2003-05-09 05:42:13 +04:00
|
|
|
// If we have an owner, make sure we have a docshell and return
|
|
|
|
// that. If not, we're most likely in the middle of being torn down,
|
|
|
|
// then we just return null.
|
|
|
|
if (mOwnerContent) {
|
2009-10-16 23:42:27 +04:00
|
|
|
nsresult rv = MaybeCreateDocShell();
|
2015-07-31 12:28:36 +03:00
|
|
|
if (NS_FAILED(rv)) {
|
2011-06-15 04:29:10 +04:00
|
|
|
return rv;
|
2009-10-16 23:42:27 +04:00
|
|
|
}
|
|
|
|
NS_ASSERTION(mDocShell,
|
|
|
|
"MaybeCreateDocShell succeeded, but null mDocShell");
|
2003-05-09 05:42:13 +04:00
|
|
|
}
|
2002-01-29 09:27:27 +03:00
|
|
|
|
|
|
|
*aDocShell = mDocShell;
|
|
|
|
NS_IF_ADDREF(*aDocShell);
|
|
|
|
|
2011-06-15 04:29:10 +04:00
|
|
|
return rv;
|
2002-01-29 09:27:27 +03:00
|
|
|
}
|
|
|
|
|
2008-08-08 03:15:40 +04:00
|
|
|
static void
|
|
|
|
SetTreeOwnerAndChromeEventHandlerOnDocshellTree(nsIDocShellTreeItem* aItem,
|
|
|
|
nsIDocShellTreeOwner* aOwner,
|
2013-04-06 04:44:15 +04:00
|
|
|
EventTarget* aHandler)
|
2008-08-08 03:15:40 +04:00
|
|
|
{
|
|
|
|
NS_PRECONDITION(aItem, "Must have item");
|
|
|
|
|
|
|
|
aItem->SetTreeOwner(aOwner);
|
|
|
|
|
2012-08-22 19:56:38 +04:00
|
|
|
int32_t childCount = 0;
|
2008-08-08 03:15:40 +04:00
|
|
|
aItem->GetChildCount(&childCount);
|
2012-08-22 19:56:38 +04:00
|
|
|
for (int32_t i = 0; i < childCount; ++i) {
|
2008-08-08 03:15:40 +04:00
|
|
|
nsCOMPtr<nsIDocShellTreeItem> item;
|
|
|
|
aItem->GetChildAt(i, getter_AddRefs(item));
|
2012-12-21 15:58:23 +04:00
|
|
|
if (aHandler) {
|
|
|
|
nsCOMPtr<nsIDocShell> shell(do_QueryInterface(item));
|
|
|
|
shell->SetChromeEventHandler(aHandler);
|
|
|
|
}
|
2008-08-08 03:15:40 +04:00
|
|
|
SetTreeOwnerAndChromeEventHandlerOnDocshellTree(item, aOwner, aHandler);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Set the type of the treeitem and hook it up to the treeowner.
|
2012-06-29 23:03:53 +04:00
|
|
|
* @param aItem the treeitem we're working with
|
2008-08-08 03:15:40 +04:00
|
|
|
* @param aTreeOwner the relevant treeowner; might be null
|
|
|
|
* @param aParentType the nsIDocShellTreeItem::GetType of our parent docshell
|
|
|
|
* @param aParentNode if non-null, the docshell we should be added as a child to
|
|
|
|
*
|
|
|
|
* @return whether aItem is top-level content
|
|
|
|
*/
|
2012-09-05 07:00:26 +04:00
|
|
|
bool
|
|
|
|
nsFrameLoader::AddTreeItemToTreeOwner(nsIDocShellTreeItem* aItem,
|
|
|
|
nsIDocShellTreeOwner* aOwner,
|
|
|
|
int32_t aParentType,
|
2014-01-07 02:34:15 +04:00
|
|
|
nsIDocShell* aParentNode)
|
2008-08-08 03:15:40 +04:00
|
|
|
{
|
|
|
|
NS_PRECONDITION(aItem, "Must have docshell treeitem");
|
2012-09-05 07:00:26 +04:00
|
|
|
NS_PRECONDITION(mOwnerContent, "Must have owning content");
|
2015-11-24 04:40:02 +03:00
|
|
|
|
2008-08-08 03:15:40 +04:00
|
|
|
nsAutoString value;
|
2017-01-04 20:33:19 +03:00
|
|
|
bool isContent = false;
|
|
|
|
mOwnerContent->GetAttr(kNameSpaceID_None, TypeAttrName(), value);
|
|
|
|
|
|
|
|
// we accept "content" and "content-xxx" values.
|
|
|
|
// We ignore anything that comes after 'content-'.
|
|
|
|
isContent = value.LowerCaseEqualsLiteral("content") ||
|
|
|
|
StringBeginsWith(value, NS_LITERAL_STRING("content-"),
|
|
|
|
nsCaseInsensitiveStringComparator());
|
|
|
|
|
2008-08-08 03:15:40 +04:00
|
|
|
|
2012-06-20 23:25:22 +04:00
|
|
|
// Force mozbrowser frames to always be typeContent, even if the
|
|
|
|
// mozbrowser interfaces are disabled.
|
|
|
|
nsCOMPtr<nsIDOMMozBrowserFrame> mozbrowser =
|
2012-09-05 07:00:26 +04:00
|
|
|
do_QueryInterface(mOwnerContent);
|
2012-06-20 23:25:22 +04:00
|
|
|
if (mozbrowser) {
|
|
|
|
bool isMozbrowser = false;
|
|
|
|
mozbrowser->GetMozbrowser(&isMozbrowser);
|
|
|
|
isContent |= isMozbrowser;
|
|
|
|
}
|
|
|
|
|
2008-08-08 03:15:40 +04:00
|
|
|
if (isContent) {
|
|
|
|
// The web shell's type is content.
|
|
|
|
|
|
|
|
aItem->SetItemType(nsIDocShellTreeItem::typeContent);
|
|
|
|
} else {
|
2009-05-07 23:21:53 +04:00
|
|
|
// Inherit our type from our parent docshell. If it is
|
2008-08-08 03:15:40 +04:00
|
|
|
// chrome, we'll be chrome. If it is content, we'll be
|
|
|
|
// content.
|
|
|
|
|
|
|
|
aItem->SetItemType(aParentType);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Now that we have our type set, add ourselves to the parent, as needed.
|
|
|
|
if (aParentNode) {
|
|
|
|
aParentNode->AddChild(aItem);
|
|
|
|
}
|
|
|
|
|
2011-09-29 10:19:26 +04:00
|
|
|
bool retval = false;
|
2008-08-08 03:15:40 +04:00
|
|
|
if (aParentType == nsIDocShellTreeItem::typeChrome && isContent) {
|
2011-10-17 18:59:28 +04:00
|
|
|
retval = true;
|
2008-08-08 03:15:40 +04:00
|
|
|
|
2016-12-09 22:23:24 +03:00
|
|
|
bool is_primary =
|
|
|
|
mOwnerContent->AttrValueIs(kNameSpaceID_None, nsGkAtoms::primary,
|
|
|
|
nsGkAtoms::_true, eIgnoreCase);
|
2008-08-08 03:15:40 +04:00
|
|
|
if (aOwner) {
|
2012-09-05 07:00:26 +04:00
|
|
|
mOwnerContent->AddMutationObserver(this);
|
|
|
|
mObservingOwnerContent = true;
|
2016-12-09 00:12:36 +03:00
|
|
|
aOwner->ContentShellAdded(aItem, is_primary);
|
2008-08-08 03:15:40 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return retval;
|
|
|
|
}
|
|
|
|
|
2011-09-29 10:19:26 +04:00
|
|
|
static bool
|
2012-08-22 19:56:38 +04:00
|
|
|
AllDescendantsOfType(nsIDocShellTreeItem* aParentItem, int32_t aType)
|
2008-10-08 17:04:32 +04:00
|
|
|
{
|
2012-08-22 19:56:38 +04:00
|
|
|
int32_t childCount = 0;
|
2008-10-08 17:04:32 +04:00
|
|
|
aParentItem->GetChildCount(&childCount);
|
|
|
|
|
2012-08-22 19:56:38 +04:00
|
|
|
for (int32_t i = 0; i < childCount; ++i) {
|
2008-10-08 17:04:32 +04:00
|
|
|
nsCOMPtr<nsIDocShellTreeItem> kid;
|
|
|
|
aParentItem->GetChildAt(i, getter_AddRefs(kid));
|
|
|
|
|
2014-01-20 11:58:26 +04:00
|
|
|
if (kid->ItemType() != aType || !AllDescendantsOfType(kid, aType)) {
|
2011-10-17 18:59:28 +04:00
|
|
|
return false;
|
2008-10-08 17:04:32 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-10-17 18:59:28 +04:00
|
|
|
return true;
|
2008-10-08 17:04:32 +04:00
|
|
|
}
|
|
|
|
|
2010-05-28 23:34:50 +04:00
|
|
|
/**
|
|
|
|
* A class that automatically sets mInShow to false when it goes
|
|
|
|
* out of scope.
|
|
|
|
*/
|
2015-09-03 19:15:23 +03:00
|
|
|
class MOZ_RAII AutoResetInShow {
|
2010-05-28 23:34:50 +04:00
|
|
|
private:
|
|
|
|
nsFrameLoader* mFrameLoader;
|
2012-01-10 09:29:30 +04:00
|
|
|
MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER
|
2010-05-28 23:34:50 +04:00
|
|
|
public:
|
2014-09-02 04:49:25 +04:00
|
|
|
explicit AutoResetInShow(nsFrameLoader* aFrameLoader MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
|
2010-05-28 23:34:50 +04:00
|
|
|
: mFrameLoader(aFrameLoader)
|
|
|
|
{
|
2012-01-10 09:29:30 +04:00
|
|
|
MOZ_GUARD_OBJECT_NOTIFIER_INIT;
|
2010-05-28 23:34:50 +04:00
|
|
|
}
|
2011-10-17 18:59:28 +04:00
|
|
|
~AutoResetInShow() { mFrameLoader->mInShow = false; }
|
2010-05-28 23:34:50 +04:00
|
|
|
};
|
|
|
|
|
|
|
|
|
2011-09-29 10:19:26 +04:00
|
|
|
bool
|
2012-08-22 19:56:38 +04:00
|
|
|
nsFrameLoader::Show(int32_t marginWidth, int32_t marginHeight,
|
|
|
|
int32_t scrollbarPrefX, int32_t scrollbarPrefY,
|
2010-08-31 04:49:07 +04:00
|
|
|
nsSubDocumentFrame* frame)
|
2009-10-16 23:42:29 +04:00
|
|
|
{
|
2010-05-28 23:34:50 +04:00
|
|
|
if (mInShow) {
|
2011-10-17 18:59:28 +04:00
|
|
|
return false;
|
2010-05-28 23:34:50 +04:00
|
|
|
}
|
|
|
|
// Reset mInShow if we exit early.
|
|
|
|
AutoResetInShow resetInShow(this);
|
2011-10-17 18:59:28 +04:00
|
|
|
mInShow = true;
|
2010-05-28 23:34:50 +04:00
|
|
|
|
2015-07-31 12:28:36 +03:00
|
|
|
ScreenIntSize size = frame->GetSubdocumentSize();
|
|
|
|
if (IsRemoteFrame()) {
|
|
|
|
return ShowRemoteFrame(size, frame);
|
|
|
|
}
|
|
|
|
|
2009-10-16 23:42:29 +04:00
|
|
|
nsresult rv = MaybeCreateDocShell();
|
|
|
|
if (NS_FAILED(rv)) {
|
2011-10-17 18:59:28 +04:00
|
|
|
return false;
|
2009-10-16 23:42:29 +04:00
|
|
|
}
|
2015-07-31 12:28:36 +03:00
|
|
|
NS_ASSERTION(mDocShell,
|
|
|
|
"MaybeCreateDocShell succeeded, but null mDocShell");
|
|
|
|
if (!mDocShell) {
|
|
|
|
return false;
|
|
|
|
}
|
2009-10-16 23:42:29 +04:00
|
|
|
|
2015-07-31 12:28:36 +03:00
|
|
|
mDocShell->SetMarginWidth(marginWidth);
|
|
|
|
mDocShell->SetMarginHeight(marginHeight);
|
2012-12-07 03:58:15 +04:00
|
|
|
|
2015-07-31 12:28:36 +03:00
|
|
|
nsCOMPtr<nsIScrollable> sc = do_QueryInterface(mDocShell);
|
|
|
|
if (sc) {
|
|
|
|
sc->SetDefaultScrollbarPreferences(nsIScrollable::ScrollOrientation_X,
|
|
|
|
scrollbarPrefX);
|
|
|
|
sc->SetDefaultScrollbarPreferences(nsIScrollable::ScrollOrientation_Y,
|
|
|
|
scrollbarPrefY);
|
2009-10-16 23:42:29 +04:00
|
|
|
}
|
|
|
|
|
2015-07-31 12:28:36 +03:00
|
|
|
nsCOMPtr<nsIPresShell> presShell = mDocShell->GetPresShell();
|
|
|
|
if (presShell) {
|
|
|
|
// Ensure root scroll frame is reflowed in case scroll preferences or
|
|
|
|
// margins have changed
|
|
|
|
nsIFrame* rootScrollFrame = presShell->GetRootScrollFrame();
|
|
|
|
if (rootScrollFrame) {
|
|
|
|
presShell->FrameNeedsReflow(rootScrollFrame, nsIPresShell::eResize,
|
|
|
|
NS_FRAME_IS_DIRTY);
|
|
|
|
}
|
|
|
|
return true;
|
2013-01-10 11:23:55 +04:00
|
|
|
}
|
|
|
|
|
2013-01-03 17:23:11 +04:00
|
|
|
nsView* view = frame->EnsureInnerView();
|
2009-10-16 23:42:29 +04:00
|
|
|
if (!view)
|
2011-10-17 18:59:28 +04:00
|
|
|
return false;
|
2009-10-16 23:42:29 +04:00
|
|
|
|
2009-10-28 23:41:46 +03:00
|
|
|
nsCOMPtr<nsIBaseWindow> baseWindow = do_QueryInterface(mDocShell);
|
|
|
|
NS_ASSERTION(baseWindow, "Found a nsIDocShell that isn't a nsIBaseWindow.");
|
2012-07-30 18:20:58 +04:00
|
|
|
baseWindow->InitWindow(nullptr, view->GetWidget(), 0, 0,
|
2010-11-04 23:06:05 +03:00
|
|
|
size.width, size.height);
|
2009-10-28 23:41:46 +03:00
|
|
|
// This is kinda whacky, this "Create()" call doesn't really
|
|
|
|
// create anything, one starts to wonder why this was named
|
|
|
|
// "Create"...
|
|
|
|
baseWindow->Create();
|
2011-10-17 18:59:28 +04:00
|
|
|
baseWindow->SetVisibility(true);
|
2013-04-13 16:30:38 +04:00
|
|
|
NS_ENSURE_TRUE(mDocShell, false);
|
2009-10-28 23:41:46 +03:00
|
|
|
|
|
|
|
// Trigger editor re-initialization if midas is turned on in the
|
|
|
|
// sub-document. This shouldn't be necessary, but given the way our
|
|
|
|
// editor works, it is. See
|
|
|
|
// https://bugzilla.mozilla.org/show_bug.cgi?id=284245
|
2015-07-31 12:28:36 +03:00
|
|
|
presShell = mDocShell->GetPresShell();
|
2009-10-28 23:41:46 +03:00
|
|
|
if (presShell) {
|
2011-05-28 11:43:57 +04:00
|
|
|
nsCOMPtr<nsIDOMHTMLDocument> doc =
|
2009-10-28 23:41:46 +03:00
|
|
|
do_QueryInterface(presShell->GetDocument());
|
2009-10-16 23:42:29 +04:00
|
|
|
|
2009-10-28 23:41:46 +03:00
|
|
|
if (doc) {
|
|
|
|
nsAutoString designMode;
|
|
|
|
doc->GetDesignMode(designMode);
|
|
|
|
|
|
|
|
if (designMode.EqualsLiteral("on")) {
|
2010-11-19 00:01:12 +03:00
|
|
|
// Hold on to the editor object to let the document reattach to the
|
|
|
|
// same editor object, instead of creating a new one.
|
|
|
|
nsCOMPtr<nsIEditor> editor;
|
2013-02-14 02:39:30 +04:00
|
|
|
nsresult rv = mDocShell->GetEditor(getter_AddRefs(editor));
|
2011-10-17 18:59:28 +04:00
|
|
|
NS_ENSURE_SUCCESS(rv, false);
|
2010-11-19 00:01:12 +03:00
|
|
|
|
2009-10-28 23:41:46 +03:00
|
|
|
doc->SetDesignMode(NS_LITERAL_STRING("off"));
|
|
|
|
doc->SetDesignMode(NS_LITERAL_STRING("on"));
|
2011-03-12 02:45:20 +03:00
|
|
|
} else {
|
2011-05-28 11:43:57 +04:00
|
|
|
// Re-initialize the presentation for contenteditable documents
|
2013-02-14 02:39:30 +04:00
|
|
|
bool editable = false,
|
|
|
|
hasEditingSession = false;
|
|
|
|
mDocShell->GetEditable(&editable);
|
|
|
|
mDocShell->GetHasEditingSession(&hasEditingSession);
|
|
|
|
nsCOMPtr<nsIEditor> editor;
|
|
|
|
mDocShell->GetEditor(getter_AddRefs(editor));
|
|
|
|
if (editable && hasEditingSession && editor) {
|
|
|
|
editor->PostCreate();
|
2011-03-12 02:45:20 +03:00
|
|
|
}
|
2009-10-16 23:42:29 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-10-17 18:59:28 +04:00
|
|
|
mInShow = false;
|
2010-05-28 23:34:50 +04:00
|
|
|
if (mHideCalled) {
|
2011-10-17 18:59:28 +04:00
|
|
|
mHideCalled = false;
|
2010-05-28 23:34:50 +04:00
|
|
|
Hide();
|
2011-10-17 18:59:28 +04:00
|
|
|
return false;
|
2010-05-28 23:34:50 +04:00
|
|
|
}
|
2011-10-17 18:59:28 +04:00
|
|
|
return true;
|
2009-10-16 23:42:29 +04:00
|
|
|
}
|
|
|
|
|
2011-05-13 21:41:00 +04:00
|
|
|
void
|
2012-08-22 19:56:38 +04:00
|
|
|
nsFrameLoader::MarginsChanged(uint32_t aMarginWidth,
|
|
|
|
uint32_t aMarginHeight)
|
2011-05-13 21:41:00 +04:00
|
|
|
{
|
|
|
|
// We assume that the margins are always zero for remote frames.
|
2015-07-31 12:28:36 +03:00
|
|
|
if (IsRemoteFrame())
|
2011-05-13 21:41:00 +04:00
|
|
|
return;
|
|
|
|
|
|
|
|
// If there's no docshell, we're probably not up and running yet.
|
|
|
|
// nsFrameLoader::Show() will take care of setting the right
|
|
|
|
// margins.
|
|
|
|
if (!mDocShell)
|
|
|
|
return;
|
|
|
|
|
|
|
|
// Set the margins
|
|
|
|
mDocShell->SetMarginWidth(aMarginWidth);
|
|
|
|
mDocShell->SetMarginHeight(aMarginHeight);
|
|
|
|
|
|
|
|
// Trigger a restyle if there's a prescontext
|
2014-10-09 01:26:57 +04:00
|
|
|
// FIXME: This could do something much less expensive.
|
2015-10-18 08:24:48 +03:00
|
|
|
RefPtr<nsPresContext> presContext;
|
2011-05-13 21:41:00 +04:00
|
|
|
mDocShell->GetPresContext(getter_AddRefs(presContext));
|
|
|
|
if (presContext)
|
2014-10-09 01:26:57 +04:00
|
|
|
presContext->RebuildAllStyleData(nsChangeHint(0), eRestyle_Subtree);
|
2011-05-13 21:41:00 +04:00
|
|
|
}
|
|
|
|
|
2009-10-28 23:41:46 +03:00
|
|
|
bool
|
2015-03-05 12:13:05 +03:00
|
|
|
nsFrameLoader::ShowRemoteFrame(const ScreenIntSize& size,
|
2013-01-10 11:23:55 +04:00
|
|
|
nsSubDocumentFrame *aFrame)
|
2009-10-28 23:41:46 +03:00
|
|
|
{
|
2016-01-15 01:03:11 +03:00
|
|
|
PROFILER_LABEL_FUNC(js::ProfileEntry::Category::GRAPHICS);
|
2015-07-31 12:28:36 +03:00
|
|
|
NS_ASSERTION(IsRemoteFrame(), "ShowRemote only makes sense on remote frames.");
|
2009-10-28 23:41:46 +03:00
|
|
|
|
2015-04-07 05:56:10 +03:00
|
|
|
if (!mRemoteBrowser && !TryRemoteBrowser()) {
|
|
|
|
NS_ERROR("Couldn't create child process.");
|
|
|
|
return false;
|
2009-10-28 23:41:46 +03:00
|
|
|
}
|
|
|
|
|
2010-08-21 07:06:53 +04:00
|
|
|
// FIXME/bug 589337: Show()/Hide() is pretty expensive for
|
|
|
|
// cross-process layers; need to figure out what behavior we really
|
|
|
|
// want here. For now, hack.
|
2010-08-21 03:35:11 +04:00
|
|
|
if (!mRemoteBrowserShown) {
|
2012-04-25 20:35:58 +04:00
|
|
|
if (!mOwnerContent ||
|
2015-02-24 17:41:43 +03:00
|
|
|
!mOwnerContent->GetComposedDoc()) {
|
2012-04-25 20:35:58 +04:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2015-10-18 08:24:48 +03:00
|
|
|
RefPtr<layers::LayerManager> layerManager =
|
2015-02-24 17:41:43 +03:00
|
|
|
nsContentUtils::LayerManagerForDocument(mOwnerContent->GetComposedDoc());
|
2012-04-25 20:35:58 +04:00
|
|
|
if (!layerManager) {
|
|
|
|
// This is just not going to work.
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2016-01-30 20:05:36 +03:00
|
|
|
nsPIDOMWindowOuter* win = mOwnerContent->OwnerDoc()->GetWindow();
|
2015-02-06 19:26:29 +03:00
|
|
|
bool parentIsActive = false;
|
|
|
|
if (win) {
|
|
|
|
nsCOMPtr<nsPIWindowRoot> windowRoot =
|
2016-01-30 20:05:36 +03:00
|
|
|
nsGlobalWindow::Cast(win)->GetTopWindowRoot();
|
2015-02-06 19:26:29 +03:00
|
|
|
if (windowRoot) {
|
2016-01-30 20:05:36 +03:00
|
|
|
nsPIDOMWindowOuter* topWin = windowRoot->GetWindow();
|
2015-02-06 19:26:29 +03:00
|
|
|
parentIsActive = topWin && topWin->IsActive();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
mRemoteBrowser->Show(size, parentIsActive);
|
2011-10-17 18:59:28 +04:00
|
|
|
mRemoteBrowserShown = true;
|
2010-08-21 03:35:11 +04:00
|
|
|
|
2012-05-08 20:20:35 +04:00
|
|
|
nsCOMPtr<nsIObserverService> os = services::GetObserverService();
|
2015-02-09 10:04:18 +03:00
|
|
|
if (os) {
|
2012-05-08 20:20:35 +04:00
|
|
|
os->NotifyObservers(NS_ISUPPORTS_CAST(nsIFrameLoader*, this),
|
2014-02-21 02:19:18 +04:00
|
|
|
"remote-browser-shown", nullptr);
|
2012-05-08 20:20:35 +04:00
|
|
|
}
|
2010-08-21 03:35:11 +04:00
|
|
|
} else {
|
2014-08-08 21:23:50 +04:00
|
|
|
nsIntRect dimensions;
|
2011-07-16 01:46:56 +04:00
|
|
|
NS_ENSURE_SUCCESS(GetWindowDimensions(dimensions), false);
|
2013-01-10 11:23:55 +04:00
|
|
|
|
|
|
|
// Don't show remote iframe if we are waiting for the completion of reflow.
|
|
|
|
if (!aFrame || !(aFrame->GetStateBits() & NS_FRAME_FIRST_REFLOW)) {
|
2015-03-31 23:39:02 +03:00
|
|
|
mRemoteBrowser->UpdateDimensions(dimensions, size);
|
2013-01-10 11:23:55 +04:00
|
|
|
}
|
2010-08-21 03:35:11 +04:00
|
|
|
}
|
2009-10-28 23:41:46 +03:00
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2009-10-16 23:42:29 +04:00
|
|
|
void
|
|
|
|
nsFrameLoader::Hide()
|
|
|
|
{
|
2010-05-28 23:34:50 +04:00
|
|
|
if (mHideCalled) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (mInShow) {
|
2011-10-17 18:59:28 +04:00
|
|
|
mHideCalled = true;
|
2010-05-28 23:34:50 +04:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2009-10-16 23:42:29 +04:00
|
|
|
if (!mDocShell)
|
|
|
|
return;
|
|
|
|
|
|
|
|
nsCOMPtr<nsIContentViewer> contentViewer;
|
|
|
|
mDocShell->GetContentViewer(getter_AddRefs(contentViewer));
|
|
|
|
if (contentViewer)
|
2011-10-17 18:59:28 +04:00
|
|
|
contentViewer->SetSticky(false);
|
2009-10-16 23:42:29 +04:00
|
|
|
|
|
|
|
nsCOMPtr<nsIBaseWindow> baseWin = do_QueryInterface(mDocShell);
|
|
|
|
NS_ASSERTION(baseWin,
|
|
|
|
"Found an nsIDocShell which doesn't implement nsIBaseWindow.");
|
2011-10-17 18:59:28 +04:00
|
|
|
baseWin->SetVisibility(false);
|
2012-07-30 18:20:58 +04:00
|
|
|
baseWin->SetParentWidget(nullptr);
|
2009-10-16 23:42:29 +04:00
|
|
|
}
|
|
|
|
|
2014-10-07 06:30:42 +04:00
|
|
|
nsresult
|
|
|
|
nsFrameLoader::SwapWithOtherRemoteLoader(nsFrameLoader* aOther,
|
2016-10-17 17:37:50 +03:00
|
|
|
nsIFrameLoaderOwner* aThisOwner,
|
|
|
|
nsIFrameLoaderOwner* aOtherOwner)
|
2014-10-07 06:30:42 +04:00
|
|
|
{
|
2015-02-09 02:50:01 +03:00
|
|
|
MOZ_ASSERT(NS_IsMainThread());
|
|
|
|
|
2016-10-17 17:37:50 +03:00
|
|
|
#ifdef DEBUG
|
|
|
|
RefPtr<nsFrameLoader> first = aThisOwner->GetFrameLoader();
|
|
|
|
RefPtr<nsFrameLoader> second = aOtherOwner->GetFrameLoader();
|
|
|
|
MOZ_ASSERT(first == this, "aThisOwner must own this");
|
|
|
|
MOZ_ASSERT(second == aOther, "aOtherOwner must own aOther");
|
|
|
|
#endif
|
|
|
|
|
2014-10-07 06:30:42 +04:00
|
|
|
Element* ourContent = mOwnerContent;
|
|
|
|
Element* otherContent = aOther->mOwnerContent;
|
|
|
|
|
|
|
|
if (!ourContent || !otherContent) {
|
|
|
|
// Can't handle this
|
|
|
|
return NS_ERROR_NOT_IMPLEMENTED;
|
|
|
|
}
|
|
|
|
|
|
|
|
// 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;
|
|
|
|
}
|
|
|
|
|
2015-02-24 17:41:43 +03:00
|
|
|
nsIDocument* ourDoc = ourContent->GetComposedDoc();
|
|
|
|
nsIDocument* otherDoc = otherContent->GetComposedDoc();
|
2014-10-07 06:30:42 +04:00
|
|
|
if (!ourDoc || !otherDoc) {
|
|
|
|
// Again, how odd, given that we had docshells
|
|
|
|
return NS_ERROR_NOT_IMPLEMENTED;
|
|
|
|
}
|
|
|
|
|
|
|
|
nsIPresShell* ourShell = ourDoc->GetShell();
|
|
|
|
nsIPresShell* otherShell = otherDoc->GetShell();
|
|
|
|
if (!ourShell || !otherShell) {
|
|
|
|
return NS_ERROR_NOT_IMPLEMENTED;
|
|
|
|
}
|
|
|
|
|
2016-11-29 22:49:17 +03:00
|
|
|
if (!mRemoteBrowser || !aOther->mRemoteBrowser) {
|
|
|
|
return NS_ERROR_NOT_IMPLEMENTED;
|
|
|
|
}
|
|
|
|
|
2016-01-09 03:11:58 +03:00
|
|
|
if (mRemoteBrowser->IsIsolatedMozBrowserElement() !=
|
2016-10-15 04:46:26 +03:00
|
|
|
aOther->mRemoteBrowser->IsIsolatedMozBrowserElement()) {
|
2016-01-09 03:11:58 +03:00
|
|
|
return NS_ERROR_NOT_IMPLEMENTED;
|
|
|
|
}
|
|
|
|
|
2016-05-30 02:48:00 +03:00
|
|
|
// When we swap docShells, maybe we have to deal with a new page created just
|
|
|
|
// for this operation. In this case, the browser code should already have set
|
|
|
|
// the correct userContextId attribute value in the owning XULElement, but our
|
|
|
|
// docShell, that has been created way before) doesn't know that that
|
|
|
|
// happened.
|
|
|
|
// This is the reason why now we must retrieve the correct value from the
|
|
|
|
// usercontextid attribute before comparing our originAttributes with the
|
|
|
|
// other one.
|
2017-01-12 19:38:48 +03:00
|
|
|
OriginAttributes ourOriginAttributes =
|
2016-05-30 02:48:00 +03:00
|
|
|
mRemoteBrowser->OriginAttributesRef();
|
|
|
|
rv = PopulateUserContextIdFromAttribute(ourOriginAttributes);
|
|
|
|
NS_ENSURE_SUCCESS(rv,rv);
|
|
|
|
|
2017-01-12 19:38:48 +03:00
|
|
|
OriginAttributes otherOriginAttributes =
|
2016-05-30 02:48:00 +03:00
|
|
|
aOther->mRemoteBrowser->OriginAttributesRef();
|
|
|
|
rv = aOther->PopulateUserContextIdFromAttribute(otherOriginAttributes);
|
|
|
|
NS_ENSURE_SUCCESS(rv,rv);
|
|
|
|
|
|
|
|
if (ourOriginAttributes != otherOriginAttributes) {
|
2016-01-09 03:11:58 +03:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2014-10-07 06:30:42 +04:00
|
|
|
if (mInSwap || aOther->mInSwap) {
|
|
|
|
return NS_ERROR_NOT_IMPLEMENTED;
|
|
|
|
}
|
|
|
|
mInSwap = aOther->mInSwap = true;
|
|
|
|
|
|
|
|
nsIFrame* ourFrame = ourContent->GetPrimaryFrame();
|
|
|
|
nsIFrame* otherFrame = otherContent->GetPrimaryFrame();
|
|
|
|
if (!ourFrame || !otherFrame) {
|
|
|
|
mInSwap = aOther->mInSwap = false;
|
|
|
|
return NS_ERROR_NOT_IMPLEMENTED;
|
|
|
|
}
|
|
|
|
|
|
|
|
nsSubDocumentFrame* ourFrameFrame = do_QueryFrame(ourFrame);
|
|
|
|
if (!ourFrameFrame) {
|
|
|
|
mInSwap = aOther->mInSwap = false;
|
|
|
|
return NS_ERROR_NOT_IMPLEMENTED;
|
|
|
|
}
|
|
|
|
|
|
|
|
rv = ourFrameFrame->BeginSwapDocShells(otherFrame);
|
|
|
|
if (NS_FAILED(rv)) {
|
|
|
|
mInSwap = aOther->mInSwap = false;
|
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
|
2015-04-10 00:55:07 +03:00
|
|
|
nsCOMPtr<nsIBrowserDOMWindow> otherBrowserDOMWindow =
|
|
|
|
aOther->mRemoteBrowser->GetBrowserDOMWindow();
|
|
|
|
nsCOMPtr<nsIBrowserDOMWindow> browserDOMWindow =
|
|
|
|
mRemoteBrowser->GetBrowserDOMWindow();
|
|
|
|
|
2016-02-04 14:50:03 +03:00
|
|
|
if (!!otherBrowserDOMWindow != !!browserDOMWindow) {
|
2015-04-10 00:55:07 +03:00
|
|
|
return NS_ERROR_NOT_IMPLEMENTED;
|
|
|
|
}
|
|
|
|
|
2016-09-09 00:00:12 +03:00
|
|
|
// Destroy browser frame scripts for content leaving a frame with browser API
|
2016-10-15 04:46:26 +03:00
|
|
|
if (OwnerIsMozBrowserFrame() && !aOther->OwnerIsMozBrowserFrame()) {
|
2016-09-09 00:00:12 +03:00
|
|
|
DestroyBrowserFrameScripts();
|
|
|
|
}
|
2016-10-15 04:46:26 +03:00
|
|
|
if (!OwnerIsMozBrowserFrame() && aOther->OwnerIsMozBrowserFrame()) {
|
2016-09-09 00:00:12 +03:00
|
|
|
aOther->DestroyBrowserFrameScripts();
|
|
|
|
}
|
|
|
|
|
2015-04-10 00:55:07 +03:00
|
|
|
aOther->mRemoteBrowser->SetBrowserDOMWindow(browserDOMWindow);
|
|
|
|
mRemoteBrowser->SetBrowserDOMWindow(otherBrowserDOMWindow);
|
|
|
|
|
2015-02-09 02:50:01 +03:00
|
|
|
// Native plugin windows used by this remote content need to be reparented.
|
2016-01-30 20:05:36 +03:00
|
|
|
if (nsPIDOMWindowOuter* newWin = ourDoc->GetWindow()) {
|
|
|
|
RefPtr<nsIWidget> newParent = nsGlobalWindow::Cast(newWin)->GetMainWidget();
|
2015-10-07 21:30:33 +03:00
|
|
|
const ManagedContainer<mozilla::plugins::PPluginWidgetParent>& plugins =
|
|
|
|
aOther->mRemoteBrowser->ManagedPPluginWidgetParent();
|
|
|
|
for (auto iter = plugins.ConstIter(); !iter.Done(); iter.Next()) {
|
|
|
|
static_cast<mozilla::plugins::PluginWidgetParent*>(iter.Get()->GetKey())->SetParent(newParent);
|
2015-02-09 02:50:01 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-10-01 20:06:51 +03:00
|
|
|
MaybeUpdatePrimaryTabParent(eTabParentRemoved);
|
|
|
|
aOther->MaybeUpdatePrimaryTabParent(eTabParentRemoved);
|
|
|
|
|
2014-10-07 06:30:42 +04:00
|
|
|
SetOwnerContent(otherContent);
|
|
|
|
aOther->SetOwnerContent(ourContent);
|
|
|
|
|
|
|
|
mRemoteBrowser->SetOwnerElement(otherContent);
|
|
|
|
aOther->mRemoteBrowser->SetOwnerElement(ourContent);
|
|
|
|
|
2015-10-01 20:06:51 +03:00
|
|
|
MaybeUpdatePrimaryTabParent(eTabParentChanged);
|
|
|
|
aOther->MaybeUpdatePrimaryTabParent(eTabParentChanged);
|
|
|
|
|
2015-10-18 08:24:48 +03:00
|
|
|
RefPtr<nsFrameMessageManager> ourMessageManager = mMessageManager;
|
|
|
|
RefPtr<nsFrameMessageManager> otherMessageManager = aOther->mMessageManager;
|
2014-10-07 06:30:42 +04:00
|
|
|
// Swap and setup things in parent message managers.
|
2016-08-24 21:12:09 +03:00
|
|
|
if (ourMessageManager) {
|
|
|
|
ourMessageManager->SetCallback(aOther);
|
2014-10-07 06:30:42 +04:00
|
|
|
}
|
2016-08-24 21:12:09 +03:00
|
|
|
if (otherMessageManager) {
|
|
|
|
otherMessageManager->SetCallback(this);
|
2014-10-07 06:30:42 +04:00
|
|
|
}
|
|
|
|
mMessageManager.swap(aOther->mMessageManager);
|
|
|
|
|
2016-10-17 17:37:50 +03:00
|
|
|
// Perform the actual swap of the internal refptrs. We keep a strong reference
|
|
|
|
// to ourselves to make sure we don't die while we overwrite our reference to
|
|
|
|
// ourself.
|
|
|
|
nsCOMPtr<nsIFrameLoader> kungFuDeathGrip(this);
|
|
|
|
aThisOwner->InternalSetFrameLoader(aOther);
|
|
|
|
aOtherOwner->InternalSetFrameLoader(kungFuDeathGrip);
|
2014-10-07 06:30:42 +04:00
|
|
|
|
|
|
|
ourFrameFrame->EndSwapDocShells(otherFrame);
|
|
|
|
|
2015-06-16 20:40:55 +03:00
|
|
|
ourShell->BackingScaleFactorChanged();
|
|
|
|
otherShell->BackingScaleFactorChanged();
|
|
|
|
|
2017-01-05 10:31:56 +03:00
|
|
|
ourDoc->FlushPendingNotifications(FlushType::Layout);
|
|
|
|
otherDoc->FlushPendingNotifications(FlushType::Layout);
|
2014-10-07 06:30:42 +04:00
|
|
|
|
2016-04-29 01:04:52 +03:00
|
|
|
// Initialize browser API if needed now that owner content has changed.
|
|
|
|
InitializeBrowserAPI();
|
|
|
|
aOther->InitializeBrowserAPI();
|
|
|
|
|
2014-10-07 06:30:42 +04:00
|
|
|
mInSwap = aOther->mInSwap = false;
|
2015-05-07 18:43:40 +03:00
|
|
|
|
2016-04-29 01:04:52 +03:00
|
|
|
// Send an updated tab context since owner content type may have changed.
|
|
|
|
MutableTabContext ourContext;
|
|
|
|
rv = GetNewTabContext(&ourContext);
|
|
|
|
if (NS_WARN_IF(NS_FAILED(rv))) {
|
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
MutableTabContext otherContext;
|
|
|
|
rv = aOther->GetNewTabContext(&otherContext);
|
|
|
|
if (NS_WARN_IF(NS_FAILED(rv))) {
|
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
|
Bug 1338241 - Part 3: Relax the SwapWithOtherRemoteLoader swap check, r=bz
In bug 1147911, the concept of a remoteType was added to a xul:browser.
This was an attribute which would control the type of remote process was
intended to be used to load the page.
In order to swap two frameLoaders, it has always been necessary for them
to either both contain remote content, or both contain non-remote
content. This check is made in nsFrameLoader::SwapWithOtherLoader, by
checking `IsRemoteFrame() != aOther->IsRemoteFrame()`, and then
returning `NS_ERROR_NOT_IMPLEMENTED` if that was not the case.
In the follow-up bug 1317293, the check which is being removed here was
added to ensure that the remoteType of two frameLoaders which are being
swapped also matched. This was not a technical limitation, but rather
something which "seemed to make sense to do".
This bug removes that check as it is not a technical limitation and
causes problems in edge cases around Large-Allocation processes now that
the remoteType is being used to denote a Large-Allocation process.
Namely, it means that attempting to drag a Large-Allocation window into
a new window when at the Large-Allocation process cap will fail, due to
being unable to create a new Large-Allocation process in the new window
to swap with.
The new swapping of the attributes which is added below is done with the
intent that the `remoteType` attribute of the xul:browser element should
match the `remoteType` attribute of the frameLoader inside of it at all
times. As the swap can now occur between two different `remoteType`s,
this is necessary to keep that constraint.
MozReview-Commit-ID: BHFgjwRGrge
2017-02-10 21:13:43 +03:00
|
|
|
// Swap the remoteType property as the frameloaders are being swapped
|
|
|
|
nsAutoString ourRemoteType;
|
|
|
|
if (!ourContent->GetAttr(kNameSpaceID_None, nsGkAtoms::RemoteType,
|
|
|
|
ourRemoteType)) {
|
|
|
|
ourRemoteType.AssignLiteral(DEFAULT_REMOTE_TYPE);
|
|
|
|
}
|
|
|
|
nsAutoString otherRemoteType;
|
|
|
|
if (!otherContent->GetAttr(kNameSpaceID_None, nsGkAtoms::RemoteType,
|
|
|
|
otherRemoteType)) {
|
|
|
|
otherRemoteType.AssignLiteral(DEFAULT_REMOTE_TYPE);
|
|
|
|
}
|
|
|
|
ourContent->SetAttr(kNameSpaceID_None, nsGkAtoms::RemoteType, otherRemoteType, false);
|
|
|
|
otherContent->SetAttr(kNameSpaceID_None, nsGkAtoms::RemoteType, ourRemoteType, false);
|
|
|
|
|
2016-04-29 01:04:52 +03:00
|
|
|
Unused << mRemoteBrowser->SendSwappedWithOtherRemoteLoader(
|
|
|
|
ourContext.AsIPCTabContext());
|
|
|
|
Unused << aOther->mRemoteBrowser->SendSwappedWithOtherRemoteLoader(
|
|
|
|
otherContext.AsIPCTabContext());
|
2014-10-07 06:30:42 +04:00
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2015-09-03 19:15:23 +03:00
|
|
|
class MOZ_RAII AutoResetInFrameSwap final
|
2015-08-07 17:17:50 +03:00
|
|
|
{
|
|
|
|
public:
|
|
|
|
AutoResetInFrameSwap(nsFrameLoader* aThisFrameLoader,
|
|
|
|
nsFrameLoader* aOtherFrameLoader,
|
|
|
|
nsDocShell* aThisDocShell,
|
|
|
|
nsDocShell* aOtherDocShell,
|
|
|
|
EventTarget* aThisEventTarget,
|
|
|
|
EventTarget* aOtherEventTarget
|
|
|
|
MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
|
|
|
|
: mThisFrameLoader(aThisFrameLoader)
|
|
|
|
, mOtherFrameLoader(aOtherFrameLoader)
|
|
|
|
, mThisDocShell(aThisDocShell)
|
|
|
|
, mOtherDocShell(aOtherDocShell)
|
|
|
|
, mThisEventTarget(aThisEventTarget)
|
|
|
|
, mOtherEventTarget(aOtherEventTarget)
|
|
|
|
{
|
|
|
|
MOZ_GUARD_OBJECT_NOTIFIER_INIT;
|
|
|
|
|
|
|
|
mThisFrameLoader->mInSwap = true;
|
|
|
|
mOtherFrameLoader->mInSwap = true;
|
|
|
|
mThisDocShell->SetInFrameSwap(true);
|
|
|
|
mOtherDocShell->SetInFrameSwap(true);
|
|
|
|
|
|
|
|
// Fire pageshow events on still-loading pages, and then fire pagehide
|
|
|
|
// events. Note that we do NOT fire these in the normal way, but just fire
|
|
|
|
// them on the chrome event handlers.
|
|
|
|
nsContentUtils::FirePageShowEvent(mThisDocShell, mThisEventTarget, false);
|
|
|
|
nsContentUtils::FirePageShowEvent(mOtherDocShell, mOtherEventTarget, false);
|
|
|
|
nsContentUtils::FirePageHideEvent(mThisDocShell, mThisEventTarget);
|
|
|
|
nsContentUtils::FirePageHideEvent(mOtherDocShell, mOtherEventTarget);
|
|
|
|
}
|
|
|
|
|
|
|
|
~AutoResetInFrameSwap()
|
|
|
|
{
|
|
|
|
nsContentUtils::FirePageShowEvent(mThisDocShell, mThisEventTarget, true);
|
|
|
|
nsContentUtils::FirePageShowEvent(mOtherDocShell, mOtherEventTarget, true);
|
|
|
|
|
|
|
|
mThisFrameLoader->mInSwap = false;
|
|
|
|
mOtherFrameLoader->mInSwap = false;
|
|
|
|
mThisDocShell->SetInFrameSwap(false);
|
|
|
|
mOtherDocShell->SetInFrameSwap(false);
|
|
|
|
}
|
|
|
|
|
|
|
|
private:
|
2015-10-18 08:24:48 +03:00
|
|
|
RefPtr<nsFrameLoader> mThisFrameLoader;
|
|
|
|
RefPtr<nsFrameLoader> mOtherFrameLoader;
|
|
|
|
RefPtr<nsDocShell> mThisDocShell;
|
|
|
|
RefPtr<nsDocShell> mOtherDocShell;
|
2015-08-07 17:17:50 +03:00
|
|
|
nsCOMPtr<EventTarget> mThisEventTarget;
|
|
|
|
nsCOMPtr<EventTarget> mOtherEventTarget;
|
|
|
|
MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER
|
|
|
|
};
|
|
|
|
|
2008-08-08 03:15:40 +04:00
|
|
|
nsresult
|
|
|
|
nsFrameLoader::SwapWithOtherLoader(nsFrameLoader* aOther,
|
2016-10-17 17:37:50 +03:00
|
|
|
nsIFrameLoaderOwner* aThisOwner,
|
|
|
|
nsIFrameLoaderOwner* aOtherOwner)
|
2008-08-08 03:15:40 +04:00
|
|
|
{
|
2016-10-17 17:37:50 +03:00
|
|
|
#ifdef DEBUG
|
|
|
|
RefPtr<nsFrameLoader> first = aThisOwner->GetFrameLoader();
|
|
|
|
RefPtr<nsFrameLoader> second = aOtherOwner->GetFrameLoader();
|
|
|
|
MOZ_ASSERT(first == this, "aThisOwner must own this");
|
|
|
|
MOZ_ASSERT(second == aOther, "aOtherOwner must own aOther");
|
|
|
|
#endif
|
|
|
|
|
2010-05-28 23:34:50 +04:00
|
|
|
NS_ENSURE_STATE(!mInShow && !aOther->mInShow);
|
2008-08-08 03:15:40 +04:00
|
|
|
|
2016-01-09 03:11:58 +03:00
|
|
|
if (IsRemoteFrame() != aOther->IsRemoteFrame()) {
|
2014-10-07 06:30:42 +04:00
|
|
|
NS_WARNING("Swapping remote and non-remote frames is not currently supported");
|
|
|
|
return NS_ERROR_NOT_IMPLEMENTED;
|
|
|
|
}
|
|
|
|
|
2011-10-01 21:14:35 +04:00
|
|
|
Element* ourContent = mOwnerContent;
|
|
|
|
Element* otherContent = aOther->mOwnerContent;
|
2008-08-08 03:15:40 +04:00
|
|
|
|
|
|
|
if (!ourContent || !otherContent) {
|
|
|
|
// Can't handle this
|
|
|
|
return NS_ERROR_NOT_IMPLEMENTED;
|
|
|
|
}
|
|
|
|
|
2016-01-09 03:11:58 +03:00
|
|
|
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 ourFullscreenAllowed =
|
|
|
|
ourContent->IsXULElement() ||
|
2016-10-15 04:46:26 +03:00
|
|
|
(OwnerIsMozBrowserFrame() &&
|
2016-01-09 03:11:58 +03:00
|
|
|
(ourContent->HasAttr(kNameSpaceID_None, nsGkAtoms::allowfullscreen) ||
|
|
|
|
ourContent->HasAttr(kNameSpaceID_None, nsGkAtoms::mozallowfullscreen)));
|
|
|
|
bool otherFullscreenAllowed =
|
|
|
|
otherContent->IsXULElement() ||
|
2016-10-15 04:46:26 +03:00
|
|
|
(aOther->OwnerIsMozBrowserFrame() &&
|
2016-01-09 03:11:58 +03:00
|
|
|
(otherContent->HasAttr(kNameSpaceID_None, nsGkAtoms::allowfullscreen) ||
|
|
|
|
otherContent->HasAttr(kNameSpaceID_None, nsGkAtoms::mozallowfullscreen)));
|
|
|
|
if (ourFullscreenAllowed != otherFullscreenAllowed) {
|
|
|
|
return NS_ERROR_NOT_IMPLEMENTED;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Divert to a separate path for the remaining steps in the remote case
|
|
|
|
if (IsRemoteFrame()) {
|
|
|
|
MOZ_ASSERT(aOther->IsRemoteFrame());
|
2016-10-17 17:37:50 +03:00
|
|
|
return SwapWithOtherRemoteLoader(aOther, aThisOwner, aOtherOwner);
|
2016-01-09 03:11:58 +03:00
|
|
|
}
|
|
|
|
|
2008-08-08 03:15:40 +04:00
|
|
|
// Make sure there are no same-origin issues
|
2011-09-29 10:19:26 +04:00
|
|
|
bool equal;
|
2008-08-08 03:15:40 +04:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2015-10-18 08:24:48 +03:00
|
|
|
RefPtr<nsDocShell> ourDocshell = static_cast<nsDocShell*>(GetExistingDocShell());
|
|
|
|
RefPtr<nsDocShell> otherDocshell = static_cast<nsDocShell*>(aOther->GetExistingDocShell());
|
2012-03-04 20:02:00 +04:00
|
|
|
if (!ourDocshell || !otherDocshell) {
|
2008-08-08 03:15:40 +04:00
|
|
|
// How odd
|
|
|
|
return NS_ERROR_NOT_IMPLEMENTED;
|
|
|
|
}
|
|
|
|
|
|
|
|
// To avoid having to mess with session history, avoid swapping
|
2008-10-08 17:04:32 +04:00
|
|
|
// frameloaders that don't correspond to root same-type docshells,
|
|
|
|
// unless both roots have session history disabled.
|
2008-08-08 03:15:40 +04:00
|
|
|
nsCOMPtr<nsIDocShellTreeItem> ourRootTreeItem, otherRootTreeItem;
|
2013-02-13 02:02:51 +04:00
|
|
|
ourDocshell->GetSameTypeRootTreeItem(getter_AddRefs(ourRootTreeItem));
|
|
|
|
otherDocshell->GetSameTypeRootTreeItem(getter_AddRefs(otherRootTreeItem));
|
2009-01-13 22:32:30 +03:00
|
|
|
nsCOMPtr<nsIWebNavigation> ourRootWebnav =
|
|
|
|
do_QueryInterface(ourRootTreeItem);
|
|
|
|
nsCOMPtr<nsIWebNavigation> otherRootWebnav =
|
|
|
|
do_QueryInterface(otherRootTreeItem);
|
2008-10-08 17:04:32 +04:00
|
|
|
|
2009-01-13 22:32:30 +03:00
|
|
|
if (!ourRootWebnav || !otherRootWebnav) {
|
|
|
|
return NS_ERROR_NOT_IMPLEMENTED;
|
|
|
|
}
|
2008-10-08 17:04:32 +04:00
|
|
|
|
2009-01-13 22:32:30 +03:00
|
|
|
nsCOMPtr<nsISHistory> ourHistory;
|
|
|
|
nsCOMPtr<nsISHistory> otherHistory;
|
|
|
|
ourRootWebnav->GetSessionHistory(getter_AddRefs(ourHistory));
|
|
|
|
otherRootWebnav->GetSessionHistory(getter_AddRefs(otherHistory));
|
|
|
|
|
2013-02-13 02:02:51 +04:00
|
|
|
if ((ourRootTreeItem != ourDocshell || otherRootTreeItem != otherDocshell) &&
|
2009-01-13 22:32:30 +03:00
|
|
|
(ourHistory || otherHistory)) {
|
|
|
|
return NS_ERROR_NOT_IMPLEMENTED;
|
2008-08-08 03:15:40 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
// Also make sure that the two docshells are the same type. Otherwise
|
2012-12-21 15:58:23 +04:00
|
|
|
// swapping is certainly not safe. If this needs to be changed then
|
|
|
|
// the code below needs to be audited as it assumes identical types.
|
2014-01-20 11:58:26 +04:00
|
|
|
int32_t ourType = ourDocshell->ItemType();
|
|
|
|
int32_t otherType = otherDocshell->ItemType();
|
2008-10-08 17:04:32 +04:00
|
|
|
if (ourType != otherType) {
|
|
|
|
return NS_ERROR_NOT_IMPLEMENTED;
|
|
|
|
}
|
|
|
|
|
2009-01-13 22:32:30 +03:00
|
|
|
// One more twist here. Setting up the right treeowners in a heterogeneous
|
2008-10-08 17:04:32 +04:00
|
|
|
// tree is a bit of a pain. So make sure that if ourType is not
|
|
|
|
// nsIDocShellTreeItem::typeContent then all of our descendants are the same
|
|
|
|
// type as us.
|
|
|
|
if (ourType != nsIDocShellTreeItem::typeContent &&
|
2013-02-13 02:02:51 +04:00
|
|
|
(!AllDescendantsOfType(ourDocshell, ourType) ||
|
|
|
|
!AllDescendantsOfType(otherDocshell, otherType))) {
|
2008-08-08 03:15:40 +04:00
|
|
|
return NS_ERROR_NOT_IMPLEMENTED;
|
|
|
|
}
|
2015-11-24 04:40:02 +03:00
|
|
|
|
2008-08-08 03:15:40 +04:00
|
|
|
// Save off the tree owners, frame elements, chrome event handlers, and
|
|
|
|
// docshell and document parents before doing anything else.
|
|
|
|
nsCOMPtr<nsIDocShellTreeOwner> ourOwner, otherOwner;
|
2013-02-13 02:02:51 +04:00
|
|
|
ourDocshell->GetTreeOwner(getter_AddRefs(ourOwner));
|
|
|
|
otherDocshell->GetTreeOwner(getter_AddRefs(otherOwner));
|
2008-08-08 03:15:40 +04:00
|
|
|
// Note: it's OK to have null treeowners.
|
|
|
|
|
|
|
|
nsCOMPtr<nsIDocShellTreeItem> ourParentItem, otherParentItem;
|
2013-02-13 02:02:51 +04:00
|
|
|
ourDocshell->GetParent(getter_AddRefs(ourParentItem));
|
|
|
|
otherDocshell->GetParent(getter_AddRefs(otherParentItem));
|
2008-08-08 03:15:40 +04:00
|
|
|
if (!ourParentItem || !otherParentItem) {
|
|
|
|
return NS_ERROR_NOT_IMPLEMENTED;
|
|
|
|
}
|
|
|
|
|
2008-10-08 17:04:32 +04:00
|
|
|
// Make sure our parents are the same type too
|
2014-01-20 11:58:26 +04:00
|
|
|
int32_t ourParentType = ourParentItem->ItemType();
|
|
|
|
int32_t otherParentType = otherParentItem->ItemType();
|
2008-10-08 17:04:32 +04:00
|
|
|
if (ourParentType != otherParentType) {
|
|
|
|
return NS_ERROR_NOT_IMPLEMENTED;
|
|
|
|
}
|
|
|
|
|
2016-01-30 20:05:36 +03:00
|
|
|
nsCOMPtr<nsPIDOMWindowOuter> ourWindow = ourDocshell->GetWindow();
|
|
|
|
nsCOMPtr<nsPIDOMWindowOuter> otherWindow = otherDocshell->GetWindow();
|
2008-08-08 03:15:40 +04:00
|
|
|
|
2013-07-24 03:39:17 +04:00
|
|
|
nsCOMPtr<Element> ourFrameElement =
|
2008-08-08 03:15:40 +04:00
|
|
|
ourWindow->GetFrameElementInternal();
|
2013-07-24 03:39:17 +04:00
|
|
|
nsCOMPtr<Element> otherFrameElement =
|
2008-08-08 03:15:40 +04:00
|
|
|
otherWindow->GetFrameElementInternal();
|
|
|
|
|
2013-04-06 04:44:15 +04:00
|
|
|
nsCOMPtr<EventTarget> ourChromeEventHandler =
|
2008-08-08 03:15:40 +04:00
|
|
|
do_QueryInterface(ourWindow->GetChromeEventHandler());
|
2013-04-06 04:44:15 +04:00
|
|
|
nsCOMPtr<EventTarget> otherChromeEventHandler =
|
2008-08-08 03:15:40 +04:00
|
|
|
do_QueryInterface(otherWindow->GetChromeEventHandler());
|
|
|
|
|
2014-09-03 07:09:24 +04:00
|
|
|
nsCOMPtr<EventTarget> ourEventTarget = ourWindow->GetParentTarget();
|
|
|
|
nsCOMPtr<EventTarget> otherEventTarget = otherWindow->GetParentTarget();
|
|
|
|
|
2008-08-08 03:15:40 +04:00
|
|
|
NS_ASSERTION(SameCOMIdentity(ourFrameElement, ourContent) &&
|
|
|
|
SameCOMIdentity(otherFrameElement, otherContent) &&
|
|
|
|
SameCOMIdentity(ourChromeEventHandler, ourContent) &&
|
|
|
|
SameCOMIdentity(otherChromeEventHandler, otherContent),
|
|
|
|
"How did that happen, exactly?");
|
|
|
|
|
2013-04-24 08:22:37 +04:00
|
|
|
nsCOMPtr<nsIDocument> ourChildDocument = ourWindow->GetExtantDoc();
|
|
|
|
nsCOMPtr<nsIDocument> otherChildDocument = otherWindow ->GetExtantDoc();
|
2008-08-08 03:15:40 +04:00
|
|
|
if (!ourChildDocument || !otherChildDocument) {
|
|
|
|
// This shouldn't be happening
|
|
|
|
return NS_ERROR_NOT_IMPLEMENTED;
|
|
|
|
}
|
|
|
|
|
|
|
|
nsCOMPtr<nsIDocument> ourParentDocument =
|
|
|
|
ourChildDocument->GetParentDocument();
|
|
|
|
nsCOMPtr<nsIDocument> otherParentDocument =
|
|
|
|
otherChildDocument->GetParentDocument();
|
|
|
|
|
|
|
|
// Make sure to swap docshells between the two frames.
|
2015-02-24 17:41:43 +03:00
|
|
|
nsIDocument* ourDoc = ourContent->GetComposedDoc();
|
|
|
|
nsIDocument* otherDoc = otherContent->GetComposedDoc();
|
2008-08-08 03:15:40 +04:00
|
|
|
if (!ourDoc || !otherDoc) {
|
|
|
|
// Again, how odd, given that we had docshells
|
|
|
|
return NS_ERROR_NOT_IMPLEMENTED;
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_ASSERTION(ourDoc == ourParentDocument, "Unexpected parent document");
|
|
|
|
NS_ASSERTION(otherDoc == otherParentDocument, "Unexpected parent document");
|
|
|
|
|
2010-06-25 17:59:57 +04:00
|
|
|
nsIPresShell* ourShell = ourDoc->GetShell();
|
|
|
|
nsIPresShell* otherShell = otherDoc->GetShell();
|
2008-08-08 03:15:40 +04:00
|
|
|
if (!ourShell || !otherShell) {
|
|
|
|
return NS_ERROR_NOT_IMPLEMENTED;
|
|
|
|
}
|
|
|
|
|
2016-02-18 06:53:32 +03:00
|
|
|
if (ourDocshell->GetIsIsolatedMozBrowserElement() !=
|
2016-10-15 04:46:26 +03:00
|
|
|
otherDocshell->GetIsIsolatedMozBrowserElement()) {
|
2016-01-09 03:11:58 +03:00
|
|
|
return NS_ERROR_NOT_IMPLEMENTED;
|
|
|
|
}
|
|
|
|
|
2016-05-30 02:48:00 +03:00
|
|
|
// When we swap docShells, maybe we have to deal with a new page created just
|
|
|
|
// for this operation. In this case, the browser code should already have set
|
|
|
|
// the correct userContextId attribute value in the owning XULElement, but our
|
|
|
|
// docShell, that has been created way before) doesn't know that that
|
|
|
|
// happened.
|
|
|
|
// This is the reason why now we must retrieve the correct value from the
|
|
|
|
// usercontextid attribute before comparing our originAttributes with the
|
|
|
|
// other one.
|
2017-01-12 19:38:48 +03:00
|
|
|
OriginAttributes ourOriginAttributes =
|
2016-05-30 02:48:00 +03:00
|
|
|
ourDocshell->GetOriginAttributes();
|
|
|
|
rv = PopulateUserContextIdFromAttribute(ourOriginAttributes);
|
|
|
|
NS_ENSURE_SUCCESS(rv,rv);
|
|
|
|
|
2017-01-12 19:38:48 +03:00
|
|
|
OriginAttributes otherOriginAttributes =
|
2016-05-30 02:48:00 +03:00
|
|
|
otherDocshell->GetOriginAttributes();
|
|
|
|
rv = aOther->PopulateUserContextIdFromAttribute(otherOriginAttributes);
|
|
|
|
NS_ENSURE_SUCCESS(rv,rv);
|
|
|
|
|
|
|
|
if (ourOriginAttributes != otherOriginAttributes) {
|
2016-01-09 03:11:58 +03:00
|
|
|
return NS_ERROR_NOT_IMPLEMENTED;
|
2012-07-19 09:26:21 +04:00
|
|
|
}
|
|
|
|
|
2008-08-08 03:15:40 +04:00
|
|
|
if (mInSwap || aOther->mInSwap) {
|
|
|
|
return NS_ERROR_NOT_IMPLEMENTED;
|
|
|
|
}
|
2015-08-07 17:17:50 +03:00
|
|
|
AutoResetInFrameSwap autoFrameSwap(this, aOther, ourDocshell, otherDocshell,
|
|
|
|
ourEventTarget, otherEventTarget);
|
|
|
|
|
2009-12-25 00:20:05 +03:00
|
|
|
nsIFrame* ourFrame = ourContent->GetPrimaryFrame();
|
|
|
|
nsIFrame* otherFrame = otherContent->GetPrimaryFrame();
|
2008-08-08 03:15:40 +04:00
|
|
|
if (!ourFrame || !otherFrame) {
|
|
|
|
return NS_ERROR_NOT_IMPLEMENTED;
|
|
|
|
}
|
|
|
|
|
2010-08-31 04:49:07 +04:00
|
|
|
nsSubDocumentFrame* ourFrameFrame = do_QueryFrame(ourFrame);
|
2008-08-08 03:15:40 +04:00
|
|
|
if (!ourFrameFrame) {
|
|
|
|
return NS_ERROR_NOT_IMPLEMENTED;
|
|
|
|
}
|
|
|
|
|
|
|
|
// OK. First begin to swap the docshells in the two nsIFrames
|
|
|
|
rv = ourFrameFrame->BeginSwapDocShells(otherFrame);
|
|
|
|
if (NS_FAILED(rv)) {
|
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
|
2016-09-09 00:00:12 +03:00
|
|
|
// Destroy browser frame scripts for content leaving a frame with browser API
|
2016-10-15 04:46:26 +03:00
|
|
|
if (OwnerIsMozBrowserFrame() && !aOther->OwnerIsMozBrowserFrame()) {
|
2016-09-09 00:00:12 +03:00
|
|
|
DestroyBrowserFrameScripts();
|
|
|
|
}
|
2016-10-15 04:46:26 +03:00
|
|
|
if (!OwnerIsMozBrowserFrame() && aOther->OwnerIsMozBrowserFrame()) {
|
2016-09-09 00:00:12 +03:00
|
|
|
aOther->DestroyBrowserFrameScripts();
|
|
|
|
}
|
|
|
|
|
2008-08-08 03:15:40 +04:00
|
|
|
// Now move the docshells to the right docshell trees. Note that this
|
|
|
|
// resets their treeowners to null.
|
2013-02-13 02:02:51 +04:00
|
|
|
ourParentItem->RemoveChild(ourDocshell);
|
|
|
|
otherParentItem->RemoveChild(otherDocshell);
|
2008-08-08 03:15:40 +04:00
|
|
|
if (ourType == nsIDocShellTreeItem::typeContent) {
|
2013-02-13 02:02:51 +04:00
|
|
|
ourOwner->ContentShellRemoved(ourDocshell);
|
|
|
|
otherOwner->ContentShellRemoved(otherDocshell);
|
2008-08-08 03:15:40 +04:00
|
|
|
}
|
2015-11-24 04:40:02 +03:00
|
|
|
|
2013-02-13 02:02:51 +04:00
|
|
|
ourParentItem->AddChild(otherDocshell);
|
|
|
|
otherParentItem->AddChild(ourDocshell);
|
2008-08-08 03:15:40 +04:00
|
|
|
|
2012-12-21 15:58:23 +04:00
|
|
|
// Restore the correct chrome event handlers.
|
|
|
|
ourDocshell->SetChromeEventHandler(otherChromeEventHandler);
|
|
|
|
otherDocshell->SetChromeEventHandler(ourChromeEventHandler);
|
2008-08-08 03:15:40 +04:00
|
|
|
// Restore the correct treeowners
|
2012-12-21 15:58:23 +04:00
|
|
|
// (and also chrome event handlers for content frames only).
|
2013-02-13 02:02:51 +04:00
|
|
|
SetTreeOwnerAndChromeEventHandlerOnDocshellTree(ourDocshell, otherOwner,
|
2016-05-01 21:29:23 +03:00
|
|
|
ourType == nsIDocShellTreeItem::typeContent ? otherChromeEventHandler.get() : nullptr);
|
2013-02-13 02:02:51 +04:00
|
|
|
SetTreeOwnerAndChromeEventHandlerOnDocshellTree(otherDocshell, ourOwner,
|
2016-05-01 21:29:23 +03:00
|
|
|
ourType == nsIDocShellTreeItem::typeContent ? ourChromeEventHandler.get() : nullptr);
|
2008-08-08 03:15:40 +04:00
|
|
|
|
2012-09-05 07:00:26 +04:00
|
|
|
// Switch the owner content before we start calling AddTreeItemToTreeOwner.
|
|
|
|
// Note that we rely on this to deal with setting mObservingOwnerContent to
|
|
|
|
// false and calling RemoveMutationObserver as needed.
|
|
|
|
SetOwnerContent(otherContent);
|
|
|
|
aOther->SetOwnerContent(ourContent);
|
|
|
|
|
2013-02-13 02:02:51 +04:00
|
|
|
AddTreeItemToTreeOwner(ourDocshell, otherOwner, otherParentType, nullptr);
|
|
|
|
aOther->AddTreeItemToTreeOwner(otherDocshell, ourOwner, ourParentType,
|
2012-09-05 07:00:26 +04:00
|
|
|
nullptr);
|
2008-08-08 03:15:40 +04:00
|
|
|
|
|
|
|
// SetSubDocumentFor nulls out parent documents on the old child doc if a
|
|
|
|
// new non-null document is passed in, so just go ahead and remove both
|
|
|
|
// kids before reinserting in the parent subdoc maps, to avoid
|
|
|
|
// complications.
|
2012-07-30 18:20:58 +04:00
|
|
|
ourParentDocument->SetSubDocumentFor(ourContent, nullptr);
|
|
|
|
otherParentDocument->SetSubDocumentFor(otherContent, nullptr);
|
2008-08-08 03:15:40 +04:00
|
|
|
ourParentDocument->SetSubDocumentFor(ourContent, otherChildDocument);
|
|
|
|
otherParentDocument->SetSubDocumentFor(otherContent, ourChildDocument);
|
|
|
|
|
|
|
|
ourWindow->SetFrameElementInternal(otherFrameElement);
|
|
|
|
otherWindow->SetFrameElementInternal(ourFrameElement);
|
|
|
|
|
2015-10-18 08:24:48 +03:00
|
|
|
RefPtr<nsFrameMessageManager> ourMessageManager = mMessageManager;
|
|
|
|
RefPtr<nsFrameMessageManager> otherMessageManager = aOther->mMessageManager;
|
2010-05-18 16:28:37 +04:00
|
|
|
// Swap pointers in child message managers.
|
|
|
|
if (mChildMessageManager) {
|
|
|
|
nsInProcessTabChildGlobal* tabChild =
|
|
|
|
static_cast<nsInProcessTabChildGlobal*>(mChildMessageManager.get());
|
|
|
|
tabChild->SetOwner(otherContent);
|
|
|
|
tabChild->SetChromeMessageManager(otherMessageManager);
|
|
|
|
}
|
|
|
|
if (aOther->mChildMessageManager) {
|
|
|
|
nsInProcessTabChildGlobal* otherTabChild =
|
|
|
|
static_cast<nsInProcessTabChildGlobal*>(aOther->mChildMessageManager.get());
|
|
|
|
otherTabChild->SetOwner(ourContent);
|
|
|
|
otherTabChild->SetChromeMessageManager(ourMessageManager);
|
|
|
|
}
|
|
|
|
// Swap and setup things in parent message managers.
|
|
|
|
if (mMessageManager) {
|
2014-01-31 22:45:54 +04:00
|
|
|
mMessageManager->SetCallback(aOther);
|
2010-05-18 16:28:37 +04:00
|
|
|
}
|
|
|
|
if (aOther->mMessageManager) {
|
2014-01-31 22:45:54 +04:00
|
|
|
aOther->mMessageManager->SetCallback(this);
|
2010-05-18 16:28:37 +04:00
|
|
|
}
|
|
|
|
mMessageManager.swap(aOther->mMessageManager);
|
|
|
|
|
2016-10-17 17:37:50 +03:00
|
|
|
// Perform the actual swap of the internal refptrs. We keep a strong reference
|
|
|
|
// to ourselves to make sure we don't die while we overwrite our reference to
|
|
|
|
// ourself.
|
|
|
|
nsCOMPtr<nsIFrameLoader> kungFuDeathGrip(this);
|
|
|
|
aThisOwner->InternalSetFrameLoader(aOther);
|
|
|
|
aOtherOwner->InternalSetFrameLoader(kungFuDeathGrip);
|
2008-08-08 03:15:40 +04:00
|
|
|
|
2009-01-13 22:32:30 +03:00
|
|
|
// Drop any cached content viewers in the two session histories.
|
|
|
|
nsCOMPtr<nsISHistoryInternal> ourInternalHistory =
|
|
|
|
do_QueryInterface(ourHistory);
|
|
|
|
nsCOMPtr<nsISHistoryInternal> otherInternalHistory =
|
|
|
|
do_QueryInterface(otherHistory);
|
|
|
|
if (ourInternalHistory) {
|
|
|
|
ourInternalHistory->EvictAllContentViewers();
|
|
|
|
}
|
|
|
|
if (otherInternalHistory) {
|
|
|
|
otherInternalHistory->EvictAllContentViewers();
|
|
|
|
}
|
|
|
|
|
2010-09-18 15:28:49 +04:00
|
|
|
NS_ASSERTION(ourFrame == ourContent->GetPrimaryFrame() &&
|
|
|
|
otherFrame == otherContent->GetPrimaryFrame(),
|
|
|
|
"changed primary frame");
|
|
|
|
|
|
|
|
ourFrameFrame->EndSwapDocShells(otherFrame);
|
2008-08-08 03:15:40 +04:00
|
|
|
|
2013-02-03 16:21:52 +04:00
|
|
|
// If the content being swapped came from windows on two screens with
|
|
|
|
// incompatible backing resolution (e.g. dragging a tab between windows on
|
|
|
|
// hi-dpi and low-dpi screens), it will have style data that is based on
|
|
|
|
// the wrong appUnitsPerDevPixel value. So we tell the PresShells that their
|
|
|
|
// backing scale factor may have changed. (Bug 822266)
|
|
|
|
ourShell->BackingScaleFactorChanged();
|
|
|
|
otherShell->BackingScaleFactorChanged();
|
|
|
|
|
2017-01-05 10:31:56 +03:00
|
|
|
ourParentDocument->FlushPendingNotifications(FlushType::Layout);
|
|
|
|
otherParentDocument->FlushPendingNotifications(FlushType::Layout);
|
2010-09-18 15:28:49 +04:00
|
|
|
|
2016-04-29 01:04:52 +03:00
|
|
|
// Initialize browser API if needed now that owner content has changed
|
|
|
|
InitializeBrowserAPI();
|
|
|
|
aOther->InitializeBrowserAPI();
|
|
|
|
|
2008-08-08 03:15:40 +04:00
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2015-02-27 08:35:26 +03:00
|
|
|
NS_IMETHODIMP
|
|
|
|
nsFrameLoader::Destroy()
|
2010-04-12 04:34:02 +04:00
|
|
|
{
|
2015-02-27 08:35:26 +03:00
|
|
|
StartDestroy();
|
|
|
|
return NS_OK;
|
2010-04-12 04:34:02 +04:00
|
|
|
}
|
|
|
|
|
2016-04-26 03:23:21 +03:00
|
|
|
class nsFrameLoaderDestroyRunnable : public Runnable
|
2015-02-27 08:35:26 +03:00
|
|
|
{
|
|
|
|
enum DestroyPhase
|
|
|
|
{
|
|
|
|
// See the implementation of Run for an explanation of these phases.
|
|
|
|
eDestroyDocShell,
|
|
|
|
eWaitForUnloadMessage,
|
|
|
|
eDestroyComplete
|
|
|
|
};
|
|
|
|
|
2015-10-18 08:24:48 +03:00
|
|
|
RefPtr<nsFrameLoader> mFrameLoader;
|
2015-02-27 08:35:26 +03:00
|
|
|
DestroyPhase mPhase;
|
|
|
|
|
|
|
|
public:
|
|
|
|
explicit nsFrameLoaderDestroyRunnable(nsFrameLoader* aFrameLoader)
|
|
|
|
: mFrameLoader(aFrameLoader), mPhase(eDestroyDocShell) {}
|
|
|
|
|
2016-08-08 03:54:47 +03:00
|
|
|
NS_IMETHOD Run() override;
|
2015-02-27 08:35:26 +03:00
|
|
|
};
|
|
|
|
|
|
|
|
void
|
|
|
|
nsFrameLoader::StartDestroy()
|
2002-04-05 09:42:10 +04:00
|
|
|
{
|
2015-02-27 08:35:26 +03:00
|
|
|
// nsFrameLoader::StartDestroy is called just before the frameloader is
|
|
|
|
// detached from the <browser> element. Destruction continues in phases via
|
|
|
|
// the nsFrameLoaderDestroyRunnable.
|
|
|
|
|
2008-02-26 17:47:51 +03:00
|
|
|
if (mDestroyCalled) {
|
2015-02-27 08:35:26 +03:00
|
|
|
return;
|
2008-02-26 17:47:51 +03:00
|
|
|
}
|
2011-10-17 18:59:28 +04:00
|
|
|
mDestroyCalled = true;
|
2008-02-26 17:47:51 +03:00
|
|
|
|
2015-02-27 08:35:26 +03:00
|
|
|
// After this point, we return an error when trying to send a message using
|
|
|
|
// the message manager on the frame.
|
2010-05-18 16:28:37 +04:00
|
|
|
if (mMessageManager) {
|
2015-02-27 08:35:26 +03:00
|
|
|
mMessageManager->Close();
|
2010-05-18 16:28:37 +04:00
|
|
|
}
|
2015-02-27 08:35:26 +03:00
|
|
|
|
|
|
|
// Retain references to the <browser> element and the frameloader in case we
|
|
|
|
// receive any messages from the message manager on the frame. These
|
|
|
|
// references are dropped in DestroyComplete.
|
|
|
|
if (mChildMessageManager || mRemoteBrowser) {
|
|
|
|
mOwnerContentStrong = mOwnerContent;
|
|
|
|
if (mRemoteBrowser) {
|
|
|
|
mRemoteBrowser->CacheFrameLoader(this);
|
|
|
|
}
|
2015-04-16 18:17:54 +03:00
|
|
|
if (mChildMessageManager) {
|
|
|
|
mChildMessageManager->CacheFrameLoader(this);
|
|
|
|
}
|
2010-05-18 16:28:37 +04:00
|
|
|
}
|
|
|
|
|
2015-03-31 23:39:02 +03:00
|
|
|
// If the TabParent has installed any event listeners on the window, this is
|
|
|
|
// its last chance to remove them while we're still in the document.
|
|
|
|
if (mRemoteBrowser) {
|
|
|
|
mRemoteBrowser->RemoveWindowListeners();
|
|
|
|
}
|
|
|
|
|
2008-02-26 17:47:51 +03:00
|
|
|
nsCOMPtr<nsIDocument> doc;
|
2011-09-29 10:19:26 +04:00
|
|
|
bool dynamicSubframeRemoval = false;
|
2002-04-17 08:17:16 +04:00
|
|
|
if (mOwnerContent) {
|
2011-10-18 14:53:36 +04:00
|
|
|
doc = mOwnerContent->OwnerDoc();
|
2011-10-18 15:19:44 +04:00
|
|
|
dynamicSubframeRemoval = !mIsTopLevelContent && !doc->InUnlinkOrDeletion();
|
2012-07-30 18:20:58 +04:00
|
|
|
doc->SetSubDocumentFor(mOwnerContent, nullptr);
|
2015-10-01 20:06:51 +03:00
|
|
|
MaybeUpdatePrimaryTabParent(eTabParentRemoved);
|
2012-07-30 18:20:58 +04:00
|
|
|
SetOwnerContent(nullptr);
|
2002-04-17 08:17:16 +04:00
|
|
|
}
|
2010-08-17 18:13:55 +04:00
|
|
|
|
|
|
|
// Seems like this is a dynamic frame removal.
|
|
|
|
if (dynamicSubframeRemoval) {
|
2013-02-15 20:07:29 +04:00
|
|
|
if (mDocShell) {
|
|
|
|
mDocShell->RemoveFromSessionHistory();
|
2010-08-17 18:13:55 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2006-02-22 06:58:48 +03:00
|
|
|
// Let the tree owner know we're gone.
|
|
|
|
if (mIsTopLevelContent) {
|
2013-02-13 02:02:51 +04:00
|
|
|
if (mDocShell) {
|
2006-02-22 06:58:48 +03:00
|
|
|
nsCOMPtr<nsIDocShellTreeItem> parentItem;
|
2013-02-13 02:02:51 +04:00
|
|
|
mDocShell->GetParent(getter_AddRefs(parentItem));
|
2006-02-22 06:58:48 +03:00
|
|
|
nsCOMPtr<nsIDocShellTreeOwner> owner = do_GetInterface(parentItem);
|
2007-10-06 03:37:25 +04:00
|
|
|
if (owner) {
|
2013-02-13 02:02:51 +04:00
|
|
|
owner->ContentShellRemoved(mDocShell);
|
2006-02-22 06:58:48 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2015-02-27 08:35:26 +03:00
|
|
|
|
2003-11-04 05:01:23 +03:00
|
|
|
// Let our window know that we are gone
|
2014-01-10 06:03:47 +04:00
|
|
|
if (mDocShell) {
|
2016-01-30 20:05:36 +03:00
|
|
|
nsCOMPtr<nsPIDOMWindowOuter> win_private(mDocShell->GetWindow());
|
2014-01-10 06:03:47 +04:00
|
|
|
if (win_private) {
|
|
|
|
win_private->SetFrameElementInternal(nullptr);
|
|
|
|
}
|
2003-11-04 05:01:23 +03:00
|
|
|
}
|
2002-04-17 08:17:16 +04:00
|
|
|
|
2016-12-15 08:17:16 +03:00
|
|
|
// Destroy the other frame loader owners now that we are being destroyed.
|
2016-12-22 11:06:50 +03:00
|
|
|
if (mPartialSHistory &&
|
|
|
|
mPartialSHistory->GetActiveState() == nsIPartialSHistory::STATE_ACTIVE) {
|
2016-12-19 10:03:17 +03:00
|
|
|
nsCOMPtr<nsIGroupedSHistory> groupedSHistory;
|
2016-12-22 11:06:50 +03:00
|
|
|
GetGroupedSHistory(getter_AddRefs(groupedSHistory));
|
2016-12-19 10:03:17 +03:00
|
|
|
if (groupedSHistory) {
|
|
|
|
NS_DispatchToCurrentThread(NS_NewRunnableFunction([groupedSHistory] () {
|
|
|
|
groupedSHistory->CloseInactiveFrameLoaderOwners();
|
|
|
|
}));
|
|
|
|
}
|
2016-12-15 08:17:16 +03:00
|
|
|
}
|
|
|
|
|
2015-02-27 08:35:26 +03:00
|
|
|
nsCOMPtr<nsIRunnable> destroyRunnable = new nsFrameLoaderDestroyRunnable(this);
|
|
|
|
if (mNeedsAsyncDestroy || !doc ||
|
|
|
|
NS_FAILED(doc->FinalizeFrameLoader(this, destroyRunnable))) {
|
|
|
|
NS_DispatchToCurrentThread(destroyRunnable);
|
|
|
|
}
|
|
|
|
}
|
2008-02-26 17:47:51 +03:00
|
|
|
|
2015-02-27 08:35:26 +03:00
|
|
|
nsresult
|
|
|
|
nsFrameLoaderDestroyRunnable::Run()
|
|
|
|
{
|
|
|
|
switch (mPhase) {
|
|
|
|
case eDestroyDocShell:
|
|
|
|
mFrameLoader->DestroyDocShell();
|
|
|
|
|
|
|
|
// In the out-of-process case, TabParent will eventually call
|
|
|
|
// DestroyComplete once it receives a __delete__ message from the child. In
|
|
|
|
// the in-process case, we dispatch a series of runnables to ensure that
|
|
|
|
// DestroyComplete gets called at the right time. The frame loader is kept
|
|
|
|
// alive by mFrameLoader during this time.
|
|
|
|
if (mFrameLoader->mChildMessageManager) {
|
|
|
|
// When the docshell is destroyed, NotifyWindowIDDestroyed is called to
|
|
|
|
// asynchronously notify {outer,inner}-window-destroyed via a runnable. We
|
|
|
|
// don't want DestroyComplete to run until after those runnables have
|
|
|
|
// run. Since we're enqueueing ourselves after the window-destroyed
|
|
|
|
// runnables are enqueued, we're guaranteed to run after.
|
|
|
|
mPhase = eWaitForUnloadMessage;
|
|
|
|
NS_DispatchToCurrentThread(this);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case eWaitForUnloadMessage:
|
|
|
|
// The *-window-destroyed observers have finished running at this
|
|
|
|
// point. However, it's possible that a *-window-destroyed observer might
|
|
|
|
// have sent a message using the message manager. These messages might not
|
|
|
|
// have been processed yet. So we enqueue ourselves again to ensure that
|
|
|
|
// DestroyComplete runs after all messages sent by *-window-destroyed
|
|
|
|
// observers have been processed.
|
|
|
|
mPhase = eDestroyComplete;
|
|
|
|
NS_DispatchToCurrentThread(this);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case eDestroyComplete:
|
|
|
|
// Now that all messages sent by unload listeners and window destroyed
|
|
|
|
// observers have been processed, we disconnect the message manager and
|
|
|
|
// finish destruction.
|
|
|
|
mFrameLoader->DestroyComplete();
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
return NS_OK;
|
|
|
|
}
|
2008-02-26 17:47:51 +03:00
|
|
|
|
2015-02-27 08:35:26 +03:00
|
|
|
void
|
|
|
|
nsFrameLoader::DestroyDocShell()
|
|
|
|
{
|
|
|
|
// This code runs after the frameloader has been detached from the <browser>
|
|
|
|
// element. We postpone this work because we may not be allowed to run
|
|
|
|
// script at that time.
|
|
|
|
|
|
|
|
// Ask the TabChild to fire the frame script "unload" event, destroy its
|
|
|
|
// docshell, and finally destroy the PBrowser actor. This eventually leads to
|
|
|
|
// nsFrameLoader::DestroyComplete being called.
|
|
|
|
if (mRemoteBrowser) {
|
|
|
|
mRemoteBrowser->Destroy();
|
2002-04-17 08:17:16 +04:00
|
|
|
}
|
|
|
|
|
2015-02-27 08:35:26 +03:00
|
|
|
// Fire the "unload" event if we're in-process.
|
|
|
|
if (mChildMessageManager) {
|
|
|
|
static_cast<nsInProcessTabChildGlobal*>(mChildMessageManager.get())->FireUnloadEvent();
|
|
|
|
}
|
2008-02-26 17:47:51 +03:00
|
|
|
|
2015-02-27 08:35:26 +03:00
|
|
|
// Destroy the docshell.
|
|
|
|
nsCOMPtr<nsIBaseWindow> base_win(do_QueryInterface(mDocShell));
|
|
|
|
if (base_win) {
|
|
|
|
base_win->Destroy();
|
|
|
|
}
|
|
|
|
mDocShell = nullptr;
|
|
|
|
|
|
|
|
if (mChildMessageManager) {
|
|
|
|
// Stop handling events in the in-process frame script.
|
|
|
|
static_cast<nsInProcessTabChildGlobal*>(mChildMessageManager.get())->DisconnectEventListeners();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
nsFrameLoader::DestroyComplete()
|
|
|
|
{
|
|
|
|
// We get here, as part of StartDestroy, after the docshell has been destroyed
|
|
|
|
// and all message manager messages sent during docshell destruction have been
|
|
|
|
// dispatched. We also get here if the child process crashes. In the latter
|
|
|
|
// case, StartDestroy might not have been called.
|
|
|
|
|
|
|
|
// Drop the strong references created in StartDestroy.
|
|
|
|
if (mChildMessageManager || mRemoteBrowser) {
|
|
|
|
mOwnerContentStrong = nullptr;
|
|
|
|
if (mRemoteBrowser) {
|
|
|
|
mRemoteBrowser->CacheFrameLoader(nullptr);
|
|
|
|
}
|
2015-04-16 18:17:54 +03:00
|
|
|
if (mChildMessageManager) {
|
|
|
|
mChildMessageManager->CacheFrameLoader(nullptr);
|
|
|
|
}
|
2015-02-27 08:35:26 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
// Call TabParent::Destroy if we haven't already (in case of a crash).
|
|
|
|
if (mRemoteBrowser) {
|
|
|
|
mRemoteBrowser->SetOwnerElement(nullptr);
|
|
|
|
mRemoteBrowser->Destroy();
|
|
|
|
mRemoteBrowser = nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (mMessageManager) {
|
|
|
|
mMessageManager->Disconnect();
|
|
|
|
}
|
|
|
|
|
|
|
|
if (mChildMessageManager) {
|
|
|
|
static_cast<nsInProcessTabChildGlobal*>(mChildMessageManager.get())->Disconnect();
|
|
|
|
}
|
2016-02-20 13:33:30 +03:00
|
|
|
|
|
|
|
mMessageManager = nullptr;
|
|
|
|
mChildMessageManager = nullptr;
|
2002-01-29 09:27:27 +03:00
|
|
|
}
|
|
|
|
|
2005-08-22 19:44:49 +04:00
|
|
|
NS_IMETHODIMP
|
2011-09-29 10:19:26 +04:00
|
|
|
nsFrameLoader::GetDepthTooGreat(bool* aDepthTooGreat)
|
2005-08-22 19:44:49 +04:00
|
|
|
{
|
|
|
|
*aDepthTooGreat = mDepthTooGreat;
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2011-01-13 20:45:14 +03:00
|
|
|
void
|
2011-10-01 21:14:35 +04:00
|
|
|
nsFrameLoader::SetOwnerContent(Element* aContent)
|
2011-01-13 20:45:14 +03:00
|
|
|
{
|
2012-09-05 07:00:26 +04:00
|
|
|
if (mObservingOwnerContent) {
|
|
|
|
mObservingOwnerContent = false;
|
|
|
|
mOwnerContent->RemoveMutationObserver(this);
|
|
|
|
}
|
2011-01-13 20:45:14 +03:00
|
|
|
mOwnerContent = aContent;
|
2015-06-09 13:30:08 +03:00
|
|
|
if (RenderFrameParent* rfp = GetCurrentRenderFrame()) {
|
2011-01-13 20:45:14 +03:00
|
|
|
rfp->OwnerContentChanged(aContent);
|
|
|
|
}
|
2011-01-13 20:45:14 +03:00
|
|
|
}
|
|
|
|
|
2012-04-25 19:29:28 +04:00
|
|
|
bool
|
2016-10-15 04:46:26 +03:00
|
|
|
nsFrameLoader::OwnerIsMozBrowserFrame()
|
2012-04-25 19:29:28 +04:00
|
|
|
{
|
2012-04-25 20:35:58 +04:00
|
|
|
nsCOMPtr<nsIMozBrowserFrame> browserFrame = do_QueryInterface(mOwnerContent);
|
2016-10-15 04:46:26 +03:00
|
|
|
return browserFrame ? browserFrame->GetReallyIsBrowser() : false;
|
2012-04-25 20:35:58 +04:00
|
|
|
}
|
2012-04-25 19:51:31 +04:00
|
|
|
|
2014-02-21 02:19:18 +04:00
|
|
|
// The xpcom getter version
|
|
|
|
NS_IMETHODIMP
|
2016-10-15 04:46:26 +03:00
|
|
|
nsFrameLoader::GetOwnerIsMozBrowserFrame(bool* aResult)
|
2014-02-21 02:19:18 +04:00
|
|
|
{
|
2016-10-15 04:46:26 +03:00
|
|
|
*aResult = OwnerIsMozBrowserFrame();
|
2014-02-21 02:19:18 +04:00
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2016-02-18 06:31:29 +03:00
|
|
|
bool
|
|
|
|
nsFrameLoader::OwnerIsIsolatedMozBrowserFrame()
|
|
|
|
{
|
|
|
|
nsCOMPtr<nsIMozBrowserFrame> browserFrame = do_QueryInterface(mOwnerContent);
|
|
|
|
if (!browserFrame) {
|
|
|
|
return false;
|
|
|
|
}
|
2016-02-18 07:57:41 +03:00
|
|
|
|
|
|
|
if (!OwnerIsMozBrowserFrame()) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool isolated = browserFrame->GetIsolated();
|
|
|
|
if (isolated) {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
2012-07-14 01:10:20 +04:00
|
|
|
}
|
|
|
|
|
2012-04-25 20:35:58 +04:00
|
|
|
bool
|
|
|
|
nsFrameLoader::ShouldUseRemoteProcess()
|
|
|
|
{
|
2011-06-07 23:23:15 +04:00
|
|
|
if (PR_GetEnv("MOZ_DISABLE_OOP_TABS") ||
|
2011-09-29 10:19:26 +04:00
|
|
|
Preferences::GetBool("dom.ipc.tabs.disabled", false)) {
|
2009-10-16 23:42:27 +04:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2014-06-11 09:44:13 +04:00
|
|
|
// Don't try to launch nested children if we don't have OMTC.
|
|
|
|
// They won't render!
|
2015-07-04 04:29:00 +03:00
|
|
|
if (XRE_IsContentProcess() &&
|
2015-11-24 04:50:51 +03:00
|
|
|
!CompositorBridgeChild::ChildProcessHasCompositorBridge()) {
|
2014-06-11 09:44:13 +04:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2015-07-04 04:29:00 +03:00
|
|
|
if (XRE_IsContentProcess() &&
|
2014-06-11 09:44:13 +04:00
|
|
|
!(PR_GetEnv("MOZ_NESTED_OOP_TABS") ||
|
|
|
|
Preferences::GetBool("dom.ipc.tabs.nested.enabled", false))) {
|
2012-07-10 07:32:47 +04:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2012-05-16 09:28:56 +04:00
|
|
|
// If we're an <iframe mozbrowser> and we don't have a "remote" attribute,
|
|
|
|
// fall back to the default.
|
2016-10-15 04:46:26 +03:00
|
|
|
if (OwnerIsMozBrowserFrame() &&
|
2012-05-16 09:28:56 +04:00
|
|
|
!mOwnerContent->HasAttr(kNameSpaceID_None, nsGkAtoms::Remote)) {
|
|
|
|
|
|
|
|
return Preferences::GetBool("dom.ipc.browser_frames.oop_by_default", false);
|
|
|
|
}
|
|
|
|
|
2012-05-16 09:28:57 +04:00
|
|
|
// Otherwise, we're remote if we have "remote=true" and we're either a
|
|
|
|
// browser frame or a XUL element.
|
2016-10-15 04:46:26 +03:00
|
|
|
return (OwnerIsMozBrowserFrame() ||
|
2012-05-16 09:28:57 +04:00
|
|
|
mOwnerContent->GetNameSpaceID() == kNameSpaceID_XUL) &&
|
|
|
|
mOwnerContent->AttrValueIs(kNameSpaceID_None,
|
2012-05-16 09:28:56 +04:00
|
|
|
nsGkAtoms::Remote,
|
|
|
|
nsGkAtoms::_true,
|
|
|
|
eCaseMatters);
|
2009-10-16 23:42:27 +04:00
|
|
|
}
|
|
|
|
|
2015-07-31 12:28:36 +03:00
|
|
|
bool
|
|
|
|
nsFrameLoader::IsRemoteFrame()
|
|
|
|
{
|
|
|
|
if (mRemoteFrame) {
|
|
|
|
MOZ_ASSERT(!mDocShell, "Found a remote frame with a DocShell");
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2002-01-29 09:27:27 +03:00
|
|
|
nsresult
|
2009-10-16 23:42:27 +04:00
|
|
|
nsFrameLoader::MaybeCreateDocShell()
|
2002-01-29 09:27:27 +03:00
|
|
|
{
|
2009-10-27 23:38:26 +03:00
|
|
|
if (mDocShell) {
|
|
|
|
return NS_OK;
|
|
|
|
}
|
2015-07-31 12:28:36 +03:00
|
|
|
if (IsRemoteFrame()) {
|
2002-01-29 09:27:27 +03:00
|
|
|
return NS_OK;
|
|
|
|
}
|
2008-02-26 17:47:51 +03:00
|
|
|
NS_ENSURE_STATE(!mDestroyCalled);
|
2002-01-29 09:27:27 +03:00
|
|
|
|
2004-05-31 20:31:15 +04:00
|
|
|
// Get our parent docshell off the document of mOwnerContent
|
|
|
|
// XXXbz this is such a total hack.... We really need to have a
|
|
|
|
// better setup for doing this.
|
2011-10-18 14:53:36 +04:00
|
|
|
nsIDocument* doc = mOwnerContent->OwnerDoc();
|
2016-05-12 19:22:25 +03:00
|
|
|
|
|
|
|
MOZ_RELEASE_ASSERT(!doc->IsResourceDoc(), "We shouldn't even exist");
|
|
|
|
|
2015-02-24 17:41:43 +03:00
|
|
|
if (!(doc->IsStaticDocument() || mOwnerContent->IsInComposedDoc())) {
|
2004-05-31 20:31:15 +04:00
|
|
|
return NS_ERROR_UNEXPECTED;
|
|
|
|
}
|
|
|
|
|
2016-05-12 19:22:25 +03:00
|
|
|
if (!doc->IsActive()) {
|
|
|
|
// Don't allow subframe loads in non-active documents.
|
|
|
|
// (See bug 610571 comment 5.)
|
2008-10-05 00:00:09 +04:00
|
|
|
return NS_ERROR_NOT_AVAILABLE;
|
|
|
|
}
|
|
|
|
|
2014-01-07 02:34:15 +04:00
|
|
|
nsCOMPtr<nsIDocShell> docShell = doc->GetDocShell();
|
|
|
|
nsCOMPtr<nsIWebNavigation> parentAsWebNav = do_QueryInterface(docShell);
|
2011-06-16 00:21:32 +04:00
|
|
|
NS_ENSURE_STATE(parentAsWebNav);
|
2002-01-29 09:27:27 +03:00
|
|
|
|
2002-04-17 08:17:16 +04:00
|
|
|
// Create the docshell...
|
2009-05-07 23:21:53 +04:00
|
|
|
mDocShell = do_CreateInstance("@mozilla.org/docshell;1");
|
2002-01-29 09:27:27 +03:00
|
|
|
NS_ENSURE_TRUE(mDocShell, NS_ERROR_FAILURE);
|
|
|
|
|
2015-01-05 22:16:09 +03:00
|
|
|
if (mIsPrerendered) {
|
2016-05-20 06:36:27 +03:00
|
|
|
nsresult rv = mDocShell->SetIsPrerendered();
|
2015-01-05 22:16:09 +03:00
|
|
|
NS_ENSURE_SUCCESS(rv,rv);
|
|
|
|
}
|
|
|
|
|
2010-08-17 18:13:55 +04:00
|
|
|
if (!mNetworkCreated) {
|
2013-02-15 20:07:29 +04:00
|
|
|
if (mDocShell) {
|
|
|
|
mDocShell->SetCreatedDynamically(true);
|
2010-08-17 18:13:55 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2002-04-17 08:17:16 +04:00
|
|
|
// Get the frame name and tell the docshell about it.
|
2013-02-13 02:02:51 +04:00
|
|
|
NS_ENSURE_TRUE(mDocShell, NS_ERROR_FAILURE);
|
2002-01-29 09:27:27 +03:00
|
|
|
nsAutoString frameName;
|
2004-09-13 03:34:00 +04:00
|
|
|
|
2012-08-22 19:56:38 +04:00
|
|
|
int32_t namespaceID = mOwnerContent->GetNameSpaceID();
|
2015-02-10 12:14:19 +03:00
|
|
|
if (namespaceID == kNameSpaceID_XHTML && !mOwnerContent->IsInHTMLDocument()) {
|
2006-12-26 20:47:52 +03:00
|
|
|
mOwnerContent->GetAttr(kNameSpaceID_None, nsGkAtoms::id, frameName);
|
2004-09-13 03:34:00 +04:00
|
|
|
} else {
|
2006-12-26 20:47:52 +03:00
|
|
|
mOwnerContent->GetAttr(kNameSpaceID_None, nsGkAtoms::name, frameName);
|
2004-10-01 22:32:18 +04:00
|
|
|
// XXX if no NAME then use ID, after a transition period this will be
|
|
|
|
// changed so that XUL only uses ID too (bug 254284).
|
2005-09-24 22:43:15 +04:00
|
|
|
if (frameName.IsEmpty() && namespaceID == kNameSpaceID_XUL) {
|
2006-12-26 20:47:52 +03:00
|
|
|
mOwnerContent->GetAttr(kNameSpaceID_None, nsGkAtoms::id, frameName);
|
2004-10-01 22:32:18 +04:00
|
|
|
}
|
2004-09-13 03:34:00 +04:00
|
|
|
}
|
2002-01-29 09:27:27 +03:00
|
|
|
|
|
|
|
if (!frameName.IsEmpty()) {
|
2013-03-20 05:47:47 +04:00
|
|
|
mDocShell->SetName(frameName);
|
2002-01-29 09:27:27 +03:00
|
|
|
}
|
|
|
|
|
2014-01-07 02:34:15 +04:00
|
|
|
// Inform our docShell that it has a new child.
|
|
|
|
// Note: This logic duplicates a lot of logic in
|
|
|
|
// nsSubDocumentFrame::AttributeChanged. We should fix that.
|
2002-01-29 09:27:27 +03:00
|
|
|
|
2014-01-20 11:58:26 +04:00
|
|
|
int32_t parentType = docShell->ItemType();
|
2006-02-22 06:58:48 +03:00
|
|
|
|
2014-01-07 02:34:15 +04:00
|
|
|
// XXXbz why is this in content code, exactly? We should handle
|
|
|
|
// this some other way..... Not sure how yet.
|
|
|
|
nsCOMPtr<nsIDocShellTreeOwner> parentTreeOwner;
|
|
|
|
docShell->GetTreeOwner(getter_AddRefs(parentTreeOwner));
|
|
|
|
NS_ENSURE_STATE(parentTreeOwner);
|
|
|
|
mIsTopLevelContent =
|
|
|
|
AddTreeItemToTreeOwner(mDocShell, parentTreeOwner, parentType, docShell);
|
2002-04-05 09:42:10 +04:00
|
|
|
|
2014-01-07 02:34:15 +04:00
|
|
|
// Make sure all shells have links back to the content element
|
|
|
|
// in the nearest enclosing chrome shell.
|
|
|
|
nsCOMPtr<nsIDOMEventTarget> chromeEventHandler;
|
2002-04-05 09:42:10 +04:00
|
|
|
|
2014-01-07 02:34:15 +04:00
|
|
|
if (parentType == nsIDocShellTreeItem::typeChrome) {
|
|
|
|
// Our parent shell is a chrome shell. It is therefore our nearest
|
|
|
|
// enclosing chrome shell.
|
2002-01-29 09:27:27 +03:00
|
|
|
|
2014-01-07 02:34:15 +04:00
|
|
|
chromeEventHandler = do_QueryInterface(mOwnerContent);
|
|
|
|
NS_ASSERTION(chromeEventHandler,
|
|
|
|
"This mContent should implement this.");
|
|
|
|
} else {
|
|
|
|
// Our parent shell is a content shell. Get the chrome event
|
|
|
|
// handler from it and use that for our shell as well.
|
2002-01-29 09:27:27 +03:00
|
|
|
|
2014-01-07 02:34:15 +04:00
|
|
|
docShell->GetChromeEventHandler(getter_AddRefs(chromeEventHandler));
|
2002-04-17 08:17:16 +04:00
|
|
|
}
|
2002-01-29 09:27:27 +03:00
|
|
|
|
2014-01-07 02:34:15 +04:00
|
|
|
mDocShell->SetChromeEventHandler(chromeEventHandler);
|
|
|
|
|
2014-01-10 06:03:47 +04:00
|
|
|
// This is nasty, this code (the mDocShell->GetWindow() below)
|
2002-04-17 08:17:16 +04:00
|
|
|
// *must* come *after* the above call to
|
|
|
|
// mDocShell->SetChromeEventHandler() for the global window to get
|
|
|
|
// the right chrome event handler.
|
2002-01-29 09:27:27 +03:00
|
|
|
|
2002-04-17 08:17:16 +04:00
|
|
|
// Tell the window about the frame that hosts it.
|
2013-07-24 03:39:17 +04:00
|
|
|
nsCOMPtr<Element> frame_element = mOwnerContent;
|
2002-04-17 08:17:16 +04:00
|
|
|
NS_ASSERTION(frame_element, "frame loader owner element not a DOM element!");
|
2002-01-29 09:27:27 +03:00
|
|
|
|
2016-01-30 20:05:36 +03:00
|
|
|
nsCOMPtr<nsPIDOMWindowOuter> win_private(mDocShell->GetWindow());
|
2002-04-17 08:17:16 +04:00
|
|
|
nsCOMPtr<nsIBaseWindow> base_win(do_QueryInterface(mDocShell));
|
2008-12-13 23:30:02 +03:00
|
|
|
if (win_private) {
|
|
|
|
win_private->SetFrameElementInternal(frame_element);
|
2016-10-17 17:37:50 +03:00
|
|
|
|
|
|
|
// Set the opener window if we have one provided here
|
|
|
|
if (mOpener) {
|
|
|
|
win_private->SetOpenerWindow(mOpener, true);
|
|
|
|
mOpener = nullptr;
|
|
|
|
}
|
2008-12-13 23:30:02 +03:00
|
|
|
}
|
2002-04-05 02:42:19 +04:00
|
|
|
|
2002-04-17 08:17:16 +04:00
|
|
|
// This is kinda whacky, this call doesn't really create anything,
|
|
|
|
// but it must be called to make sure things are properly
|
2009-01-08 23:16:33 +03:00
|
|
|
// initialized.
|
2008-12-13 23:30:02 +03:00
|
|
|
if (NS_FAILED(base_win->Create()) || !win_private) {
|
2009-01-08 23:16:33 +03:00
|
|
|
// Do not call Destroy() here. See bug 472312.
|
2009-01-09 00:36:22 +03:00
|
|
|
NS_WARNING("Something wrong when creating the docshell for a frameloader!");
|
2008-12-13 23:30:02 +03:00
|
|
|
return NS_ERROR_FAILURE;
|
|
|
|
}
|
2002-04-04 06:09:19 +04:00
|
|
|
|
2014-02-12 23:07:19 +04:00
|
|
|
if (mIsTopLevelContent &&
|
2015-03-03 14:08:59 +03:00
|
|
|
mOwnerContent->IsXULElement(nsGkAtoms::browser) &&
|
2014-02-12 23:07:19 +04:00
|
|
|
!mOwnerContent->HasAttr(kNameSpaceID_None, nsGkAtoms::disablehistory)) {
|
|
|
|
nsresult rv;
|
|
|
|
nsCOMPtr<nsISHistory> sessionHistory =
|
|
|
|
do_CreateInstance(NS_SHISTORY_CONTRACTID, &rv);
|
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
|
|
|
|
nsCOMPtr<nsIWebNavigation> webNav(do_QueryInterface(mDocShell));
|
|
|
|
webNav->SetSessionHistory(sessionHistory);
|
2016-10-14 10:31:02 +03:00
|
|
|
|
|
|
|
|
|
|
|
if (GroupedSHistory::GroupedHistoryEnabled()) {
|
2016-12-22 11:06:50 +03:00
|
|
|
mPartialSHistory = new PartialSHistory(this);
|
|
|
|
nsCOMPtr<nsISHistoryListener> listener(do_QueryInterface(mPartialSHistory));
|
|
|
|
nsCOMPtr<nsIPartialSHistoryListener> partialListener(do_QueryInterface(mPartialSHistory));
|
2016-10-14 10:31:02 +03:00
|
|
|
sessionHistory->AddSHistoryListener(listener);
|
|
|
|
sessionHistory->SetPartialSHistoryListener(partialListener);
|
|
|
|
}
|
2014-02-12 23:07:19 +04:00
|
|
|
}
|
|
|
|
|
2017-01-12 19:38:48 +03:00
|
|
|
OriginAttributes attrs;
|
2016-07-07 21:54:30 +03:00
|
|
|
if (docShell->ItemType() == mDocShell->ItemType()) {
|
|
|
|
attrs = nsDocShell::Cast(docShell)->GetOriginAttributes();
|
2016-02-16 10:04:14 +03:00
|
|
|
}
|
|
|
|
|
2016-08-26 07:41:37 +03:00
|
|
|
// Inherit origin attributes from parent document if
|
|
|
|
// 1. It's in a content docshell.
|
|
|
|
// 2. its nodePrincipal is not a SystemPrincipal.
|
2016-10-15 04:46:26 +03:00
|
|
|
// 3. It's not a mozbrowser frame.
|
2016-08-26 07:41:37 +03:00
|
|
|
//
|
|
|
|
// For example, firstPartyDomain is computed from top-level document, it
|
|
|
|
// doesn't exist in the top-level docshell.
|
|
|
|
if (parentType == nsIDocShellTreeItem::typeContent &&
|
|
|
|
!nsContentUtils::IsSystemPrincipal(doc->NodePrincipal()) &&
|
2016-10-15 04:46:26 +03:00
|
|
|
!OwnerIsMozBrowserFrame()) {
|
2017-01-12 19:38:48 +03:00
|
|
|
OriginAttributes oa = doc->NodePrincipal()->OriginAttributesRef();
|
2016-08-26 07:41:37 +03:00
|
|
|
|
|
|
|
// Assert on the firstPartyDomain from top-level docshell should be empty
|
2016-10-20 10:24:50 +03:00
|
|
|
if (mIsTopLevelContent) {
|
|
|
|
MOZ_ASSERT(attrs.mFirstPartyDomain.IsEmpty(),
|
|
|
|
"top-level docshell shouldn't have firstPartyDomain attribute.");
|
|
|
|
}
|
2016-08-26 07:41:37 +03:00
|
|
|
|
2017-01-12 19:38:48 +03:00
|
|
|
// So far we want to make sure Inherit doesn't override any other origin
|
|
|
|
// attribute than firstPartyDomain.
|
|
|
|
MOZ_ASSERT(attrs.mAppId == oa.mAppId,
|
2016-08-26 07:41:37 +03:00
|
|
|
"docshell and document should have the same appId attribute.");
|
2017-01-12 19:38:48 +03:00
|
|
|
MOZ_ASSERT(attrs.mUserContextId == oa.mUserContextId,
|
2016-08-26 07:41:37 +03:00
|
|
|
"docshell and document should have the same userContextId attribute.");
|
2017-01-12 19:38:48 +03:00
|
|
|
MOZ_ASSERT(attrs.mInIsolatedMozBrowser == oa.mInIsolatedMozBrowser,
|
2016-08-26 07:41:37 +03:00
|
|
|
"docshell and document should have the same inIsolatedMozBrowser attribute.");
|
2017-01-12 19:38:48 +03:00
|
|
|
MOZ_ASSERT(attrs.mPrivateBrowsingId == oa.mPrivateBrowsingId,
|
2016-08-26 07:41:37 +03:00
|
|
|
"docshell and document should have the same privateBrowsingId attribute.");
|
|
|
|
|
2017-01-12 19:38:48 +03:00
|
|
|
attrs.Inherit(oa);
|
2016-08-26 07:41:37 +03:00
|
|
|
}
|
|
|
|
|
2016-02-18 06:31:29 +03:00
|
|
|
if (OwnerIsMozBrowserFrame()) {
|
2016-10-15 04:46:26 +03:00
|
|
|
attrs.mAppId = nsIScriptSecurityManager::NO_APP_ID;
|
2016-02-16 10:04:14 +03:00
|
|
|
attrs.mInIsolatedMozBrowser = OwnerIsIsolatedMozBrowserFrame();
|
|
|
|
mDocShell->SetFrameType(nsIDocShell::FRAME_TYPE_BROWSER);
|
Bug 802366 - The main event: Let a browser process inherit its app's id. r=bz,cjones
The main bug fixed here is that in half of our interfaces, we use "is browser frame/element" to mean "browser or app", and in the other half, we use it to mean "is browser not app".
There's a related, functional bug also fixed here, which is that a browser process doesn't inherit its parent's app-id. This causes problems e.g. for IndexedDB: If a browser inside an app uses IndexedDB, the DB should have the app's app-id.
I also modified Tab{Parent,Child} and nsFrameLoader to call "app" "ownOrContainingApp", to emphasize that we might have inherited the app from a parent process. I left nsIDocShell::appId alone, because changing that would have necessitated changing nsILoadGroup and therefore a /lot/ of users in Necko; it's also not clear it would have clarified anything in those cases.
2012-11-10 22:32:37 +04:00
|
|
|
}
|
2012-06-22 05:17:52 +04:00
|
|
|
|
2016-06-21 21:31:00 +03:00
|
|
|
// Apply sandbox flags even if our owner is not an iframe, as this copies
|
|
|
|
// flags from our owning content's owning document.
|
|
|
|
// Note: ApplySandboxFlags should be called after mDocShell->SetFrameType
|
|
|
|
// because we need to get the correct presentation URL in ApplySandboxFlags.
|
|
|
|
uint32_t sandboxFlags = 0;
|
|
|
|
HTMLIFrameElement* iframe = HTMLIFrameElement::FromContent(mOwnerContent);
|
|
|
|
if (iframe) {
|
|
|
|
sandboxFlags = iframe->GetSandboxFlags();
|
|
|
|
}
|
|
|
|
ApplySandboxFlags(sandboxFlags);
|
|
|
|
|
2016-02-16 10:04:14 +03:00
|
|
|
// Grab the userContextId from owner if XUL
|
2016-05-30 02:48:00 +03:00
|
|
|
nsresult rv = PopulateUserContextIdFromAttribute(attrs);
|
|
|
|
if (NS_WARN_IF(NS_FAILED(rv))) {
|
|
|
|
return rv;
|
2016-02-16 10:04:14 +03:00
|
|
|
}
|
|
|
|
|
2016-06-03 00:02:29 +03:00
|
|
|
bool isPrivate = false;
|
|
|
|
nsCOMPtr<nsILoadContext> parentContext = do_QueryInterface(docShell);
|
|
|
|
NS_ENSURE_STATE(parentContext);
|
|
|
|
|
|
|
|
rv = parentContext->GetUsePrivateBrowsing(&isPrivate);
|
|
|
|
if (NS_WARN_IF(NS_FAILED(rv))) {
|
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
attrs.SyncAttributesWithPrivateBrowsing(isPrivate);
|
|
|
|
|
2016-10-15 04:46:26 +03:00
|
|
|
if (OwnerIsMozBrowserFrame()) {
|
2014-11-24 22:05:35 +03:00
|
|
|
// For inproc frames, set the docshell properties.
|
|
|
|
nsAutoString name;
|
|
|
|
if (mOwnerContent->GetAttr(kNameSpaceID_None, nsGkAtoms::name, name)) {
|
2016-04-12 17:58:21 +03:00
|
|
|
docShell->SetName(name);
|
2014-11-24 22:05:35 +03:00
|
|
|
}
|
|
|
|
mDocShell->SetFullscreenAllowed(
|
|
|
|
mOwnerContent->HasAttr(kNameSpaceID_None, nsGkAtoms::allowfullscreen) ||
|
|
|
|
mOwnerContent->HasAttr(kNameSpaceID_None, nsGkAtoms::mozallowfullscreen));
|
|
|
|
bool isPrivate = mOwnerContent->HasAttr(kNameSpaceID_None, nsGkAtoms::mozprivatebrowsing);
|
|
|
|
if (isPrivate) {
|
2016-08-12 08:19:29 +03:00
|
|
|
if (mDocShell->GetHasLoadedNonBlankURI()) {
|
2014-11-24 22:05:35 +03:00
|
|
|
nsContentUtils::ReportToConsoleNonLocalized(
|
|
|
|
NS_LITERAL_STRING("We should not switch to Private Browsing after loading a document."),
|
|
|
|
nsIScriptError::warningFlag,
|
|
|
|
NS_LITERAL_CSTRING("mozprivatebrowsing"),
|
|
|
|
nullptr);
|
|
|
|
} else {
|
2016-06-06 08:42:00 +03:00
|
|
|
// This handles the case where a frames private browsing is set by chrome flags
|
|
|
|
// and not inherited by its parent.
|
|
|
|
attrs.SyncAttributesWithPrivateBrowsing(isPrivate);
|
2014-11-24 22:05:35 +03:00
|
|
|
}
|
|
|
|
}
|
2012-06-22 05:17:52 +04:00
|
|
|
}
|
|
|
|
|
2016-06-06 08:42:00 +03:00
|
|
|
nsDocShell::Cast(mDocShell)->SetOriginAttributes(attrs);
|
|
|
|
|
2015-07-31 13:08:36 +03:00
|
|
|
ReallyLoadFrameScripts();
|
|
|
|
InitializeBrowserAPI();
|
|
|
|
|
|
|
|
nsCOMPtr<nsIObserverService> os = services::GetObserverService();
|
|
|
|
if (os) {
|
|
|
|
os->NotifyObservers(NS_ISUPPORTS_CAST(nsIFrameLoader*, this),
|
|
|
|
"inprocess-browser-shown", nullptr);
|
|
|
|
}
|
|
|
|
|
2002-04-04 11:31:16 +04:00
|
|
|
return NS_OK;
|
|
|
|
}
|
2002-04-04 06:09:19 +04:00
|
|
|
|
2002-04-17 08:17:16 +04:00
|
|
|
void
|
2005-02-08 02:53:47 +03:00
|
|
|
nsFrameLoader::GetURL(nsString& aURI)
|
2002-04-04 11:31:16 +04:00
|
|
|
{
|
2002-04-17 08:17:16 +04:00
|
|
|
aURI.Truncate();
|
2002-04-05 02:42:19 +04:00
|
|
|
|
2015-03-03 14:09:00 +03:00
|
|
|
if (mOwnerContent->IsHTMLElement(nsGkAtoms::object)) {
|
2006-12-26 20:47:52 +03:00
|
|
|
mOwnerContent->GetAttr(kNameSpaceID_None, nsGkAtoms::data, aURI);
|
2002-04-17 08:17:16 +04:00
|
|
|
} else {
|
2006-12-26 20:47:52 +03:00
|
|
|
mOwnerContent->GetAttr(kNameSpaceID_None, nsGkAtoms::src, aURI);
|
2002-04-17 08:17:16 +04:00
|
|
|
}
|
2002-01-29 09:27:27 +03:00
|
|
|
}
|
|
|
|
|
2005-03-08 03:02:55 +03:00
|
|
|
nsresult
|
|
|
|
nsFrameLoader::CheckForRecursiveLoad(nsIURI* aURI)
|
|
|
|
{
|
2009-10-16 23:42:27 +04:00
|
|
|
nsresult rv;
|
|
|
|
|
2015-07-31 12:28:36 +03:00
|
|
|
MOZ_ASSERT(!IsRemoteFrame(),
|
|
|
|
"Shouldn't call CheckForRecursiveLoad on remote frames.");
|
|
|
|
|
2011-10-17 18:59:28 +04:00
|
|
|
mDepthTooGreat = false;
|
2009-10-16 23:42:27 +04:00
|
|
|
rv = MaybeCreateDocShell();
|
|
|
|
if (NS_FAILED(rv)) {
|
|
|
|
return rv;
|
|
|
|
}
|
2015-07-31 12:28:36 +03:00
|
|
|
NS_ASSERTION(mDocShell,
|
|
|
|
"MaybeCreateDocShell succeeded, but null mDocShell");
|
2009-10-16 23:42:27 +04:00
|
|
|
if (!mDocShell) {
|
|
|
|
return NS_ERROR_FAILURE;
|
|
|
|
}
|
2007-07-17 11:43:36 +04:00
|
|
|
|
2010-09-15 20:10:16 +04:00
|
|
|
// Check that we're still in the docshell tree.
|
|
|
|
nsCOMPtr<nsIDocShellTreeOwner> treeOwner;
|
2013-02-13 02:02:51 +04:00
|
|
|
mDocShell->GetTreeOwner(getter_AddRefs(treeOwner));
|
2016-09-01 08:01:16 +03:00
|
|
|
NS_WARNING_ASSERTION(treeOwner,
|
|
|
|
"Trying to load a new url to a docshell without owner!");
|
2010-09-15 20:10:16 +04:00
|
|
|
NS_ENSURE_STATE(treeOwner);
|
2015-11-24 04:40:02 +03:00
|
|
|
|
2014-01-20 11:58:26 +04:00
|
|
|
if (mDocShell->ItemType() != nsIDocShellTreeItem::typeContent) {
|
2005-03-08 03:02:55 +03:00
|
|
|
// No need to do recursion-protection here XXXbz why not?? Do we really
|
|
|
|
// trust people not to screw up with non-content docshells?
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Bug 8065: Don't exceed some maximum depth in content frames
|
|
|
|
// (MAX_DEPTH_CONTENT_FRAMES)
|
|
|
|
nsCOMPtr<nsIDocShellTreeItem> parentAsItem;
|
2013-02-13 02:02:51 +04:00
|
|
|
mDocShell->GetSameTypeParent(getter_AddRefs(parentAsItem));
|
2012-08-22 19:56:38 +04:00
|
|
|
int32_t depth = 0;
|
2005-03-08 03:02:55 +03:00
|
|
|
while (parentAsItem) {
|
|
|
|
++depth;
|
2015-11-24 04:40:02 +03:00
|
|
|
|
2005-03-08 03:02:55 +03:00
|
|
|
if (depth >= MAX_DEPTH_CONTENT_FRAMES) {
|
2011-10-17 18:59:28 +04:00
|
|
|
mDepthTooGreat = true;
|
2005-03-08 03:02:55 +03:00
|
|
|
NS_WARNING("Too many nested content frames so giving up");
|
|
|
|
|
|
|
|
return NS_ERROR_UNEXPECTED; // Too deep, give up! (silently?)
|
|
|
|
}
|
|
|
|
|
|
|
|
nsCOMPtr<nsIDocShellTreeItem> temp;
|
|
|
|
temp.swap(parentAsItem);
|
|
|
|
temp->GetSameTypeParent(getter_AddRefs(parentAsItem));
|
|
|
|
}
|
2014-02-09 06:05:48 +04:00
|
|
|
|
|
|
|
// Bug 136580: Check for recursive frame loading excluding about:srcdoc URIs.
|
|
|
|
// srcdoc URIs require their contents to be specified inline, so it isn't
|
|
|
|
// possible for undesirable recursion to occur without the aid of a
|
|
|
|
// non-srcdoc URI, which this method will block normally.
|
|
|
|
// Besides, URI is not enough to guarantee uniqueness of srcdoc documents.
|
|
|
|
nsAutoCString buffer;
|
|
|
|
rv = aURI->GetScheme(buffer);
|
|
|
|
if (NS_SUCCEEDED(rv) && buffer.EqualsLiteral("about")) {
|
|
|
|
rv = aURI->GetPath(buffer);
|
|
|
|
if (NS_SUCCEEDED(rv) && buffer.EqualsLiteral("srcdoc")) {
|
|
|
|
// Duplicates allowed up to depth limits
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
}
|
2012-08-22 19:56:38 +04:00
|
|
|
int32_t matchCount = 0;
|
2013-02-13 02:02:51 +04:00
|
|
|
mDocShell->GetSameTypeParent(getter_AddRefs(parentAsItem));
|
2005-03-08 03:02:55 +03:00
|
|
|
while (parentAsItem) {
|
|
|
|
// Check the parent URI with the URI we're loading
|
|
|
|
nsCOMPtr<nsIWebNavigation> parentAsNav(do_QueryInterface(parentAsItem));
|
|
|
|
if (parentAsNav) {
|
|
|
|
// Does the URI match the one we're about to load?
|
|
|
|
nsCOMPtr<nsIURI> parentURI;
|
|
|
|
parentAsNav->GetCurrentURI(getter_AddRefs(parentURI));
|
|
|
|
if (parentURI) {
|
2011-05-22 05:12:46 +04:00
|
|
|
// Bug 98158/193011: We need to ignore data after the #
|
2011-09-29 10:19:26 +04:00
|
|
|
bool equal;
|
2011-05-22 05:12:46 +04:00
|
|
|
rv = aURI->EqualsExceptRef(parentURI, &equal);
|
2005-03-10 00:59:18 +03:00
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
2015-11-24 04:40:02 +03:00
|
|
|
|
2005-03-10 00:59:18 +03:00
|
|
|
if (equal) {
|
2005-03-08 03:02:55 +03:00
|
|
|
matchCount++;
|
|
|
|
if (matchCount >= MAX_SAME_URL_CONTENT_FRAMES) {
|
|
|
|
NS_WARNING("Too many nested content frames have the same url (recursion?) so giving up");
|
|
|
|
return NS_ERROR_UNEXPECTED;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
nsCOMPtr<nsIDocShellTreeItem> temp;
|
|
|
|
temp.swap(parentAsItem);
|
|
|
|
temp->GetSameTypeParent(getter_AddRefs(parentAsItem));
|
|
|
|
}
|
|
|
|
|
|
|
|
return NS_OK;
|
|
|
|
}
|
2009-07-01 00:39:22 +04:00
|
|
|
|
2011-07-16 01:46:56 +04:00
|
|
|
nsresult
|
2014-08-08 21:23:50 +04:00
|
|
|
nsFrameLoader::GetWindowDimensions(nsIntRect& aRect)
|
2011-07-16 01:46:56 +04:00
|
|
|
{
|
|
|
|
// Need to get outer window position here
|
2014-08-23 00:11:27 +04:00
|
|
|
nsIDocument* doc = mOwnerContent->GetComposedDoc();
|
2011-07-16 01:46:56 +04:00
|
|
|
if (!doc) {
|
|
|
|
return NS_ERROR_FAILURE;
|
|
|
|
}
|
|
|
|
|
2016-05-12 19:22:25 +03:00
|
|
|
MOZ_RELEASE_ASSERT(!doc->IsResourceDoc(), "We shouldn't even exist");
|
2011-07-16 01:46:56 +04:00
|
|
|
|
2016-01-30 20:05:36 +03:00
|
|
|
nsCOMPtr<nsPIDOMWindowOuter> win = doc->GetWindow();
|
2014-01-10 06:03:47 +04:00
|
|
|
if (!win) {
|
2011-07-16 01:46:56 +04:00
|
|
|
return NS_ERROR_FAILURE;
|
|
|
|
}
|
|
|
|
|
2014-01-10 06:03:47 +04:00
|
|
|
nsCOMPtr<nsIDocShellTreeItem> parentAsItem(win->GetDocShell());
|
|
|
|
if (!parentAsItem) {
|
|
|
|
return NS_ERROR_FAILURE;
|
|
|
|
}
|
2011-07-16 01:46:56 +04:00
|
|
|
|
|
|
|
nsCOMPtr<nsIDocShellTreeOwner> parentOwner;
|
|
|
|
if (NS_FAILED(parentAsItem->GetTreeOwner(getter_AddRefs(parentOwner))) ||
|
|
|
|
!parentOwner) {
|
|
|
|
return NS_ERROR_FAILURE;
|
|
|
|
}
|
|
|
|
|
|
|
|
nsCOMPtr<nsIBaseWindow> treeOwnerAsWin(do_GetInterface(parentOwner));
|
|
|
|
treeOwnerAsWin->GetPosition(&aRect.x, &aRect.y);
|
|
|
|
treeOwnerAsWin->GetSize(&aRect.width, &aRect.height);
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2009-10-05 15:52:19 +04:00
|
|
|
NS_IMETHODIMP
|
2013-01-10 11:23:55 +04:00
|
|
|
nsFrameLoader::UpdatePositionAndSize(nsSubDocumentFrame *aIFrame)
|
2009-10-05 15:52:19 +04:00
|
|
|
{
|
2015-07-31 12:28:36 +03:00
|
|
|
if (IsRemoteFrame()) {
|
2010-07-19 22:33:33 +04:00
|
|
|
if (mRemoteBrowser) {
|
2015-03-05 12:13:05 +03:00
|
|
|
ScreenIntSize size = aIFrame->GetSubdocumentSize();
|
2014-08-08 21:23:50 +04:00
|
|
|
nsIntRect dimensions;
|
2011-07-16 01:46:56 +04:00
|
|
|
NS_ENSURE_SUCCESS(GetWindowDimensions(dimensions), NS_ERROR_FAILURE);
|
2016-04-08 03:04:57 +03:00
|
|
|
mLazySize = size;
|
2015-03-31 23:39:02 +03:00
|
|
|
mRemoteBrowser->UpdateDimensions(dimensions, size);
|
2009-10-16 23:42:29 +04:00
|
|
|
}
|
2009-10-05 15:52:19 +04:00
|
|
|
return NS_OK;
|
|
|
|
}
|
2015-01-14 22:04:00 +03:00
|
|
|
UpdateBaseWindowPositionAndSize(aIFrame);
|
|
|
|
return NS_OK;
|
2009-10-05 15:52:19 +04:00
|
|
|
}
|
|
|
|
|
2015-01-14 22:04:00 +03:00
|
|
|
void
|
2013-01-10 11:23:55 +04:00
|
|
|
nsFrameLoader::UpdateBaseWindowPositionAndSize(nsSubDocumentFrame *aIFrame)
|
2009-10-05 15:52:19 +04:00
|
|
|
{
|
|
|
|
nsCOMPtr<nsIDocShell> docShell;
|
|
|
|
GetDocShell(getter_AddRefs(docShell));
|
|
|
|
nsCOMPtr<nsIBaseWindow> baseWindow(do_QueryInterface(docShell));
|
|
|
|
|
|
|
|
// resize the sub document
|
|
|
|
if (baseWindow) {
|
2012-08-22 19:56:38 +04:00
|
|
|
int32_t x = 0;
|
|
|
|
int32_t y = 0;
|
2009-10-05 15:52:19 +04:00
|
|
|
|
|
|
|
nsWeakFrame weakFrame(aIFrame);
|
|
|
|
|
2015-01-14 22:03:59 +03:00
|
|
|
baseWindow->GetPosition(&x, &y);
|
2009-10-05 15:52:19 +04:00
|
|
|
|
|
|
|
if (!weakFrame.IsAlive()) {
|
2015-01-14 22:03:59 +03:00
|
|
|
// GetPosition() killed us
|
2015-01-14 22:04:00 +03:00
|
|
|
return;
|
2009-10-05 15:52:19 +04:00
|
|
|
}
|
|
|
|
|
2015-03-05 12:13:05 +03:00
|
|
|
ScreenIntSize size = aIFrame->GetSubdocumentSize();
|
2016-04-08 03:04:57 +03:00
|
|
|
mLazySize = size;
|
2009-10-05 15:52:19 +04:00
|
|
|
|
2016-05-12 03:07:45 +03:00
|
|
|
baseWindow->SetPositionAndSize(x, y, size.width, size.height,
|
|
|
|
nsIBaseWindow::eDelayResize);
|
2009-10-05 15:52:19 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-04-08 03:04:57 +03:00
|
|
|
NS_IMETHODIMP
|
|
|
|
nsFrameLoader::GetLazyWidth(uint32_t* aLazyWidth)
|
|
|
|
{
|
|
|
|
*aLazyWidth = mLazySize.width;
|
|
|
|
|
|
|
|
nsIFrame* frame = GetPrimaryFrameOfOwningContent();
|
|
|
|
if (frame) {
|
|
|
|
*aLazyWidth = frame->PresContext()->DevPixelsToIntCSSPixels(*aLazyWidth);
|
|
|
|
}
|
|
|
|
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
nsFrameLoader::GetLazyHeight(uint32_t* aLazyHeight)
|
|
|
|
{
|
|
|
|
*aLazyHeight = mLazySize.height;
|
|
|
|
|
|
|
|
nsIFrame* frame = GetPrimaryFrameOfOwningContent();
|
|
|
|
if (frame) {
|
|
|
|
*aLazyHeight = frame->PresContext()->DevPixelsToIntCSSPixels(*aLazyHeight);
|
|
|
|
}
|
|
|
|
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2011-06-22 04:32:43 +04:00
|
|
|
NS_IMETHODIMP
|
2012-08-22 19:56:38 +04:00
|
|
|
nsFrameLoader::GetEventMode(uint32_t* aEventMode)
|
2011-06-22 04:32:43 +04:00
|
|
|
{
|
|
|
|
*aEventMode = mEventMode;
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
2012-08-22 19:56:38 +04:00
|
|
|
nsFrameLoader::SetEventMode(uint32_t aEventMode)
|
2011-06-22 04:32:43 +04:00
|
|
|
{
|
|
|
|
mEventMode = aEventMode;
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2011-12-05 16:38:46 +04:00
|
|
|
NS_IMETHODIMP
|
|
|
|
nsFrameLoader::GetClipSubdocument(bool* aResult)
|
|
|
|
{
|
|
|
|
*aResult = mClipSubdocument;
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
nsFrameLoader::SetClipSubdocument(bool aClip)
|
|
|
|
{
|
|
|
|
mClipSubdocument = aClip;
|
|
|
|
nsIFrame* frame = GetPrimaryFrameOfOwningContent();
|
|
|
|
if (frame) {
|
2012-08-29 09:39:31 +04:00
|
|
|
frame->InvalidateFrame();
|
2011-12-05 16:38:46 +04:00
|
|
|
frame->PresContext()->PresShell()->
|
|
|
|
FrameNeedsReflow(frame, nsIPresShell::eResize, NS_FRAME_IS_DIRTY);
|
|
|
|
nsSubDocumentFrame* subdocFrame = do_QueryFrame(frame);
|
|
|
|
if (subdocFrame) {
|
|
|
|
nsIFrame* subdocRootFrame = subdocFrame->GetSubdocumentRootFrame();
|
|
|
|
if (subdocRootFrame) {
|
|
|
|
nsIFrame* subdocRootScrollFrame = subdocRootFrame->PresContext()->PresShell()->
|
|
|
|
GetRootScrollFrame();
|
|
|
|
if (subdocRootScrollFrame) {
|
|
|
|
frame->PresContext()->PresShell()->
|
|
|
|
FrameNeedsReflow(frame, nsIPresShell::eResize, NS_FRAME_IS_DIRTY);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2012-02-18 03:41:13 +04:00
|
|
|
NS_IMETHODIMP
|
|
|
|
nsFrameLoader::GetClampScrollPosition(bool* aResult)
|
|
|
|
{
|
|
|
|
*aResult = mClampScrollPosition;
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
nsFrameLoader::SetClampScrollPosition(bool aClamp)
|
|
|
|
{
|
|
|
|
mClampScrollPosition = aClamp;
|
|
|
|
|
|
|
|
// When turning clamping on, make sure the current position is clamped.
|
|
|
|
if (aClamp) {
|
|
|
|
nsIFrame* frame = GetPrimaryFrameOfOwningContent();
|
2014-03-25 19:36:49 +04:00
|
|
|
nsSubDocumentFrame* subdocFrame = do_QueryFrame(frame);
|
|
|
|
if (subdocFrame) {
|
|
|
|
nsIFrame* subdocRootFrame = subdocFrame->GetSubdocumentRootFrame();
|
|
|
|
if (subdocRootFrame) {
|
|
|
|
nsIScrollableFrame* subdocRootScrollFrame = subdocRootFrame->PresContext()->PresShell()->
|
|
|
|
GetRootScrollFrameAsScrollable();
|
|
|
|
if (subdocRootScrollFrame) {
|
|
|
|
subdocRootScrollFrame->ScrollTo(subdocRootScrollFrame->GetScrollPosition(), nsIScrollableFrame::INSTANT);
|
2012-02-18 03:41:13 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2016-08-16 04:04:04 +03:00
|
|
|
static
|
|
|
|
ContentParent*
|
|
|
|
GetContentParent(Element* aBrowser)
|
|
|
|
{
|
|
|
|
nsCOMPtr<nsIBrowser> browser = do_QueryInterface(aBrowser);
|
|
|
|
if (!browser) {
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
2017-02-14 23:12:35 +03:00
|
|
|
nsCOMPtr<nsIFrameLoader> otherLoader;
|
|
|
|
browser->GetSameProcessAsFrameLoader(getter_AddRefs(otherLoader));
|
|
|
|
if (!otherLoader) {
|
2016-08-16 04:04:04 +03:00
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
TabParent* tabParent = TabParent::GetFrom(otherLoader);
|
|
|
|
if (tabParent &&
|
|
|
|
tabParent->Manager() &&
|
|
|
|
tabParent->Manager()->IsContentParent()) {
|
|
|
|
return tabParent->Manager()->AsContentParent();
|
|
|
|
}
|
|
|
|
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
2009-10-28 23:41:46 +03:00
|
|
|
bool
|
2010-08-21 03:24:40 +04:00
|
|
|
nsFrameLoader::TryRemoteBrowser()
|
2009-07-01 00:39:22 +04:00
|
|
|
{
|
2010-08-21 03:24:40 +04:00
|
|
|
NS_ASSERTION(!mRemoteBrowser, "TryRemoteBrowser called with a remote browser already?");
|
2009-07-02 20:54:22 +04:00
|
|
|
|
2014-08-23 00:11:27 +04:00
|
|
|
//XXXsmaug Per spec (2014/08/21) frameloader should not work in case the
|
|
|
|
// element isn't in document, only in shadow dom, but that will change
|
|
|
|
// https://www.w3.org/Bugs/Public/show_bug.cgi?id=26365#c0
|
|
|
|
nsIDocument* doc = mOwnerContent->GetComposedDoc();
|
2009-07-01 00:39:22 +04:00
|
|
|
if (!doc) {
|
2009-10-28 23:41:46 +03:00
|
|
|
return false;
|
2009-07-01 00:39:22 +04:00
|
|
|
}
|
|
|
|
|
2016-05-12 19:22:25 +03:00
|
|
|
MOZ_RELEASE_ASSERT(!doc->IsResourceDoc(), "We shouldn't even exist");
|
|
|
|
|
|
|
|
if (!doc->IsActive()) {
|
|
|
|
// Don't allow subframe loads in non-active documents.
|
|
|
|
// (See bug 610571 comment 5.)
|
2009-10-28 23:41:46 +03:00
|
|
|
return false;
|
2009-07-01 00:39:22 +04:00
|
|
|
}
|
|
|
|
|
2016-01-30 20:05:36 +03:00
|
|
|
nsCOMPtr<nsPIDOMWindowOuter> parentWin = doc->GetWindow();
|
2014-01-10 06:03:47 +04:00
|
|
|
if (!parentWin) {
|
2009-10-28 23:41:46 +03:00
|
|
|
return false;
|
2009-07-01 00:39:22 +04:00
|
|
|
}
|
|
|
|
|
2014-06-20 21:55:40 +04:00
|
|
|
nsCOMPtr<nsIDocShell> parentDocShell = parentWin->GetDocShell();
|
|
|
|
if (!parentDocShell) {
|
2014-01-10 06:03:47 +04:00
|
|
|
return false;
|
|
|
|
}
|
2009-07-01 00:39:22 +04:00
|
|
|
|
2015-02-06 00:47:32 +03:00
|
|
|
TabParent* openingTab = TabParent::GetFrom(parentDocShell->GetOpener());
|
2014-06-20 21:55:40 +04:00
|
|
|
ContentParent* openerContentParent = nullptr;
|
|
|
|
|
|
|
|
if (openingTab &&
|
|
|
|
openingTab->Manager() &&
|
|
|
|
openingTab->Manager()->IsContentParent()) {
|
|
|
|
openerContentParent = openingTab->Manager()->AsContentParent();
|
|
|
|
}
|
|
|
|
|
2012-04-25 20:35:58 +04:00
|
|
|
// <iframe mozbrowser> gets to skip these checks.
|
2016-10-15 04:46:26 +03:00
|
|
|
if (!OwnerIsMozBrowserFrame()) {
|
2014-06-20 21:55:40 +04:00
|
|
|
if (parentDocShell->ItemType() != nsIDocShellTreeItem::typeChrome) {
|
2016-11-16 02:01:50 +03:00
|
|
|
// Allow about:addon an exception to this rule so it can load remote
|
|
|
|
// extension options pages.
|
|
|
|
//
|
|
|
|
// Note that the new frame's message manager will not be a child of the
|
|
|
|
// chrome window message manager, and, the values of window.top and
|
|
|
|
// window.parent will be different than they would be for a non-remote
|
|
|
|
// frame.
|
|
|
|
nsCOMPtr<nsIWebNavigation> parentWebNav;
|
|
|
|
nsCOMPtr<nsIURI> aboutAddons;
|
|
|
|
nsCOMPtr<nsIURI> parentURI;
|
|
|
|
bool equals;
|
|
|
|
if (!((parentWebNav = do_GetInterface(parentDocShell)) &&
|
|
|
|
NS_SUCCEEDED(NS_NewURI(getter_AddRefs(aboutAddons), "about:addons")) &&
|
|
|
|
NS_SUCCEEDED(parentWebNav->GetCurrentURI(getter_AddRefs(parentURI))) &&
|
|
|
|
NS_SUCCEEDED(parentURI->EqualsExceptRef(aboutAddons, &equals)) && equals)) {
|
|
|
|
return false;
|
|
|
|
}
|
2012-04-25 20:35:58 +04:00
|
|
|
}
|
2009-07-01 00:39:22 +04:00
|
|
|
|
2015-03-03 14:08:59 +03:00
|
|
|
if (!mOwnerContent->IsXULElement()) {
|
2012-04-25 20:35:58 +04:00
|
|
|
return false;
|
|
|
|
}
|
2009-07-01 00:39:22 +04:00
|
|
|
|
2017-01-04 20:33:19 +03:00
|
|
|
nsAutoString value;
|
|
|
|
mOwnerContent->GetAttr(kNameSpaceID_None, nsGkAtoms::type, value);
|
|
|
|
|
|
|
|
if (!value.LowerCaseEqualsLiteral("content") &&
|
|
|
|
!StringBeginsWith(value, NS_LITERAL_STRING("content-"),
|
|
|
|
nsCaseInsensitiveStringComparator())) {
|
2012-04-25 20:35:58 +04:00
|
|
|
return false;
|
|
|
|
}
|
2016-08-16 04:04:04 +03:00
|
|
|
|
|
|
|
// Try to get the related content parent from our browser element.
|
|
|
|
openerContentParent = GetContentParent(mOwnerContent);
|
2009-07-01 00:39:22 +04:00
|
|
|
}
|
|
|
|
|
2012-08-22 19:56:38 +04:00
|
|
|
uint32_t chromeFlags = 0;
|
2010-07-19 22:33:33 +04:00
|
|
|
nsCOMPtr<nsIDocShellTreeOwner> parentOwner;
|
2014-06-20 21:55:40 +04:00
|
|
|
if (NS_FAILED(parentDocShell->GetTreeOwner(getter_AddRefs(parentOwner))) ||
|
2010-07-19 22:33:33 +04:00
|
|
|
!parentOwner) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
nsCOMPtr<nsIXULWindow> window(do_GetInterface(parentOwner));
|
2014-06-11 09:44:13 +04:00
|
|
|
if (window && NS_FAILED(window->GetChromeFlags(&chromeFlags))) {
|
2010-07-19 22:33:33 +04:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2014-05-24 01:12:29 +04:00
|
|
|
PROFILER_LABEL("nsFrameLoader", "CreateRemoteBrowser",
|
|
|
|
js::ProfileEntry::Category::OTHER);
|
2013-01-31 10:40:43 +04:00
|
|
|
|
Bug 802366 - The main event: Let a browser process inherit its app's id. r=bz,cjones
The main bug fixed here is that in half of our interfaces, we use "is browser frame/element" to mean "browser or app", and in the other half, we use it to mean "is browser not app".
There's a related, functional bug also fixed here, which is that a browser process doesn't inherit its parent's app-id. This causes problems e.g. for IndexedDB: If a browser inside an app uses IndexedDB, the DB should have the app's app-id.
I also modified Tab{Parent,Child} and nsFrameLoader to call "app" "ownOrContainingApp", to emphasize that we might have inherited the app from a parent process. I left nsIDocShell::appId alone, because changing that would have necessitated changing nsILoadGroup and therefore a /lot/ of users in Necko; it's also not clear it would have clarified anything in those cases.
2012-11-10 22:32:37 +04:00
|
|
|
MutableTabContext context;
|
2015-10-08 09:44:36 +03:00
|
|
|
nsresult rv = GetNewTabContext(&context);
|
|
|
|
NS_ENSURE_SUCCESS(rv, false);
|
2012-07-22 04:16:11 +04:00
|
|
|
|
2013-07-24 03:39:17 +04:00
|
|
|
nsCOMPtr<Element> ownerElement = mOwnerContent;
|
2017-02-10 00:30:59 +03:00
|
|
|
mRemoteBrowser = ContentParent::CreateBrowser(context, ownerElement, openerContentParent);
|
2015-04-07 05:56:10 +03:00
|
|
|
if (!mRemoteBrowser) {
|
|
|
|
return false;
|
|
|
|
}
|
2017-01-17 23:52:45 +03:00
|
|
|
// Now that mRemoteBrowser is set, we can initialize the RenderFrameParent
|
|
|
|
mRemoteBrowser->InitRenderFrame();
|
2012-08-09 06:58:06 +04:00
|
|
|
|
2015-10-01 20:06:51 +03:00
|
|
|
MaybeUpdatePrimaryTabParent(eTabParentChanged);
|
|
|
|
|
2015-04-07 05:56:10 +03:00
|
|
|
mChildID = mRemoteBrowser->Manager()->ChildID();
|
2013-08-13 11:56:57 +04:00
|
|
|
|
2015-04-07 05:56:10 +03:00
|
|
|
nsCOMPtr<nsIDocShellTreeItem> rootItem;
|
|
|
|
parentDocShell->GetRootTreeItem(getter_AddRefs(rootItem));
|
2016-01-30 20:05:36 +03:00
|
|
|
nsCOMPtr<nsPIDOMWindowOuter> rootWin = rootItem->GetWindow();
|
2015-04-07 05:56:10 +03:00
|
|
|
nsCOMPtr<nsIDOMChromeWindow> rootChromeWin = do_QueryInterface(rootWin);
|
|
|
|
|
|
|
|
if (rootChromeWin) {
|
|
|
|
nsCOMPtr<nsIBrowserDOMWindow> browserDOMWin;
|
|
|
|
rootChromeWin->GetBrowserDOMWindow(getter_AddRefs(browserDOMWin));
|
|
|
|
mRemoteBrowser->SetBrowserDOMWindow(browserDOMWin);
|
2009-11-05 21:14:22 +03:00
|
|
|
}
|
2015-04-07 05:56:10 +03:00
|
|
|
|
2015-07-31 13:08:36 +03:00
|
|
|
ReallyLoadFrameScripts();
|
|
|
|
InitializeBrowserAPI();
|
|
|
|
|
|
|
|
return true;
|
2009-07-01 00:39:22 +04:00
|
|
|
}
|
2009-10-29 20:58:31 +03:00
|
|
|
|
2010-07-19 22:33:33 +04:00
|
|
|
mozilla::dom::PBrowserParent*
|
2015-06-09 13:20:41 +03:00
|
|
|
nsFrameLoader::GetRemoteBrowser() const
|
2009-10-29 20:58:31 +03:00
|
|
|
{
|
2010-07-19 22:33:33 +04:00
|
|
|
return mRemoteBrowser;
|
2009-10-29 20:58:31 +03:00
|
|
|
}
|
2009-11-05 21:14:22 +03:00
|
|
|
|
2015-06-09 13:20:41 +03:00
|
|
|
RenderFrameParent*
|
2015-06-09 13:30:08 +03:00
|
|
|
nsFrameLoader::GetCurrentRenderFrame() const
|
2015-06-09 13:20:41 +03:00
|
|
|
{
|
|
|
|
if (mRemoteBrowser) {
|
|
|
|
return mRemoteBrowser->GetRenderFrame();
|
|
|
|
}
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
2009-11-05 21:14:22 +03:00
|
|
|
NS_IMETHODIMP
|
|
|
|
nsFrameLoader::ActivateRemoteFrame() {
|
2010-07-19 22:33:33 +04:00
|
|
|
if (mRemoteBrowser) {
|
|
|
|
mRemoteBrowser->Activate();
|
2009-11-05 21:14:22 +03:00
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
return NS_ERROR_UNEXPECTED;
|
|
|
|
}
|
2009-11-05 21:21:09 +03:00
|
|
|
|
2011-06-18 04:08:32 +04:00
|
|
|
NS_IMETHODIMP
|
|
|
|
nsFrameLoader::DeactivateRemoteFrame() {
|
|
|
|
if (mRemoteBrowser) {
|
|
|
|
mRemoteBrowser->Deactivate();
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
return NS_ERROR_UNEXPECTED;
|
|
|
|
}
|
|
|
|
|
2009-11-05 21:21:09 +03:00
|
|
|
NS_IMETHODIMP
|
|
|
|
nsFrameLoader::SendCrossProcessMouseEvent(const nsAString& aType,
|
|
|
|
float aX,
|
|
|
|
float aY,
|
2012-08-22 19:56:38 +04:00
|
|
|
int32_t aButton,
|
|
|
|
int32_t aClickCount,
|
|
|
|
int32_t aModifiers,
|
2011-09-29 10:19:26 +04:00
|
|
|
bool aIgnoreRootScrollFrame)
|
2009-11-05 21:21:09 +03:00
|
|
|
{
|
2010-07-19 22:33:33 +04:00
|
|
|
if (mRemoteBrowser) {
|
|
|
|
mRemoteBrowser->SendMouseEvent(aType, aX, aY, aButton,
|
2011-01-20 06:21:50 +03:00
|
|
|
aClickCount, aModifiers,
|
|
|
|
aIgnoreRootScrollFrame);
|
|
|
|
return NS_OK;
|
2009-11-05 21:21:09 +03:00
|
|
|
}
|
|
|
|
return NS_ERROR_FAILURE;
|
|
|
|
}
|
|
|
|
|
2009-11-17 17:22:23 +03:00
|
|
|
NS_IMETHODIMP
|
|
|
|
nsFrameLoader::ActivateFrameEvent(const nsAString& aType,
|
2011-09-29 10:19:26 +04:00
|
|
|
bool aCapture)
|
2009-11-17 17:22:23 +03:00
|
|
|
{
|
2010-07-19 22:33:33 +04:00
|
|
|
if (mRemoteBrowser) {
|
|
|
|
return mRemoteBrowser->SendActivateFrameEvent(nsString(aType), aCapture) ?
|
|
|
|
NS_OK : NS_ERROR_NOT_AVAILABLE;
|
2009-11-17 17:22:23 +03:00
|
|
|
}
|
|
|
|
return NS_ERROR_FAILURE;
|
2010-03-19 09:52:18 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
nsFrameLoader::SendCrossProcessKeyEvent(const nsAString& aType,
|
2012-08-22 19:56:38 +04:00
|
|
|
int32_t aKeyCode,
|
|
|
|
int32_t aCharCode,
|
|
|
|
int32_t aModifiers,
|
2011-09-29 10:19:26 +04:00
|
|
|
bool aPreventDefault)
|
2010-03-19 09:52:18 +03:00
|
|
|
{
|
2010-07-19 22:33:33 +04:00
|
|
|
if (mRemoteBrowser) {
|
|
|
|
mRemoteBrowser->SendKeyEvent(aType, aKeyCode, aCharCode, aModifiers,
|
2011-01-20 06:21:50 +03:00
|
|
|
aPreventDefault);
|
|
|
|
return NS_OK;
|
2010-03-19 09:52:18 +03:00
|
|
|
}
|
|
|
|
return NS_ERROR_FAILURE;
|
2009-11-17 17:22:23 +03:00
|
|
|
}
|
|
|
|
|
2009-12-11 07:02:13 +03:00
|
|
|
nsresult
|
|
|
|
nsFrameLoader::CreateStaticClone(nsIFrameLoader* aDest)
|
|
|
|
{
|
|
|
|
nsFrameLoader* dest = static_cast<nsFrameLoader*>(aDest);
|
2009-12-12 21:38:25 +03:00
|
|
|
dest->MaybeCreateDocShell();
|
2009-12-11 07:02:13 +03:00
|
|
|
NS_ENSURE_STATE(dest->mDocShell);
|
|
|
|
|
2016-08-24 21:12:09 +03:00
|
|
|
nsCOMPtr<nsIDocument> kungFuDeathGrip = dest->mDocShell->GetDocument();
|
|
|
|
Unused << kungFuDeathGrip;
|
|
|
|
|
2009-12-11 07:02:13 +03:00
|
|
|
nsCOMPtr<nsIContentViewer> viewer;
|
|
|
|
dest->mDocShell->GetContentViewer(getter_AddRefs(viewer));
|
|
|
|
NS_ENSURE_STATE(viewer);
|
|
|
|
|
|
|
|
nsCOMPtr<nsIDocShell> origDocShell;
|
|
|
|
GetDocShell(getter_AddRefs(origDocShell));
|
2014-01-10 06:03:47 +04:00
|
|
|
NS_ENSURE_STATE(origDocShell);
|
|
|
|
|
|
|
|
nsCOMPtr<nsIDocument> doc = origDocShell->GetDocument();
|
2009-12-11 07:02:13 +03:00
|
|
|
NS_ENSURE_STATE(doc);
|
2014-01-10 06:03:47 +04:00
|
|
|
|
2009-12-11 07:02:13 +03:00
|
|
|
nsCOMPtr<nsIDocument> clonedDoc = doc->CreateStaticClone(dest->mDocShell);
|
|
|
|
nsCOMPtr<nsIDOMDocument> clonedDOMDoc = do_QueryInterface(clonedDoc);
|
|
|
|
|
|
|
|
viewer->SetDOMDocument(clonedDOMDoc);
|
|
|
|
return NS_OK;
|
|
|
|
}
|
2010-02-20 20:05:20 +03:00
|
|
|
|
2012-09-28 09:43:12 +04:00
|
|
|
bool
|
2015-02-20 04:11:32 +03:00
|
|
|
nsFrameLoader::DoLoadMessageManagerScript(const nsAString& aURL, bool aRunInGlobalScope)
|
2010-02-20 20:05:20 +03:00
|
|
|
{
|
2015-02-06 00:47:32 +03:00
|
|
|
auto* tabParent = TabParent::GetFrom(GetRemoteBrowser());
|
2010-02-20 20:05:20 +03:00
|
|
|
if (tabParent) {
|
2013-11-24 09:32:45 +04:00
|
|
|
return tabParent->SendLoadRemoteScript(nsString(aURL), aRunInGlobalScope);
|
2010-02-20 20:05:20 +03:00
|
|
|
}
|
2015-10-18 08:24:48 +03:00
|
|
|
RefPtr<nsInProcessTabChildGlobal> tabChild =
|
2012-09-28 09:43:12 +04:00
|
|
|
static_cast<nsInProcessTabChildGlobal*>(GetTabChildGlobalAsEventTarget());
|
2010-05-18 16:28:37 +04:00
|
|
|
if (tabChild) {
|
2013-11-24 09:32:45 +04:00
|
|
|
tabChild->LoadFrameScript(aURL, aRunInGlobalScope);
|
2010-05-18 16:28:37 +04:00
|
|
|
}
|
|
|
|
return true;
|
2010-02-20 20:05:20 +03:00
|
|
|
}
|
|
|
|
|
2014-03-12 18:22:00 +04:00
|
|
|
class nsAsyncMessageToChild : public nsSameProcessAsyncMessageBase,
|
2016-04-26 03:23:21 +03:00
|
|
|
public Runnable
|
2010-05-18 16:28:37 +04:00
|
|
|
{
|
|
|
|
public:
|
2016-08-12 12:39:16 +03:00
|
|
|
nsAsyncMessageToChild(JS::RootingContext* aRootingCx,
|
|
|
|
JS::Handle<JSObject*> aCpows,
|
|
|
|
nsFrameLoader* aFrameLoader)
|
|
|
|
: nsSameProcessAsyncMessageBase(aRootingCx, aCpows)
|
2014-03-12 18:22:00 +04:00
|
|
|
, mFrameLoader(aFrameLoader)
|
2012-08-02 10:02:29 +04:00
|
|
|
{
|
2013-07-11 02:05:39 +04:00
|
|
|
}
|
|
|
|
|
2016-08-08 05:18:10 +03:00
|
|
|
NS_IMETHOD Run() override
|
2010-05-18 16:28:37 +04:00
|
|
|
{
|
|
|
|
nsInProcessTabChildGlobal* tabChild =
|
|
|
|
static_cast<nsInProcessTabChildGlobal*>(mFrameLoader->mChildMessageManager.get());
|
2016-02-29 14:25:48 +03:00
|
|
|
// Since bug 1126089, messages can arrive even when the docShell is destroyed.
|
|
|
|
// Here we make sure that those messages are not delivered.
|
|
|
|
if (tabChild && tabChild->GetInnerManager() && mFrameLoader->GetExistingDocShell()) {
|
2013-06-30 19:00:18 +04:00
|
|
|
nsCOMPtr<nsIXPConnectJSObjectHolder> kungFuDeathGrip(tabChild->GetGlobal());
|
2015-04-16 18:17:54 +03:00
|
|
|
ReceiveMessage(static_cast<EventTarget*>(tabChild), mFrameLoader,
|
2014-03-12 18:22:00 +04:00
|
|
|
tabChild->GetInnerManager());
|
2010-05-18 16:28:37 +04:00
|
|
|
}
|
|
|
|
return NS_OK;
|
|
|
|
}
|
2015-10-18 08:24:48 +03:00
|
|
|
RefPtr<nsFrameLoader> mFrameLoader;
|
2010-05-18 16:28:37 +04:00
|
|
|
};
|
|
|
|
|
2015-10-07 13:42:43 +03:00
|
|
|
nsresult
|
2013-07-11 02:05:39 +04:00
|
|
|
nsFrameLoader::DoSendAsyncMessage(JSContext* aCx,
|
|
|
|
const nsAString& aMessage,
|
2015-09-10 23:50:58 +03:00
|
|
|
StructuredCloneData& aData,
|
2013-11-06 21:21:15 +04:00
|
|
|
JS::Handle<JSObject *> aCpows,
|
|
|
|
nsIPrincipal* aPrincipal)
|
2010-02-20 20:05:20 +03:00
|
|
|
{
|
2013-07-10 21:07:51 +04:00
|
|
|
TabParent* tabParent = mRemoteBrowser;
|
2010-02-20 20:05:20 +03:00
|
|
|
if (tabParent) {
|
2012-08-02 10:02:29 +04:00
|
|
|
ClonedMessageData data;
|
2014-06-11 09:44:03 +04:00
|
|
|
nsIContentParent* cp = tabParent->Manager();
|
2015-09-10 23:50:58 +03:00
|
|
|
if (!BuildClonedMessageDataForParent(cp, aData, data)) {
|
2015-10-07 13:42:43 +03:00
|
|
|
MOZ_CRASH();
|
|
|
|
return NS_ERROR_DOM_DATA_CLONE_ERR;
|
2012-08-02 10:02:29 +04:00
|
|
|
}
|
2013-07-11 02:05:39 +04:00
|
|
|
InfallibleTArray<mozilla::jsipc::CpowEntry> cpows;
|
2015-04-28 03:05:05 +03:00
|
|
|
jsipc::CPOWManager* mgr = cp->GetCPOWManager();
|
|
|
|
if (aCpows && (!mgr || !mgr->Wrap(aCx, aCpows, &cpows))) {
|
2015-10-07 13:42:43 +03:00
|
|
|
return NS_ERROR_UNEXPECTED;
|
|
|
|
}
|
2016-04-09 16:50:59 +03:00
|
|
|
if (tabParent->SendAsyncMessage(nsString(aMessage), cpows,
|
|
|
|
IPC::Principal(aPrincipal), data)) {
|
2015-10-07 13:42:43 +03:00
|
|
|
return NS_OK;
|
|
|
|
} else {
|
|
|
|
return NS_ERROR_UNEXPECTED;
|
2013-07-11 02:05:39 +04:00
|
|
|
}
|
2010-02-20 20:05:20 +03:00
|
|
|
}
|
2012-08-02 10:02:29 +04:00
|
|
|
|
2012-09-28 09:43:12 +04:00
|
|
|
if (mChildMessageManager) {
|
2016-08-12 12:39:16 +03:00
|
|
|
JS::RootingContext* rcx = JS::RootingContext::get(aCx);
|
|
|
|
RefPtr<nsAsyncMessageToChild> ev = new nsAsyncMessageToChild(rcx, aCpows, this);
|
|
|
|
nsresult rv = ev->Init(aMessage, aData, aPrincipal);
|
2015-10-07 13:42:43 +03:00
|
|
|
if (NS_FAILED(rv)) {
|
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
rv = NS_DispatchToCurrentThread(ev);
|
|
|
|
if (NS_FAILED(rv)) {
|
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
return rv;
|
2012-09-19 15:08:36 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
// We don't have any targets to send our asynchronous message to.
|
2015-10-07 13:42:43 +03:00
|
|
|
return NS_ERROR_UNEXPECTED;
|
2010-05-18 16:28:37 +04:00
|
|
|
}
|
2010-02-20 20:05:20 +03:00
|
|
|
|
|
|
|
NS_IMETHODIMP
|
2012-08-27 18:13:02 +04:00
|
|
|
nsFrameLoader::GetMessageManager(nsIMessageSender** aManager)
|
2010-02-20 20:05:20 +03:00
|
|
|
{
|
2010-05-24 18:45:59 +04:00
|
|
|
EnsureMessageManager();
|
2010-06-10 13:26:19 +04:00
|
|
|
if (mMessageManager) {
|
2015-10-18 08:24:48 +03:00
|
|
|
RefPtr<nsFrameMessageManager> mm(mMessageManager);
|
2015-03-12 20:20:29 +03:00
|
|
|
mm.forget(aManager);
|
|
|
|
return NS_OK;
|
2010-06-10 13:26:19 +04:00
|
|
|
}
|
2010-05-18 16:28:37 +04:00
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
nsresult
|
|
|
|
nsFrameLoader::EnsureMessageManager()
|
|
|
|
{
|
2010-02-20 20:05:20 +03:00
|
|
|
NS_ENSURE_STATE(mOwnerContent);
|
|
|
|
|
2015-07-30 06:07:14 +03:00
|
|
|
if (mMessageManager) {
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2015-01-08 19:44:00 +03:00
|
|
|
if (!mIsTopLevelContent &&
|
2016-10-15 04:46:26 +03:00
|
|
|
!OwnerIsMozBrowserFrame() &&
|
2015-07-31 12:28:36 +03:00
|
|
|
!IsRemoteFrame() &&
|
2015-03-03 14:08:59 +03:00
|
|
|
!(mOwnerContent->IsXULElement() &&
|
2015-01-08 19:44:00 +03:00
|
|
|
mOwnerContent->AttrValueIs(kNameSpaceID_None,
|
|
|
|
nsGkAtoms::forcemessagemanager,
|
|
|
|
nsGkAtoms::_true, eCaseMatters))) {
|
2010-08-10 19:10:22 +04:00
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2010-05-18 16:28:37 +04:00
|
|
|
nsCOMPtr<nsIDOMChromeWindow> chromeWindow =
|
2012-05-11 11:47:40 +04:00
|
|
|
do_QueryInterface(GetOwnerDoc()->GetWindow());
|
2012-08-27 18:13:02 +04:00
|
|
|
nsCOMPtr<nsIMessageBroadcaster> parentManager;
|
2014-05-23 16:49:09 +04:00
|
|
|
|
2012-05-11 11:47:40 +04:00
|
|
|
if (chromeWindow) {
|
2014-05-23 16:49:09 +04:00
|
|
|
nsAutoString messagemanagergroup;
|
2015-03-03 14:08:59 +03:00
|
|
|
if (mOwnerContent->IsXULElement() &&
|
2014-05-23 16:49:09 +04:00
|
|
|
mOwnerContent->GetAttr(kNameSpaceID_None,
|
|
|
|
nsGkAtoms::messagemanagergroup,
|
|
|
|
messagemanagergroup)) {
|
|
|
|
chromeWindow->GetGroupMessageManager(messagemanagergroup, getter_AddRefs(parentManager));
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!parentManager) {
|
|
|
|
chromeWindow->GetMessageManager(getter_AddRefs(parentManager));
|
|
|
|
}
|
2015-11-24 03:25:15 +03:00
|
|
|
} else {
|
|
|
|
parentManager = do_GetService("@mozilla.org/globalmessagemanager;1");
|
2012-05-11 11:47:40 +04:00
|
|
|
}
|
2010-05-18 16:28:37 +04:00
|
|
|
|
2015-07-30 06:07:14 +03:00
|
|
|
mMessageManager = new nsFrameMessageManager(nullptr,
|
|
|
|
static_cast<nsFrameMessageManager*>(parentManager.get()),
|
|
|
|
MM_CHROME);
|
2015-07-31 12:28:36 +03:00
|
|
|
if (!IsRemoteFrame()) {
|
|
|
|
nsresult rv = MaybeCreateDocShell();
|
|
|
|
if (NS_FAILED(rv)) {
|
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
NS_ASSERTION(mDocShell,
|
|
|
|
"MaybeCreateDocShell succeeded, but null mDocShell");
|
|
|
|
if (!mDocShell) {
|
|
|
|
return NS_ERROR_FAILURE;
|
|
|
|
}
|
2010-05-24 18:45:59 +04:00
|
|
|
mChildMessageManager =
|
|
|
|
new nsInProcessTabChildGlobal(mDocShell, mOwnerContent, mMessageManager);
|
2015-07-30 06:07:14 +03:00
|
|
|
}
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
nsresult
|
|
|
|
nsFrameLoader::ReallyLoadFrameScripts()
|
|
|
|
{
|
|
|
|
nsresult rv = EnsureMessageManager();
|
|
|
|
if (NS_WARN_IF(NS_FAILED(rv))) {
|
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
if (mMessageManager) {
|
2014-01-31 22:45:54 +04:00
|
|
|
mMessageManager->InitWithCallback(this);
|
2010-02-20 20:05:20 +03:00
|
|
|
}
|
|
|
|
return NS_OK;
|
2010-05-18 16:28:37 +04:00
|
|
|
}
|
|
|
|
|
2013-04-06 04:44:26 +04:00
|
|
|
EventTarget*
|
2010-05-18 16:28:37 +04:00
|
|
|
nsFrameLoader::GetTabChildGlobalAsEventTarget()
|
|
|
|
{
|
|
|
|
return static_cast<nsInProcessTabChildGlobal*>(mChildMessageManager.get());
|
2010-02-20 20:05:20 +03:00
|
|
|
}
|
2012-05-08 20:20:35 +04:00
|
|
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
nsFrameLoader::GetOwnerElement(nsIDOMElement **aElement)
|
|
|
|
{
|
|
|
|
nsCOMPtr<nsIDOMElement> ownerElement = do_QueryInterface(mOwnerContent);
|
|
|
|
ownerElement.forget(aElement);
|
|
|
|
return NS_OK;
|
|
|
|
}
|
2012-06-13 02:01:25 +04:00
|
|
|
|
2013-09-12 23:24:10 +04:00
|
|
|
NS_IMETHODIMP
|
|
|
|
nsFrameLoader::GetChildID(uint64_t* aChildID)
|
|
|
|
{
|
|
|
|
*aChildID = mChildID;
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2012-06-13 02:01:25 +04:00
|
|
|
void
|
|
|
|
nsFrameLoader::SetRemoteBrowser(nsITabParent* aTabParent)
|
|
|
|
{
|
|
|
|
MOZ_ASSERT(!mRemoteBrowser);
|
2012-08-18 01:07:54 +04:00
|
|
|
mRemoteFrame = true;
|
2015-02-06 00:47:32 +03:00
|
|
|
mRemoteBrowser = TabParent::GetFrom(aTabParent);
|
2013-09-12 23:24:10 +04:00
|
|
|
mChildID = mRemoteBrowser ? mRemoteBrowser->Manager()->ChildID() : 0;
|
2015-10-01 20:06:51 +03:00
|
|
|
MaybeUpdatePrimaryTabParent(eTabParentChanged);
|
2015-07-31 13:08:36 +03:00
|
|
|
ReallyLoadFrameScripts();
|
|
|
|
InitializeBrowserAPI();
|
2015-09-01 10:39:25 +03:00
|
|
|
ShowRemoteFrame(ScreenIntSize(0, 0));
|
2012-06-13 02:01:25 +04:00
|
|
|
}
|
2012-07-31 06:09:31 +04:00
|
|
|
|
2012-08-14 08:06:44 +04:00
|
|
|
void
|
2016-05-05 00:12:48 +03:00
|
|
|
nsFrameLoader::SetDetachedSubdocFrame(nsIFrame* aDetachedFrame,
|
|
|
|
nsIDocument* aContainerDoc)
|
2012-08-14 08:06:44 +04:00
|
|
|
{
|
2016-05-05 00:12:48 +03:00
|
|
|
mDetachedSubdocFrame = aDetachedFrame;
|
2012-08-14 08:06:44 +04:00
|
|
|
mContainerDocWhileDetached = aContainerDoc;
|
|
|
|
}
|
|
|
|
|
2016-05-05 00:12:48 +03:00
|
|
|
nsIFrame*
|
|
|
|
nsFrameLoader::GetDetachedSubdocFrame(nsIDocument** aContainerDoc) const
|
2012-08-14 08:06:44 +04:00
|
|
|
{
|
|
|
|
NS_IF_ADDREF(*aContainerDoc = mContainerDocWhileDetached);
|
2016-05-05 00:12:48 +03:00
|
|
|
return mDetachedSubdocFrame.GetFrame();
|
2012-08-14 08:06:44 +04:00
|
|
|
}
|
|
|
|
|
2013-08-06 14:01:23 +04:00
|
|
|
void
|
|
|
|
nsFrameLoader::ApplySandboxFlags(uint32_t sandboxFlags)
|
|
|
|
{
|
|
|
|
if (mDocShell) {
|
|
|
|
uint32_t parentSandboxFlags = mOwnerContent->OwnerDoc()->GetSandboxFlags();
|
|
|
|
|
|
|
|
// The child can only add restrictions, never remove them.
|
|
|
|
sandboxFlags |= parentSandboxFlags;
|
2016-06-21 21:31:00 +03:00
|
|
|
|
|
|
|
// If this frame is a receiving browsing context, we should add
|
|
|
|
// sandboxed auxiliary navigation flag to sandboxFlags. See
|
|
|
|
// https://w3c.github.io/presentation-api/#creating-a-receiving-browsing-context
|
|
|
|
nsAutoString presentationURL;
|
|
|
|
nsContentUtils::GetPresentationURL(mDocShell, presentationURL);
|
|
|
|
if (!presentationURL.IsEmpty()) {
|
|
|
|
sandboxFlags |= SANDBOXED_AUXILIARY_NAVIGATION;
|
|
|
|
}
|
2013-08-06 14:01:23 +04:00
|
|
|
mDocShell->SetSandboxFlags(sandboxFlags);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-09-05 07:00:26 +04:00
|
|
|
/* virtual */ void
|
|
|
|
nsFrameLoader::AttributeChanged(nsIDocument* aDocument,
|
|
|
|
mozilla::dom::Element* aElement,
|
|
|
|
int32_t aNameSpaceID,
|
|
|
|
nsIAtom* aAttribute,
|
2015-07-25 09:01:19 +03:00
|
|
|
int32_t aModType,
|
|
|
|
const nsAttrValue* aOldValue)
|
2012-09-05 07:00:26 +04:00
|
|
|
{
|
|
|
|
MOZ_ASSERT(mObservingOwnerContent);
|
|
|
|
|
2016-12-09 22:23:24 +03:00
|
|
|
if (aNameSpaceID != kNameSpaceID_None ||
|
|
|
|
(aAttribute != TypeAttrName() && aAttribute != nsGkAtoms::primary)) {
|
2012-09-05 07:00:26 +04:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (aElement != mOwnerContent) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Note: This logic duplicates a lot of logic in
|
|
|
|
// MaybeCreateDocshell. We should fix that.
|
|
|
|
|
|
|
|
// Notify our enclosing chrome that our type has changed. We only do this
|
|
|
|
// if our parent is chrome, since in all other cases we're random content
|
|
|
|
// subframes and the treeowner shouldn't worry about us.
|
2013-02-13 02:02:51 +04:00
|
|
|
if (!mDocShell) {
|
2015-10-01 20:06:51 +03:00
|
|
|
MaybeUpdatePrimaryTabParent(eTabParentChanged);
|
2012-09-05 07:00:26 +04:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
nsCOMPtr<nsIDocShellTreeItem> parentItem;
|
2013-02-13 02:02:51 +04:00
|
|
|
mDocShell->GetParent(getter_AddRefs(parentItem));
|
2012-09-05 07:00:26 +04:00
|
|
|
if (!parentItem) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2014-01-20 11:58:26 +04:00
|
|
|
if (parentItem->ItemType() != nsIDocShellTreeItem::typeChrome) {
|
2012-09-05 07:00:26 +04:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
nsCOMPtr<nsIDocShellTreeOwner> parentTreeOwner;
|
|
|
|
parentItem->GetTreeOwner(getter_AddRefs(parentTreeOwner));
|
|
|
|
if (!parentTreeOwner) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2016-12-09 22:23:24 +03:00
|
|
|
bool is_primary =
|
|
|
|
aElement->AttrValueIs(kNameSpaceID_None, nsGkAtoms::primary, nsGkAtoms::_true, eIgnoreCase);
|
2012-09-05 07:00:26 +04:00
|
|
|
|
|
|
|
#ifdef MOZ_XUL
|
|
|
|
// when a content panel is no longer primary, hide any open popups it may have
|
|
|
|
if (!is_primary) {
|
|
|
|
nsXULPopupManager* pm = nsXULPopupManager::GetInstance();
|
|
|
|
if (pm)
|
2013-02-13 02:02:51 +04:00
|
|
|
pm->HidePopupsInDocShell(mDocShell);
|
2012-09-05 07:00:26 +04:00
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2013-02-13 02:02:51 +04:00
|
|
|
parentTreeOwner->ContentShellRemoved(mDocShell);
|
2017-01-04 20:33:19 +03:00
|
|
|
|
|
|
|
nsAutoString value;
|
|
|
|
aElement->GetAttr(kNameSpaceID_None, TypeAttrName(), value);
|
|
|
|
|
|
|
|
if (value.LowerCaseEqualsLiteral("content") ||
|
|
|
|
StringBeginsWith(value, NS_LITERAL_STRING("content-"),
|
|
|
|
nsCaseInsensitiveStringComparator())) {
|
2016-12-09 00:12:36 +03:00
|
|
|
parentTreeOwner->ContentShellAdded(mDocShell, is_primary);
|
2012-09-05 07:00:26 +04:00
|
|
|
}
|
|
|
|
}
|
2013-01-06 02:02:29 +04:00
|
|
|
|
2014-05-23 22:19:00 +04:00
|
|
|
/**
|
|
|
|
* Send the RequestNotifyAfterRemotePaint message to the current Tab.
|
|
|
|
*/
|
|
|
|
NS_IMETHODIMP
|
|
|
|
nsFrameLoader::RequestNotifyAfterRemotePaint()
|
|
|
|
{
|
|
|
|
// If remote browsing (e10s), handle this with the TabParent.
|
|
|
|
if (mRemoteBrowser) {
|
2015-11-02 08:53:26 +03:00
|
|
|
Unused << mRemoteBrowser->SendRequestNotifyAfterRemotePaint();
|
2014-05-23 22:19:00 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2016-10-14 10:31:02 +03:00
|
|
|
NS_IMETHODIMP
|
|
|
|
nsFrameLoader::RequestFrameLoaderClose()
|
|
|
|
{
|
|
|
|
nsCOMPtr<nsIBrowser> browser = do_QueryInterface(mOwnerContent);
|
|
|
|
if (NS_WARN_IF(!browser)) {
|
|
|
|
// OwnerElement other than nsIBrowser is not supported yet.
|
|
|
|
return NS_ERROR_NOT_IMPLEMENTED;
|
|
|
|
}
|
|
|
|
|
|
|
|
return browser->CloseBrowser();
|
|
|
|
}
|
|
|
|
|
2016-05-16 12:40:54 +03:00
|
|
|
NS_IMETHODIMP
|
2016-05-25 09:41:54 +03:00
|
|
|
nsFrameLoader::Print(uint64_t aOuterWindowID,
|
|
|
|
nsIPrintSettings* aPrintSettings,
|
2016-05-16 12:40:54 +03:00
|
|
|
nsIWebProgressListener* aProgressListener)
|
|
|
|
{
|
|
|
|
#if defined(NS_PRINTING)
|
|
|
|
if (mRemoteBrowser) {
|
|
|
|
RefPtr<embedding::PrintingParent> printingParent =
|
|
|
|
mRemoteBrowser->Manager()->AsContentParent()->GetPrintingParent();
|
|
|
|
|
|
|
|
embedding::PrintData printData;
|
|
|
|
nsresult rv = printingParent->SerializeAndEnsureRemotePrintJob(
|
|
|
|
aPrintSettings, aProgressListener, nullptr, &printData);
|
|
|
|
if (NS_WARN_IF(NS_FAILED(rv))) {
|
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
|
2016-05-25 09:41:54 +03:00
|
|
|
bool success = mRemoteBrowser->SendPrint(aOuterWindowID, printData);
|
2016-05-16 12:40:54 +03:00
|
|
|
return success ? NS_OK : NS_ERROR_FAILURE;
|
|
|
|
}
|
|
|
|
|
2016-05-25 09:41:54 +03:00
|
|
|
nsGlobalWindow* outerWindow =
|
|
|
|
nsGlobalWindow::GetOuterWindowWithId(aOuterWindowID);
|
|
|
|
if (NS_WARN_IF(!outerWindow)) {
|
|
|
|
return NS_ERROR_FAILURE;
|
|
|
|
}
|
2016-05-16 12:40:54 +03:00
|
|
|
|
2016-05-25 09:41:54 +03:00
|
|
|
nsCOMPtr<nsIWebBrowserPrint> webBrowserPrint =
|
|
|
|
do_GetInterface(outerWindow->AsOuter());
|
|
|
|
if (NS_WARN_IF(!webBrowserPrint)) {
|
|
|
|
return NS_ERROR_FAILURE;
|
2016-05-16 12:40:54 +03:00
|
|
|
}
|
|
|
|
|
2016-05-25 09:41:54 +03:00
|
|
|
return webBrowserPrint->Print(aPrintSettings, aProgressListener);
|
2016-05-16 12:40:54 +03:00
|
|
|
#endif
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2013-04-26 04:53:26 +04:00
|
|
|
/* [infallible] */ NS_IMETHODIMP
|
|
|
|
nsFrameLoader::SetVisible(bool aVisible)
|
|
|
|
{
|
2013-05-10 19:46:08 +04:00
|
|
|
if (mVisible == aVisible) {
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2013-04-26 04:53:26 +04:00
|
|
|
mVisible = aVisible;
|
|
|
|
nsCOMPtr<nsIObserverService> os = services::GetObserverService();
|
|
|
|
if (os) {
|
|
|
|
os->NotifyObservers(NS_ISUPPORTS_CAST(nsIFrameLoader*, this),
|
|
|
|
"frameloader-visible-changed", nullptr);
|
|
|
|
}
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* [infallible] */ NS_IMETHODIMP
|
|
|
|
nsFrameLoader::GetVisible(bool* aVisible)
|
|
|
|
{
|
|
|
|
*aVisible = mVisible;
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
nsFrameLoader::GetTabParent(nsITabParent** aTabParent)
|
|
|
|
{
|
|
|
|
nsCOMPtr<nsITabParent> tp = mRemoteBrowser;
|
|
|
|
tp.forget(aTabParent);
|
|
|
|
return NS_OK;
|
|
|
|
}
|
2014-01-11 05:10:57 +04:00
|
|
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
nsFrameLoader::GetLoadContext(nsILoadContext** aLoadContext)
|
|
|
|
{
|
|
|
|
nsCOMPtr<nsILoadContext> loadContext;
|
|
|
|
if (mRemoteBrowser) {
|
|
|
|
loadContext = mRemoteBrowser->GetLoadContext();
|
|
|
|
} else {
|
|
|
|
nsCOMPtr<nsIDocShell> docShell;
|
|
|
|
GetDocShell(getter_AddRefs(docShell));
|
|
|
|
loadContext = do_GetInterface(docShell);
|
|
|
|
}
|
|
|
|
loadContext.forget(aLoadContext);
|
|
|
|
return NS_OK;
|
|
|
|
}
|
2015-02-09 10:04:18 +03:00
|
|
|
|
|
|
|
void
|
|
|
|
nsFrameLoader::InitializeBrowserAPI()
|
|
|
|
{
|
2016-10-15 04:46:26 +03:00
|
|
|
if (!OwnerIsMozBrowserFrame()) {
|
2016-09-09 00:00:12 +03:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (!IsRemoteFrame()) {
|
|
|
|
nsresult rv = EnsureMessageManager();
|
|
|
|
if (NS_WARN_IF(NS_FAILED(rv))) {
|
|
|
|
return;
|
2015-07-31 13:08:36 +03:00
|
|
|
}
|
2016-09-09 00:00:12 +03:00
|
|
|
if (mMessageManager) {
|
|
|
|
mMessageManager->LoadFrameScript(
|
|
|
|
NS_LITERAL_STRING("chrome://global/content/BrowserElementChild.js"),
|
|
|
|
/* allowDelayedLoad = */ true,
|
|
|
|
/* aRunInGlobalScope */ true);
|
2015-07-31 13:08:36 +03:00
|
|
|
}
|
2015-02-09 10:04:18 +03:00
|
|
|
}
|
2016-09-09 00:00:12 +03:00
|
|
|
nsCOMPtr<nsIMozBrowserFrame> browserFrame = do_QueryInterface(mOwnerContent);
|
|
|
|
if (browserFrame) {
|
|
|
|
browserFrame->InitializeBrowserAPI();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
nsFrameLoader::DestroyBrowserFrameScripts()
|
|
|
|
{
|
2016-10-15 04:46:26 +03:00
|
|
|
if (!OwnerIsMozBrowserFrame()) {
|
2016-09-09 00:00:12 +03:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
nsCOMPtr<nsIMozBrowserFrame> browserFrame = do_QueryInterface(mOwnerContent);
|
|
|
|
if (browserFrame) {
|
|
|
|
browserFrame->DestroyBrowserFrameScripts();
|
|
|
|
}
|
2015-02-09 10:04:18 +03:00
|
|
|
}
|
2015-08-06 00:25:39 +03:00
|
|
|
|
|
|
|
NS_IMETHODIMP
|
2015-08-06 17:44:16 +03:00
|
|
|
nsFrameLoader::StartPersistence(uint64_t aOuterWindowID,
|
|
|
|
nsIWebBrowserPersistDocumentReceiver* aRecv)
|
2015-08-06 00:25:39 +03:00
|
|
|
{
|
2015-08-06 17:44:16 +03:00
|
|
|
if (!aRecv) {
|
|
|
|
return NS_ERROR_INVALID_POINTER;
|
|
|
|
}
|
|
|
|
|
2015-08-06 00:25:39 +03:00
|
|
|
if (mRemoteBrowser) {
|
2015-08-06 17:44:16 +03:00
|
|
|
return mRemoteBrowser->StartPersistence(aOuterWindowID, aRecv);
|
2015-08-06 00:25:39 +03:00
|
|
|
}
|
2015-08-06 17:44:16 +03:00
|
|
|
|
2016-04-12 10:40:36 +03:00
|
|
|
nsCOMPtr<nsIDocument> rootDoc =
|
|
|
|
mDocShell ? mDocShell->GetDocument() : nullptr;
|
2015-08-06 17:44:16 +03:00
|
|
|
nsCOMPtr<nsIDocument> foundDoc;
|
|
|
|
if (aOuterWindowID) {
|
|
|
|
foundDoc = nsContentUtils::GetSubdocumentWithOuterWindowId(rootDoc, aOuterWindowID);
|
|
|
|
} else {
|
|
|
|
foundDoc = rootDoc;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!foundDoc) {
|
|
|
|
aRecv->OnError(NS_ERROR_NO_CONTENT);
|
|
|
|
} else {
|
2015-08-06 00:25:39 +03:00
|
|
|
nsCOMPtr<nsIWebBrowserPersistDocument> pdoc =
|
2015-08-06 17:44:16 +03:00
|
|
|
new mozilla::WebBrowserPersistLocalDocument(foundDoc);
|
2015-08-06 00:25:39 +03:00
|
|
|
aRecv->OnDocumentReady(pdoc);
|
|
|
|
}
|
2015-08-06 17:44:16 +03:00
|
|
|
return NS_OK;
|
2015-08-06 00:25:39 +03:00
|
|
|
}
|
2015-10-01 20:06:51 +03:00
|
|
|
|
|
|
|
void
|
|
|
|
nsFrameLoader::MaybeUpdatePrimaryTabParent(TabParentChange aChange)
|
|
|
|
{
|
|
|
|
if (mRemoteBrowser && mOwnerContent) {
|
|
|
|
nsCOMPtr<nsIDocShell> docShell = mOwnerContent->OwnerDoc()->GetDocShell();
|
|
|
|
if (!docShell) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
int32_t parentType = docShell->ItemType();
|
|
|
|
if (parentType != nsIDocShellTreeItem::typeChrome) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
nsCOMPtr<nsIDocShellTreeOwner> parentTreeOwner;
|
|
|
|
docShell->GetTreeOwner(getter_AddRefs(parentTreeOwner));
|
|
|
|
if (!parentTreeOwner) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!mObservingOwnerContent) {
|
|
|
|
mOwnerContent->AddMutationObserver(this);
|
|
|
|
mObservingOwnerContent = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
parentTreeOwner->TabParentRemoved(mRemoteBrowser);
|
|
|
|
if (aChange == eTabParentChanged) {
|
|
|
|
bool isPrimary =
|
2016-12-09 22:23:24 +03:00
|
|
|
mOwnerContent->AttrValueIs(kNameSpaceID_None, nsGkAtoms::primary,
|
|
|
|
nsGkAtoms::_true, eIgnoreCase);
|
2015-10-01 20:06:51 +03:00
|
|
|
parentTreeOwner->TabParentAdded(mRemoteBrowser, isPrimary);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2015-10-08 09:44:36 +03:00
|
|
|
|
|
|
|
nsresult
|
2015-10-22 06:44:00 +03:00
|
|
|
nsFrameLoader::GetNewTabContext(MutableTabContext* aTabContext,
|
2016-11-06 18:15:36 +03:00
|
|
|
nsIURI* aURI)
|
2015-10-08 09:44:36 +03:00
|
|
|
{
|
2017-01-12 19:38:48 +03:00
|
|
|
OriginAttributes attrs;
|
2016-02-18 06:31:29 +03:00
|
|
|
attrs.mInIsolatedMozBrowser = OwnerIsIsolatedMozBrowserFrame();
|
2016-10-31 21:03:12 +03:00
|
|
|
nsresult rv;
|
2015-10-08 09:44:36 +03:00
|
|
|
|
2016-10-15 04:46:26 +03:00
|
|
|
attrs.mAppId = nsIScriptSecurityManager::NO_APP_ID;
|
2015-10-08 09:44:36 +03:00
|
|
|
|
2015-11-24 04:40:02 +03:00
|
|
|
// set the userContextId on the attrs before we pass them into
|
|
|
|
// the tab context
|
2016-10-31 21:03:12 +03:00
|
|
|
rv = PopulateUserContextIdFromAttribute(attrs);
|
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
2015-11-24 04:40:02 +03:00
|
|
|
|
2016-05-17 06:10:59 +03:00
|
|
|
nsAutoString presentationURLStr;
|
|
|
|
mOwnerContent->GetAttr(kNameSpaceID_None,
|
|
|
|
nsGkAtoms::mozpresentation,
|
|
|
|
presentationURLStr);
|
|
|
|
|
2016-06-08 08:42:00 +03:00
|
|
|
nsCOMPtr<nsIDocShell> docShell = mOwnerContent->OwnerDoc()->GetDocShell();
|
|
|
|
nsCOMPtr<nsILoadContext> parentContext = do_QueryInterface(docShell);
|
|
|
|
NS_ENSURE_STATE(parentContext);
|
|
|
|
|
|
|
|
bool isPrivate = parentContext->UsePrivateBrowsing();
|
2016-06-03 00:02:29 +03:00
|
|
|
attrs.SyncAttributesWithPrivateBrowsing(isPrivate);
|
|
|
|
|
2016-06-09 14:59:31 +03:00
|
|
|
UIStateChangeType showAccelerators = UIStateChangeType_NoChange;
|
|
|
|
UIStateChangeType showFocusRings = UIStateChangeType_NoChange;
|
|
|
|
nsIDocument* doc = mOwnerContent->OwnerDoc();
|
|
|
|
if (doc) {
|
|
|
|
nsCOMPtr<nsPIWindowRoot> root = nsContentUtils::GetWindowRoot(doc);
|
|
|
|
if (root) {
|
|
|
|
showAccelerators =
|
|
|
|
root->ShowAccelerators() ? UIStateChangeType_Set : UIStateChangeType_Clear;
|
|
|
|
showFocusRings =
|
|
|
|
root->ShowFocusRings() ? UIStateChangeType_Set : UIStateChangeType_Clear;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-11-03 04:50:54 +03:00
|
|
|
bool tabContextUpdated =
|
2016-02-18 07:35:45 +03:00
|
|
|
aTabContext->SetTabContext(OwnerIsMozBrowserFrame(),
|
2016-05-20 06:36:27 +03:00
|
|
|
mIsPrerendered,
|
2016-06-09 14:59:31 +03:00
|
|
|
showAccelerators,
|
|
|
|
showFocusRings,
|
2016-02-18 07:35:45 +03:00
|
|
|
attrs,
|
2016-05-17 06:10:59 +03:00
|
|
|
presentationURLStr);
|
2015-10-08 09:44:36 +03:00
|
|
|
NS_ENSURE_STATE(tabContextUpdated);
|
|
|
|
|
|
|
|
return NS_OK;
|
|
|
|
}
|
2016-05-30 02:48:00 +03:00
|
|
|
|
|
|
|
nsresult
|
2017-01-12 19:38:48 +03:00
|
|
|
nsFrameLoader::PopulateUserContextIdFromAttribute(OriginAttributes& aAttr)
|
2016-05-30 02:48:00 +03:00
|
|
|
{
|
|
|
|
if (aAttr.mUserContextId ==
|
|
|
|
nsIScriptSecurityManager::DEFAULT_USER_CONTEXT_ID) {
|
|
|
|
// Grab the userContextId from owner if XUL
|
|
|
|
nsAutoString userContextIdStr;
|
|
|
|
int32_t namespaceID = mOwnerContent->GetNameSpaceID();
|
|
|
|
if ((namespaceID == kNameSpaceID_XUL) &&
|
|
|
|
mOwnerContent->GetAttr(kNameSpaceID_None, nsGkAtoms::usercontextid,
|
|
|
|
userContextIdStr) &&
|
|
|
|
!userContextIdStr.IsEmpty()) {
|
|
|
|
nsresult rv;
|
|
|
|
aAttr.mUserContextId = userContextIdStr.ToInteger(&rv);
|
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return NS_OK;
|
|
|
|
}
|
2016-08-22 11:28:04 +03:00
|
|
|
|
2016-12-13 11:32:54 +03:00
|
|
|
NS_IMETHODIMP
|
|
|
|
nsFrameLoader::GetIsDead(bool* aIsDead)
|
|
|
|
{
|
|
|
|
*aIsDead = mDestroyCalled;
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2016-08-22 11:28:04 +03:00
|
|
|
nsIMessageSender*
|
|
|
|
nsFrameLoader::GetProcessMessageManager() const
|
|
|
|
{
|
|
|
|
return mRemoteBrowser ? mRemoteBrowser->Manager()->GetMessageManager()
|
|
|
|
: nullptr;
|
|
|
|
};
|