Bug 1496722 - Make nsIDocShellTreeItem.itemType readonly. r=peterv
authorAndreas Farre <farre@mozilla.com>
Thu, 08 Nov 2018 21:58:58 +0000
changeset 445252 2c428c8fc56826581f8cc72df1491b098e5c89ee
parent 445251 50861e73409e37b15c5051a20ac40d39db6752b6
child 445253 412a0c8ee8c479e0b29e2ca9540c7c7a20876168
push id72654
push userafarre@mozilla.com
push dateFri, 09 Nov 2018 01:18:42 +0000
treeherderautoland@2c428c8fc568 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerspeterv
bugs1496722
milestone65.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 1496722 - Make nsIDocShellTreeItem.itemType readonly. r=peterv Differential Revision: https://phabricator.services.mozilla.com/D7900
docshell/base/nsDocShell.cpp
docshell/base/nsDocShell.h
docshell/base/nsIDocShellTreeItem.idl
dom/ipc/TabChild.cpp
toolkit/components/browser/nsWebBrowser.cpp
toolkit/components/browser/nsWebBrowser.h
xpfe/appshell/nsAppShellService.cpp
--- a/docshell/base/nsDocShell.cpp
+++ b/docshell/base/nsDocShell.cpp
@@ -306,30 +306,31 @@ DecreasePrivateDocShellCount()
 
     nsCOMPtr<nsIObserverService> obsvc = services::GetObserverService();
     if (obsvc) {
       obsvc->NotifyObservers(nullptr, "last-pb-context-exited", nullptr);
     }
   }
 }
 
-nsDocShell::nsDocShell()
+nsDocShell::nsDocShell(BrowsingContext* aBrowsingContext)
   : nsDocLoader()
   , mContentWindowID(NextWindowID())
+  , mBrowsingContext(aBrowsingContext)
   , mForcedCharset(nullptr)
   , mParentCharset(nullptr)
   , mTreeOwner(nullptr)
   , mChromeEventHandler(nullptr)
   , mDefaultScrollbarPref(Scrollbar_Auto, Scrollbar_Auto)
   , mCharsetReloadState(eCharsetReloadInit)
   , mOrientationLock(hal::eScreenOrientation_None)
   , mParentCharsetSource(0)
   , mMarginWidth(-1)
   , mMarginHeight(-1)
-  , mItemType(typeContent)
+  , mItemType(aBrowsingContext->IsContent() ? typeContent : typeChrome)
   , mPreviousEntryIndex(-1)
   , mLoadedEntryIndex(-1)
   , mChildOffset(0)
   , mSandboxFlags(0)
   , mBusyFlags(BUSY_FLAGS_NONE)
   , mAppType(nsIDocShell::APP_TYPE_UNKNOWN)
   , mLoadType(0)
   , mDefaultLoadFlags(nsIRequest::LOAD_NORMAL)
@@ -356,17 +357,17 @@ nsDocShell::nsDocShell()
   , mAllowDNSPrefetch(true)
   , mAllowWindowControl(true)
   , mAllowContentRetargeting(true)
   , mAllowContentRetargetingOnChildren(true)
   , mUseErrorPages(false)
   , mUseStrictSecurityChecks(false)
   , mObserveErrorPages(true)
   , mCSSErrorReportingEnabled(false)
-  , mAllowAuth(true)
+  , mAllowAuth(mItemType == typeContent)
   , mAllowKeywordFixup(false)
   , mIsOffScreenBrowser(false)
   , mIsActive(true)
   , mDisableMetaRefreshWhenInactive(false)
   , mIsAppTab(false)
   , mUseGlobalHistory(false)
   , mUseRemoteTabs(false)
   , mUseTrackingProtection(false)
@@ -455,18 +456,17 @@ nsDocShell::~nsDocShell()
 }
 
 /* static */ already_AddRefed<nsDocShell>
 nsDocShell::Create(BrowsingContext* aBrowsingContext)
 {
   MOZ_ASSERT(aBrowsingContext, "DocShell without a BrowsingContext!");
 
   nsresult rv;
-  RefPtr<nsDocShell> ds = new nsDocShell();
-  ds->mBrowsingContext = aBrowsingContext;
+  RefPtr<nsDocShell> ds = new nsDocShell(aBrowsingContext);
 
   // Initialize the underlying nsDocLoader.
   rv = ds->nsDocLoader::Init();
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return nullptr;
   }
 
   // Create our ContentListener
