Skip to content

Commit 5fd3bb1

Browse files
committed
Support getting a service worker target.
- This allows the client to execute javascript in a Chrome extension context. - Bump the version
1 parent a92bf73 commit 5fd3bb1

File tree

5 files changed

+92
-5
lines changed

5 files changed

+92
-5
lines changed

browserdebuggertools/chrome/interface.py

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
logging.basicConfig(format='%(levelname)s:%(message)s')
1111

1212

13-
class ChromeInterface(object):
13+
class ChromeInterface:
1414
""" The Chrome Interface communicates with the browser through the remote-debugging-port using
1515
the Chrome DevTools Protocol.
1616
For a thorough reference check: https://chromedevtools.github.io/devtools-protocol/
@@ -40,6 +40,7 @@ def __init__(
4040
:param attach: If set to true, the interface will attach to the first page target found.
4141
If there are no page targets, a new tab will be created.
4242
"""
43+
self._timeout = timeout
4344
self._targets_manager = TargetsManager(timeout, port, host=host, domains=domains)
4445
if attach:
4546
self.switch_target()
@@ -291,3 +292,12 @@ def get_all_events(self, domain, clear=False):
291292

292293
def reload(self):
293294
return self.execute("Page", "reload")
295+
296+
@contextlib.contextmanager
297+
def service_worker(self, service_script_name):
298+
target = self._targets_manager.get_service_worker(service_script_name)
299+
target.attach()
300+
try:
301+
yield target
302+
finally:
303+
target.detach()

browserdebuggertools/targets_manager.py

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919
DevToolsTimeoutException, DomainNotEnabledError,
2020
MethodNotFoundError, UnknownError, ResourceNotFoundError, MessagingThreadIsDeadError,
2121
InvalidParametersError, WebSocketBlockedException,
22-
TargetNotAttachedError
22+
TargetNotAttachedError, TargetNotFoundError
2323
)
2424

2525

@@ -217,6 +217,12 @@ def detach(self):
217217
self.wsm.close()
218218

219219

220+
class ServiceWorkerTarget(_Target):
221+
222+
def __init__(self, info: dict, timeout):
223+
super().__init__(info, timeout)
224+
225+
220226
class EventHandlers(NamedTuple):
221227
pageLoad: PageLoadEventHandler
222228
javascriptDialog: JavascriptDialogEventHandler
@@ -675,3 +681,19 @@ def _create_tab(self):
675681
return requests.put(
676682
f"http://{self._host}:{self._port}/json/new", timeout=self._connection_timeout
677683
)
684+
685+
def get_service_worker(self, service_script_name):
686+
687+
def find_target_info():
688+
for target in self._get_targets():
689+
if (
690+
target["type"] == "service_worker"
691+
and target["url"].endswith(service_script_name)
692+
):
693+
return target
694+
695+
targetInfo = find_target_info()
696+
if targetInfo:
697+
return ServiceWorkerTarget(targetInfo, self._connection_timeout)
698+
else:
699+
raise TargetNotFoundError(service_script_name)

setup.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111

1212
setup(
1313
name="browserdebuggertools",
14-
version="6.2.0",
14+
version="6.2.1",
1515
python_requires='>=3.8',
1616
include_package_data=True,
1717
packages=PACKAGES,

tests/unittests/chrome/test_interface.py

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,3 +74,16 @@ def test_target_id_does_not_exist(self):
7474

7575
with self.assertRaises(TargetNotFoundError):
7676
self.interface.switch_target("target_3")
77+
78+
79+
class Test_ChromeInterface_service_worker(ChromeInterfaceTest):
80+
81+
def test(self):
82+
service_worker = MagicMock()
83+
self.interface._targets_manager.get_service_worker.return_value = service_worker
84+
85+
with self.interface.service_worker("myExtension.json") as service_worker:
86+
service_worker.attach.assert_called_once_with()
87+
self.assertFalse(service_worker.detach.called)
88+
89+
service_worker.detach.assert_called_once_with()

tests/unittests/test_targets_manager.py

Lines changed: 44 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
DevToolsException,
1616
DomainNotEnabledError, DevToolsTimeoutException, MethodNotFoundError,
1717
InvalidParametersError, WebSocketBlockedException, MessagingThreadIsDeadError,
18-
MaxRetriesException, ResourceNotFoundError, TargetNotAttachedError
18+
MaxRetriesException, ResourceNotFoundError, TargetNotAttachedError, TargetNotFoundError
1919
)
2020
from browserdebuggertools.targets_manager import (
2121
_WSSessionManager, _WSMessageProducer, TargetsManager, _Target, _DOMManager
@@ -1061,7 +1061,7 @@ def test(self, _targets_manager):
10611061

10621062

10631063
@patch(MODULE_PATH + "requests")
1064-
class Test_TargetsManager__create_tab(WSMessageProducerTest):
1064+
class Test_TargetsManager__create_tab(unittest.TestCase):
10651065

10661066
def setUp(self):
10671067
self._targets_manager = TargetsManager(10, 9222)
@@ -1085,6 +1085,48 @@ def test_not_ok_response(self, requests):
10851085
self._targets_manager._create_tab()
10861086

10871087

1088+
class Test_TargetsManager_get_service_worker(unittest.TestCase):
1089+
1090+
def setUp(self):
1091+
self._targets_manager = TargetsManager(10, 9222)
1092+
self._targets_manager._get_targets = MagicMock()
1093+
self._targets_manager._get_targets.return_value = [
1094+
{
1095+
"description": "",
1096+
"devtoolsFrontendUrl":
1097+
"/devtools/inspector.html?ws=172.17.0.2:10000/devtools/page/extension-id",
1098+
"id": "extension-id",
1099+
"title": "Service Worker chrome-extension://..../service.js",
1100+
"type": "service_worker",
1101+
"url": "chrome-extension://..../service.js",
1102+
"webSocketDebuggerUrl": "ws://172.17.0.2:10000/devtools/page/extension-ID"
1103+
},
1104+
{
1105+
"description": "",
1106+
"devtoolsFrontendUrl":
1107+
"/devtools/inspector.html?ws=172.17.0.2:10001/devtools/page/other-extension-id",
1108+
"id": "other-extension-id",
1109+
"title": "Service Worker chrome-extension://ih...gi/other-service.js",
1110+
"type": "service_worker",
1111+
"url": "chrome-extension://ih...gi/other-service.js",
1112+
"webSocketDebuggerUrl": "ws://172.17.0.2:10000/devtools/page/other-extension-id"
1113+
}
1114+
]
1115+
1116+
def test(self):
1117+
self.assertEqual(
1118+
"extension-id", self._targets_manager.get_service_worker("service.js").id
1119+
)
1120+
self.assertEqual(
1121+
"other-extension-id", self._targets_manager.get_service_worker("other-service.js").id
1122+
)
1123+
1124+
def test_target_not_found(self):
1125+
with self.assertRaises(TargetNotFoundError):
1126+
self._targets_manager.get_service_worker("not-installed")
1127+
1128+
1129+
10881130
class DOMManagerTest(TestCase):
10891131

10901132
def setUp(self):

0 commit comments

Comments
 (0)