Bug 832700 - Add private browsing to b2g, API implementation r=ehsan,smaug
authorFabrice Desré <fabrice@mozilla.com>
Fri, 10 Oct 2014 14:28:04 -0700
changeset 233193 0990e633fd0dcdefdc171f0d0cf49c0db18e84e0
parent 233192 44168a7af20de3db73f0a7ed63abd923ad3a3732
child 233194 89b935e3119d64d6235751bab28f289d99fd8a17
push id4187
push userbhearsum@mozilla.com
push dateFri, 28 Nov 2014 15:29:12 +0000
treeherdermozilla-beta@f23cc6a30c11 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersehsan, smaug
bugs832700
milestone35.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 832700 - Add private browsing to b2g, API implementation r=ehsan,smaug
content/base/src/nsGkAtomList.h
docshell/base/nsDocShell.cpp
docshell/base/nsDocShell.h
docshell/base/nsIDocShell.idl
dom/browser-element/BrowserElementChild.js
dom/browser-element/BrowserElementParent.cpp
dom/browser-element/BrowserElementParent.jsm
--- a/content/base/src/nsGkAtomList.h
+++ b/content/base/src/nsGkAtomList.h
@@ -604,16 +604,17 @@ GK_ATOM(mousethrough, "mousethrough")
 GK_ATOM(mouseup, "mouseup")
 GK_ATOM(mozaudiochannel, "mozaudiochannel")
 GK_ATOM(mozasyncpanzoom, "mozasyncpanzoom")
 GK_ATOM(mozfullscreenchange, "mozfullscreenchange")
 GK_ATOM(mozfullscreenerror, "mozfullscreenerror")
 GK_ATOM(mozpasspointerevents, "mozpasspointerevents")
 GK_ATOM(mozpointerlockchange, "mozpointerlockchange")
 GK_ATOM(mozpointerlockerror, "mozpointerlockerror")
+GK_ATOM(mozprivatebrowsing, "mozprivatebrowsing")
 GK_ATOM(moz_opaque, "moz-opaque")
 GK_ATOM(moz_action_hint, "mozactionhint")
 GK_ATOM(x_moz_errormessage, "x-moz-errormessage")
 GK_ATOM(msthemecompatible, "msthemecompatible")
 GK_ATOM(multicol, "multicol")
 GK_ATOM(multiple, "multiple")
 GK_ATOM(muted, "muted")
 GK_ATOM(name, "name")
--- a/docshell/base/nsDocShell.cpp
+++ b/docshell/base/nsDocShell.cpp
@@ -846,16 +846,17 @@ nsDocShell::nsDocShell():
     mIsExecutingOnLoadHandler(false),
     mIsPrintingOrPP(false),
     mSavingOldViewer(false),
 #ifdef DEBUG
     mInEnsureScriptEnv(false),
 #endif
     mAffectPrivateSessionLifetime(true),
     mInvisible(false),
