Bug 1546736 Part 1 - Keep track of whether docshells and workers are being watched by the devtools, r=bzbarsky.
authorBrian Hackett <bhackett1024@gmail.com>
Wed, 08 May 2019 09:27:32 -1000
changeset 536099 4d7e10772f554bda346bc5f256ea2bbc9f0cd618
parent 536098 181465d74bc486fee79406d4270b2372d5aea1e5
child 536100 a2f8435fe7ed425c770d4ee59143dada8aab143b
push id2082
push userffxbld-merge
push dateMon, 01 Jul 2019 08:34:18 +0000
treeherdermozilla-release@2fb19d0466d2 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbzbarsky
bugs1546736
milestone68.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 1546736 Part 1 - Keep track of whether docshells and workers are being watched by the devtools, r=bzbarsky.
docshell/base/nsDocShell.cpp
docshell/base/nsDocShell.h
docshell/base/nsIDocShell.idl
dom/base/SerializedStackHolder.h
dom/workers/WorkerLoadInfo.cpp
dom/workers/WorkerLoadInfo.h
dom/workers/WorkerPrivate.cpp
dom/workers/WorkerPrivate.h
--- a/docshell/base/nsDocShell.cpp
+++ b/docshell/base/nsDocShell.cpp
@@ -381,17 +381,18 @@ nsDocShell::nsDocShell(BrowsingContext* 
       mSavingOldViewer(false),
       mDynamicallyCreated(false),
       mAffectPrivateSessionLifetime(true),
       mInvisible(false),
       mHasLoadedNonBlankURI(false),
       mBlankTiming(false),
       mTitleValidForCurrentURI(false),
       mIsFrame(false),
-      mSkipBrowsingContextDetachOnDestroy(false) {
+      mSkipBrowsingContextDetachOnDestroy(false),
+      mWatchedByDevtools(false) {
   mHistoryID.m0 = 0;
   mHistoryID.m1 = 0;
   mHistoryID.m2 = 0;
   AssertOriginAttributesMatchPrivateBrowsing();
 
   nsContentUtils::GenerateUUIDInPlace(mHistoryID);
 
   if (gDocShellCount++ == 0) {
@@ -13543,8 +13544,21 @@ bool nsDocShell::GetIsAttemptingToNaviga
       // This is a javascript: load that might lead to a new document,
       // hence a navigation.
       return true;
     }
   }
 
   return false;
 }
+
+NS_IMETHODIMP
+nsDocShell::GetWatchedByDevtools(bool* aWatched) {
+  NS_ENSURE_ARG(aWatched);
+  *aWatched = mWatchedByDevtools;
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+nsDocShell::SetWatchedByDevtools(bool aWatched) {
+  mWatchedByDevtools = aWatched;
+  return NS_OK;
+}
--- a/docshell/base/nsDocShell.h
+++ b/docshell/base/nsDocShell.h
@@ -1240,11 +1240,14 @@ class nsDocShell final : public nsDocLoa
   bool mTitleValidForCurrentURI : 1;
 
   bool mIsFrame : 1;
 
   // If mSkipBrowsingContextDetachOnDestroy is set to true, then when the
   // docshell is destroyed, the browsing context will not be detached. This is
   // for cases where we want to preserve the BC for future use.
   bool mSkipBrowsingContextDetachOnDestroy : 1;
+
+  // Set when activity in this docshell is being watched by the developer tools.
+  bool mWatchedByDevtools : 1;
 };
 
 #endif /* nsDocShell_h__ */
--- a/docshell/base/nsIDocShell.idl
+++ b/docshell/base/nsIDocShell.idl
@@ -1162,9 +1162,14 @@ interface nsIDocShell : nsIDocShellTreeI
    */
   Promise getContentBlockingLog();
 
   /**
    * Return whether this docshell is "attempting to navigate" in the
    * sense that's relevant to document.open.
    */
   [notxpcom, nostdcall] readonly attribute boolean isAttemptingToNavigate;
+
+  /**
+   * Whether developer tools are watching activity in this docshell.
+   */
+  [infallible] attribute boolean watchedByDevtools;
 };
--- a/dom/base/SerializedStackHolder.h
+++ b/dom/base/SerializedStackHolder.h
@@ -44,20 +44,19 @@ class SerializedStackHolder {
   // This returns null on failure, and does not leave an exception on aCx.
   JSObject* ReadStack(JSContext* aCx);
 };
 
 // Construct a stack for the current thread, which may be consumed by the net
 // monitor later on. This may be called on either the main or a worker thread.
 //
 // This always creates a stack, even if the net monitor isn't active for the
