Bug 827188 - Initialize the hidden private window lazily; r=bzbarsky

This commit is contained in:
Ehsan Akhgari
2013-01-06 21:16:48 -05:00
parent c95ee8f5e1
commit ce9f1908ee
6 changed files with 118 additions and 36 deletions

View File

@@ -368,6 +368,9 @@ nsCCUncollectableMarker::Observe(nsISupports* aSubject, const char* aTopic,
MarkDocShell(shellTreeNode, cleanupJS, prepareForCC);
}
#ifdef MOZ_PER_WINDOW_PRIVATE_BROWSING
bool hasHiddenPrivateWindow = false;
appShell->GetHasHiddenPrivateWindow(&hasHiddenPrivateWindow);
if (hasHiddenPrivateWindow) {
appShell->GetHiddenPrivateWindow(getter_AddRefs(hw));
if (hw) {
nsCOMPtr<nsIDocShell> shell;
@@ -375,6 +378,7 @@ nsCCUncollectableMarker::Observe(nsISupports* aSubject, const char* aTopic,
nsCOMPtr<nsIDocShellTreeNode> shellTreeNode = do_QueryInterface(shell);
MarkDocShell(shellTreeNode, cleanupJS, prepareForCC);
}
}
#endif
}

View File

@@ -193,7 +193,10 @@
#include "mozilla/Telemetry.h"
#include "nsISecurityUITelemetry.h"
#ifndef MOZ_PER_WINDOW_PRIVATE_BROWSING
#ifdef MOZ_PER_WINDOW_PRIVATE_BROWSING
#include "nsIAppShellService.h"
#include "nsAppShellCID.h"
#else
#include "nsIPrivateBrowsingService.h"
#endif
@@ -220,9 +223,9 @@ static uint32_t gNumberOfPrivateDocShells = 0;
// Global count of private docshells which will always remain open
#ifdef MOZ_PER_WINDOW_PRIVATE_BROWSING
static const uint32_t kNumberOfAlwaysOpenPrivateDocShells = 1; // the private hidden window
static uint32_t gNumberOfAlwaysOpenPrivateDocShells = 0; // the private hidden window
#else
static const uint32_t kNumberOfAlwaysOpenPrivateDocShells = 0;
static const uint32_t gNumberOfAlwaysOpenPrivateDocShells = 0;
#endif
// Global reference to the URI fixup service.
@@ -688,11 +691,27 @@ ConvertLoadTypeToNavigationType(uint32_t aLoadType)
static nsISHEntry* GetRootSHEntry(nsISHEntry *entry);
static void
AdjustAlwaysOpenPrivateDocShellCount()
{
#ifdef MOZ_PER_WINDOW_PRIVATE_BROWSING
nsCOMPtr<nsIAppShellService> appShell
(do_GetService(NS_APPSHELLSERVICE_CONTRACTID));
bool hasHiddenPrivateWindow = false;
if (appShell) {
appShell->GetHasHiddenPrivateWindow(&hasHiddenPrivateWindow);
}
gNumberOfAlwaysOpenPrivateDocShells = hasHiddenPrivateWindow ? 1 : 0;
#endif
}
static void
IncreasePrivateDocShellCount()
{
AdjustAlwaysOpenPrivateDocShellCount();
gNumberOfPrivateDocShells++;
if (gNumberOfPrivateDocShells > kNumberOfAlwaysOpenPrivateDocShells + 1 ||
if (gNumberOfPrivateDocShells > gNumberOfAlwaysOpenPrivateDocShells + 1 ||
XRE_GetProcessType() != GeckoProcessType_Content) {
return;
}
@@ -704,9 +723,11 @@ IncreasePrivateDocShellCount()
static void
DecreasePrivateDocShellCount()
{
AdjustAlwaysOpenPrivateDocShellCount();
MOZ_ASSERT(gNumberOfPrivateDocShells > 0);
gNumberOfPrivateDocShells--;
if (gNumberOfPrivateDocShells == kNumberOfAlwaysOpenPrivateDocShells)
if (gNumberOfPrivateDocShells == gNumberOfAlwaysOpenPrivateDocShells)
{
if (XRE_GetProcessType() == GeckoProcessType_Content) {
mozilla::dom::ContentChild* cc = mozilla::dom::ContentChild::GetSingleton();

View File

@@ -314,19 +314,23 @@ nsAppStartup::Quit(uint32_t aMode)
// If we're considering quitting, we will only do so if:
if (ferocity == eConsiderQuit) {
#ifdef XP_MACOSX
nsCOMPtr<nsIAppShellService> appShell
(do_GetService(NS_APPSHELLSERVICE_CONTRACTID));
bool hasHiddenPrivateWindow = false;
if (appShell) {
appShell->GetHasHiddenPrivateWindow(&hasHiddenPrivateWindow);
}
int32_t suspiciousCount = hasHiddenPrivateWindow ? 2 : 1;
#endif
if (mConsiderQuitStopper == 0) {
// there are no windows...
ferocity = eAttemptQuit;
}
#ifdef XP_MACOSX
#ifdef MOZ_PER_WINDOW_PRIVATE_BROWSING
else if (mConsiderQuitStopper == 2) {
#else
else if (mConsiderQuitStopper == 1) {
#endif
else if (mConsiderQuitStopper == suspiciousCount) {
// ... or there is only a hiddenWindow left, and it's useless:
nsCOMPtr<nsIAppShellService> appShell
(do_GetService(NS_APPSHELLSERVICE_CONTRACTID));
// Failure shouldn't be fatal, but will abort quit attempt:
if (!appShell)
@@ -337,11 +341,15 @@ nsAppStartup::Quit(uint32_t aMode)
nsCOMPtr<nsIXULWindow> hiddenWindow;
appShell->GetHiddenWindow(getter_AddRefs(hiddenWindow));
#ifdef MOZ_PER_WINDOW_PRIVATE_BROWSING
nsCOMPtr<nsIXULWindow> hiddenPrivateWindow;
appShell->GetHiddenPrivateWindow(getter_AddRefs(hiddenPrivateWindow));
// If the remaining windows are useful, we won't quit:
nsCOMPtr<nsIXULWindow> hiddenPrivateWindow;
if (hasHiddenPrivateWindow) {
appShell->GetHiddenPrivateWindow(getter_AddRefs(hiddenPrivateWindow));
if ((!hiddenWindow && !hiddenPrivateWindow) || usefulHiddenWindow)
return NS_OK;
} else if (!hiddenWindow || usefulHiddenWindow) {
return NS_OK;
}
#else
// If the one window is useful, we won't quit:
if (!hiddenWindow || usefulHiddenWindow)

View File

@@ -16,7 +16,7 @@ interface nsIAppShell;
struct JSContext;
%}
[scriptable, uuid(76e6364a-5453-47c7-ad83-8c30eff20a75)]
[scriptable, uuid(5c19ab54-67bf-46d0-ac5b-21abd9050c3b)]
interface nsIAppShellService : nsISupports
{
/**
@@ -117,4 +117,10 @@ interface nsIAppShellService : nsISupports
* @param aWindow you see the pattern
*/
void unregisterTopLevelWindow(in nsIXULWindow aWindow);
/**
* Whether the hidden private window has been lazily created.
*/
[noscript]
readonly attribute boolean hasHiddenPrivateWindow;
};

View File

@@ -82,6 +82,22 @@ NS_IMPL_ISUPPORTS2(nsAppShellService,
NS_IMETHODIMP
nsAppShellService::CreateHiddenWindow()
{
return CreateHiddenWindowHelper(false);
}
void
nsAppShellService::EnsurePrivateHiddenWindow()
{
#ifdef MOZ_PER_WINDOW_PRIVATE_BROWSING
if (!mHiddenPrivateWindow) {
CreateHiddenWindowHelper(true);
}
#endif
}
nsresult
nsAppShellService::CreateHiddenWindowHelper(bool aIsPrivate)
{
nsresult rv;
int32_t initialHeight = 100, initialWidth = 100;
@@ -91,7 +107,11 @@ nsAppShellService::CreateHiddenWindow()
nsAdoptingCString prefVal =
Preferences::GetCString("browser.hiddenWindowChromeURL");
const char* hiddenWindowURL = prefVal.get() ? prefVal.get() : DEFAULT_HIDDENWINDOW_URL;
if (aIsPrivate) {
hiddenWindowURL = DEFAULT_HIDDENWINDOW_URL;
} else {
mApplicationProvidedHiddenWindow = prefVal.get() ? true : false;
}
#else
static const char hiddenWindowURL[] = DEFAULT_HIDDENWINDOW_URL;
uint32_t chromeMask = nsIWebBrowserChrome::CHROME_ALL;
@@ -102,14 +122,16 @@ nsAppShellService::CreateHiddenWindow()
NS_ENSURE_SUCCESS(rv, rv);
nsRefPtr<nsWebShellWindow> newWindow;
if (!aIsPrivate) {
rv = JustCreateTopWindow(nullptr, url,
chromeMask, initialWidth, initialHeight,
true, getter_AddRefs(newWindow));
NS_ENSURE_SUCCESS(rv, rv);
mHiddenWindow.swap(newWindow);
}
#ifdef MOZ_PER_WINDOW_PRIVATE_BROWSING
else {
// Create the hidden private window
chromeMask |= nsIWebBrowserChrome::CHROME_PRIVATE_WINDOW;
@@ -119,6 +141,7 @@ nsAppShellService::CreateHiddenWindow()
NS_ENSURE_SUCCESS(rv, rv);
mHiddenPrivateWindow.swap(newWindow);
}
#endif
// RegisterTopLevelWindow(newWindow); -- Mac only
@@ -446,6 +469,8 @@ nsAppShellService::GetHiddenPrivateWindow(nsIXULWindow **aWindow)
#ifdef MOZ_PER_WINDOW_PRIVATE_BROWSING
NS_ENSURE_ARG_POINTER(aWindow);
EnsurePrivateHiddenWindow();
*aWindow = mHiddenPrivateWindow;
NS_IF_ADDREF(*aWindow);
return *aWindow ? NS_OK : NS_ERROR_FAILURE;
@@ -458,6 +483,8 @@ NS_IMETHODIMP
nsAppShellService::GetHiddenPrivateDOMWindow(nsIDOMWindow **aWindow)
{
#ifdef MOZ_PER_WINDOW_PRIVATE_BROWSING
EnsurePrivateHiddenWindow();
nsresult rv;
nsCOMPtr<nsIDocShell> docShell;
NS_ENSURE_TRUE(mHiddenPrivateWindow, NS_ERROR_FAILURE);
@@ -476,6 +503,19 @@ nsAppShellService::GetHiddenPrivateDOMWindow(nsIDOMWindow **aWindow)
#endif
}
NS_IMETHODIMP
nsAppShellService::GetHasHiddenPrivateWindow(bool* aHasPrivateWindow)
{
#ifdef MOZ_PER_WINDOW_PRIVATE_BROWSING
NS_ENSURE_ARG_POINTER(aHasPrivateWindow);
*aHasPrivateWindow = !!mHiddenPrivateWindow;
return NS_OK;
#else
return NS_ERROR_NOT_IMPLEMENTED;
#endif
}
NS_IMETHODIMP
nsAppShellService::GetHiddenWindowAndJSContext(nsIDOMWindow **aWindow,
JSContext **aJSContext)

View File

@@ -32,6 +32,9 @@ public:
protected:
~nsAppShellService();
nsresult CreateHiddenWindowHelper(bool aIsPrivate);
void EnsurePrivateHiddenWindow();
nsresult JustCreateTopWindow(nsIXULWindow *aParent,
nsIURI *aUrl,
uint32_t aChromeMask,