@@ -501,19 +501,16 @@ nsDocShell::Create(BrowsingContext* aBro
   // holds an nsWeakPtr to |ds|, so it's ok.
   rv = ds->AddProgressListener(ds,
                                nsIWebProgress::NOTIFY_STATE_DOCUMENT |
                                  nsIWebProgress::NOTIFY_STATE_NETWORK);
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return nullptr;
   }
 
-  // Set our DocShellTreeItem type based on our BrowsingContext
-  ds->SetItemType(aBrowsingContext->IsContent() ? typeContent : typeChrome);
-
   // If our parent is present in this process, set up our parent now.
   RefPtr<BrowsingContext> parent = aBrowsingContext->GetParent();
   if (parent && parent->GetDocShell()) {
     parent->GetDocShell()->AddChild(ds);
   }
 
   // Make |ds| the primary DocShell for the given context.
   aBrowsingContext->SetDocShell(ds);
@@ -2592,44 +2589,18 @@ nsDocShell::ItemType()
   return mItemType;
 }
 
 NS_IMETHODIMP
 nsDocShell::GetItemType(int32_t* aItemType)
 {
   NS_ENSURE_ARG_POINTER(aItemType);
 
-  *aItemType = ItemType();
-  return NS_OK;
-}
-
-NS_IMETHODIMP
-nsDocShell::SetItemType(int32_t aItemType)
-{
-  NS_ENSURE_ARG((aItemType == typeChrome) || (typeContent == aItemType));
-
-  // Only allow setting the type on root docshells.  Those would be the ones
-  // that have the docloader service as mParent or have no mParent at all.
-  nsCOMPtr<nsIDocumentLoader> docLoaderService =
-    do_GetService(NS_DOCUMENTLOADER_SERVICE_CONTRACTID);
-  NS_ENSURE_TRUE(docLoaderService, NS_ERROR_UNEXPECTED);
-
-  NS_ENSURE_STATE(!mParent || mParent == docLoaderService);
-
-  mItemType = aItemType;
-
-  // disable auth prompting for anything but content
-  mAllowAuth = mItemType == typeContent;
-
-  RefPtr<nsPresContext> presContext = nullptr;
-  GetPresContext(getter_AddRefs(presContext));
-  if (presContext) {
-    presContext->UpdateIsChrome();
-  }
-
+  MOZ_DIAGNOSTIC_ASSERT((mBrowsingContext->IsContent() ? typeContent : typeChrome) == mItemType);
+  *aItemType = mItemType;
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsDocShell::GetParent(nsIDocShellTreeItem** aParent)
 {
   if (!mParent) {
     *aParent = nullptr;
--- a/docshell/base/nsDocShell.h
+++ b/docshell/base/nsDocShell.h
@@ -404,17 +404,17 @@ private: // member functions
   friend void mozilla::TimelineConsumers::AddMarkerForDocShell(
     nsDocShell*, const char*, const TimeStamp&, MarkerTracingType,
     MarkerStackRequest);
   friend void mozilla::TimelineConsumers::AddMarkerForDocShell(
     nsDocShell*, UniquePtr<AbstractTimelineMarker>&&);
   friend void mozilla::TimelineConsumers::PopMarkers(nsDocShell*,
     JSContext*, nsTArray<dom::ProfileTimelineMarker>&);
 
-  nsDocShell();
+  explicit nsDocShell(mozilla::dom::BrowsingContext* aBrowsingContext);
 
   // Security checks to prevent frameset spoofing. See comments at
   // implementation sites.
   static bool CanAccessItem(nsIDocShellTreeItem* aTargetItem,
                             nsIDocShellTreeItem* aAccessingItem,
                             bool aConsiderOpener = true);
   static bool ValidateOrigin(nsIDocShellTreeItem* aOriginTreeItem,
                              nsIDocShellTreeItem* aTargetTreeItem);
@@ -1038,19 +1038,18 @@ private: // data members
   eCharsetReloadState mCharsetReloadState;
 
   mozilla::hal::ScreenOrientation mOrientationLock;
 
   int32_t mParentCharsetSource;
   int32_t mMarginWidth;
   int32_t mMarginHeight;
 
-  // This can either be a content docshell or a chrome docshell. After
-  // Create() is called, the type is not expected to change.
-  int32_t mItemType;
+  // This can either be a content docshell or a chrome docshell.
+  const int32_t mItemType;
 
   // Index into the nsISHEntry array, indicating the previous and current
   // entry at the time that this DocShell begins to load. Consequently
   // root docshell's indices can differ from child docshells'.
   int32_t mPreviousEntryIndex;
   int32_t mLoadedEntryIndex;
 
   // Offset in the parent's child list.
--- a/docshell/base/nsIDocShellTreeItem.idl
+++ b/docshell/base/nsIDocShellTreeItem.idl
@@ -42,17 +42,17 @@ interface nsIDocShellTreeItem : nsISuppo
 	const long typeContentWrapper=2;    // typeContentWrapper must equal 2
 	const long typeChromeWrapper=3;     // typeChromeWrapper must equal 3
 
 	const long typeAll=0x7FFFFFFF;
 
 	/*
 	The type this item is.  
 	*/
-	attribute long itemType;
+	readonly attribute long itemType;
 	[noscript,notxpcom,nostdcall] long ItemType();
 
 	/*
 	Parent DocShell.
 	*/
 	readonly attribute nsIDocShellTreeItem parent;
 
 	/*
--- a/dom/ipc/TabChild.cpp
+++ b/dom/ipc/TabChild.cpp
@@ -543,27 +543,24 @@ nsresult
 TabChild::Init()
 {
   if (!mTabGroup) {
     mTabGroup = TabGroup::GetFromActor(this);
   }
 
   // Directly create our web browser object and store it, so we can start
   // eliminating QIs.
-  mWebBrowser = new nsWebBrowser();
+  mWebBrowser = new nsWebBrowser(nsIDocShellTreeItem::typeContentWrapper);
   nsIWebBrowser* webBrowser = mWebBrowser;
 
   webBrowser->SetContainerWindow(this);
   webBrowser->SetOriginAttributes(OriginAttributesRef());
   mWebNav = do_QueryInterface(webBrowser);
   NS_ASSERTION(mWebNav, "nsWebBrowser doesn't implement nsIWebNavigation?");
 
-  nsCOMPtr<nsIDocShellTreeItem> docShellItem(do_QueryInterface(WebNavigation()));
-  docShellItem->SetItemType(nsIDocShellTreeItem::typeContentWrapper);
-
   nsCOMPtr<nsIBaseWindow> baseWindow = do_QueryInterface(WebNavigation());
   if (!baseWindow) {
     NS_ERROR("mWebNav doesn't QI to nsIBaseWindow");
     return NS_ERROR_FAILURE;
   }
 
   nsCOMPtr<nsIWidget> widget = nsIWidget::CreatePuppetWidget(this);
   mPuppetWidget = static_cast<PuppetWidget*>(widget.get());
--- a/toolkit/components/browser/nsWebBrowser.cpp
+++ b/toolkit/components/browser/nsWebBrowser.cpp
@@ -51,19 +51,19 @@
 // PSM2 includes
 #include "nsISecureBrowserUI.h"
 #include "nsXULAppAPI.h"
 
 using namespace mozilla;
 using namespace mozilla::gfx;
 using namespace mozilla::layers;
 
-nsWebBrowser::nsWebBrowser()
+nsWebBrowser::nsWebBrowser(int aItemType)
   : mInitInfo(new nsWebBrowserInitInfo())
-  , mContentType(typeContentWrapper)
+  , mContentType(aItemType)
   , mActivating(false)
   , mShouldEnableHistory(true)
   , mIsActive(true)
   , mParentNativeWindow(nullptr)
   , mProgressListener(nullptr)
   , mWidgetListenerDelegate(this)
   , mBackgroundColor(0)
   , mPersistCurrentState(nsIWebBrowserPersist::PERSIST_STATE_READY)
@@ -296,32 +296,16 @@ nsWebBrowser::GetItemType(int32_t* aItem
 {
   NS_ENSURE_ARG_POINTER(aItemType);
 
   *aItemType = ItemType();
   return NS_OK;
 }
 
 NS_IMETHODIMP
-nsWebBrowser::SetItemType(int32_t aItemType)
-{
-  NS_ENSURE_TRUE(
-    aItemType == typeContentWrapper || aItemType == typeChromeWrapper,
-    NS_ERROR_FAILURE);
-  mContentType = aItemType;
-  if (mDocShell) {
-    mDocShell->SetItemType(mContentType == typeChromeWrapper ?
-                             static_cast<int32_t>(typeChrome) :
-                             static_cast<int32_t>(typeContent));
-  }
-
-  return NS_OK;
-}
-
-NS_IMETHODIMP
 nsWebBrowser::GetParent(nsIDocShellTreeItem** aParent)
 {
   *aParent = nullptr;
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsWebBrowser::GetSameTypeParent(nsIDocShellTreeItem** aParent)
--- a/toolkit/components/browser/nsWebBrowser.h
+++ b/toolkit/components/browser/nsWebBrowser.h
@@ -82,17 +82,17 @@ public:
       nsIWidget* aWidget, mozilla::LayoutDeviceIntRegion aRegion) override;
 
   private:
     // The lifetime of WidgetListenerDelegate is bound to nsWebBrowser so we
     // just use raw pointer here.
     nsWebBrowser* mWebBrowser;
   };
 
-  nsWebBrowser();
+  explicit nsWebBrowser(int aItemType = typeContentWrapper);
 
   NS_DECL_CYCLE_COLLECTING_ISUPPORTS
   NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(nsWebBrowser, nsIWebBrowser)
 
   NS_DECL_NSIBASEWINDOW
   NS_DECL_NSIDOCSHELLTREEITEM
   NS_DECL_NSIINTERFACEREQUESTOR
   NS_DECL_NSISCROLLABLE
@@ -129,17 +129,17 @@ protected:
   nsCOMPtr<nsIBaseWindow> mDocShellAsWin;
   nsCOMPtr<nsIWebNavigation> mDocShellAsNav;
   nsCOMPtr<nsIScrollable> mDocShellAsScrollable;
   mozilla::OriginAttributes mOriginAttributes;
 
   nsCOMPtr<nsIWidget> mInternalWidget;
   nsCOMPtr<nsIWindowWatcher> mWWatch;
   nsAutoPtr<nsWebBrowserInitInfo> mInitInfo;
-  uint32_t mContentType;
+  const uint32_t mContentType;
   bool mActivating;
   bool mShouldEnableHistory;
   bool mIsActive;
   nativeWindow mParentNativeWindow;
   nsIWebProgressListener* mProgressListener;
   nsCOMPtr<nsIWebProgress> mWebProgress;
 
   nsCOMPtr<nsIPrintSettings> mPrintSettings;
--- a/xpfe/appshell/nsAppShellService.cpp
+++ b/xpfe/appshell/nsAppShellService.cpp
@@ -41,16 +41,18 @@
 #include "mozilla/StartupTimeline.h"
 #include "mozilla/intl/LocaleService.h"
 
 #include "nsEmbedCID.h"
 #include "nsIWebBrowser.h"
 #include "nsIDocShell.h"
 #include "gfxPlatform.h"
 
+#include "nsWebBrowser.h"
+
 #ifdef MOZ_INSTRUMENT_EVENT_LOOP
 #include "EventTracer.h"
 #endif
 
 using namespace mozilla;
 using mozilla::intl::LocaleService;
 
 // Default URL for the hidden window, can be overridden by a pref on Mac
@@ -474,36 +476,35 @@ WindowlessBrowser::GetDocShell(nsIDocShe
 
 
 NS_IMETHODIMP
 nsAppShellService::CreateWindowlessBrowser(bool aIsChrome, nsIWindowlessBrowser **aResult)
 {
   /* First, we create an instance of nsWebBrowser. Instances of this class have
    * an associated doc shell, which is what we're interested in.
    */
-  nsCOMPtr<nsIWebBrowser> browser = do_CreateInstance(NS_WEBBROWSER_CONTRACTID);
+  nsCOMPtr<nsIWebBrowser> browser =
+    new nsWebBrowser(aIsChrome ? nsIDocShellTreeItem::typeChromeWrapper
+                               : nsIDocShellTreeItem::typeContentWrapper);
+
   if (!browser) {
     NS_ERROR("Couldn't create instance of nsWebBrowser!");
     return NS_ERROR_FAILURE;
   }
 
   /* Next, we set the container window for our instance of nsWebBrowser. Since
    * we don't actually have a window, we instead set the container window to be
    * an instance of WebBrowserChrome2Stub, which provides a stub implementation
    * of nsIWebBrowserChrome2.
    */
   RefPtr<WebBrowserChrome2Stub> stub = new WebBrowserChrome2Stub(browser);
   browser->SetContainerWindow(stub);
 
   nsCOMPtr<nsIWebNavigation> navigation = do_QueryInterface(browser);
 
-  nsCOMPtr<nsIDocShellTreeItem> item = do_QueryInterface(navigation);
-  item->SetItemType(aIsChrome ? nsIDocShellTreeItem::typeChromeWrapper
-                              : nsIDocShellTreeItem::typeContentWrapper);
-
   /* A windowless web browser doesn't have an associated OS level window. To
    * accomplish this, we initialize the window associated with our instance of
    * nsWebBrowser with an instance of HeadlessWidget/PuppetWidget, which provide
    * a stub implementation of nsIWidget.
    */
   nsCOMPtr<nsIWidget> widget;
   if (gfxPlatform::IsHeadless()) {
     widget = nsIWidget::CreateHeadlessWidget();