-// associated window. Ideally we would only create the stack if the net monitor
-// was active, but there doesn't seem to be an easy way to determine this.
-// The operations this is used with should be rare enough and/or have enough
-// other associated costs that the perf impact is low. See bug 1546736.
+// associated window. The net monitor will only be active if the associated
+// docshell or worker's WatchedByDevtools flag is set, so this should be checked
+// before creating the stack.
 UniquePtr<SerializedStackHolder> GetCurrentStackForNetMonitor(JSContext* aCx);
 
 // If aStackHolder is non-null, this notifies the net monitor that aStackHolder
 // is the stack from which aChannel originates. This must be called on the main
 // thread. This call is synchronous, and aChannel and aStackHolder will not be
 // used afterward. aChannel is an nsISupports object because this can be used
 // with either nsIChannel or nsIWebSocketChannel.
 void NotifyNetworkMonitorAlternateStack(nsISupports* aChannel,
--- a/dom/workers/WorkerLoadInfo.cpp
+++ b/dom/workers/WorkerLoadInfo.cpp
@@ -82,16 +82,17 @@ WorkerLoadInfoData::WorkerLoadInfoData()
     : mLoadFlags(nsIRequest::LOAD_NORMAL),
       mWindowID(UINT64_MAX),
       mReferrerPolicy(net::RP_Unset),
       mFromWindow(false),
       mEvalAllowed(false),
       mReportCSPViolations(false),
       mXHRParamsAllowed(false),
       mPrincipalIsSystem(false),
+      mWatchedByDevtools(false),
       mStorageAccess(nsContentUtils::StorageAccess::eDeny),
       mFirstPartyStorageAccessGranted(false),
       mServiceWorkersTestingInWindow(false),
       mSecureContext(eNotSet) {}
 
 nsresult WorkerLoadInfo::SetPrincipalsOnMainThread(
     nsIPrincipal* aPrincipal, nsIPrincipal* aStoragePrincipal,
     nsILoadGroup* aLoadGroup) {
--- a/dom/workers/WorkerLoadInfo.h
+++ b/dom/workers/WorkerLoadInfo.h
@@ -113,16 +113,17 @@ struct WorkerLoadInfoData {
   uint64_t mWindowID;
 
   net::ReferrerPolicy mReferrerPolicy;
   bool mFromWindow;
   bool mEvalAllowed;
   bool mReportCSPViolations;
   bool mXHRParamsAllowed;
   bool mPrincipalIsSystem;
+  bool mWatchedByDevtools;
   nsContentUtils::StorageAccess mStorageAccess;
   bool mFirstPartyStorageAccessGranted;
   bool mServiceWorkersTestingInWindow;
   OriginAttributes mOriginAttributes;
 
   enum {
     eNotSet,
     eInsecureContext,
--- a/dom/workers/WorkerPrivate.cpp
+++ b/dom/workers/WorkerPrivate.cpp
@@ -2361,16 +2361,17 @@ nsresult WorkerPrivate::GetLoadInfo(JSCo
     loadInfo.mDomain = aParent->Domain();
     loadInfo.mFromWindow = aParent->IsFromWindow();
     loadInfo.mWindowID = aParent->WindowID();
     loadInfo.mStorageAccess = aParent->StorageAccess();
     loadInfo.mOriginAttributes = aParent->GetOriginAttributes();
     loadInfo.mServiceWorkersTestingInWindow =
         aParent->ServiceWorkersTestingInWindow();
     loadInfo.mParentController = aParent->GetController();
+    loadInfo.mWatchedByDevtools = aParent->IsWatchedByDevtools();
   } else {
     AssertIsOnMainThread();
 
     // Make sure that the IndexedDatabaseManager is set up
     Unused << NS_WARN_IF(!IndexedDatabaseManager::GetOrCreate());
 
     nsIScriptSecurityManager* ssm = nsContentUtils::GetSecurityManager();
     MOZ_ASSERT(ssm);
@@ -2481,16 +2482,21 @@ nsresult WorkerPrivate::GetLoadInfo(JSCo
 
       uint32_t perm;
       rv = permMgr->TestPermissionFromPrincipal(
           loadInfo.mLoadingPrincipal, NS_LITERAL_CSTRING("systemXHR"), &perm);
       NS_ENSURE_SUCCESS(rv, rv);
 
       loadInfo.mXHRParamsAllowed = perm == nsIPermissionManager::ALLOW_ACTION;
 
+      nsIDocShell* docShell = globalWindow->GetDocShell();
+      if (docShell) {
+        loadInfo.mWatchedByDevtools = docShell->GetWatchedByDevtools();
+      }
+
       loadInfo.mFromWindow = true;
       loadInfo.mWindowID = globalWindow->WindowID();
       loadInfo.mStorageAccess =
           nsContentUtils::StorageAllowedForWindow(globalWindow);
       loadInfo.mCookieSettings = document->CookieSettings();
       loadInfo.mOriginAttributes =
           nsContentUtils::GetOriginAttributes(document);
       loadInfo.mParentController = globalWindow->GetController();
--- a/dom/workers/WorkerPrivate.h
+++ b/dom/workers/WorkerPrivate.h
@@ -763,16 +763,20 @@ class WorkerPrivate : public RelativeTim
     return mLoadInfo.mOriginAttributes;
   }
 
   // Determine if the SW testing per-window flag is set by devtools
   bool ServiceWorkersTestingInWindow() const {
     return mLoadInfo.mServiceWorkersTestingInWindow;
   }
 
+  bool IsWatchedByDevtools() const {
+    return mLoadInfo.mWatchedByDevtools;
+  }
+
   // Determine if the worker is currently loading its top level script.
   bool IsLoadingWorkerScript() const { return mLoadingWorkerScript; }
 
   // Called by ScriptLoader to track when this worker is loading its
   // top level script.
   void SetLoadingWorkerScript(bool aLoadingWorkerScript) {
     // any thread
     mLoadingWorkerScript = aLoadingWorkerScript;