test_console_serviceworker.html 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158
  1. <!DOCTYPE HTML>
  2. <html lang="en">
  3. <head>
  4. <meta charset="utf8">
  5. <title>Test for the Console API and Service Workers</title>
  6. <script type="text/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
  7. <script type="text/javascript;version=1.8" src="common.js"></script>
  8. <!-- Any copyright is dedicated to the Public Domain.
  9. - http://creativecommons.org/publicdomain/zero/1.0/ -->
  10. </head>
  11. <body>
  12. <p>Test for the Console API and Service Workers</p>
  13. <script class="testbody" type="text/javascript;version=1.8">
  14. SimpleTest.waitForExplicitFinish();
  15. let BASE_URL = "https://example.com/chrome/devtools/shared/webconsole/test/";
  16. let SERVICE_WORKER_URL = BASE_URL + "helper_serviceworker.js";
  17. let SCOPE = BASE_URL + "foo/";
  18. let NONSCOPE_FRAME_URL = BASE_URL + "sandboxed_iframe.html";
  19. let SCOPE_FRAME_URL = SCOPE + "fake.html";
  20. let SCOPE_FRAME_URL2 = SCOPE + "whatsit.html";
  21. let MESSAGE = 'Tic Tock';
  22. let expectedConsoleCalls = [
  23. {
  24. level: "log",
  25. filename: /helper_serviceworker/,
  26. arguments: ['script evaluation'],
  27. },
  28. {
  29. level: "log",
  30. filename: /helper_serviceworker/,
  31. arguments: ['install event'],
  32. },
  33. {
  34. level: "log",
  35. filename: /helper_serviceworker/,
  36. arguments: ['activate event'],
  37. },
  38. {
  39. level: "log",
  40. filename: /helper_serviceworker/,
  41. arguments: ['fetch event: ' + SCOPE_FRAME_URL],
  42. },
  43. {
  44. level: "log",
  45. filename: /helper_serviceworker/,
  46. arguments: ['fetch event: ' + SCOPE_FRAME_URL2],
  47. },
  48. {
  49. level: "log",
  50. filename: /helper_serviceworker/,
  51. arguments: ['message event: ' + MESSAGE],
  52. },
  53. ];
  54. let consoleCalls = [];
  55. let startTest = Task.async(function*() {
  56. removeEventListener("load", startTest);
  57. yield new Promise(resolve => {
  58. SpecialPowers.pushPrefEnv({"set": [
  59. ["dom.serviceWorkers.enabled", true],
  60. ["devtools.webconsole.filter.serviceworkers", true]
  61. ]}, resolve);
  62. });
  63. attachConsoleToTab(["ConsoleAPI"], onAttach);
  64. });
  65. addEventListener("load", startTest);
  66. let onAttach = Task.async(function*(state, response) {
  67. onConsoleAPICall = onConsoleAPICall.bind(null, state);
  68. state.dbgClient.addListener("consoleAPICall", onConsoleAPICall);
  69. let currentFrame;
  70. try {
  71. // First, we need a frame from which to register our script. This
  72. // will not trigger any console calls.
  73. info("Loading a non-scope frame from which to register a service worker.");
  74. currentFrame = yield withFrame(NONSCOPE_FRAME_URL);
  75. // Now register the service worker and wait for it to become
  76. // activate. This should trigger 3 console calls; 1 for script
  77. // evaluation, 1 for the install event, and 1 for the activate
  78. // event. These console calls are received because we called
  79. // register(), not because we are in scope for the worker.
  80. info("Registering the service worker");
  81. yield withActiveServiceWorker(currentFrame.contentWindow,
  82. SERVICE_WORKER_URL, SCOPE);
  83. ok(!currentFrame.contentWindow.navigator.serviceWorker.controller,
  84. 'current frame should not be controlled');
  85. // Now that the service worker is activate, lets navigate our frame.
  86. // This will trigger 1 more console call for the fetch event.
  87. info("Service worker registered. Navigating frame.");
  88. yield navigateFrame(currentFrame, SCOPE_FRAME_URL);
  89. ok(currentFrame.contentWindow.navigator.serviceWorker.controller,
  90. 'navigated frame should be controlled');
  91. // We now have a controlled frame. Lets perform a non-navigation fetch.
  92. // This should produce another console call for the fetch event.
  93. info("Frame navigated. Calling fetch().");
  94. yield currentFrame.contentWindow.fetch(SCOPE_FRAME_URL2);
  95. // Now force refresh our controlled frame. This will cause the frame
  96. // to bypass the service worker and become an uncontrolled frame. It
  97. // also happens to make the frame display a 404 message because the URL
  98. // does not resolve to a real resource. This is ok, as we really only
  99. // care about the frame being non-controlled, but still having a location
  100. // that matches our service worker scope so we can provide its not
  101. // incorrectly getting console calls.
  102. info("Completed fetch(). Force refreshing to get uncontrolled frame.");
  103. yield forceReloadFrame(currentFrame);
  104. ok(!currentFrame.contentWindow.navigator.serviceWorker.controller,
  105. 'current frame should not be controlled after force refresh');
  106. is(currentFrame.contentWindow.location.toString(), SCOPE_FRAME_URL,
  107. 'current frame should still have in-scope location URL even though it got 404');
  108. // Now postMessage() the service worker to trigger its message event
  109. // handler. This will generate 1 or 2 to console.log() statements
  110. // depending on if the worker thread needs to spin up again. Although we
  111. // don't have a controlled or registering document in both cases, we still
  112. // could get console calls since we only flush reports when the channel is
  113. // finally destroyed.
  114. info("Completed force refresh. Messaging service worker.");
  115. yield messageServiceWorker(currentFrame.contentWindow, SCOPE, MESSAGE);
  116. info("Done messaging service worker. Unregistering service worker.");
  117. yield unregisterServiceWorker(currentFrame.contentWindow);
  118. info('Service worker unregistered. Checking console calls.');
  119. state.dbgClient.removeListener("consoleAPICall", onConsoleAPICall);
  120. checkConsoleAPICalls(consoleCalls, expectedConsoleCalls);
  121. } catch(error) {
  122. ok(false, 'unexpected error: ' + error);
  123. } finally {
  124. if (currentFrame) {
  125. currentFrame.remove();
  126. currentFrame = null;
  127. }
  128. consoleCalls = [];
  129. closeDebugger(state, function() {
  130. SimpleTest.finish();
  131. });
  132. }
  133. });
  134. function onConsoleAPICall(state, type, packet) {
  135. info("received message level: " + packet.message.level);
  136. is(packet.from, state.actor, "console API call actor");
  137. consoleCalls.push(packet.message);
  138. }
  139. </script>
  140. </body>
  141. </html>