Bug 1353440 - Annotate background hang reports which occur while the user is interacting with the browser, r=ehsan

MozReview-Commit-ID: CSO0K5wiK5H
This commit is contained in:
Michael Layzell 2017-04-24 16:27:35 -04:00
Родитель fd01a9ec9f
Коммит bbb295c668
3 изменённых файлов: 117 добавлений и 5 удалений

Просмотреть файл

@ -219,6 +219,7 @@
#include "mozilla/dom/TabGroup.h"
#include "nsIWebNavigationInfo.h"
#include "nsPluginHost.h"
#include "mozilla/HangAnnotations.h"
#include "nsIBidiKeyboard.h"
@ -303,6 +304,9 @@ bool nsContentUtils::sRequestIdleCallbackEnabled = false;
int32_t nsContentUtils::sPrivacyMaxInnerWidth = 1000;
int32_t nsContentUtils::sPrivacyMaxInnerHeight = 1000;
nsContentUtils::UserInteractionObserver*
nsContentUtils::sUserInteractionObserver = nullptr;
uint32_t nsContentUtils::sHandlingInputTimeout = 1000;
uint32_t nsContentUtils::sCookiesLifetimePolicy = nsICookieService::ACCEPT_NORMALLY;
@ -494,6 +498,32 @@ private:
} // namespace
/**
* This class is used to determine whether or not the user is currently
* interacting with the browser. It listens to observer events to toggle the
* value of the sUserActive static.
*
* This class is an internal implementation detail.
* nsContentUtils::GetUserIsInteracting() should be used to access current
* user interaction status.
*/
class nsContentUtils::UserInteractionObserver final : public nsIObserver
, public HangMonitor::Annotator
{
public:
NS_DECL_ISUPPORTS
NS_DECL_NSIOBSERVER
void Init();
void Shutdown();
virtual void AnnotateHang(HangMonitor::HangAnnotations& aAnnotations) override;
static Atomic<bool> sUserActive;
private:
~UserInteractionObserver() {}
};
/* static */
TimeDuration
nsContentUtils::HandlingUserInputTimeout()
@ -663,6 +693,10 @@ nsContentUtils::Init()
}
uuidGenerator.forget(&sUUIDGenerator);
RefPtr<UserInteractionObserver> uio = new UserInteractionObserver();
uio->Init();
uio.forget(&sUserInteractionObserver);
sInitialized = true;
return NS_OK;
@ -2029,6 +2063,11 @@ nsContentUtils::Shutdown()
NS_IF_RELEASE(sSameOriginChecker);
if (sUserInteractionObserver) {
sUserInteractionObserver->Shutdown();
NS_RELEASE(sUserInteractionObserver);
}
HTMLInputElement::Shutdown();
nsMappedAttributes::Shutdown();
}
@ -10345,5 +10384,71 @@ nsContentUtils::GenerateTabId()
uint64_t tabBits = tabId & ((uint64_t(1) << kTabIdTabBits) - 1);
return (processBits << kTabIdTabBits) | tabBits;
}
/* static */ bool
nsContentUtils::GetUserIsInteracting()
{
return UserInteractionObserver::sUserActive;
}
static const char* kUserInteractionInactive = "user-interaction-inactive";
static const char* kUserInteractionActive = "user-interaction-active";
void
nsContentUtils::UserInteractionObserver::Init()
{
// Listen for the observer messages from EventStateManager which are telling
// us whether or not the user is interacting.
nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
obs->AddObserver(this, kUserInteractionInactive, false);
obs->AddObserver(this, kUserInteractionActive, false);
// Register ourselves as an annotator for the Background Hang Reporter, so
// that hang stacks are annotated with whether or not the user was
// interacting with the browser when the hang occurred.
HangMonitor::RegisterAnnotator(*this);
}
void
nsContentUtils::UserInteractionObserver::Shutdown()
{
nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
if (obs) {
obs->RemoveObserver(this, kUserInteractionInactive);
obs->RemoveObserver(this, kUserInteractionActive);
}
HangMonitor::UnregisterAnnotator(*this);
}
/**
* NB: This function is always called by the HangMonitor thread.
* Plan accordingly
*/
void
nsContentUtils::UserInteractionObserver::AnnotateHang(HangMonitor::HangAnnotations& aAnnotations)
{
// NOTE: Only annotate the hang report if the user is known to be interacting.
if (sUserActive) {
aAnnotations.AddAnnotation(NS_LITERAL_STRING("UserInteracting"), true);
}
}
NS_IMETHODIMP
nsContentUtils::UserInteractionObserver::Observe(nsISupports* aSubject,
const char* aTopic,
const char16_t* aData)
{
if (!strcmp(aTopic, kUserInteractionInactive)) {
sUserActive = false;
} else if (!strcmp(aTopic, kUserInteractionActive)) {
sUserActive = true;
} else {
NS_WARNING("Unexpected observer notification");
}
return NS_OK;
}
Atomic<bool> nsContentUtils::UserInteractionObserver::sUserActive(false);
NS_IMPL_ISUPPORTS(nsContentUtils::UserInteractionObserver, nsIObserver)

Просмотреть файл

@ -2927,6 +2927,13 @@ public:
static bool
SkipCursorMoveForSameValueSet() { return sSkipCursorMoveForSameValueSet; }
/**
* Determine whether or not the user is currently interacting with the web
* browser. This method is safe to call from off of the main thread.
*/
static bool
GetUserIsInteracting();
private:
static bool InitializeEventTable();
@ -3059,6 +3066,9 @@ private:
static int32_t sPrivacyMaxInnerWidth;
static int32_t sPrivacyMaxInnerHeight;
class UserInteractionObserver;
static UserInteractionObserver* sUserInteractionObserver;
static nsHtml5StringParser* sHTMLFragmentParser;
static nsIParser* sXMLFragmentParser;
static nsIFragmentContentSink* sXMLFragmentSink;

Просмотреть файл

@ -189,7 +189,6 @@ static bool sNeedsFullGC = false;
static bool sNeedsGCAfterCC = false;
static bool sIncrementalCC = false;
static bool sDidPaintAfterPreviousICCSlice = false;
static bool sUserActive = false;
static int32_t sActiveIntersliceGCBudget = 0; // ms;
static nsScriptNameSpaceManager *gNameSpaceManager;
@ -350,12 +349,10 @@ nsJSEnvironmentObserver::Observe(nsISupports* aSubject, const char* aTopic,
}
}
} else if (!nsCRT::strcmp(aTopic, "user-interaction-inactive")) {
sUserActive = false;
if (sCompactOnUserInactive) {
nsJSContext::PokeShrinkingGC();
}
} else if (!nsCRT::strcmp(aTopic, "user-interaction-active")) {
sUserActive = true;
nsJSContext::KillShrinkingGCTimer();
if (sIsCompactingOnUserInactive) {
JS::AbortIncrementalGC(sContext);
@ -1744,7 +1741,7 @@ InterSliceGCTimerFired(nsITimer *aTimer, void *aClosure)
{
nsJSContext::KillInterSliceGCTimer();
bool e10sParent = XRE_IsParentProcess() && BrowserTabsRemoteAutostart();
int64_t budget = e10sParent && sUserActive && sActiveIntersliceGCBudget ?
int64_t budget = e10sParent && nsContentUtils::GetUserIsInteracting() && sActiveIntersliceGCBudget ?
sActiveIntersliceGCBudget : NS_INTERSLICE_GC_BUDGET;
nsJSContext::GarbageCollectNow(JS::gcreason::INTER_SLICE_GC,
nsJSContext::IncrementalGC,