# HG changeset patch # User Jarda Snajdr Bug 1134073 - Part 5: show network request cause in netmonitor UI - mochitest diff --git a/devtools/client/netmonitor/test/browser.ini b/devtools/client/netmonitor/test/browser.ini index f807a93..dda51a9 100644 --- a/devtools/client/netmonitor/test/browser.ini +++ b/devtools/client/netmonitor/test/browser.ini @@ -1,14 +1,15 @@ [DEFAULT] tags = devtools subsuite = devtools support-files = dropmarker.svg head.js + html_cause-test-page.html html_content-type-test-page.html html_content-type-without-cache-test-page.html html_custom-get-page.html html_single-get-page.html html_cyrillic-test-page.html html_filter-test-page.html html_infinite-get-page.html html_json-custom-mime-test-page.html @@ -27,30 +28,33 @@ support-files = html_statistics-test-page.html html_status-codes-test-page.html html_api-calls-test-page.html html_copy-as-curl.html html_curl-utils.html sjs_content-type-test-server.sjs sjs_cors-test-server.sjs sjs_https-redirect-test-server.sjs + sjs_https-sts-test-server.sjs sjs_simple-test-server.sjs sjs_sorting-test-server.sjs sjs_status-codes-test-server.sjs test-image.png service-workers/status-codes.html service-workers/status-codes-service-worker.js [browser_net_aaa_leaktest.js] [browser_net_accessibility-01.js] [browser_net_accessibility-02.js] skip-if = (toolkit == "cocoa" && e10s) # bug 1252254 [browser_net_api-calls.js] [browser_net_autoscroll.js] [browser_net_cached-status.js] +[browser_net_cause.js] +[browser_net_cause_redirect.js] [browser_net_service-worker-status.js] [browser_net_charts-01.js] [browser_net_charts-02.js] [browser_net_charts-03.js] [browser_net_charts-04.js] [browser_net_charts-05.js] [browser_net_charts-06.js] [browser_net_charts-07.js] diff --git a/devtools/client/netmonitor/test/browser_net_cause.js b/devtools/client/netmonitor/test/browser_net_cause.js new file mode 100644 index 0000000..8f73e96 --- /dev/null +++ b/devtools/client/netmonitor/test/browser_net_cause.js @@ -0,0 +1,56 @@ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +/** + * Tests if request cause is reported correctly. + */ + +var test = Task.async(function*() { + const EXPECTED_REQUESTS = [ + [ "GET", CAUSE_URL, "document", "", false ], + [ "GET", EXAMPLE_URL + "stylesheet_request", "stylesheet", CAUSE_URL, false ], + [ "GET", EXAMPLE_URL + "img_request", "img", CAUSE_URL, false ], + [ "GET", EXAMPLE_URL + "xhr_request", "xhr", CAUSE_URL, true ], + [ "POST", EXAMPLE_URL + "beacon_request", "beacon", CAUSE_URL, true ], + ]; + + // the initNetMonitor function clears the network request list after the + // page is loaded. That's why we first load a bogus page from SIMPLE_URL, + // and only then load the real thing from CAUSE_URL - we want to catch + // all the requests the page is making, not only the XHRs. + // We can't use about:blank here, because initNetMonitor checks that the + // page has actually made at least one request. + let [tab, debuggee, monitor] = yield initNetMonitor(SIMPLE_URL); + let { RequestsMenu } = monitor.panelWin.NetMonitorView; + RequestsMenu.lazyUpdate = false; + + debuggee.location = CAUSE_URL; + + yield waitForNetworkEvents(monitor, EXPECTED_REQUESTS.length); + + is(RequestsMenu.itemCount, EXPECTED_REQUESTS.length, + "All the page events should be recorded."); + + EXPECTED_REQUESTS.forEach((spec, i) => { + let [ method, url, causeType, causeUri, hasStack ] = spec; + + let requestItem = RequestsMenu.getItemAtIndex(i); + verifyRequestItemTarget(requestItem, + method, url, { cause: { type: causeType, loadingDocumentUri: causeUri } } + ); + + let { stacktrace } = requestItem.attachment.cause; + if (hasStack) { + ok(stacktrace, `Request #${i} has a stacktrace`); + let stackLen = (stacktrace || []).length; + ok(stackLen > 0, + `Request #${i} (${causeType}) has a stacktrace with ${stackLen} items`); + } else { + is((stacktrace || []).length, 0, + `Request #${i} (${causeType}) has an empty stacktrace`); + } + }); + + yield teardown(monitor); + finish(); +}); diff --git a/devtools/client/netmonitor/test/browser_net_cause_redirect.js b/devtools/client/netmonitor/test/browser_net_cause_redirect.js new file mode 100644 index 0000000..0910fcd --- /dev/null +++ b/devtools/client/netmonitor/test/browser_net_cause_redirect.js @@ -0,0 +1,49 @@ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +/** + * Tests if request JS stack is property reported if the request is internally + * redirected without hitting the network (HSTS is one of such cases) + */ + +var test = Task.async(function* () { + const EXPECTED_REQUESTS = [ + // Request to HTTP URL, redirects to HTTPS, has callstack + { status: 302, hasStack: true }, + // Serves HTTPS, sets the Strict-Transport-Security header, no stack + { status: 200, hasStack: false }, + // Second request to HTTP redirects to HTTPS internally + { status: 200, hasStack: true }, + ]; + + let [, debuggee, monitor] = yield initNetMonitor(CUSTOM_GET_URL); + let { RequestsMenu } = monitor.panelWin.NetMonitorView; + RequestsMenu.lazyUpdate = false; + + debuggee.performRequests(2, HTTPS_STS_SJS); + yield waitForNetworkEvents(monitor, EXPECTED_REQUESTS.length); + + EXPECTED_REQUESTS.forEach(({status, hasStack}, i) => { + let { attachment } = RequestsMenu.getItemAtIndex(i); + + is(attachment.status, status, + `Request #${i} has the expected status`); + + let { stacktrace } = attachment.cause; + + if (hasStack) { + ok(stacktrace, `Request #${i} has a stacktrace`); + let stackLen = (stacktrace || []).length; + ok(stackLen > 0, + `Request #${i} has a stacktrace with ${stackLen} items`); + } else { + is((stacktrace || []).length, 0, + `Request #${i} has an empty stacktrace`); + } + }); + + yield teardown(monitor); + finish(); +}); diff --git a/devtools/client/netmonitor/test/head.js b/devtools/client/netmonitor/test/head.js index adbdbcc..937eca7 100644 --- a/devtools/client/netmonitor/test/head.js +++ b/devtools/client/netmonitor/test/head.js @@ -37,22 +37,24 @@ const SORTING_URL = EXAMPLE_URL + "html_sorting-test-page.html"; const FILTERING_URL = EXAMPLE_URL + "html_filter-test-page.html"; const INFINITE_GET_URL = EXAMPLE_URL + "html_infinite-get-page.html"; const CUSTOM_GET_URL = EXAMPLE_URL + "html_custom-get-page.html"; const SINGLE_GET_URL = EXAMPLE_URL + "html_single-get-page.html"; const STATISTICS_URL = EXAMPLE_URL + "html_statistics-test-page.html"; const CURL_URL = EXAMPLE_URL + "html_copy-as-curl.html"; const CURL_UTILS_URL = EXAMPLE_URL + "html_curl-utils.html"; const SEND_BEACON_URL = EXAMPLE_URL + "html_send-beacon.html"; +const CAUSE_URL = EXAMPLE_URL + "html_cause-test-page.html"; const SIMPLE_SJS = EXAMPLE_URL + "sjs_simple-test-server.sjs"; const CONTENT_TYPE_SJS = EXAMPLE_URL + "sjs_content-type-test-server.sjs"; const STATUS_CODES_SJS = EXAMPLE_URL + "sjs_status-codes-test-server.sjs"; const SORTING_SJS = EXAMPLE_URL + "sjs_sorting-test-server.sjs"; const HTTPS_REDIRECT_SJS = EXAMPLE_URL + "sjs_https-redirect-test-server.sjs"; +const HTTPS_STS_SJS = EXAMPLE_URL + "sjs_https-sts-test-server.sjs"; const CORS_SJS_PATH = "/browser/devtools/client/netmonitor/test/sjs_cors-test-server.sjs"; const TEST_IMAGE = EXAMPLE_URL + "test-image.png"; const TEST_IMAGE_DATA_URI = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAAK/INwWK6QAAABl0RVh0U29mdHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAAHWSURBVHjaYvz//z8DJQAggJiQOe/fv2fv7Oz8rays/N+VkfG/iYnJfyD/1+rVq7ffu3dPFpsBAAHEAHIBCJ85c8bN2Nj4vwsDw/8zQLwKiO8CcRoQu0DxqlWrdsHUwzBAAIGJmTNnPgYa9j8UqhFElwPxf2MIDeIrKSn9FwSJoRkAEEAM0DD4DzMAyPi/G+QKY4hh5WAXGf8PDQ0FGwJ22d27CjADAAIIrLmjo+MXA9R2kAHvGBA2wwx6B8W7od6CeQcggKCmCEL8bgwxYCbUIGTDVkHDBia+CuotgACCueD3TDQN75D4xmAvCoK9ARMHBzAw0AECiBHkAlC0Mdy7x9ABNA3obAZXIAa6iKEcGlMVQHwWyjYuL2d4v2cPg8vZswx7gHyAAAK7AOif7SAbOqCmn4Ha3AHFsIDtgPq/vLz8P4MSkJ2W9h8ggBjevXvHDo4FQUQg/kdypqCg4H8lUIACnQ/SOBMYI8bAsAJFPcj1AAEEjwVQqLpAbXmH5BJjqI0gi9DTAAgDBBCcAVLkgmQ7yKCZxpCQxqUZhAECCJ4XgMl493ug21ZD+aDAXH0WLM4A9MZPXJkJIIAwTAR5pQMalaCABQUULttBGCCAGCnNzgABBgAMJ5THwGvJLAAAAABJRU5ErkJggg=="; const FRAME_SCRIPT_UTILS_URL = "chrome://devtools/content/shared/frame-script-utils.js" DevToolsUtils.testing = true; @@ -277,17 +279,17 @@ function verifyRequestItemTarget(aRequestItem, aMethod, aUrl, aData = {}) { let requestsMenu = aRequestItem.ownerView; let widgetIndex = requestsMenu.indexOfItem(aRequestItem); let visibleIndex = requestsMenu.visibleItems.indexOf(aRequestItem); info("Widget index of item: " + widgetIndex); info("Visible index of item: " + visibleIndex); - let { fuzzyUrl, status, statusText, type, fullMimeType, + let { fuzzyUrl, status, statusText, cause, type, fullMimeType, transferred, size, time, displayedStatus } = aData; let { attachment, target } = aRequestItem let uri = Services.io.newURI(aUrl, null, null).QueryInterface(Ci.nsIURL); let unicodeUrl = NetworkHelper.convertToUnicode(unescape(aUrl)); let name = NetworkHelper.convertToUnicode(unescape(uri.fileName || uri.filePath || "/")); let query = NetworkHelper.convertToUnicode(unescape(uri.query)); let hostPort = uri.hostPort; @@ -329,16 +331,24 @@ function verifyRequestItemTarget(aRequestItem, aMethod, aUrl, aData = {}) { let tooltip = target.querySelector(".requests-menu-status").getAttribute("tooltiptext"); info("Displayed status: " + value); info("Displayed code: " + codeValue); info("Tooltip status: " + tooltip); is(value, displayedStatus ? displayedStatus : status, "The displayed status is correct."); is(codeValue, status, "The displayed status code is correct."); is(tooltip, status + " " + statusText, "The tooltip status is correct."); } + if (cause !== undefined) { + let value = target.querySelector(".requests-menu-cause").getAttribute("value"); + let tooltip = target.querySelector(".requests-menu-cause").getAttribute("tooltiptext"); + info("Displayed cause: " + value); + info("Tooltip cause: " + tooltip); + is(value, cause.type, "The displayed cause is correct."); + is(tooltip, cause.loadingDocumentUri, "The tooltip cause is correct.") + } if (type !== undefined) { let value = target.querySelector(".requests-menu-type").getAttribute("value"); let tooltip = target.querySelector(".requests-menu-type").getAttribute("tooltiptext"); info("Displayed type: " + value); info("Tooltip type: " + tooltip); is(value, type, "The displayed type is correct."); is(tooltip, fullMimeType, "The tooltip type is correct."); } diff --git a/devtools/client/netmonitor/test/html_cause-test-page.html b/devtools/client/netmonitor/test/html_cause-test-page.html new file mode 100644 index 0000000..40a6f40 --- /dev/null +++ b/devtools/client/netmonitor/test/html_cause-test-page.html @@ -0,0 +1,33 @@ + + + + + + + + + + Network Monitor test page + + + + +

Request cause test

+ + + + diff --git a/devtools/client/netmonitor/test/sjs_https-sts-test-server.sjs b/devtools/client/netmonitor/test/sjs_https-sts-test-server.sjs new file mode 100644 index 0000000..b10fa1c --- /dev/null +++ b/devtools/client/netmonitor/test/sjs_https-sts-test-server.sjs @@ -0,0 +1,17 @@ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +function handleRequest(request, response) { + response.setHeader("Cache-Control", "no-cache, no-store, must-revalidate"); + response.setHeader("Pragma", "no-cache"); + response.setHeader("Expires", "0"); + + if (request.scheme === "http") { + response.setStatusLine(request.httpVersion, 302, "Found"); + response.setHeader("Location", "https://" + request.host + request.path); + } else { + response.setStatusLine(request.httpVersion, 200, "OK"); + response.setHeader("Strict-Transport-Security", "max-age=100"); + response.write("Page was accessed over HTTPS!"); + } +}