author | Tim Huang <tihuang@mozilla.com> |
Tue, 01 Nov 2016 15:54:02 +0800 (2016-11-01) | |
changeset 321332 | 4128e57e39bda4d6fe223e911906c81851d76e70 |
parent 321331 | 82d1209499f2c551d13362f1cf52d291443548bd |
child 321333 | 908557c762f798605a2f96e4c943791cbada1b50 |
child 321358 | 81c8a80250c825a973c3e727900202690db8e01c |
push id | 30923 |
push user | philringnalda@gmail.com |
push date | Mon, 07 Nov 2016 02:21:38 +0000 (2016-11-07) |
treeherder | mozilla-central@908557c762f7 [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
reviewers | mayhemer, arthuredelstein |
bugs | 1264577, 13749 |
milestone | 52.0a1 |
first release with | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
last release without | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
--- a/browser/components/originattributes/test/browser/browser.ini +++ b/browser/components/originattributes/test/browser/browser.ini @@ -1,23 +1,42 @@ [DEFAULT] tags = usercontextid firstpartyisolation originattributes support-files = dummy.html file_broadcastChannel.html file_broadcastChanneliFrame.html + file_cache.html file_favicon.html file_favicon.png file_favicon.png^headers^ file_favicon_cache.html file_favicon_cache.png file_favicon_thirdParty.html file_firstPartyBasic.html file_sharedworker.html file_sharedworker.js + file_thirdPartyChild.audio.ogg + file_thirdPartyChild.embed.png + file_thirdPartyChild.fetch.html + file_thirdPartyChild.iframe.html + file_thirdPartyChild.img.png + file_thirdPartyChild.import.js + file_thirdPartyChild.link.css + file_thirdPartyChild.object.png + file_thirdPartyChild.request.html + file_thirdPartyChild.script.js + file_thirdPartyChild.sharedworker.js + file_thirdPartyChild.track.vtt + file_thirdPartyChild.video.ogv + file_thirdPartyChild.worker.fetch.html + file_thirdPartyChild.worker.js + file_thirdPartyChild.worker.request.html + file_thirdPartyChild.worker.xhr.html + file_thirdPartyChild.xhr.html head.js test.js test.js^headers^ test.html test2.html test2.js test2.js^headers^ test_firstParty.html @@ -27,16 +46,17 @@ support-files = test_firstParty_http_redirect.html^headers^ test_firstParty_iframe_http_redirect.html test_firstParty_postMessage.html window.html worker_blobify.js worker_deblobify.js [browser_broadcastChannel.js] +[browser_cache.js] [browser_cookieIsolation.js] [browser_favicon_firstParty.js] [browser_favicon_userContextId.js] [browser_firstPartyIsolation.js] [browser_localStorageIsolation.js] [browser_blobURLIsolation.js] [browser_imageCacheIsolation.js] [browser_sharedworker.js]
new file mode 100644 --- /dev/null +++ b/browser/components/originattributes/test/browser/browser_cache.js @@ -0,0 +1,247 @@ +/* + * Bug 1264577 - A test case for testing caches of various submodules. + * This test case will load two pages that each page loads various resources + * within the same third party domain for the same originAttributes or different + * originAttributes. And then, it verifies the number of cache entries and + * the originAttributes of loading channels. If these two pages belong to + * the same originAttributes, the number of cache entries for a certain + * resource would be one. Otherwise, it would be two. + */ + +const { classes: Cc, Constructor: CC, interfaces: Ci, utils: Cu } = Components; + +let {LoadContextInfo} = Cu.import("resource://gre/modules/LoadContextInfo.jsm", {}); +let protocolProxyService = Cc["@mozilla.org/network/protocol-proxy-service;1"] + .getService(Ci.nsIProtocolProxyService); + +const TEST_DOMAIN = "http://example.net"; +const TEST_PATH = "/browser/browser/components/originattributes/test/browser/"; +const TEST_PAGE = TEST_DOMAIN + TEST_PATH + "file_cache.html"; + +let suffixes = ["iframe.html", "link.css", "script.js", "img.png", "object.png", + "embed.png", "xhr.html", "worker.xhr.html", "audio.ogg", + "video.ogv", "track.vtt", + "fetch.html", "worker.fetch.html", + "request.html", "worker.request.html", + "import.js", "worker.js", "sharedworker.js"]; + +// A random value for isolating video/audio elements across different tests. +let randomSuffix; + +function clearAllImageCaches() { + let tools = SpecialPowers.Cc["@mozilla.org/image/tools;1"] + .getService(SpecialPowers.Ci.imgITools); + let imageCache = tools.getImgCacheForDocument(window.document); + imageCache.clearCache(true); // true=chrome + imageCache.clearCache(false); // false=content +} + +function cacheDataForContext(loadContextInfo) { + return new Promise(resolve => { + let cacheEntries = []; + let cacheVisitor = { + onCacheStorageInfo(num, consumption) {}, + onCacheEntryInfo(uri, idEnhance) { + cacheEntries.push({ uri: uri, + idEnhance: idEnhance }); + }, + onCacheEntryVisitCompleted() { + resolve(cacheEntries); + }, + QueryInterface(iid) { + if (iid.equals(Ci.nsICacheStorageVisitor)) + return this; + + throw Components.results.NS_ERROR_NO_INTERFACE; + } + }; + // Visiting the disk cache also visits memory storage so we do not + // need to use Services.cache2.memoryCacheStorage() here. + let storage = Services.cache2.diskCacheStorage(loadContextInfo, false); + storage.asyncVisitStorage(cacheVisitor, true); + }); +} + +let countMatchingCacheEntries = function (cacheEntries, domain, fileSuffix) { + return cacheEntries.map(entry => entry.uri.asciiSpec) + .filter(spec => spec.includes(domain)) + .filter(spec => spec.includes("file_thirdPartyChild." + fileSuffix)) + .length; +}; + +function observeChannels(onChannel) { + // We use a dummy proxy filter to catch all channels, even those that do not + // generate an "http-on-modify-request" notification, such as link preconnects. + let proxyFilter = { + applyFilter : function (aProxyService, aChannel, aProxy) { + // We have the channel; provide it to the callback. + onChannel(aChannel); + // Pass on aProxy unmodified. + return aProxy; + } + }; + protocolProxyService.registerChannelFilter(proxyFilter, 0); + // Return the stop() function: + return () => protocolProxyService.unregisterChannelFilter(proxyFilter); +} + +function startObservingChannels(aMode) { + let stopObservingChannels = observeChannels(function (channel) { + let originalURISpec = channel.originalURI.spec; + if (originalURISpec.includes("example.net")) { + let loadInfo = channel.loadInfo; + + switch (aMode) { + case TEST_MODE_FIRSTPARTY: + ok(loadInfo.originAttributes.firstPartyDomain === "example.com" || + loadInfo.originAttributes.firstPartyDomain === "example.org", + "first party for " + originalURISpec + " is " + loadInfo.originAttributes.firstPartyDomain); + break; + + case TEST_MODE_NO_ISOLATION: + ok(ChromeUtils.isOriginAttributesEqual(loadInfo.originAttributes, ChromeUtils.fillNonDefaultOriginAttributes()), + "OriginAttributes for " + originalURISpec + " is default."); + break; + + case TEST_MODE_CONTAINERS: + ok(loadInfo.originAttributes.userContextId === 1 || + loadInfo.originAttributes.userContextId === 2, + "userContextId for " + originalURISpec + " is " + loadInfo.originAttributes.userContextId); + break; + + default: + ok(false, "Unknown test mode."); + } + } + }); + return stopObservingChannels; +} + +let stopObservingChannels; + +// The init function, which clears image and network caches, and generates +// the random value for isolating video and audio elements across different +// test runs. +function* doInit(aMode) { + yield SpecialPowers.pushPrefEnv({"set": [["network.predictor.enabled", false], + ["network.predictor.enable-prefetch", false]]}); + clearAllImageCaches(); + + let networkCache = Cc["@mozilla.org/netwerk/cache-storage-service;1"] + .getService(Ci.nsICacheStorageService); + networkCache.clear(); + + randomSuffix = Math.random(); + stopObservingChannels = startObservingChannels(aMode); +} + +// In the test function, we dynamically generate the video and audio element, +// and assign a random suffix to their URL to isolate them across different +// test runs. +function* doTest(aBrowser) { + + let argObj = { + randomSuffix: randomSuffix, + urlPrefix: TEST_DOMAIN + TEST_PATH, + }; + + yield ContentTask.spawn(aBrowser, argObj, function* (arg) { + let videoURL = arg.urlPrefix + "file_thirdPartyChild.video.ogv"; + let audioURL = arg.urlPrefix + "file_thirdPartyChild.audio.ogg"; + let trackURL = arg.urlPrefix + "file_thirdPartyChild.track.vtt"; + let URLSuffix = "?r=" + arg.randomSuffix; + + // Create the audio and video elements. + let audio = content.document.createElement('audio'); + let video = content.document.createElement('video'); + let audioSource = content.document.createElement('source'); + let audioTrack = content.document.createElement('track'); + + // Assign attributes for the audio element. + audioSource.setAttribute("src", audioURL + URLSuffix); + audioSource.setAttribute("type", "audio/ogg"); + audioTrack.setAttribute("src", trackURL); + audioTrack.setAttribute("kind", "subtitles"); + + // Append the audio and track element into the body, and wait until they're finished. + yield new Promise(resolve => { + let audioLoaded = false; + let trackLoaded = false; + + let audioListener = () => { + audio.removeEventListener("canplaythrough", audioListener); + + audioLoaded = true; + if (audioLoaded && trackLoaded) { + resolve(); + } + }; + + let trackListener = () => { + audioTrack.removeEventListener("load", trackListener); + + trackLoaded = true; + if (audioLoaded && trackLoaded) { + resolve(); + } + }; + + audio.appendChild(audioSource); + audio.appendChild(audioTrack); + audio.autoplay = true; + + audioTrack.addEventListener("load", trackListener, false); + audio.addEventListener("canplaythrough", audioListener, false); + content.document.body.appendChild(audio); + }); + + // Append the video element into the body, and wait until it's finished. + yield new Promise(resolve => { + let listener = () => { + video.removeEventListener("canplaythrough", listener); + resolve(); + }; + + // Assign attributes for the video element. + video.setAttribute("src", videoURL + URLSuffix); + video.setAttribute("type", "video/ogg"); + + video.addEventListener("canplaythrough", listener, false); + content.document.body.appendChild(video); + }); + }); + + return 0; +} + +// The check function, which checks the number of cache entries. +function* doCheck(aShouldIsolate, aInputA, aInputB) { + let expectedEntryCount = 1; + let data = []; + data = data.concat(yield cacheDataForContext(LoadContextInfo.default)); + data = data.concat(yield cacheDataForContext(LoadContextInfo.private)); + data = data.concat(yield cacheDataForContext(LoadContextInfo.custom(true, {}))); + + if (aShouldIsolate) { + expectedEntryCount = 2; + } + + for (let suffix of suffixes) { + let foundEntryCount = countMatchingCacheEntries(data, "example.net", suffix); + let result = (expectedEntryCount === foundEntryCount); + ok(result, "Cache entries expected for " + suffix + ": " + expectedEntryCount + + ", and found " + foundEntryCount); + } + + stopObservingChannels(); + stopObservingChannels = undefined; + return true; +} + +let testArgs = { + url: TEST_PAGE, + firstFrameSetting: DEFAULT_FRAME_SETTING, + secondFrameSetting: [TEST_TYPE_FRAME], +}; + +IsolationTestTools.runTests(testArgs, doTest, doCheck, doInit);
new file mode 100644 --- /dev/null +++ b/browser/components/originattributes/test/browser/file_cache.html @@ -0,0 +1,25 @@ +<!DOCTYPE html> +<html> +<meta content="text/html;charset=utf-8" http-equiv="Content-Type"> +<head> + <link rel="stylesheet" type="text/css" + href="http://example.net/browser/browser/components/originattributes/test/browser/file_thirdPartyChild.link.css"> + <link rel="preconnect" href="http://example.net"> +</head> +<body> +<div>file_cache.html</div> + +<iframe src="http://example.net/browser/browser/components/originattributes/test/browser/file_thirdPartyChild.iframe.html"> +</iframe> + +<script src="http://example.net/browser/browser/components/originattributes/test/browser/file_thirdPartyChild.script.js"> +</script> + +<img src="http://example.net/browser/browser/components/originattributes/test/browser/file_thirdPartyChild.img.png"> + +<embed src="http://example.net/browser/browser/components/originattributes/test/browser/file_thirdPartyChild.embed.png"> + +<object data="http://example.net/browser/browser/components/originattributes/test/browser/file_thirdPartyChild.object.png" + type="image/png"></object> +</body> +</html>
new file mode 100644 index 0000000000000000000000000000000000000000..edda4e9128435b0cc9ba500c9daca90e2be30acf GIT binary patch literal 2603 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
new file mode 100644 index 0000000000000000000000000000000000000000..c5916f289705642eec4975cf51458b9afeefe46c GIT binary patch literal 95 zc%17D@N?(olHy`uVBq!ia0vp^j3CU&3?x-=hn)ga%mF?juK#@*VoWXSL2@NQe!*uh mnS}iXa=1KQ978JRBqsscYz)k1<~1vTECx?kKbLh*2~7ZT-W2Wt
new file mode 100644 --- /dev/null +++ b/browser/components/originattributes/test/browser/file_thirdPartyChild.fetch.html @@ -0,0 +1,8 @@ +<!DOCTYPE html> +<html> +<meta content="text/html;charset=utf-8" http-equiv="Content-Type"> +<!-- The child page, used by browser_cache.js --> +<body> +<div>thirdPartyChild.fetch.html</div> +</body> +</html>
new file mode 100644 --- /dev/null +++ b/browser/components/originattributes/test/browser/file_thirdPartyChild.iframe.html @@ -0,0 +1,18 @@ +<!DOCTYPE html> +<html> +<meta content="text/html;charset=utf-8" http-equiv="Content-Type"> +<!-- The child page, used by browser_cache.js --> +<body> +<div>thirdPartyChild.html</div> +<script> + var xhr = new XMLHttpRequest(); + xhr.open("GET", "http://example.net/browser/browser/components/originattributes/test/browser/file_thirdPartyChild.xhr.html", true); + xhr.send(); + var worker = new Worker("http://example.net/browser/browser/components/originattributes/test/browser/file_thirdPartyChild.worker.js"); + var sharedWorker = new SharedWorker("http://example.net/browser/browser/components/originattributes/test/browser/file_thirdPartyChild.sharedworker.js"); + + fetch("file_thirdPartyChild.fetch.html", {cache: "force-cache"} ); + fetch(new Request("file_thirdPartyChild.request.html"), {cache: "force-cache"} ); +</script> +</body> +</html>
new file mode 100644 index 0000000000000000000000000000000000000000..c5916f289705642eec4975cf51458b9afeefe46c GIT binary patch literal 95 zc%17D@N?(olHy`uVBq!ia0vp^j3CU&3?x-=hn)ga%mF?juK#@*VoWXSL2@NQe!*uh mnS}iXa=1KQ978JRBqsscYz)k1<~1vTECx?kKbLh*2~7ZT-W2Wt
new file mode 100644 --- /dev/null +++ b/browser/components/originattributes/test/browser/file_thirdPartyChild.import.js @@ -0,0 +1,1 @@ +// dummy script, to be called by self.importScripts(...)
new file mode 100644 --- /dev/null +++ b/browser/components/originattributes/test/browser/file_thirdPartyChild.link.css @@ -0,0 +1,1 @@ +/* Dummy CSS file, used by browser_cache.js. */ \ No newline at end of file
new file mode 100644 index 0000000000000000000000000000000000000000..c5916f289705642eec4975cf51458b9afeefe46c GIT binary patch literal 95 zc%17D@N?(olHy`uVBq!ia0vp^j3CU&3?x-=hn)ga%mF?juK#@*VoWXSL2@NQe!*uh mnS}iXa=1KQ978JRBqsscYz)k1<~1vTECx?kKbLh*2~7ZT-W2Wt
new file mode 100644 --- /dev/null +++ b/browser/components/originattributes/test/browser/file_thirdPartyChild.request.html @@ -0,0 +1,8 @@ +<!DOCTYPE html> +<html> +<meta content="text/html;charset=utf-8" http-equiv="Content-Type"> +<!-- The child page, used by browser_cache.js --> +<body> +<div>thirdPartyChild.request.html</div> +</body> +</html>
new file mode 100644 --- /dev/null +++ b/browser/components/originattributes/test/browser/file_thirdPartyChild.script.js @@ -0,0 +1,1 @@ +// Dummy child script, used by browser_cache.js
new file mode 100644 --- /dev/null +++ b/browser/components/originattributes/test/browser/file_thirdPartyChild.sharedworker.js @@ -0,0 +1,1 @@ +// dummy file
new file mode 100644 --- /dev/null +++ b/browser/components/originattributes/test/browser/file_thirdPartyChild.track.vtt @@ -0,0 +1,13 @@ +WEBVTT FILE + +1 +00:00:00.500 --> 00:00:02.000 D:vertical A:start +blah blah blah + +2 +00:00:02.500 --> 00:00:04.300 +this is a test + +3 +00:00:05.000 --> 00:00:07.000 +one more line
new file mode 100644 index 0000000000000000000000000000000000000000..68dee3cf2b1de3d820a7b606cdca809f8224e855 GIT binary patch literal 16049 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 NW^56gvQ&sQ|3Brd7xw@F
new file mode 100644 --- /dev/null +++ b/browser/components/originattributes/test/browser/file_thirdPartyChild.worker.fetch.html @@ -0,0 +1,8 @@ +<!DOCTYPE html> +<html> +<meta content="text/html;charset=utf-8" http-equiv="Content-Type"> +<!-- The child page, used by browser_cache.js --> +<body> +<div>thirdPartyChild.worker.fetch.html</div> +</body> +</html>
new file mode 100644 --- /dev/null +++ b/browser/components/originattributes/test/browser/file_thirdPartyChild.worker.js @@ -0,0 +1,9 @@ +var xhr = new XMLHttpRequest(); +xhr.open("GET", "http://example.net/browser/browser/components/originattributes/test/browser/file_thirdPartyChild.worker.xhr.html", true); +xhr.send(); + +fetch("http://example.net/browser/browser/components/originattributes/test/browser/file_thirdPartyChild.worker.fetch.html", {cache: "force-cache"} ); +var myRequest = new Request("http://example.net/browser/browser/components/originattributes/test/browser/file_thirdPartyChild.worker.request.html"); +fetch(myRequest, {cache: "force-cache"} ); + +self.importScripts("http://example.net/browser/browser/components/originattributes/test/browser/file_thirdPartyChild.import.js");
new file mode 100644 --- /dev/null +++ b/browser/components/originattributes/test/browser/file_thirdPartyChild.worker.request.html @@ -0,0 +1,8 @@ +<!DOCTYPE html> +<html> +<meta content="text/html;charset=utf-8" http-equiv="Content-Type"> +<!-- The child page, used by browser_cache.js --> +<body> +<div>thirdPartyChild.worker.request.html</div> +</body> +</html>
new file mode 100644 --- /dev/null +++ b/browser/components/originattributes/test/browser/file_thirdPartyChild.worker.xhr.html @@ -0,0 +1,8 @@ +<!DOCTYPE html> +<html> +<meta content="text/html;charset=utf-8" http-equiv="Content-Type"> +<!-- The child page, used by browser_cache.js --> +<body> +<div>thirdPartyChild.worker.xhr.html</div> +</body> +</html>
new file mode 100644 --- /dev/null +++ b/browser/components/originattributes/test/browser/file_thirdPartyChild.xhr.html @@ -0,0 +1,8 @@ +<!DOCTYPE html> +<html> +<meta content="text/html;charset=utf-8" http-equiv="Content-Type"> +<!-- The child page, used by browser_cache.js --> +<body> +<div>thirdPartyChild.html</div> +</body> +</html>
--- a/browser/components/originattributes/test/browser/head.js +++ b/browser/components/originattributes/test/browser/head.js @@ -304,17 +304,17 @@ this.IsolationTestTools = { ]; this._add_task(function* (aMode) { let tabSettingA = 0; for (let tabSettingB of [0, 1]) { // Give the test a chance to set up before each case is run. if (aBeforeFunc) { - yield aBeforeFunc(); + yield aBeforeFunc(aMode); } // Create Tabs. let tabInfoA = yield IsolationTestTools._addTab(aMode, pageURL, tabSettings[tabSettingA], firstFrameSetting); let tabInfoB = yield IsolationTestTools._addTab(aMode,