Bug 1661812 - Consider to use longer timeout for slow script warning if there isn't any important user input pending r=mccr8,geckoview-reviewers,snorp

The patch converts the relevant prefs to use StaticPrefList and let's content JS in child processes to run longer if there
aren't mousedown/ups or keyevents or such. mousemove or wheel aren't considered as important events.

Differential Revision: https://phabricator.services.mozilla.com/D88668
This commit is contained in:
Olli Pettay 2020-09-01 07:21:26 +00:00
parent a7ab41b822
commit b163d0ab51
5 changed files with 64 additions and 14 deletions

View File

@ -28,6 +28,7 @@
#ifdef FUZZING
# include "mozilla/StaticPrefs_fuzzing.h"
#endif
#include "mozilla/StaticPrefs_dom.h"
#include "mozilla/StaticPrefs_browser.h"
#include "mozilla/StaticPrefs_javascript.h"
#include "mozilla/dom/ScriptSettings.h"
@ -40,6 +41,7 @@
#include "js/ContextOptions.h"
#include "js/MemoryMetrics.h"
#include "mozilla/dom/BindingUtils.h"
#include "mozilla/dom/ContentChild.h"
#include "mozilla/dom/Element.h"
#include "mozilla/dom/ScriptLoader.h"
#include "mozilla/dom/WindowBinding.h"
@ -378,18 +380,15 @@ class WatchdogManager {
}
if (mWatchdog) {
int32_t contentTime =
Preferences::GetInt(PREF_MAX_SCRIPT_RUN_TIME_CONTENT, 10);
int32_t contentTime = StaticPrefs::dom_max_script_run_time();
if (contentTime <= 0) {
contentTime = INT32_MAX;
}
int32_t chromeTime =
Preferences::GetInt(PREF_MAX_SCRIPT_RUN_TIME_CHROME, 20);
int32_t chromeTime = StaticPrefs::dom_max_chrome_script_run_time();
if (chromeTime <= 0) {
chromeTime = INT32_MAX;
}
int32_t extTime =
Preferences::GetInt(PREF_MAX_SCRIPT_RUN_TIME_EXT_CONTENT, 5);
int32_t extTime = StaticPrefs::dom_max_ext_content_script_run_time();
if (extTime <= 0) {
extTime = INT32_MAX;
}
@ -620,19 +619,20 @@ bool XPCJSContext::InterruptCallback(JSContext* cx) {
nsString addonId;
const char* prefName;
bool runningContentJS = false;
auto principal = BasePrincipal::Cast(nsContentUtils::SubjectPrincipal(cx));
bool chrome = principal->Is<SystemPrincipal>();
if (chrome) {
prefName = PREF_MAX_SCRIPT_RUN_TIME_CHROME;
limit = Preferences::GetInt(prefName, 20);
limit = StaticPrefs::dom_max_chrome_script_run_time();
} else if (auto policy = principal->ContentScriptAddonPolicy()) {
policy->GetId(addonId);
prefName = PREF_MAX_SCRIPT_RUN_TIME_EXT_CONTENT;
limit = Preferences::GetInt(prefName, 5);
limit = StaticPrefs::dom_max_ext_content_script_run_time();
} else {
prefName = PREF_MAX_SCRIPT_RUN_TIME_CONTENT;
limit = Preferences::GetInt(prefName, 10);
limit = StaticPrefs::dom_max_script_run_time();
runningContentJS = true;
}
// If there's no limit, or we're within the limit, let it go.
@ -651,6 +651,33 @@ bool XPCJSContext::InterruptCallback(JSContext* cx) {
return true;
}
int32_t limitWithoutImportantUserInput =
StaticPrefs::dom_max_script_run_time_without_important_user_input();
if (runningContentJS && XRE_IsContentProcess() && limit &&
limitWithoutImportantUserInput > limit &&
limitWithoutImportantUserInput >
self->mSlowScriptActualWait.ToSeconds()) {
// Call possibly slow PeekMessages after the other common early returns in
// this method.
ContentChild* contentChild = ContentChild::GetSingleton();
mozilla::ipc::MessageChannel* channel =
contentChild ? contentChild->GetIPCChannel() : nullptr;
if (channel) {
bool foundInputEvent = false;
channel->PeekMessages(
[&foundInputEvent](const IPC::Message& aMsg) -> bool {
if (nsContentUtils::IsMessageCriticalInputEvent(aMsg)) {
foundInputEvent = true;
return false;
}
return true;
});
if (!foundInputEvent) {
return true;
}
}
}
//
// This has gone on long enough! Time to take action. ;-)
//

View File

@ -314,7 +314,6 @@ pref("privacy.item.syncAccount", true);
pref("javascript.options.mem.high_water_mark", 32);
pref("dom.max_chrome_script_run_time", 0); // disable slow script dialog for chrome
pref("dom.max_script_run_time", 20);
// Absolute path to the devtools unix domain socket file used

View File

@ -360,6 +360,7 @@ class ContentDelegateTest : BaseSessionTest() {
private fun setHangReportTestPrefs(timeout: Int = 20000) {
sessionRule.setPrefsUntilTestEnd(mapOf(
"dom.max_script_run_time" to 1,
"dom.max_script_run_time_without_important_user_input" to 1,
"dom.max_chrome_script_run_time" to 1,
"dom.max_ext_content_script_run_time" to 1,
"dom.ipc.cpow.timeout" to 100,

View File

@ -3373,6 +3373,32 @@
value: @IS_ANDROID@
mirror: always
# The following four prefs control the maximum script run time before slow
# script warning.
- name: dom.max_script_run_time
type: int32_t
value: 10
mirror: always
- name: dom.max_script_run_time_without_important_user_input
type: int32_t
#ifdef NIGHTLY_BUILD
value: 20
#else
value: 10
#endif
mirror: always
- name: dom.max_chrome_script_run_time
type: int32_t
value: 0
mirror: always
- name: dom.max_ext_content_script_run_time
type: int32_t
value: 5
mirror: always
#---------------------------------------------------------------------------
# Prefs starting with "editor"
#---------------------------------------------------------------------------

View File

@ -2455,9 +2455,6 @@ pref("editor.resizing.preserve_ratio", true);
pref("editor.positioning.offset", 0);
pref("dom.use_watchdog", true);
pref("dom.max_chrome_script_run_time", 0);
pref("dom.max_script_run_time", 10);
pref("dom.max_ext_content_script_run_time", 5);
// Stop all scripts in a compartment when the "stop script" dialog is used.
pref("dom.global_stop_script", true);