Bug 1213932 - Restrict ServiceWorker logging to windows that match navigator.serviceWorker.controller.scriptURL;r=baku,r=past

--HG--
extra : commitid : 4ObOwLPCliV
This commit is contained in:
Brian Grinstead 2015-11-05 12:03:31 -08:00
Родитель c1930e0865
Коммит 47dcb4d935
6 изменённых файлов: 187 добавлений и 18 удалений

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

@ -1534,8 +1534,7 @@ WebConsoleActor.prototype =
{
let result = WebConsoleUtils.cloneObject(aMessage);
result.workerType = CONSOLE_WORKER_IDS.indexOf(result.innerID) == -1
? 'none' : result.innerID;
result.workerType = WebConsoleUtils.getWorkerType(result) || "none";
delete result.wrappedJSObject;
delete result.ID;

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

@ -5,6 +5,7 @@ support-files =
common.js
data.json
data.json^headers^
helper_serviceworker.js
network_requests_iframe.html
sandboxed_iframe.html
console-test-worker.js
@ -16,6 +17,7 @@ support-files =
[test_commands_registration.html]
[test_consoleapi.html]
[test_consoleapi_innerID.html]
[test_console_serviceworker.html]
[test_console_styling.html]
[test_file_uri.html]
[test_reflow.html]

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

@ -0,0 +1,2 @@
console.log("Hello from serviceworker");

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

@ -0,0 +1,95 @@
<!DOCTYPE HTML>
<html lang="en">
<head>
<meta charset="utf8">
<title>Test for the Console API and Service Workers</title>
<script type="text/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
<script type="text/javascript;version=1.8" src="common.js"></script>
<!-- Any copyright is dedicated to the Public Domain.
- http://creativecommons.org/publicdomain/zero/1.0/ -->
</head>
<body>
<p>Test for the Console API and Service Workers</p>
<script class="testbody" type="text/javascript;version=1.8">
SimpleTest.waitForExplicitFinish();
let SERVICE_WORKER_URL = "https://example.com/chrome/devtools/shared/webconsole/test/helper_serviceworker.js";
let FRAME_URL = "https://example.com/chrome/devtools/shared/webconsole/test/sandboxed_iframe.html";
let swClosed = new Promise(() => {});
let expectedConsoleCalls = [
{
level: "log",
filename: /helper_serviceworker/,
arguments: ["Hello from serviceworker"],
}
];
let consoleCalls = [];
let startTest = Task.async(function*() {
removeEventListener("load", startTest);
yield new Promise(resolve => {
SpecialPowers.pushPrefEnv({"set": [
["devtools.webconsole.filter.serviceworkers", true]
]}, resolve);
});
attachConsoleToTab(["ConsoleAPI"], onAttach);
});
addEventListener("load", startTest);
function onAttach(state, response) {
onConsoleAPICall = onConsoleAPICall.bind(null, state);
state.dbgClient.addListener("consoleAPICall", onConsoleAPICall);
info("Loading a ServiceWorker that will use console API");
swClosed = new Promise(resolve => {
let iframe = document.createElement("iframe");
iframe.onload = function() {
let win = iframe.contentWindow;
info("Registering the service worker");
win.navigator.serviceWorker.register(SERVICE_WORKER_URL).then(swr => {
info("Service worker registered. Unregistering");
swr.unregister().then(() => {
resolve();
});
}, error => {
info("Error registering service worker: " + error);
});
};
iframe.src = FRAME_URL;
document.body.appendChild(iframe);
});
}
function onConsoleAPICall(state, type, packet) {
info("received message level: " + packet.message.level);
is(packet.from, state.actor, "console API call actor");
consoleCalls.push(packet.message);
if (consoleCalls.length != expectedConsoleCalls.length) {
return;
}
state.dbgClient.removeListener("consoleAPICall", onConsoleAPICall);
expectedConsoleCalls.forEach(function(aMessage, aIndex) {
info("checking received console call #" + aIndex);
checkConsoleAPICall(consoleCalls[aIndex], expectedConsoleCalls[aIndex]);
});
consoleCalls = [];
closeDebugger(state, function() {
swClosed.then(() => {
SimpleTest.finish();
});
});
}
</script>
</body>
</html>

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

@ -51,6 +51,17 @@ var WebConsoleUtils = {
return str;
},
/**
* Given a message, return one of CONSOLE_WORKER_IDS if it matches
* one of those.
*
* @return string
*/
getWorkerType: function(message) {
let id = message ? message.innerID : null;
return CONSOLE_WORKER_IDS[CONSOLE_WORKER_IDS.indexOf(id)] || null;
},
/**
* Clone an object.
*
@ -115,6 +126,29 @@ var WebConsoleUtils = {
aTo.style.fontStyle = style.getPropertyCSSValue("font-style").cssText;
},
/**
* Recursively gather a list of window locations given
* a top level window.
*
* @param nsIDOMWindow aWindow
* @return Array
* list of window locations as strings
*/
getLocationsForFrames: function(aWindow)
{
let location = aWindow.location.toString();
let locations = [location];
if (aWindow.frames) {
for (let i = 0; i < aWindow.frames.length; i++) {
let frame = aWindow.frames[i];
locations = locations.concat(this.getLocationsForFrames(frame));
}
}
return locations;
},
/**
* Gets the ID of the inner window of this DOM window.
*
@ -935,20 +969,53 @@ ConsoleAPIListener.prototype =
// by the XPCOM component which allows us to unwrap the XPCOM interface and
// access the underlying JSObject.
let apiMessage = aMessage.wrappedJSObject;
if (this.window && CONSOLE_WORKER_IDS.indexOf(apiMessage.innerID) == -1) {
let msgWindow = Services.wm.getCurrentInnerWindowWithId(apiMessage.innerID);
if (!msgWindow || !isWindowIncluded(this.window, msgWindow)) {
// Not the same window!
return;
}
}
if (this.consoleID && apiMessage.consoleID != this.consoleID) {
if (!this.isMessageRelevant(apiMessage)) {
return;
}
this.owner.onConsoleAPICall(apiMessage);
},
/**
* Given a message, return true if this window should show it and false
* if it should be ignored.
*
* @param message
* The message from the Storage Service
* @return bool
* Do we care about this message?
*/
isMessageRelevant: function(message) {
let workerType = WebConsoleUtils.getWorkerType(message);
if (this.window && workerType === "ServiceWorker") {
// For messages from Service Workers, message.ID is the
// scope, which can be used to determine whether it's controlling
// a window.
let scope = message.ID;
let locations = WebConsoleUtils.getLocationsForFrames(this.window);
if (!locations.some(loc => loc.startsWith(scope))) {
return false;
}
}
if (this.window && !workerType) {
let msgWindow = Services.wm.getCurrentInnerWindowWithId(message.innerID);
if (!msgWindow || !isWindowIncluded(this.window, msgWindow)) {
// Not the same window!
return false;
}
}
if (this.consoleID && message.consoleID !== this.consoleID) {
return false;
}
return true;
},
/**
* Get the cached messages for the current inner window and its (i)frames.
*
@ -979,9 +1046,9 @@ ConsoleAPIListener.prototype =
messages = messages.concat(ConsoleAPIStorage.getEvents(id));
});
if (this.consoleID) {
messages = messages.filter((m) => m.consoleID == this.consoleID);
}
messages = messages.filter(msg => {
return this.isMessageRelevant(msg);
});
if (aIncludePrivate) {
return messages;

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

@ -498,16 +498,20 @@ private:
frame = *mCallData->mTopStackFrame;
}
nsString id;
nsString id = frame.mFilename;
nsString innerID;
if (mWorkerPrivate->IsSharedWorker()) {
id = NS_LITERAL_STRING("SharedWorker");
innerID = NS_LITERAL_STRING("SharedWorker");
} else if (mWorkerPrivate->IsServiceWorker()) {
id = NS_LITERAL_STRING("ServiceWorker");
innerID = NS_LITERAL_STRING("ServiceWorker");
// Use scope as ID so the webconsole can decide if the message should
// show up per tab
id.AssignWithConversion(mWorkerPrivate->WorkerName());
} else {
id = NS_LITERAL_STRING("Worker");
innerID = NS_LITERAL_STRING("Worker");
}
mCallData->SetIDs(frame.mFilename, id);
mCallData->SetIDs(id, innerID);
}
// Now we could have the correct window (if we are not window-less).