зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1261842 - Factor out logic for creating windows for content processes from nsWindowWatcher::OpenWindowInternal. r=smaug
MozReview-Commit-ID: 1dhGthT8bmu --HG-- extra : rebase_source : 34d321ebd3c27f414c63c72908c72d23aabb5396 extra : source : 0f8b603781817f58c4664a33429325bc316598e9
This commit is contained in:
Родитель
febff2f77c
Коммит
688f1f9516
|
@ -11833,7 +11833,7 @@ nsGlobalWindow::OpenInternal(const nsAString& aUrl, const nsAString& aName,
|
|||
// !aCalledNoScript.
|
||||
rv = pwwatch->OpenWindow2(AsOuter(), url.get(), name_ptr,
|
||||
options_ptr, /* aCalledFromScript = */ true,
|
||||
aDialog, aNavigate, nullptr, argv,
|
||||
aDialog, aNavigate, argv,
|
||||
1.0f, 0, getter_AddRefs(domReturn));
|
||||
} else {
|
||||
// Force a system caller here so that the window watcher won't screw us
|
||||
|
@ -11853,7 +11853,7 @@ nsGlobalWindow::OpenInternal(const nsAString& aUrl, const nsAString& aName,
|
|||
|
||||
rv = pwwatch->OpenWindow2(AsOuter(), url.get(), name_ptr,
|
||||
options_ptr, /* aCalledFromScript = */ false,
|
||||
aDialog, aNavigate, nullptr, aExtraArgument,
|
||||
aDialog, aNavigate, aExtraArgument,
|
||||
1.0f, 0, getter_AddRefs(domReturn));
|
||||
|
||||
}
|
||||
|
|
|
@ -5317,13 +5317,6 @@ ContentParent::RecvCreateWindow(PBrowserParent* aThisTab,
|
|||
return false;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsPIWindowWatcher> pwwatch =
|
||||
do_GetService(NS_WINDOWWATCHER_CONTRACTID, aResult);
|
||||
|
||||
if (NS_WARN_IF(NS_FAILED(*aResult))) {
|
||||
return true;
|
||||
}
|
||||
|
||||
TabParent* newTab = TabParent::GetFrom(aNewTab);
|
||||
MOZ_ASSERT(newTab);
|
||||
|
||||
|
@ -5419,41 +5412,22 @@ ContentParent::RecvCreateWindow(PBrowserParent* aThisTab,
|
|||
|
||||
const char* features = aFeatures.IsVoid() ? nullptr : aFeatures.get();
|
||||
|
||||
*aResult = pwwatch->OpenWindow2(parent, nullptr,
|
||||
aName.IsVoid() ?
|
||||
nullptr :
|
||||
NS_ConvertUTF16toUTF8(aName).get(),
|
||||
features, aCalledFromJS,
|
||||
false, false, thisTabParent, nullptr,
|
||||
aFullZoom, 1, getter_AddRefs(window));
|
||||
nsCOMPtr<nsPIWindowWatcher> pwwatch =
|
||||
do_GetService(NS_WINDOWWATCHER_CONTRACTID, aResult);
|
||||
|
||||
if (NS_WARN_IF(!window)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
*aResult = NS_ERROR_FAILURE;
|
||||
auto* pwindow = nsPIDOMWindowOuter::From(window);
|
||||
nsCOMPtr<nsIDocShell> windowDocShell = pwindow->GetDocShell();
|
||||
if (NS_WARN_IF(!windowDocShell)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIDocShellTreeOwner> treeOwner;
|
||||
windowDocShell->GetTreeOwner(getter_AddRefs(treeOwner));
|
||||
|
||||
nsCOMPtr<nsIXULWindow> xulWin = do_GetInterface(treeOwner);
|
||||
if (NS_WARN_IF(!xulWin)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIXULBrowserWindow> xulBrowserWin;
|
||||
xulWin->GetXULBrowserWindow(getter_AddRefs(xulBrowserWin));
|
||||
if (NS_WARN_IF(!xulBrowserWin)) {
|
||||
if (NS_WARN_IF(NS_FAILED(*aResult))) {
|
||||
return true;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsITabParent> newRemoteTab;
|
||||
*aResult = xulBrowserWin->ForceInitialBrowserRemote(getter_AddRefs(newRemoteTab));
|
||||
if (!thisTabParent) {
|
||||
// Because we weren't passed an opener tab, the content process has asked us
|
||||
// to open a new window that is unrelated to a pre-existing tab.
|
||||
*aResult = pwwatch->OpenWindowWithoutParent(getter_AddRefs(newRemoteTab));
|
||||
} else {
|
||||
*aResult = pwwatch->OpenWindowWithTabParent(thisTabParent, features, aCalledFromJS,
|
||||
aFullZoom, getter_AddRefs(newRemoteTab));
|
||||
}
|
||||
|
||||
if (NS_WARN_IF(NS_FAILED(*aResult))) {
|
||||
return true;
|
||||
|
|
|
@ -606,7 +606,7 @@ private:
|
|||
spec.get(),
|
||||
nullptr,
|
||||
nullptr,
|
||||
false, false, true, nullptr, nullptr, 1.0f, 0,
|
||||
false, false, true, nullptr, 1.0f, 0,
|
||||
getter_AddRefs(newWindow));
|
||||
nsCOMPtr<nsPIDOMWindowOuter> pwindow = nsPIDOMWindowOuter::From(newWindow);
|
||||
pwindow.forget(aWindow);
|
||||
|
|
|
@ -45,3 +45,5 @@ LOCAL_INCLUDES += [
|
|||
|
||||
if CONFIG['GNU_CXX']:
|
||||
CXXFLAGS += ['-Wno-error=shadow']
|
||||
|
||||
include('/ipc/chromium/chromium-config.mozbuild')
|
||||
|
|
|
@ -54,9 +54,6 @@ interface nsPIWindowWatcher : nsISupports
|
|||
@param aDialog use dialog defaults (see nsIDOMWindow::openDialog)
|
||||
@param aNavigate true if we should navigate the new window to the
|
||||
specified URL.
|
||||
@param aOpeningTab the nsITabParent that is opening the new window. The
|
||||
nsITabParent is a remote tab belonging to aParent. Can
|
||||
be nullptr if this window is not being opened from a tab.
|
||||
@param aArgs Window argument
|
||||
@param aOpenerFullZoom the full zoom multiplier for the opener window.
|
||||
this can be null in the single process case where
|
||||
|
@ -77,10 +74,41 @@ interface nsPIWindowWatcher : nsISupports
|
|||
in boolean aCalledFromScript,
|
||||
in boolean aDialog,
|
||||
in boolean aNavigate,
|
||||
in nsITabParent aOpeningTab,
|
||||
in nsISupports aArgs,
|
||||
[optional] in float aOpenerFullZoom);
|
||||
|
||||
/**
|
||||
* Opens a new window using the most recent non-private browser
|
||||
* window as its parent.
|
||||
*
|
||||
* @return the nsITabParent of the initial browser for the newly opened
|
||||
* window.
|
||||
*/
|
||||
nsITabParent openWindowWithoutParent();
|
||||
|
||||
/**
|
||||
* Opens a new window so that the window that aOpeningTab belongs to
|
||||
* is set as the parent window. The newly opened window will also
|
||||
* inherit load context information from aOpeningTab.
|
||||
*
|
||||
* @param aOpeningTab
|
||||
* The nsITabParent that is requesting the new window be opened.
|
||||
* @param aFeatures
|
||||
* Window features if called with window.open or similar.
|
||||
* @param aCalledFromJS
|
||||
* True if called via window.open or similar.
|
||||
* @param aOpenerFullZoom
|
||||
* The current zoom multiplier for the opener tab. This is then
|
||||
* applied to the newly opened window.
|
||||
*
|
||||
* @return the nsITabParent of the initial browser for the newly opened
|
||||
* window.
|
||||
*/
|
||||
nsITabParent openWindowWithTabParent(in nsITabParent aOpeningTab,
|
||||
in string aFeatures,
|
||||
in boolean aCalledFromJS,
|
||||
in float aOpenerFullZoom);
|
||||
|
||||
/**
|
||||
* Find a named docshell tree item amongst all windows registered
|
||||
* with the window watcher. This may be a subframe in some window,
|
||||
|
|
|
@ -64,6 +64,9 @@
|
|||
#include "mozilla/Preferences.h"
|
||||
#include "mozilla/dom/DOMStorage.h"
|
||||
#include "mozilla/dom/ScriptSettings.h"
|
||||
#include "mozilla/dom/TabParent.h"
|
||||
#include "nsIXULWindow.h"
|
||||
#include "nsIXULBrowserWindow.h"
|
||||
|
||||
#ifdef USEWEAKREFS
|
||||
#include "nsIWeakReference.h"
|
||||
|
@ -368,7 +371,7 @@ nsWindowWatcher::OpenWindow(mozIDOMWindowProxy* aParent,
|
|||
|
||||
return OpenWindowInternal(aParent, aUrl, aName, aFeatures,
|
||||
/* calledFromJS = */ false, dialog,
|
||||
/* navigate = */ true, nullptr, argv,
|
||||
/* navigate = */ true, argv,
|
||||
/* openerFullZoom = */ nullptr, aResult);
|
||||
}
|
||||
|
||||
|
@ -425,7 +428,6 @@ nsWindowWatcher::OpenWindow2(mozIDOMWindowProxy* aParent,
|
|||
bool aCalledFromScript,
|
||||
bool aDialog,
|
||||
bool aNavigate,
|
||||
nsITabParent* aOpeningTab,
|
||||
nsISupports* aArguments,
|
||||
float aOpenerFullZoom,
|
||||
uint8_t aOptionalArgc,
|
||||
|
@ -448,7 +450,7 @@ nsWindowWatcher::OpenWindow2(mozIDOMWindowProxy* aParent,
|
|||
|
||||
return OpenWindowInternal(aParent, aUrl, aName, aFeatures,
|
||||
aCalledFromScript, dialog,
|
||||
aNavigate, aOpeningTab, argv,
|
||||
aNavigate, argv,
|
||||
aOptionalArgc >= 1 ? &aOpenerFullZoom : nullptr,
|
||||
aResult);
|
||||
}
|
||||
|
@ -486,6 +488,154 @@ CheckUserContextCompatibility(nsIDocShell* aDocShell)
|
|||
return principalUserContextId == userContextId;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsWindowWatcher::OpenWindowWithoutParent(nsITabParent** aResult)
|
||||
{
|
||||
return OpenWindowWithTabParent(nullptr, "", true, 1.0f, aResult);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsWindowWatcher::OpenWindowWithTabParent(nsITabParent* aOpeningTabParent,
|
||||
const char* aFeatures,
|
||||
bool aCalledFromJS,
|
||||
float aOpenerFullZoom,
|
||||
nsITabParent** aResult)
|
||||
{
|
||||
MOZ_ASSERT(XRE_IsParentProcess());
|
||||
MOZ_ASSERT(mWindowCreator);
|
||||
|
||||
if (!nsContentUtils::IsSafeToRunScript()) {
|
||||
nsContentUtils::WarnScriptWasIgnored(nullptr);
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
if (NS_WARN_IF(!mWindowCreator)) {
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
|
||||
bool isPrivateBrowsingWindow =
|
||||
Preferences::GetBool("browser.privatebrowsing.autostart");
|
||||
|
||||
nsCOMPtr<nsPIDOMWindowOuter> parentWindowOuter;
|
||||
if (aOpeningTabParent) {
|
||||
// We need to examine the window that aOpeningTabParent belongs to in
|
||||
// order to inform us of what kind of window we're going to open.
|
||||
TabParent* openingTab = TabParent::GetFrom(aOpeningTabParent);
|
||||
parentWindowOuter = openingTab->GetParentWindowOuter();
|
||||
|
||||
// Propagate the privacy status of the parent window, if
|
||||
// available, to the child.
|
||||
if (!isPrivateBrowsingWindow) {
|
||||
nsCOMPtr<nsILoadContext> parentContext = openingTab->GetLoadContext();
|
||||
if (parentContext) {
|
||||
isPrivateBrowsingWindow = parentContext->UsePrivateBrowsing();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!parentWindowOuter) {
|
||||
// We couldn't find a browser window for the opener, so either we
|
||||
// never were passed aOpeningTabParent, the window is closed,
|
||||
// or it's in the process of closing. Either way, we'll use
|
||||
// the most recently opened browser window instead.
|
||||
parentWindowOuter = nsContentUtils::GetMostRecentNonPBWindow();
|
||||
}
|
||||
|
||||
if (NS_WARN_IF(!parentWindowOuter)) {
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIDocShellTreeOwner> parentTreeOwner;
|
||||
GetWindowTreeOwner(parentWindowOuter, getter_AddRefs(parentTreeOwner));
|
||||
if (NS_WARN_IF(!parentTreeOwner)) {
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIWindowCreator2> windowCreator2(do_QueryInterface(mWindowCreator));
|
||||
if (NS_WARN_IF(!windowCreator2)) {
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
|
||||
uint32_t contextFlags = 0;
|
||||
if (parentWindowOuter->IsLoadingOrRunningTimeout()) {
|
||||
contextFlags |=
|
||||
nsIWindowCreator2::PARENT_IS_LOADING_OR_RUNNING_TIMEOUT;
|
||||
}
|
||||
|
||||
// B2G multi-screen support. mozDisplayId is returned from the
|
||||
// "display-changed" event, it is also platform-dependent.
|
||||
#ifdef MOZ_WIDGET_GONK
|
||||
int retval = WinHasOption(features, "mozDisplayId", 0, nullptr);
|
||||
windowCreator2->SetScreenId(retval);
|
||||
#endif
|
||||
|
||||
nsAutoCString features(aFeatures);
|
||||
uint32_t chromeFlags = CalculateChromeFlagsForChild(features);
|
||||
|
||||
// A content process has asked for a new window, which implies
|
||||
// that the new window will need to be remote.
|
||||
chromeFlags |= nsIWebBrowserChrome::CHROME_REMOTE_WINDOW;
|
||||
|
||||
bool cancel = false;
|
||||
nsCOMPtr<nsIWebBrowserChrome> parentChrome(do_GetInterface(parentTreeOwner));
|
||||
nsCOMPtr<nsIWebBrowserChrome> newWindowChrome;
|
||||
|
||||
nsresult rv =
|
||||
windowCreator2->CreateChromeWindow2(parentChrome, chromeFlags, contextFlags,
|
||||
aOpeningTabParent, &cancel,
|
||||
getter_AddRefs(newWindowChrome));
|
||||
|
||||
if (NS_SUCCEEDED(rv) && cancel) {
|
||||
newWindowChrome = nullptr; // just in case
|
||||
return NS_ERROR_ABORT;
|
||||
}
|
||||
|
||||
if (NS_WARN_IF(!newWindowChrome)) {
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIDocShellTreeItem> chromeTreeItem = do_GetInterface(newWindowChrome);
|
||||
if (NS_WARN_IF(!chromeTreeItem)) {
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIDocShellTreeOwner> chromeTreeOwner;
|
||||
chromeTreeItem->GetTreeOwner(getter_AddRefs(chromeTreeOwner));
|
||||
if (NS_WARN_IF(!chromeTreeOwner)) {
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsILoadContext> chromeContext = do_QueryInterface(chromeTreeItem);
|
||||
if (NS_WARN_IF(!chromeContext)) {
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
|
||||
chromeContext->SetPrivateBrowsing(isPrivateBrowsingWindow);
|
||||
|
||||
// Tabs opened from a content process can only open new windows
|
||||
// that will also run with out-of-process tabs.
|
||||
chromeContext->SetRemoteTabs(true);
|
||||
|
||||
if (PL_strcasestr(features.get(), "width=") ||
|
||||
PL_strcasestr(features.get(), "height=")) {
|
||||
chromeTreeOwner->SetPersistence(false, false, false);
|
||||
}
|
||||
|
||||
SizeSpec sizeSpec;
|
||||
CalcSizeSpec(features, sizeSpec);
|
||||
SizeOpenedDocShellItem(chromeTreeItem, parentWindowOuter, false, sizeSpec,
|
||||
&aOpenerFullZoom);
|
||||
|
||||
nsCOMPtr<nsITabParent> newTabParent;
|
||||
chromeTreeOwner->GetPrimaryTabParent(getter_AddRefs(newTabParent));
|
||||
if (NS_WARN_IF(!newTabParent)) {
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
|
||||
newTabParent.forget(aResult);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsWindowWatcher::OpenWindowInternal(mozIDOMWindowProxy* aParent,
|
||||
const char* aUrl,
|
||||
|
@ -494,7 +644,6 @@ nsWindowWatcher::OpenWindowInternal(mozIDOMWindowProxy* aParent,
|
|||
bool aCalledFromJS,
|
||||
bool aDialog,
|
||||
bool aNavigate,
|
||||
nsITabParent* aOpeningTab,
|
||||
nsIArray* aArgv,
|
||||
float* aOpenerFullZoom,
|
||||
mozIDOMWindowProxy** aResult)
|
||||
|
@ -507,10 +656,6 @@ nsWindowWatcher::OpenWindowInternal(mozIDOMWindowProxy* aParent,
|
|||
bool uriToLoadIsChrome = false;
|
||||
bool windowIsModalContentDialog = false;
|
||||
|
||||
// Opening tabs are only ever passed to OpenWindowInternal if we're opening
|
||||
// a window from a remote tab.
|
||||
bool openedFromRemoteTab = !!aOpeningTab;
|
||||
|
||||
uint32_t chromeFlags;
|
||||
nsAutoString name; // string version of aName
|
||||
nsAutoCString features; // string version of aFeatures
|
||||
|
@ -521,10 +666,6 @@ nsWindowWatcher::OpenWindowInternal(mozIDOMWindowProxy* aParent,
|
|||
nsCOMPtr<nsPIDOMWindowOuter> parent =
|
||||
aParent ? nsPIDOMWindowOuter::From(aParent) : nullptr;
|
||||
|
||||
// When the opener is a remote tab, the url passed from the child process
|
||||
// isn't actually used. This code needs some serious refactoring.
|
||||
MOZ_ASSERT_IF(openedFromRemoteTab, !aUrl);
|
||||
MOZ_ASSERT_IF(openedFromRemoteTab, XRE_IsParentProcess());
|
||||
NS_ENSURE_ARG_POINTER(aResult);
|
||||
*aResult = 0;
|
||||
|
||||
|
@ -538,7 +679,7 @@ nsWindowWatcher::OpenWindowInternal(mozIDOMWindowProxy* aParent,
|
|||
// We expect TabParent to have provided us the absolute URI of the window
|
||||
// we're to open, so there's no need to call URIfromURL (or more importantly,
|
||||
// to check for a chrome URI, which cannot be opened from a remote tab).
|
||||
if (aUrl && !openedFromRemoteTab) {
|
||||
if (aUrl) {
|
||||
rv = URIfromURL(aUrl, aParent, getter_AddRefs(uriToLoad));
|
||||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
|
@ -554,26 +695,16 @@ nsWindowWatcher::OpenWindowInternal(mozIDOMWindowProxy* aParent,
|
|||
name.SetIsVoid(true);
|
||||
}
|
||||
|
||||
bool featuresSpecified = false;
|
||||
if (aFeatures) {
|
||||
features.Assign(aFeatures);
|
||||
featuresSpecified = true;
|
||||
features.StripWhitespace();
|
||||
} else {
|
||||
features.SetIsVoid(true);
|
||||
}
|
||||
|
||||
// We only want to check for existing named windows if:
|
||||
// a) We're the child process
|
||||
// b) We're the parent process, and aOpeningTab wasn't passed
|
||||
// in.
|
||||
// This is because when using child processes, the parent process shouldn't
|
||||
// know or care about names - unless we're opening named windows from chrome.
|
||||
if (!aOpeningTab) {
|
||||
// try to find an extant window with the given name
|
||||
nsCOMPtr<nsPIDOMWindowOuter> foundWindow = SafeGetWindowByName(name, aParent);
|
||||
GetWindowTreeItem(foundWindow, getter_AddRefs(newDocShellItem));
|
||||
}
|
||||
|
||||
// Do sandbox checks here, instead of waiting until nsIDocShell::LoadURI.
|
||||
// The state of the window can change before this call and if we are blocked
|
||||
|
@ -598,23 +729,29 @@ nsWindowWatcher::OpenWindowInternal(mozIDOMWindowProxy* aParent,
|
|||
if (aParent) {
|
||||
// Check if the parent document has chrome privileges.
|
||||
nsIDocument* doc = parentWindow->GetDoc();
|
||||
hasChromeParent =
|
||||
doc && nsContentUtils::IsChromeDoc(doc) && !openedFromRemoteTab;
|
||||
hasChromeParent = doc && nsContentUtils::IsChromeDoc(doc);
|
||||
}
|
||||
|
||||
// Make sure we call CalculateChromeFlags() *before* we push the
|
||||
// callee context onto the context stack so that
|
||||
// CalculateChromeFlags() sees the actual caller when doing its
|
||||
// security checks.
|
||||
chromeFlags = CalculateChromeFlags(aParent, features, featuresSpecified,
|
||||
aDialog, uriToLoadIsChrome,
|
||||
hasChromeParent, aCalledFromJS,
|
||||
openedFromRemoteTab);
|
||||
bool isCallerChrome = nsContentUtils::LegacyIsCallerChromeOrNativeCode();
|
||||
|
||||
// If we are opening a window from a remote browser, the resulting window
|
||||
// should also be remote.
|
||||
MOZ_ASSERT_IF(openedFromRemoteTab,
|
||||
chromeFlags & nsIWebBrowserChrome::CHROME_REMOTE_WINDOW);
|
||||
// Make sure we calculate the chromeFlags *before* we push the
|
||||
// callee context onto the context stack so that
|
||||
// the calculation sees the actual caller when doing its
|
||||
// security checks.
|
||||
if (isCallerChrome && XRE_IsParentProcess()) {
|
||||
chromeFlags = CalculateChromeFlagsForParent(aParent, features,
|
||||
aDialog, uriToLoadIsChrome,
|
||||
hasChromeParent, aCalledFromJS);
|
||||
} else {
|
||||
chromeFlags = CalculateChromeFlagsForChild(features);
|
||||
|
||||
// Until ShowModalDialog is removed, it's still possible for content to
|
||||
// request dialogs, but only in single-process mode.
|
||||
if (aDialog) {
|
||||
MOZ_ASSERT(XRE_IsParentProcess());
|
||||
chromeFlags |= nsIWebBrowserChrome::CHROME_OPENAS_DIALOG;
|
||||
}
|
||||
}
|
||||
|
||||
// If we're not called through our JS version of the API, and we got
|
||||
// our internal modal option, treat the window we're opening as a
|
||||
|
@ -638,8 +775,6 @@ nsWindowWatcher::OpenWindowInternal(mozIDOMWindowProxy* aParent,
|
|||
nsCOMPtr<nsIScriptSecurityManager> sm(
|
||||
do_GetService(NS_SCRIPTSECURITYMANAGER_CONTRACTID));
|
||||
|
||||
bool isCallerChrome =
|
||||
nsContentUtils::LegacyIsCallerChromeOrNativeCode() && !openedFromRemoteTab;
|
||||
|
||||
// XXXbz Why is an AutoJSAPI good enough here? Wouldn't AutoEntryScript (so
|
||||
// we affect the entry global) make more sense? Or do we just want to affect
|
||||
|
@ -837,7 +972,7 @@ nsWindowWatcher::OpenWindowInternal(mozIDOMWindowProxy* aParent,
|
|||
|
||||
bool cancel = false;
|
||||
rv = windowCreator2->CreateChromeWindow2(parentChrome, chromeFlags,
|
||||
contextFlags, aOpeningTab,
|
||||
contextFlags, nullptr,
|
||||
&cancel, getter_AddRefs(newChrome));
|
||||
if (NS_SUCCEEDED(rv) && cancel) {
|
||||
newChrome = 0; // just in case
|
||||
|
@ -849,6 +984,14 @@ nsWindowWatcher::OpenWindowInternal(mozIDOMWindowProxy* aParent,
|
|||
}
|
||||
|
||||
if (newChrome) {
|
||||
nsCOMPtr<nsIXULWindow> xulWin = do_GetInterface(newChrome);
|
||||
if (xulWin) {
|
||||
nsCOMPtr<nsIXULBrowserWindow> xulBrowserWin;
|
||||
xulWin->GetXULBrowserWindow(getter_AddRefs(xulBrowserWin));
|
||||
if (xulBrowserWin) {
|
||||
xulBrowserWin->ForceInitialBrowserNonRemote();
|
||||
}
|
||||
}
|
||||
/* It might be a chrome nsXULWindow, in which case it won't have
|
||||
an nsIDOMWindow (primary content shell). But in that case, it'll
|
||||
be able to hand over an nsIDocShellTreeItem directly. */
|
||||
|
@ -1542,108 +1685,39 @@ nsWindowWatcher::URIfromURL(const char* aURL,
|
|||
|
||||
#define NS_CALCULATE_CHROME_FLAG_FOR(feature, flag) \
|
||||
prefBranch->GetBoolPref(feature, &forceEnable); \
|
||||
if (forceEnable && !(aDialog && !openedFromContentScript) && \
|
||||
!(!openedFromContentScript && aHasChromeParent) && !aChromeURL) { \
|
||||
if (forceEnable && !aDialog && !aHasChromeParent && !aChromeURL) { \
|
||||
chromeFlags |= flag; \
|
||||
} else { \
|
||||
chromeFlags |= \
|
||||
WinHasOption(aFeatures, feature, 0, &presenceFlag) ? flag : 0; \
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculate the chrome bitmask from a string list of features.
|
||||
* @param aParent the opener window
|
||||
* @param aFeatures a string containing a list of named chrome features
|
||||
* @param aNullFeatures true if aFeatures was a null pointer (which fact
|
||||
* is lost by its conversion to a string in the caller)
|
||||
* @param aDialog affects the assumptions made about unnamed features
|
||||
* @return the chrome bitmask
|
||||
*/
|
||||
// static
|
||||
uint32_t
|
||||
nsWindowWatcher::CalculateChromeFlags(mozIDOMWindowProxy* aParent,
|
||||
nsWindowWatcher::CalculateChromeFlagsHelper(uint32_t aInitialFlags,
|
||||
const nsACString& aFeatures,
|
||||
bool aFeaturesSpecified,
|
||||
bool& presenceFlag,
|
||||
bool aDialog,
|
||||
bool aChromeURL,
|
||||
bool aHasChromeParent,
|
||||
bool aCalledFromJS,
|
||||
bool aOpenedFromRemoteTab)
|
||||
bool aChromeURL)
|
||||
{
|
||||
const bool inContentProcess = XRE_IsContentProcess();
|
||||
uint32_t chromeFlags = 0;
|
||||
|
||||
// The features string is made void by OpenWindowInternal
|
||||
// if nullptr was originally passed as the features string.
|
||||
if (aFeatures.IsVoid()) {
|
||||
chromeFlags = nsIWebBrowserChrome::CHROME_ALL;
|
||||
if (aDialog) {
|
||||
chromeFlags |= nsIWebBrowserChrome::CHROME_OPENAS_DIALOG |
|
||||
nsIWebBrowserChrome::CHROME_OPENAS_CHROME;
|
||||
}
|
||||
|
||||
if (inContentProcess) {
|
||||
return chromeFlags;
|
||||
}
|
||||
} else {
|
||||
chromeFlags = nsIWebBrowserChrome::CHROME_WINDOW_BORDERS;
|
||||
}
|
||||
|
||||
bool openedFromContentScript =
|
||||
aOpenedFromRemoteTab ? aCalledFromJS
|
||||
: !nsContentUtils::LegacyIsCallerChromeOrNativeCode();
|
||||
|
||||
/* This function has become complicated since browser windows and
|
||||
dialogs diverged. The difference is, browser windows assume all
|
||||
chrome not explicitly mentioned is off, if the features string
|
||||
is not null. Exceptions are some OS border chrome new with Mozilla.
|
||||
Dialogs interpret a (mostly) empty features string to mean
|
||||
"OS's choice," and also support an "all" flag explicitly disallowed
|
||||
in the standards-compliant window.(normal)open. */
|
||||
|
||||
bool presenceFlag = false;
|
||||
if (aDialog && WinHasOption(aFeatures, "all", 0, &presenceFlag)) {
|
||||
chromeFlags = nsIWebBrowserChrome::CHROME_ALL;
|
||||
}
|
||||
|
||||
/* Next, allow explicitly named options to override the initial settings */
|
||||
|
||||
if (!inContentProcess && !openedFromContentScript) {
|
||||
// Determine whether the window is a private browsing window
|
||||
chromeFlags |= WinHasOption(aFeatures, "private", 0, &presenceFlag) ?
|
||||
nsIWebBrowserChrome::CHROME_PRIVATE_WINDOW : 0;
|
||||
chromeFlags |= WinHasOption(aFeatures, "non-private", 0, &presenceFlag) ?
|
||||
nsIWebBrowserChrome::CHROME_NON_PRIVATE_WINDOW : 0;
|
||||
}
|
||||
|
||||
if (!inContentProcess) {
|
||||
// Determine whether the window should have remote tabs.
|
||||
bool remote = BrowserTabsRemoteAutostart();
|
||||
|
||||
if (!openedFromContentScript) {
|
||||
if (remote) {
|
||||
remote = !WinHasOption(aFeatures, "non-remote", 0, &presenceFlag);
|
||||
} else {
|
||||
remote = WinHasOption(aFeatures, "remote", 0, &presenceFlag);
|
||||
}
|
||||
}
|
||||
|
||||
if (remote) {
|
||||
chromeFlags |= nsIWebBrowserChrome::CHROME_REMOTE_WINDOW;
|
||||
}
|
||||
}
|
||||
uint32_t chromeFlags = aInitialFlags;
|
||||
|
||||
nsresult rv;
|
||||
|
||||
nsCOMPtr<nsIPrefBranch> prefBranch;
|
||||
nsCOMPtr<nsIPrefService> prefs =
|
||||
do_GetService(NS_PREFSERVICE_CONTRACTID, &rv);
|
||||
NS_ENSURE_SUCCESS(rv, true);
|
||||
|
||||
NS_ENSURE_SUCCESS(rv, nsIWebBrowserChrome::CHROME_DEFAULT);
|
||||
|
||||
rv = prefs->GetBranch("dom.disable_window_open_feature.",
|
||||
getter_AddRefs(prefBranch));
|
||||
NS_ENSURE_SUCCESS(rv, true);
|
||||
|
||||
NS_ENSURE_SUCCESS(rv, nsIWebBrowserChrome::CHROME_DEFAULT);
|
||||
|
||||
// NS_CALCULATE_CHROME_FLAG_FOR requires aFeatures, forceEnable, aDialog
|
||||
// aHasChromeParent, aChromeURL, presenceFlag and chromeFlags to be in
|
||||
// scope.
|
||||
bool forceEnable = false;
|
||||
|
||||
NS_CALCULATE_CHROME_FLAG_FOR("titlebar",
|
||||
|
@ -1670,6 +1744,130 @@ nsWindowWatcher::CalculateChromeFlags(mozIDOMWindowProxy* aParent,
|
|||
chromeFlags |= nsIWebBrowserChrome::CHROME_SCROLLBARS;
|
||||
}
|
||||
|
||||
return chromeFlags;
|
||||
}
|
||||
|
||||
// static
|
||||
uint32_t
|
||||
nsWindowWatcher::EnsureFlagsSafeForContent(uint32_t aChromeFlags,
|
||||
bool aChromeURL)
|
||||
{
|
||||
aChromeFlags |= nsIWebBrowserChrome::CHROME_TITLEBAR;
|
||||
aChromeFlags |= nsIWebBrowserChrome::CHROME_WINDOW_CLOSE;
|
||||
aChromeFlags &= ~nsIWebBrowserChrome::CHROME_WINDOW_LOWERED;
|
||||
aChromeFlags &= ~nsIWebBrowserChrome::CHROME_WINDOW_RAISED;
|
||||
aChromeFlags &= ~nsIWebBrowserChrome::CHROME_WINDOW_POPUP;
|
||||
/* Untrusted script is allowed to pose modal windows with a chrome
|
||||
scheme. This check could stand to be better. But it effectively
|
||||
prevents untrusted script from opening modal windows in general
|
||||
while still allowing alerts and the like. */
|
||||
if (!aChromeURL) {
|
||||
aChromeFlags &= ~(nsIWebBrowserChrome::CHROME_MODAL |
|
||||
nsIWebBrowserChrome::CHROME_OPENAS_CHROME);
|
||||
}
|
||||
|
||||
if (!(aChromeFlags & nsIWebBrowserChrome::CHROME_OPENAS_CHROME)) {
|
||||
aChromeFlags &= ~nsIWebBrowserChrome::CHROME_DEPENDENT;
|
||||
}
|
||||
|
||||
return aChromeFlags;
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculate the chrome bitmask from a string list of features requested
|
||||
* from a child process. Feature strings that are restricted to the parent
|
||||
* process are ignored here.
|
||||
* @param aFeatures a string containing a list of named features
|
||||
* @return the chrome bitmask
|
||||
*/
|
||||
// static
|
||||
uint32_t
|
||||
nsWindowWatcher::CalculateChromeFlagsForChild(const nsACString& aFeatures)
|
||||
{
|
||||
if (aFeatures.IsVoid()) {
|
||||
return nsIWebBrowserChrome::CHROME_ALL;
|
||||
}
|
||||
|
||||
bool presenceFlag = false;
|
||||
uint32_t chromeFlags = CalculateChromeFlagsHelper(
|
||||
nsIWebBrowserChrome::CHROME_WINDOW_BORDERS, aFeatures, presenceFlag);
|
||||
|
||||
return EnsureFlagsSafeForContent(chromeFlags);
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculate the chrome bitmask from a string list of features for a new
|
||||
* privileged window.
|
||||
* @param aParent the opener window
|
||||
* @param aFeatures a string containing a list of named chrome features
|
||||
* @param aDialog affects the assumptions made about unnamed features
|
||||
* @param aChromeURL true if the window is being sent to a chrome:// URL
|
||||
* @param aHasChromeParent true if the parent window is privileged
|
||||
* @param aCalledFromJS true if the window open request came from script.
|
||||
* @return the chrome bitmask
|
||||
*/
|
||||
// static
|
||||
uint32_t
|
||||
nsWindowWatcher::CalculateChromeFlagsForParent(mozIDOMWindowProxy* aParent,
|
||||
const nsACString& aFeatures,
|
||||
bool aDialog,
|
||||
bool aChromeURL,
|
||||
bool aHasChromeParent,
|
||||
bool aCalledFromJS)
|
||||
{
|
||||
MOZ_ASSERT(XRE_IsParentProcess());
|
||||
MOZ_ASSERT(nsContentUtils::LegacyIsCallerChromeOrNativeCode());
|
||||
|
||||
uint32_t chromeFlags = 0;
|
||||
|
||||
// The features string is made void by OpenWindowInternal
|
||||
// if nullptr was originally passed as the features string.
|
||||
if (aFeatures.IsVoid()) {
|
||||
chromeFlags = nsIWebBrowserChrome::CHROME_ALL;
|
||||
if (aDialog) {
|
||||
chromeFlags |= nsIWebBrowserChrome::CHROME_OPENAS_DIALOG |
|
||||
nsIWebBrowserChrome::CHROME_OPENAS_CHROME;
|
||||
}
|
||||
} else {
|
||||
chromeFlags = nsIWebBrowserChrome::CHROME_WINDOW_BORDERS;
|
||||
}
|
||||
|
||||
/* This function has become complicated since browser windows and
|
||||
dialogs diverged. The difference is, browser windows assume all
|
||||
chrome not explicitly mentioned is off, if the features string
|
||||
is not null. Exceptions are some OS border chrome new with Mozilla.
|
||||
Dialogs interpret a (mostly) empty features string to mean
|
||||
"OS's choice," and also support an "all" flag explicitly disallowed
|
||||
in the standards-compliant window.(normal)open. */
|
||||
|
||||
bool presenceFlag = false;
|
||||
if (aDialog && WinHasOption(aFeatures, "all", 0, &presenceFlag)) {
|
||||
chromeFlags = nsIWebBrowserChrome::CHROME_ALL;
|
||||
}
|
||||
|
||||
/* Next, allow explicitly named options to override the initial settings */
|
||||
chromeFlags = CalculateChromeFlagsHelper(chromeFlags, aFeatures, presenceFlag,
|
||||
aDialog, aHasChromeParent, aChromeURL);
|
||||
|
||||
// Determine whether the window is a private browsing window
|
||||
chromeFlags |= WinHasOption(aFeatures, "private", 0, &presenceFlag) ?
|
||||
nsIWebBrowserChrome::CHROME_PRIVATE_WINDOW : 0;
|
||||
chromeFlags |= WinHasOption(aFeatures, "non-private", 0, &presenceFlag) ?
|
||||
nsIWebBrowserChrome::CHROME_NON_PRIVATE_WINDOW : 0;
|
||||
|
||||
// Determine whether the window should have remote tabs.
|
||||
bool remote = BrowserTabsRemoteAutostart();
|
||||
|
||||
if (remote) {
|
||||
remote = !WinHasOption(aFeatures, "non-remote", 0, &presenceFlag);
|
||||
} else {
|
||||
remote = WinHasOption(aFeatures, "remote", 0, &presenceFlag);
|
||||
}
|
||||
|
||||
if (remote) {
|
||||
chromeFlags |= nsIWebBrowserChrome::CHROME_REMOTE_WINDOW;
|
||||
}
|
||||
|
||||
chromeFlags |= WinHasOption(aFeatures, "popup", 0, &presenceFlag) ?
|
||||
nsIWebBrowserChrome::CHROME_WINDOW_POPUP : 0;
|
||||
|
||||
|
@ -1723,16 +1921,11 @@ nsWindowWatcher::CalculateChromeFlags(mozIDOMWindowProxy* aParent,
|
|||
does not provide any affordance for dialog windows. This does not interfere
|
||||
with dialog windows created through openDialog. */
|
||||
bool disableDialogFeature = false;
|
||||
nsCOMPtr<nsIPrefBranch> branch = do_QueryInterface(prefs);
|
||||
nsCOMPtr<nsIPrefBranch> branch = do_GetService(NS_PREFSERVICE_CONTRACTID);
|
||||
|
||||
branch->GetBoolPref("dom.disable_window_open_dialog_feature",
|
||||
&disableDialogFeature);
|
||||
|
||||
if (openedFromContentScript) {
|
||||
// If the caller context is content, we do not support the
|
||||
// dialog feature. See bug 1095236.
|
||||
disableDialogFeature = true;
|
||||
}
|
||||
|
||||
if (!disableDialogFeature) {
|
||||
chromeFlags |= WinHasOption(aFeatures, "dialog", 0, nullptr) ?
|
||||
nsIWebBrowserChrome::CHROME_OPENAS_DIALOG : 0;
|
||||
|
@ -1754,27 +1947,8 @@ nsWindowWatcher::CalculateChromeFlags(mozIDOMWindowProxy* aParent,
|
|||
*/
|
||||
|
||||
// Check security state for use in determing window dimensions
|
||||
if (openedFromContentScript || !aHasChromeParent) {
|
||||
// If priv check fails (or if we're called from chrome, but the
|
||||
// parent is not a chrome window), set all elements to minimum
|
||||
// reqs., else leave them alone.
|
||||
chromeFlags |= nsIWebBrowserChrome::CHROME_TITLEBAR;
|
||||
chromeFlags |= nsIWebBrowserChrome::CHROME_WINDOW_CLOSE;
|
||||
chromeFlags &= ~nsIWebBrowserChrome::CHROME_WINDOW_LOWERED;
|
||||
chromeFlags &= ~nsIWebBrowserChrome::CHROME_WINDOW_RAISED;
|
||||
chromeFlags &= ~nsIWebBrowserChrome::CHROME_WINDOW_POPUP;
|
||||
/* Untrusted script is allowed to pose modal windows with a chrome
|
||||
scheme. This check could stand to be better. But it effectively
|
||||
prevents untrusted script from opening modal windows in general
|
||||
while still allowing alerts and the like. */
|
||||
if (!aChromeURL)
|
||||
chromeFlags &= ~(nsIWebBrowserChrome::CHROME_MODAL |
|
||||
nsIWebBrowserChrome::CHROME_OPENAS_CHROME);
|
||||
}
|
||||
|
||||
if (!(chromeFlags & nsIWebBrowserChrome::CHROME_OPENAS_CHROME)) {
|
||||
// Remove the dependent flag if we're not opening as chrome
|
||||
chromeFlags &= ~nsIWebBrowserChrome::CHROME_DEPENDENT;
|
||||
if (!aHasChromeParent) {
|
||||
chromeFlags = EnsureFlagsSafeForContent(chromeFlags, aChromeURL);
|
||||
}
|
||||
|
||||
// Disable CHROME_OPENAS_DIALOG if the window is inside <iframe mozbrowser>.
|
||||
|
|
|
@ -82,7 +82,6 @@ protected:
|
|||
bool aCalledFromJS,
|
||||
bool aDialog,
|
||||
bool aNavigate,
|
||||
nsITabParent* aOpeningTab,
|
||||
nsIArray* aArgv,
|
||||
float* aOpenerFullZoom,
|
||||
mozIDOMWindowProxy** aResult);
|
||||
|
@ -91,14 +90,15 @@ protected:
|
|||
mozIDOMWindowProxy* aParent,
|
||||
nsIURI** aURI);
|
||||
|
||||
static uint32_t CalculateChromeFlags(mozIDOMWindowProxy* aParent,
|
||||
const nsACString& aFeatures,
|
||||
bool aFeaturesSpecified,
|
||||
static uint32_t CalculateChromeFlagsForChild(const nsACString& aFeaturesStr);
|
||||
|
||||
static uint32_t CalculateChromeFlagsForParent(mozIDOMWindowProxy* aParent,
|
||||
const nsACString& aFeaturesStr,
|
||||
bool aDialog,
|
||||
bool aChromeURL,
|
||||
bool aHasChromeParent,
|
||||
bool aCalledFromJS,
|
||||
bool aOpenedFromRemoteTab);
|
||||
bool aCalledFromJS);
|
||||
|
||||
static int32_t WinHasOption(const nsACString& aOptions, const char* aName,
|
||||
int32_t aDefault, bool* aPresenceFlag);
|
||||
/* Compute the right SizeSpec based on aFeatures */
|
||||
|
@ -117,6 +117,17 @@ protected:
|
|||
static void GetWindowTreeOwner(nsPIDOMWindowOuter* aWindow,
|
||||
nsIDocShellTreeOwner** aResult);
|
||||
|
||||
private:
|
||||
static uint32_t CalculateChromeFlagsHelper(uint32_t aInitialFlags,
|
||||
const nsACString& aFeatures,
|
||||
bool &presenceFlag,
|
||||
bool aDialog = false,
|
||||
bool aHasChromeParent = false,
|
||||
bool aChromeURL = false);
|
||||
static uint32_t EnsureFlagsSafeForContent(uint32_t aChromeFlags,
|
||||
bool aChromeURL = false);
|
||||
|
||||
protected:
|
||||
nsTArray<nsWatcherWindowEnumerator*> mEnumeratorList;
|
||||
nsWatcherWindowEntry* mOldestWindow;
|
||||
mozilla::Mutex mListLock;
|
||||
|
|
Загрузка…
Ссылка в новой задаче