Bug 1638097 - ServiceWorkerManager should not store registration related to temporary addons. r=asuth

This patch include a small change to ServiceWorkerManager::StoreRegistration which does early exist
and not store the registration on disk if:
- the principal is from a WebExtension
- the addon is not enabled (or was already uninstalled) by the time we got to store the registration
- the addon is temporarily installed

At the moment it should not happen, but if ServiceWorkerManager::StoreRegistration was reached too late
for some reason and the registration was meant to be stored, the service worker would still be registered
again when the addon is started again on the next browser startup and stored on disk if it was meant to.

Depends on D119529

Differential Revision: https://phabricator.services.mozilla.com/D119530
This commit is contained in:
Luca Greco 2021-07-14 14:13:00 +00:00
Родитель e1f61e1957
Коммит 0995284f7d
6 изменённых файлов: 147 добавлений и 40 удалений

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

@ -1537,6 +1537,25 @@ void ServiceWorkerManager::StoreRegistration(
return;
}
// Do not store a registration for addons that are not installed, not enabled
// or installed temporarily.
//
// If the dom.serviceWorkers.testing.persistTemporaryInstalledAddons is set
// to true, the registration for a temporary installed addon will still be
// persisted (only meant to be used to make it easier to test some particular
// scenario with a temporary installed addon which doesn't need to be signed
// to be installed on release channel builds).
if (aPrincipal->SchemeIs("moz-extension")) {
RefPtr<extensions::WebExtensionPolicy> addonPolicy =
BasePrincipal::Cast(aPrincipal)->AddonPolicy();
if (!addonPolicy || !addonPolicy->Active() ||
(addonPolicy->TemporarilyInstalled() &&
!StaticPrefs::
dom_serviceWorkers_testing_persistTemporarilyInstalledAddons())) {
return;
}
}
ServiceWorkerRegistrationData data;
nsresult rv = PopulateRegistrationData(aPrincipal, aRegistration, data);
if (NS_WARN_IF(NS_FAILED(rv))) {

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

@ -3135,6 +3135,16 @@
value: false
mirror: always
# Whether ServiceWorkerManager should persist the service worker
# registered by temporary installed extension (only meant to be used
# for testing purpose, to make it easier to test some particular scenario
# with a temporary installed addon, which doesn't need to be signed to be
# installed on release channel builds).
- name: dom.serviceWorkers.testing.persistTemporarilyInstalledAddons
type: RelaxedAtomicBool
value: false
mirror: always
- name: dom.workers.serialized-sab-access
type: RelaxedAtomicBool
value: false

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

@ -1 +1,2 @@
[test_extension_serviceworkers_purged_on_pref_disabled.py]
[test_temporary_extension_serviceworkers_not_persisted.py]

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

@ -0,0 +1,49 @@
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
from marionette_harness import MarionetteTestCase
EXT_ID = "extension-with-bg-sw@test"
EXT_DIR_PATH = "extension-with-bg-sw"
PREF_BG_SW_ENABLED = "extensions.backgroundServiceWorker.enabled"
PREF_PERSIST_TEMP_ADDONS = (
"dom.serviceWorkers.testing.persistTemporarilyInstalledAddons"
)
class MarionetteServiceWorkerTestCase(MarionetteTestCase):
def get_extension_url(self, path="/"):
with self.marionette.using_context("chrome"):
return self.marionette.execute_script(
"""
let policy = WebExtensionPolicy.getByID(arguments[0]);
return policy.getURL(arguments[1])
""",
script_args=(self.test_extension_id, path),
)
@property
def is_extension_service_worker_registered(self):
with self.marionette.using_context("chrome"):
return self.marionette.execute_script(
"""
let serviceWorkerManager = Cc["@mozilla.org/serviceworkers/manager;1"].getService(
Ci.nsIServiceWorkerManager
);
let serviceWorkers = serviceWorkerManager.getAllRegistrations();
for (let i = 0; i < serviceWorkers.length; i++) {
let sw = serviceWorkers.queryElementAt(
i,
Ci.nsIServiceWorkerRegistrationInfo
);
if (sw.scope == arguments[0]) {
return true;
}
}
return false;
""",
script_args=(self.test_extension_base_url,),
)

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

@ -4,22 +4,30 @@
from marionette_driver import Wait
from marionette_driver.addons import Addons
from marionette_harness import MarionetteTestCase
import os
import sys
EXT_ID = "extension-with-bg-sw@test"
EXT_DIR_PATH = "extension-with-bg-sw"
PREF_BG_SW_ENABLED = "extensions.backgroundServiceWorker.enabled"
# Add this directory to the import path.
sys.path.append(os.path.dirname(__file__))
from service_worker_testutils import (
MarionetteServiceWorkerTestCase,
EXT_ID,
EXT_DIR_PATH,
PREF_BG_SW_ENABLED,
PREF_PERSIST_TEMP_ADDONS,
)
class PurgeExtensionServiceWorkersOnPrefDisabled(MarionetteTestCase):
class PurgeExtensionServiceWorkersOnPrefDisabled(MarionetteServiceWorkerTestCase):
def setUp(self):
super(PurgeExtensionServiceWorkersOnPrefDisabled, self).setUp()
self.test_extension_id = EXT_ID
# Flip the "mirror: once" pref and restart Firefox to be able
# to run the extension successfully.
self.marionette.set_pref(PREF_BG_SW_ENABLED, True)
self.marionette.set_pref(PREF_PERSIST_TEMP_ADDONS, True)
self.marionette.restart(in_app=True)
def tearDown(self):
@ -46,37 +54,3 @@ class PurgeExtensionServiceWorkersOnPrefDisabled(MarionetteTestCase):
lambda _: self.is_extension_service_worker_registered,
message="Wait the extension service worker to be registered",
)
def get_extension_url(self, path="/"):
with self.marionette.using_context("chrome"):
return self.marionette.execute_script(
"""
let policy = WebExtensionPolicy.getByID(arguments[0]);
return policy.getURL(arguments[1])
""",
script_args=(self.test_extension_id, path),
)
@property
def is_extension_service_worker_registered(self):
with self.marionette.using_context("chrome"):
return self.marionette.execute_script(
"""
let serviceWorkerManager = Cc["@mozilla.org/serviceworkers/manager;1"].getService(
Ci.nsIServiceWorkerManager
);
let serviceWorkers = serviceWorkerManager.getAllRegistrations();
for (let i = 0; i < serviceWorkers.length; i++) {
let sw = serviceWorkers.queryElementAt(
i,
Ci.nsIServiceWorkerRegistrationInfo
);
if (sw.scope == arguments[0]) {
return true;
}
}
return false;
""",
script_args=(self.test_extension_base_url,),
)

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