+    mHasLoadedNonBlankURI(false),
     mDefaultLoadFlags(nsIRequest::LOAD_NORMAL),
     mFrameType(eFrameTypeRegular),
     mOwnOrContainingAppId(nsIScriptSecurityManager::UNKNOWN_APP_ID),
     mParentCharsetSource(0)
 {
     mHistoryID = ++gDocshellIDCounter;
     if (gDocShellCount++ == 0) {
         NS_ASSERTION(sURIFixup == nullptr,
@@ -1923,16 +1924,20 @@ nsDocShell::SetCurrentURI(nsIURI *aURI, 
     // We don't want to send a location change when we're displaying an error
     // page, and we don't want to change our idea of "current URI" either
     if (mLoadType == LOAD_ERROR_PAGE) {
         return false;
     }
 
     mCurrentURI = NS_TryToMakeImmutable(aURI);
     
+    if (!NS_IsAboutBlank(mCurrentURI)) {
+      mHasLoadedNonBlankURI = true;
+    }
+
     bool isRoot = false;   // Is this the root docshell
     bool isSubFrame = false;  // Is this a subframe navigation?
 
     nsCOMPtr<nsIDocShellTreeItem> root;
 
     GetSameTypeRootTreeItem(getter_AddRefs(root));
     if (root.get() == static_cast<nsIDocShellTreeItem *>(this)) 
     {
@@ -2273,16 +2278,25 @@ nsDocShell::SetPrivateBrowsing(bool aUse
                 obs->PrivateModeChanged(aUsePrivateBrowsing);
             }
         }
     }
     return NS_OK;
 }
 
 NS_IMETHODIMP
+nsDocShell::GetHasLoadedNonBlankURI(bool* aResult)
+{
+    NS_ENSURE_ARG_POINTER(aResult);
+
+    *aResult = mHasLoadedNonBlankURI;
+    return NS_OK;
+}
+
+NS_IMETHODIMP
 nsDocShell::GetUseRemoteTabs(bool* aUseRemoteTabs)
 {
     NS_ENSURE_ARG_POINTER(aUseRemoteTabs);
 
     *aUseRemoteTabs = mUseRemoteTabs;
     return NS_OK;
 }
 
--- a/docshell/base/nsDocShell.h
+++ b/docshell/base/nsDocShell.h
@@ -910,16 +910,17 @@ protected:
     
     // @see nsIDocShellHistory::createdDynamically
     bool                       mDynamicallyCreated;
 #ifdef DEBUG
     bool                       mInEnsureScriptEnv;
 #endif
     bool                       mAffectPrivateSessionLifetime;
     bool                       mInvisible;
+    bool                       mHasLoadedNonBlankURI;
     uint64_t                   mHistoryID;
     uint32_t                   mDefaultLoadFlags;
 
     static nsIURIFixup *sURIFixup;
 
     nsRefPtr<nsDOMNavigationTiming> mTiming;
 
     // Are we a regular frame, a browser frame, or an app frame?
--- a/docshell/base/nsIDocShell.idl
+++ b/docshell/base/nsIDocShell.idl
@@ -49,17 +49,17 @@ interface nsIWebBrowserPrint;
 interface nsIVariant;
 interface nsIPrivacyTransitionObserver;
 interface nsIReflowObserver;
 interface nsIScrollObserver;
 interface nsITabParent;
  
 typedef unsigned long nsLoadFlags;
 
-[scriptable, builtinclass, uuid(2b8e4a50-7744-454d-a05b-debead8070fe)]
+[scriptable, builtinclass, uuid(23157a63-26fd-44a0-a0f9-fdc64dcc004c)]
 interface nsIDocShell : nsIDocShellTreeItem
 {
   /**
    * Loads a given URI.  This will give priority to loading the requested URI
    * in the object implementing	this interface.  If it can't be loaded here
    * however, the URL dispatcher will go through its normal process of content
    * loading.
    *
@@ -1012,9 +1012,16 @@ interface nsIDocShell : nsIDocShellTreeI
    * See the documentation for setOpener and getOpener about why we
    * don't use attribute here instead.
    */
   [noscript,notxpcom,nostdcall] void setOpenedRemote(in nsITabParent aOpenedRemote);
   [noscript,notxpcom,nostdcall] nsITabParent getOpenedRemote();
 
   // URLSearchParams for the window.location is owned by the docShell.
   [noscript,notxpcom] URLSearchParams getURLSearchParams();
+
+  /**
+   * This attribute determines whether a document which is not about:blank has
+   * already be loaded by this docShell.
+   */
+  [infallible] readonly attribute boolean hasLoadedNonBlankURI;
+
 };
--- a/dom/browser-element/BrowserElementChild.js
+++ b/dom/browser-element/BrowserElementChild.js
@@ -51,8 +51,15 @@ if (!('BrowserElementIsPreloaded' in thi
 }
 
 var BrowserElementIsReady = true;
 
 let infos = sendSyncMessage('browser-element-api:call',
                             { 'msg_name': 'hello' })[0];
 docShell.QueryInterface(Ci.nsIDocShellTreeItem).name = infos.name;
 docShell.setFullscreenAllowed(infos.fullscreenAllowed);
+if (infos.isPrivate) {
+  if (docShell.hasLoadedNonBlankURI) {
+    Cu.reportError("We should not switch to Private Browsing after loading a document.");
+  } else {
+    docShell.QueryInterface(Ci.nsILoadContext).usePrivateBrowsing = true;
+  }
+}
--- a/dom/browser-element/BrowserElementParent.cpp
+++ b/dom/browser-element/BrowserElementParent.cpp
@@ -71,16 +71,24 @@ CreateIframe(Element* aOpenerFrameElemen
                              aName, /* aNotify = */ false);
 
   // Indicate whether the iframe is should be remote.
   popupFrameElement->SetAttr(kNameSpaceID_None, nsGkAtoms::Remote,
                              aRemote ? NS_LITERAL_STRING("true") :
                                        NS_LITERAL_STRING("false"),
                              /* aNotify = */ false);
 
+  // Copy the opener frame's mozprivatebrowsing attribute to the popup frame.
+  nsAutoString mozprivatebrowsing;
+  if (aOpenerFrameElement->GetAttr(kNameSpaceID_None, nsGkAtoms::mozprivatebrowsing,
+                                   mozprivatebrowsing)) {
+    popupFrameElement->SetAttr(kNameSpaceID_None, nsGkAtoms::mozprivatebrowsing,
+                               mozprivatebrowsing, /* aNotify = */ false);
+  }
+
   return popupFrameElement.forget();
 }
 
 bool
 DispatchCustomDOMEvent(Element* aFrameElement, const nsAString& aEventName,
                        JSContext* cx, JS::Handle<JS::Value> aDetailValue,
                        nsEventStatus *aStatus)
 {
--- a/dom/browser-element/BrowserElementParent.jsm
+++ b/dom/browser-element/BrowserElementParent.jsm
@@ -384,17 +384,18 @@ BrowserElementParent.prototype = {
       this._domRequestReady = true;
       this._runPendingAPICall();
     }
 
     return {
       name: this._frameElement.getAttribute('name'),
       fullscreenAllowed:
         this._frameElement.hasAttribute('allowfullscreen') ||
-        this._frameElement.hasAttribute('mozallowfullscreen')
+        this._frameElement.hasAttribute('mozallowfullscreen'),
+      isPrivate: this._frameElement.hasAttribute('mozprivatebrowsing')
     };
   },
 
   _fireCtxMenuEvent: function(data) {
     let detail = data.json;
     let evtName = detail.msg_name;
 
     debug('fireCtxMenuEventFromMsg: ' + evtName + ' ' + detail);