mirror of
https://github.com/mozilla/gecko-dev.git
synced 2025-02-25 03:49:42 +00:00
Bug 1356334: Part 3 - Enforce a stricter slow script timeout for extension content scripts. r=billm
MozReview-Commit-ID: LLvPQn1x1Xj --HG-- extra : source : 805c568069301ae91ead5780cdc118af73907229 extra : histedit_source : b188836d1dc3ad8021bf2d0b1c89aebedf2db185%2C8c7b51c9f4af4eb5ad67811c29b56c72b43fa31d
This commit is contained in:
parent
5e014eb540
commit
faa8815613
@ -54,6 +54,7 @@ const char* mozilla::dom::ContentPrefs::gInitPrefs[] = {
|
||||
"dom.ipc.processPriorityManager.backgroundPerceivableGracePeriodMS",
|
||||
"dom.ipc.useNativeEventProcessing.content",
|
||||
"dom.max_chrome_script_run_time",
|
||||
"dom.max_ext_content_script_run_time",
|
||||
"dom.max_script_run_time",
|
||||
"dom.mozBrowserFramesEnabled",
|
||||
"dom.performance.enable_notify_performance_timing",
|
||||
|
@ -61,6 +61,8 @@
|
||||
#include "nsIInputStream.h"
|
||||
#include "nsIXULRuntime.h"
|
||||
#include "nsJSPrincipals.h"
|
||||
#include "ExpandedPrincipal.h"
|
||||
#include "SystemPrincipal.h"
|
||||
|
||||
#ifdef MOZ_CRASHREPORTER
|
||||
#include "nsExceptionHandler.h"
|
||||
@ -227,6 +229,7 @@ class Watchdog
|
||||
|
||||
#define PREF_MAX_SCRIPT_RUN_TIME_CONTENT "dom.max_script_run_time"
|
||||
#define PREF_MAX_SCRIPT_RUN_TIME_CHROME "dom.max_chrome_script_run_time"
|
||||
#define PREF_MAX_SCRIPT_RUN_TIME_EXT_CONTENT "dom.max_ext_content_script_run_time"
|
||||
|
||||
class WatchdogManager : public nsIObserver
|
||||
{
|
||||
@ -247,6 +250,7 @@ class WatchdogManager : public nsIObserver
|
||||
mozilla::Preferences::AddStrongObserver(this, "dom.use_watchdog");
|
||||
mozilla::Preferences::AddStrongObserver(this, PREF_MAX_SCRIPT_RUN_TIME_CONTENT);
|
||||
mozilla::Preferences::AddStrongObserver(this, PREF_MAX_SCRIPT_RUN_TIME_CHROME);
|
||||
mozilla::Preferences::AddStrongObserver(this, PREF_MAX_SCRIPT_RUN_TIME_EXT_CONTENT);
|
||||
}
|
||||
|
||||
protected:
|
||||
@ -266,6 +270,7 @@ class WatchdogManager : public nsIObserver
|
||||
mozilla::Preferences::RemoveObserver(this, "dom.use_watchdog");
|
||||
mozilla::Preferences::RemoveObserver(this, PREF_MAX_SCRIPT_RUN_TIME_CONTENT);
|
||||
mozilla::Preferences::RemoveObserver(this, PREF_MAX_SCRIPT_RUN_TIME_CHROME);
|
||||
mozilla::Preferences::RemoveObserver(this, PREF_MAX_SCRIPT_RUN_TIME_EXT_CONTENT);
|
||||
}
|
||||
|
||||
NS_IMETHOD Observe(nsISupports* aSubject, const char* aTopic,
|
||||
@ -341,7 +346,10 @@ class WatchdogManager : public nsIObserver
|
||||
int32_t chromeTime = Preferences::GetInt(PREF_MAX_SCRIPT_RUN_TIME_CHROME, 20);
|
||||
if (chromeTime <= 0)
|
||||
chromeTime = INT32_MAX;
|
||||
mWatchdog->SetMinScriptRunTimeSeconds(std::min(contentTime, chromeTime));
|
||||
int32_t extTime = Preferences::GetInt(PREF_MAX_SCRIPT_RUN_TIME_EXT_CONTENT, 5);
|
||||
if (extTime <= 0)
|
||||
extTime = INT32_MAX;
|
||||
mWatchdog->SetMinScriptRunTimeSeconds(std::min({contentTime, chromeTime, extTime}));
|
||||
}
|
||||
}
|
||||
|
||||
@ -463,6 +471,33 @@ XPCJSContext::ActivityCallback(void* arg, bool active)
|
||||
self->mWatchdogManager->RecordContextActivity(active);
|
||||
}
|
||||
|
||||
static inline bool
|
||||
IsWebExtensionPrincipal(nsIPrincipal* principal, nsAString& addonId)
|
||||
{
|
||||
return (NS_SUCCEEDED(principal->GetAddonId(addonId)) &&
|
||||
!addonId.IsEmpty());
|
||||
}
|
||||
|
||||
static bool
|
||||
IsWebExtensionContentScript(BasePrincipal* principal, nsAString& addonId)
|
||||
{
|
||||
if (!principal->Is<ExpandedPrincipal>()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
auto expanded = principal->As<ExpandedPrincipal>();
|
||||
|
||||
nsTArray<nsCOMPtr<nsIPrincipal>>* principals;
|
||||
expanded->GetWhiteList(&principals);
|
||||
for (auto prin : *principals) {
|
||||
if (IsWebExtensionPrincipal(prin, addonId)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// static
|
||||
bool
|
||||
XPCJSContext::InterruptCallback(JSContext* cx)
|
||||
@ -492,10 +527,23 @@ XPCJSContext::InterruptCallback(JSContext* cx)
|
||||
// returning to the event loop. See how long it's been, and what the limit
|
||||
// is.
|
||||
TimeDuration duration = TimeStamp::NowLoRes() - self->mSlowScriptCheckpoint;
|
||||
bool chrome = nsContentUtils::IsSystemCaller(cx);
|
||||
const char* prefName = chrome ? PREF_MAX_SCRIPT_RUN_TIME_CHROME
|
||||
: PREF_MAX_SCRIPT_RUN_TIME_CONTENT;
|
||||
int32_t limit = Preferences::GetInt(prefName, chrome ? 20 : 10);
|
||||
int32_t limit;
|
||||
|
||||
nsString addonId;
|
||||
const char* prefName;
|
||||
|
||||
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);
|
||||
} else if (IsWebExtensionContentScript(principal, addonId)) {
|
||||
prefName = PREF_MAX_SCRIPT_RUN_TIME_EXT_CONTENT;
|
||||
limit = Preferences::GetInt(prefName, 5);
|
||||
} else {
|
||||
prefName = PREF_MAX_SCRIPT_RUN_TIME_CONTENT;
|
||||
limit = Preferences::GetInt(prefName, 10);
|
||||
}
|
||||
|
||||
// If there's no limit, or we're within the limit, let it go.
|
||||
if (limit == 0 || duration.ToSeconds() < limit / 2.0)
|
||||
|
@ -324,10 +324,18 @@ PrincipalImmuneToScriptPolicy(nsIPrincipal* aPrincipal)
|
||||
if (nsXPConnect::SecurityManager()->IsSystemPrincipal(aPrincipal))
|
||||
return true;
|
||||
|
||||
auto principal = BasePrincipal::Cast(aPrincipal);
|
||||
|
||||
// ExpandedPrincipal gets a free pass.
|
||||
nsCOMPtr<nsIExpandedPrincipal> ep = do_QueryInterface(aPrincipal);
|
||||
if (ep)
|
||||
if (principal->Is<ExpandedPrincipal>()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// WebExtension principals get a free pass.
|
||||
nsString addonId;
|
||||
if (IsWebExtensionPrincipal(principal, addonId)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Check whether our URI is an "about:" URI that allows scripts. If it is,
|
||||
// we need to allow JS to run.
|
||||
@ -335,14 +343,6 @@ PrincipalImmuneToScriptPolicy(nsIPrincipal* aPrincipal)
|
||||
aPrincipal->GetURI(getter_AddRefs(principalURI));
|
||||
MOZ_ASSERT(principalURI);
|
||||
|
||||
// WebExtension principals gets a free pass.
|
||||
nsString addonId;
|
||||
aPrincipal->GetAddonId(addonId);
|
||||
bool isWebExtension = !addonId.IsEmpty();
|
||||
if (isWebExtension) {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool isAbout;
|
||||
nsresult rv = principalURI->SchemeIs("about", &isAbout);
|
||||
if (NS_SUCCEEDED(rv) && isAbout) {
|
||||
|
@ -3167,6 +3167,7 @@ pref("editor.positioning.offset", 0);
|
||||
pref("dom.use_watchdog", true);
|
||||
pref("dom.max_chrome_script_run_time", 20);
|
||||
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);
|
||||
|
@ -61,6 +61,7 @@ skip-if = os == 'android' # Android does not support multiple windows.
|
||||
[test_ext_content_security_policy.html]
|
||||
[test_ext_contentscript_api_injection.html]
|
||||
[test_ext_contentscript_async_loading.html]
|
||||
skip-if = os == 'android' && debug # The generated script takes too long to load on Android debug
|
||||
[test_ext_contentscript_cache.html]
|
||||
skip-if = (os == 'linux' && debug) || (toolkit == 'android' && debug) # bug 1348241
|
||||
[test_ext_contentscript_canvas.html]
|
||||
|
Loading…
x
Reference in New Issue
Block a user