@ -0,0 +1,54 @@
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
from marionette_driver import Wait
from marionette_driver.addons import Addons
import os
import sys
# Add this directory to the import path.
sys.path.append(os.path.dirname(__file__))
from service_worker_testutils import (
MarionetteServiceWorkerTestCase,
EXT_ID,
EXT_DIR_PATH,
PREF_BG_SW_ENABLED,
)
class TemporarilyInstalledAddonServiceWorkerNotPersisted(
MarionetteServiceWorkerTestCase
):
def setUp(self):
super(TemporarilyInstalledAddonServiceWorkerNotPersisted, self).setUp()
self.test_extension_id = EXT_ID
# Flip the "mirror: once" pref and restart Firefox to be able
# to run the extension successfully.
self.marionette.set_pref(PREF_BG_SW_ENABLED, True)
self.marionette.restart(in_app=True)
def tearDown(self):
self.marionette.restart(clean=True)
super(TemporarilyInstalledAddonServiceWorkerNotPersisted, self).tearDown()
def test_temporarily_installed_addon_serviceWorkers_not_persisted(self):
self.install_temporary_extension_with_service_worker()
# Make sure the extension worker registration is persisted
# across restarts when the pref stays set to true.
self.marionette.restart(in_app=True)
self.assertFalse(self.is_extension_service_worker_registered)
def install_temporary_extension_with_service_worker(self):
addons = Addons(self.marionette)
test_extension_path = os.path.join(
os.path.dirname(self.filepath), "data", EXT_DIR_PATH
)
addons.install(test_extension_path, temp=True)
self.test_extension_base_url = self.get_extension_url()
Wait(self.marionette).until(
lambda _: self.is_extension_service_worker_registered,
message="Wait the extension service worker to be registered",
)