From b050d571cc770a06df763d2fca99d905e8cbfbc9 Mon Sep 17 00:00:00 2001 From: Marco Castelluccio Date: Tue, 16 Jan 2024 00:28:15 +0000 Subject: [PATCH] Bug 1861445 - Add the runtime.onPerformanceWarning WebExtension event r=zombie When an extension's content script is very slow and causes a webpage to hang noticeably, a warning banner is displayed to the user. It would be useful to also notify the extension developer when that happens, so that they can address the issue. Let's add a new event runtime.onPerformanceWarning that can be dispatched when the browser needs to warn an extension of runtime performance issues. For now, let's just dispatch that event when the slow extension warning banner is displayed to the user. See also https://github.com/w3c/webextensions/issues/456 Differential Revision: https://phabricator.services.mozilla.com/D194708 UltraBlame original commit: 199b3c24b8b43b8053831d7c287bbe83e43037c4 --- .../extensions/test/browser/browser.toml | 7 + ...rowser_ext_runtime_onPerformanceWarning.js | 575 ++++++++++++++++++ .../extensions/parent/ext-runtime.js | 216 +++++++ .../extensions/schemas/runtime.json | 315 ++++++++++ .../test/mochitest/test_ext_all_apis.js | 15 + 5 files changed, 1128 insertions(+) create mode 100644 browser/components/extensions/test/browser/browser_ext_runtime_onPerformanceWarning.js diff --git a/browser/components/extensions/test/browser/browser.toml b/browser/components/extensions/test/browser/browser.toml index 13dba2e334c4b..4cf81c94cf45e 100644 --- a/browser/components/extensions/test/browser/browser.toml +++ b/browser/components/extensions/test/browser/browser.toml @@ -2025,6 +2025,13 @@ js ] [ " +browser_ext_runtime_onPerformanceWarning +. +js +" +] +[ +" browser_ext_runtime_openOptionsPage . js diff --git a/browser/components/extensions/test/browser/browser_ext_runtime_onPerformanceWarning.js b/browser/components/extensions/test/browser/browser_ext_runtime_onPerformanceWarning.js new file mode 100644 index 0000000000000..e4099a92cc0cc --- /dev/null +++ b/browser/components/extensions/test/browser/browser_ext_runtime_onPerformanceWarning.js @@ -0,0 +1,575 @@ +" +use +strict +" +; +const +{ +Management +: +{ +global +: +{ +tabTracker +} +} +} += +ChromeUtils +. +importESModule +( +" +resource +: +/ +/ +gre +/ +modules +/ +Extension +. +sys +. +mjs +" +) +; +const +{ +ExtensionUtils +: +{ +promiseObserved +} +} += +ChromeUtils +. +importESModule +( +" +resource +: +/ +/ +gre +/ +modules +/ +ExtensionUtils +. +sys +. +mjs +" +) +; +class +TestHangReport +{ +constructor +( +addonId +scriptBrowser +) +{ +this +. +addonId += +addonId +; +this +. +scriptBrowser += +scriptBrowser +; +this +. +QueryInterface += +ChromeUtils +. +generateQI +( +[ +" +nsIHangReport +" +] +) +; +} +} +function +dispatchHangReport +( +extensionId +scriptBrowser +) +{ +const +hangObserved += +promiseObserved +( +" +process +- +hang +- +report +" +) +; +Services +. +obs +. +notifyObservers +( +new +TestHangReport +( +extensionId +scriptBrowser +) +" +process +- +hang +- +report +" +) +; +return +hangObserved +; +} +function +background +( +) +{ +let +onPerformanceWarningDetails += +null +; +browser +. +runtime +. +onPerformanceWarning +. +addListener +( +details += +> +{ +onPerformanceWarningDetails += +details +; +} +) +; +browser +. +test +. +onMessage +. +addListener +( +message += +> +{ +if +( +message += += += +" +get +- +on +- +performance +- +warning +- +details +" +) +{ +browser +. +test +. +sendMessage +( +" +on +- +performance +- +warning +- +details +" +onPerformanceWarningDetails +) +; +onPerformanceWarningDetails += +null +; +} +} +) +; +} +async +function +expectOnPerformanceWarningDetails +( +extension +expectedOnPerformanceWarningDetails +) +{ +extension +. +sendMessage +( +" +get +- +on +- +performance +- +warning +- +details +" +) +; +let +actualOnPerformanceWarningDetails += +await +extension +. +awaitMessage +( +" +on +- +performance +- +warning +- +details +" +) +; +Assert +. +deepEqual +( +actualOnPerformanceWarningDetails +expectedOnPerformanceWarningDetails +expectedOnPerformanceWarningDetails +? +" +runtime +. +onPerformanceWarning +fired +with +correct +details +" +: +" +runtime +. +onPerformanceWarning +didn +' +t +fire +" +) +; +} +add_task +( +async +function +test_should_fire_on_process_hang_report +( +) +{ +const +description += +" +Slow +extension +content +script +caused +a +page +hang +user +was +warned +. +" +; +const +extension += +ExtensionTestUtils +. +loadExtension +( +{ +background +} +) +; +await +extension +. +startup +( +) +; +const +tabs += +await +Promise +. +all +( +[ +BrowserTestUtils +. +openNewForegroundTab +( +gBrowser +) +BrowserTestUtils +. +openNewForegroundTab +( +gBrowser +) +] +) +; +await +expectOnPerformanceWarningDetails +( +extension +null +) +; +await +dispatchHangReport +( +extension +. +id +tabs +[ +0 +] +. +linkedBrowser +) +; +await +expectOnPerformanceWarningDetails +( +extension +{ +category +: +" +content_script +" +severity +: +" +high +" +description +tabId +: +tabTracker +. +getId +( +tabs +[ +0 +] +) +} +) +; +await +dispatchHangReport +( +" +wrong +- +addon +- +id +" +tabs +[ +0 +] +. +linkedBrowser +) +; +await +expectOnPerformanceWarningDetails +( +extension +null +) +; +await +dispatchHangReport +( +null +tabs +[ +0 +] +. +linkedBrowser +) +; +await +expectOnPerformanceWarningDetails +( +extension +null +) +; +await +dispatchHangReport +( +extension +. +id +tabs +[ +1 +] +. +linkedBrowser +) +; +await +expectOnPerformanceWarningDetails +( +extension +{ +category +: +" +content_script +" +severity +: +" +high +" +description +tabId +: +tabTracker +. +getId +( +tabs +[ +1 +] +) +} +) +; +await +dispatchHangReport +( +extension +. +id +null +) +; +await +expectOnPerformanceWarningDetails +( +extension +{ +category +: +" +content_script +" +severity +: +" +high +" +description +} +) +; +await +Promise +. +all +( +tabs +. +map +( +BrowserTestUtils +. +removeTab +) +) +; +await +extension +. +unload +( +) +; +} +) +; diff --git a/toolkit/components/extensions/parent/ext-runtime.js b/toolkit/components/extensions/parent/ext-runtime.js index 121f94d8c7ba0..ae07f453b2f32 100644 --- a/toolkit/components/extensions/parent/ext-runtime.js +++ b/toolkit/components/extensions/parent/ext-runtime.js @@ -377,6 +377,196 @@ _fire } ; } +onPerformanceWarning +( +{ +fire +} +) +{ +let +{ +extension +} += +this +; +let +observer += +( +subject +topic +) += +> +{ +let +report += +subject +. +QueryInterface +( +Ci +. +nsIHangReport +) +; +if +( +report +? +. +addonId +! += += +extension +. +id +) +{ +return +; +} +const +performanceWarningEventDetails += +{ +category +: +" +content_script +" +severity +: +" +high +" +description +: +" +Slow +extension +content +script +caused +a +page +hang +user +was +warned +. +" +} +; +let +scriptBrowser += +report +. +scriptBrowser +; +let +nativeTab += +scriptBrowser +? +. +ownerGlobal +. +gBrowser +? +. +getTabForBrowser +( +scriptBrowser +) +; +if +( +nativeTab +) +{ +performanceWarningEventDetails +. +tabId += +tabTracker +. +getId +( +nativeTab +) +; +} +fire +. +async +( +performanceWarningEventDetails +) +; +} +; +Services +. +obs +. +addObserver +( +observer +" +process +- +hang +- +report +" +) +; +return +{ +unregister +: +( +) += +> +{ +Services +. +obs +. +removeObserver +( +observer +" +process +- +hang +- +report +" +) +; +} +convert +( +_fire +context +) +{ +fire += +_fire +; +} +} +; +} } ; getAPI @@ -801,6 +991,32 @@ listener api ( ) +onPerformanceWarning +: +new +EventManager +( +{ +context +module +: +" +runtime +" +event +: +" +onPerformanceWarning +" +extensionApi +: +this +} +) +. +api +( +) reload : async diff --git a/toolkit/components/extensions/schemas/runtime.json b/toolkit/components/extensions/schemas/runtime.json index 4014aed3f2b77..4bc5ff55f48b0 100644 --- a/toolkit/components/extensions/schemas/runtime.json +++ b/toolkit/components/extensions/schemas/runtime.json @@ -1400,6 +1400,106 @@ periodic " ] } +{ +" +id +" +: +" +OnPerformanceWarningCategory +" +" +type +" +: +" +string +" +" +enum +" +: +[ +" +content_script +" +] +" +description +" +: +" +The +performance +warning +event +category +e +. +g +. +' +content_script +' +. +" +} +{ +" +id +" +: +" +OnPerformanceWarningSeverity +" +" +type +" +: +" +string +" +" +enum +" +: +[ +" +low +" +" +medium +" +" +high +" +] +" +description +" +: +" +The +performance +warning +event +severity +. +Will +be +' +high +' +for +serious +and +user +- +visible +issues +. +" +} ] " properties @@ -5691,6 +5791,221 @@ dispatched } ] } +{ +" +name +" +: +" +onPerformanceWarning +" +" +type +" +: +" +function +" +" +description +" +: +" +Fired +when +a +runtime +performance +issue +is +detected +with +the +extension +. +Observe +this +event +to +be +proactively +notified +of +runtime +performance +problems +with +the +extension +. +" +" +parameters +" +: +[ +{ +" +type +" +: +" +object +" +" +name +" +: +" +details +" +" +properties +" +: +{ +" +category +" +: +{ +" +ref +" +: +" +OnPerformanceWarningCategory +" +" +description +" +: +" +The +performance +warning +event +category +e +. +g +. +' +content_script +' +. +" +} +" +severity +" +: +{ +" +ref +" +: +" +OnPerformanceWarningSeverity +" +" +description +" +: +" +The +performance +warning +event +severity +e +. +g +. +' +high +' +. +" +} +" +tabId +" +: +{ +" +type +" +: +" +integer +" +" +optional +" +: +true +" +description +" +: +" +The +( +ref +: +tabs +. +Tab +) +that +the +performance +warning +relates +to +if +any +. +" +} +" +description +" +: +{ +" +type +" +: +" +string +" +" +description +" +: +" +An +explanation +of +what +the +warning +means +and +hopefully +how +to +address +it +. +" +} +} +} +] +} ] } ] diff --git a/toolkit/components/extensions/test/mochitest/test_ext_all_apis.js b/toolkit/components/extensions/test/mochitest/test_ext_all_apis.js index 43e5dec9dc5bf..37f89c0ce211a 100644 --- a/toolkit/components/extensions/test/mochitest/test_ext_all_apis.js +++ b/toolkit/components/extensions/test/mochitest/test_ext_all_apis.js @@ -403,6 +403,11 @@ onMessageExternal " runtime . +onPerformanceWarning +" +" +runtime +. onStartup " " @@ -436,6 +441,16 @@ runtime setUninstallURL " " +runtime +. +OnPerformanceWarningCategory +" +" +runtime +. +OnPerformanceWarningSeverity +" +" theme . getCurrent