mirror of
https://repo.dactyloidae.xyz/Dactyloidae/UXP.git
synced 2026-09-07 00:08:39 +09:00
Merge remote-tracking branch 'origin/master' into custom
This commit is contained in:
commit
55828393ce
2798 changed files with 8839 additions and 257595 deletions
|
|
@ -4,9 +4,6 @@
|
|||
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
BROWSER_CHROME_MANIFESTS += ['test/browser.ini']
|
||||
XPCSHELL_TESTS_MANIFESTS += ['test/xpcshell.ini']
|
||||
|
||||
EXTRA_COMPONENTS += [
|
||||
'BrowserPageThumbs.manifest',
|
||||
'PageThumbsProtocol.js',
|
||||
|
|
@ -22,5 +19,4 @@ EXTRA_PP_JS_MODULES += [
|
|||
'PageThumbUtils.jsm',
|
||||
]
|
||||
|
||||
|
||||
JAR_MANIFESTS += ['jar.mn']
|
||||
|
|
|
|||
|
|
@ -1,8 +0,0 @@
|
|||
"use strict";
|
||||
|
||||
module.exports = {
|
||||
"extends": [
|
||||
"../../../../testing/mochitest/browser.eslintrc.js",
|
||||
"../../../../testing/xpcshell/xpcshell.eslintrc.js"
|
||||
]
|
||||
};
|
||||
|
|
@ -1,220 +0,0 @@
|
|||
function handleRequest(request, response)
|
||||
{
|
||||
try {
|
||||
reallyHandleRequest(request, response);
|
||||
} catch (e) {
|
||||
response.setStatusLine("1.0", 200, "AlmostOK");
|
||||
response.write("Error handling request: " + e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function reallyHandleRequest(request, response) {
|
||||
var match;
|
||||
var requestAuth = true, requestProxyAuth = true;
|
||||
|
||||
// Allow the caller to drive how authentication is processed via the query.
|
||||
// Eg, http://localhost:8888/authenticate.sjs?user=foo&realm=bar
|
||||
// The extra ? allows the user/pass/realm checks to succeed if the name is
|
||||
// at the beginning of the query string.
|
||||
var query = "?" + request.queryString;
|
||||
|
||||
var expected_user = "", expected_pass = "", realm = "mochitest";
|
||||
var proxy_expected_user = "", proxy_expected_pass = "", proxy_realm = "mochi-proxy";
|
||||
var huge = false, plugin = false, anonymous = false;
|
||||
var authHeaderCount = 1;
|
||||
// user=xxx
|
||||
match = /[^_]user=([^&]*)/.exec(query);
|
||||
if (match)
|
||||
expected_user = match[1];
|
||||
|
||||
// pass=xxx
|
||||
match = /[^_]pass=([^&]*)/.exec(query);
|
||||
if (match)
|
||||
expected_pass = match[1];
|
||||
|
||||
// realm=xxx
|
||||
match = /[^_]realm=([^&]*)/.exec(query);
|
||||
if (match)
|
||||
realm = match[1];
|
||||
|
||||
// proxy_user=xxx
|
||||
match = /proxy_user=([^&]*)/.exec(query);
|
||||
if (match)
|
||||
proxy_expected_user = match[1];
|
||||
|
||||
// proxy_pass=xxx
|
||||
match = /proxy_pass=([^&]*)/.exec(query);
|
||||
if (match)
|
||||
proxy_expected_pass = match[1];
|
||||
|
||||
// proxy_realm=xxx
|
||||
match = /proxy_realm=([^&]*)/.exec(query);
|
||||
if (match)
|
||||
proxy_realm = match[1];
|
||||
|
||||
// huge=1
|
||||
match = /huge=1/.exec(query);
|
||||
if (match)
|
||||
huge = true;
|
||||
|
||||
// plugin=1
|
||||
match = /plugin=1/.exec(query);
|
||||
if (match)
|
||||
plugin = true;
|
||||
|
||||
// multiple=1
|
||||
match = /multiple=([^&]*)/.exec(query);
|
||||
if (match)
|
||||
authHeaderCount = match[1]+0;
|
||||
|
||||
// anonymous=1
|
||||
match = /anonymous=1/.exec(query);
|
||||
if (match)
|
||||
anonymous = true;
|
||||
|
||||
// Look for an authentication header, if any, in the request.
|
||||
//
|
||||
// EG: Authorization: Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==
|
||||
//
|
||||
// This test only supports Basic auth. The value sent by the client is
|
||||
// "username:password", obscured with base64 encoding.
|
||||
|
||||
var actual_user = "", actual_pass = "", authHeader, authPresent = false;
|
||||
if (request.hasHeader("Authorization")) {
|
||||
authPresent = true;
|
||||
authHeader = request.getHeader("Authorization");
|
||||
match = /Basic (.+)/.exec(authHeader);
|
||||
if (match.length != 2)
|
||||
throw "Couldn't parse auth header: " + authHeader;
|
||||
|
||||
var userpass = base64ToString(match[1]); // no atob() :-(
|
||||
match = /(.*):(.*)/.exec(userpass);
|
||||
if (match.length != 3)
|
||||
throw "Couldn't decode auth header: " + userpass;
|
||||
actual_user = match[1];
|
||||
actual_pass = match[2];
|
||||
}
|
||||
|
||||
var proxy_actual_user = "", proxy_actual_pass = "";
|
||||
if (request.hasHeader("Proxy-Authorization")) {
|
||||
authHeader = request.getHeader("Proxy-Authorization");
|
||||
match = /Basic (.+)/.exec(authHeader);
|
||||
if (match.length != 2)
|
||||
throw "Couldn't parse auth header: " + authHeader;
|
||||
|
||||
var userpass = base64ToString(match[1]); // no atob() :-(
|
||||
match = /(.*):(.*)/.exec(userpass);
|
||||
if (match.length != 3)
|
||||
throw "Couldn't decode auth header: " + userpass;
|
||||
proxy_actual_user = match[1];
|
||||
proxy_actual_pass = match[2];
|
||||
}
|
||||
|
||||
// Don't request authentication if the credentials we got were what we
|
||||
// expected.
|
||||
if (expected_user == actual_user &&
|
||||
expected_pass == actual_pass) {
|
||||
requestAuth = false;
|
||||
}
|
||||
if (proxy_expected_user == proxy_actual_user &&
|
||||
proxy_expected_pass == proxy_actual_pass) {
|
||||
requestProxyAuth = false;
|
||||
}
|
||||
|
||||
if (anonymous) {
|
||||
if (authPresent) {
|
||||
response.setStatusLine("1.0", 400, "Unexpected authorization header found");
|
||||
} else {
|
||||
response.setStatusLine("1.0", 200, "Authorization header not found");
|
||||
}
|
||||
} else {
|
||||
if (requestProxyAuth) {
|
||||
response.setStatusLine("1.0", 407, "Proxy authentication required");
|
||||
for (i = 0; i < authHeaderCount; ++i)
|
||||
response.setHeader("Proxy-Authenticate", "basic realm=\"" + proxy_realm + "\"", true);
|
||||
} else if (requestAuth) {
|
||||
response.setStatusLine("1.0", 401, "Authentication required");
|
||||
for (i = 0; i < authHeaderCount; ++i)
|
||||
response.setHeader("WWW-Authenticate", "basic realm=\"" + realm + "\"", true);
|
||||
} else {
|
||||
response.setStatusLine("1.0", 200, "OK");
|
||||
}
|
||||
}
|
||||
|
||||
response.setHeader("Content-Type", "application/xhtml+xml", false);
|
||||
response.write("<html xmlns='http://www.w3.org/1999/xhtml'>");
|
||||
response.write("<p>Login: <span id='ok'>" + (requestAuth ? "FAIL" : "PASS") + "</span></p>\n");
|
||||
response.write("<p>Proxy: <span id='proxy'>" + (requestProxyAuth ? "FAIL" : "PASS") + "</span></p>\n");
|
||||
response.write("<p>Auth: <span id='auth'>" + authHeader + "</span></p>\n");
|
||||
response.write("<p>User: <span id='user'>" + actual_user + "</span></p>\n");
|
||||
response.write("<p>Pass: <span id='pass'>" + actual_pass + "</span></p>\n");
|
||||
|
||||
if (huge) {
|
||||
response.write("<div style='display: none'>");
|
||||
for (i = 0; i < 100000; i++) {
|
||||
response.write("123456789\n");
|
||||
}
|
||||
response.write("</div>");
|
||||
response.write("<span id='footnote'>This is a footnote after the huge content fill</span>");
|
||||
}
|
||||
|
||||
if (plugin) {
|
||||
response.write("<embed id='embedtest' style='width: 400px; height: 100px;' " +
|
||||
"type='application/x-test'></embed>\n");
|
||||
}
|
||||
|
||||
response.write("</html>");
|
||||
}
|
||||
|
||||
|
||||
// base64 decoder
|
||||
//
|
||||
// Yoinked from extensions/xml-rpc/src/nsXmlRpcClient.js because btoa()
|
||||
// doesn't seem to exist. :-(
|
||||
/* Convert Base64 data to a string */
|
||||
const toBinaryTable = [
|
||||
-1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1,
|
||||
-1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1,
|
||||
-1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,62, -1,-1,-1,63,
|
||||
52,53,54,55, 56,57,58,59, 60,61,-1,-1, -1, 0,-1,-1,
|
||||
-1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10, 11,12,13,14,
|
||||
15,16,17,18, 19,20,21,22, 23,24,25,-1, -1,-1,-1,-1,
|
||||
-1,26,27,28, 29,30,31,32, 33,34,35,36, 37,38,39,40,
|
||||
41,42,43,44, 45,46,47,48, 49,50,51,-1, -1,-1,-1,-1
|
||||
];
|
||||
const base64Pad = '=';
|
||||
|
||||
function base64ToString(data) {
|
||||
|
||||
var result = '';
|
||||
var leftbits = 0; // number of bits decoded, but yet to be appended
|
||||
var leftdata = 0; // bits decoded, but yet to be appended
|
||||
|
||||
// Convert one by one.
|
||||
for (var i = 0; i < data.length; i++) {
|
||||
var c = toBinaryTable[data.charCodeAt(i) & 0x7f];
|
||||
var padding = (data[i] == base64Pad);
|
||||
// Skip illegal characters and whitespace
|
||||
if (c == -1) continue;
|
||||
|
||||
// Collect data into leftdata, update bitcount
|
||||
leftdata = (leftdata << 6) | c;
|
||||
leftbits += 6;
|
||||
|
||||
// If we have 8 or more bits, append 8 bits to the result
|
||||
if (leftbits >= 8) {
|
||||
leftbits -= 8;
|
||||
// Append if not padding.
|
||||
if (!padding)
|
||||
result += String.fromCharCode((leftdata >> leftbits) & 0xff);
|
||||
leftdata &= (1 << leftbits) - 1;
|
||||
}
|
||||
}
|
||||
|
||||
// If there are any bits left, the base64 string was corrupted
|
||||
if (leftbits)
|
||||
throw Components.Exception('Corrupted base64 string');
|
||||
|
||||
return result;
|
||||
}
|
||||
|
|
@ -1,3 +0,0 @@
|
|||
<html>
|
||||
<body bgcolor=ff0000></body>
|
||||
</html>
|
||||
|
|
@ -1,10 +0,0 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
function handleRequest(aRequest, aResponse) {
|
||||
// Set HTTP Status.
|
||||
aResponse.setStatusLine(aRequest.httpVersion, 301, "Moved Permanently");
|
||||
|
||||
// Set redirect URI.
|
||||
aResponse.setHeader("Location", "http://mochi.test:8888/browser/toolkit/components/thumbnails/test/background_red.html");
|
||||
}
|
||||
|
|
@ -1,3 +0,0 @@
|
|||
<html>
|
||||
<body bgcolor=ff0000 style="overflow: scroll;"></body>
|
||||
</html>
|
||||
|
|
@ -1,38 +0,0 @@
|
|||
[DEFAULT]
|
||||
support-files =
|
||||
authenticate.sjs
|
||||
background_red.html
|
||||
background_red_redirect.sjs
|
||||
background_red_scroll.html
|
||||
head.js
|
||||
privacy_cache_control.sjs
|
||||
thumbnails_background.sjs
|
||||
thumbnails_crash_content_helper.js
|
||||
thumbnails_update.sjs
|
||||
|
||||
[browser_thumbnails_bg_bad_url.js]
|
||||
[browser_thumbnails_bg_crash_during_capture.js]
|
||||
skip-if = !crashreporter
|
||||
[browser_thumbnails_bg_crash_while_idle.js]
|
||||
skip-if = !crashreporter
|
||||
[browser_thumbnails_bg_basic.js]
|
||||
[browser_thumbnails_bg_queueing.js]
|
||||
[browser_thumbnails_bg_timeout.js]
|
||||
[browser_thumbnails_bg_redirect.js]
|
||||
[browser_thumbnails_bg_destroy_browser.js]
|
||||
[browser_thumbnails_bg_no_cookies_sent.js]
|
||||
[browser_thumbnails_bg_no_cookies_stored.js]
|
||||
[browser_thumbnails_bg_no_auth_prompt.js]
|
||||
[browser_thumbnails_bg_no_alert.js]
|
||||
[browser_thumbnails_bg_no_duplicates.js]
|
||||
[browser_thumbnails_bg_captureIfMissing.js]
|
||||
[browser_thumbnails_bug726727.js]
|
||||
[browser_thumbnails_bug727765.js]
|
||||
[browser_thumbnails_bug818225.js]
|
||||
[browser_thumbnails_capture.js]
|
||||
[browser_thumbnails_expiration.js]
|
||||
[browser_thumbnails_privacy.js]
|
||||
[browser_thumbnails_redirect.js]
|
||||
[browser_thumbnails_storage.js]
|
||||
[browser_thumbnails_storage_migrate3.js]
|
||||
[browser_thumbnails_update.js]
|
||||
|
|
@ -1,23 +0,0 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
function* runTests() {
|
||||
let url = "invalid-protocol://ffggfsdfsdf/";
|
||||
ok(!thumbnailExists(url), "Thumbnail should not be cached already.");
|
||||
let numCalls = 0;
|
||||
BackgroundPageThumbs.capture(url, {
|
||||
onDone: function onDone(capturedURL) {
|
||||
is(capturedURL, url, "Captured URL should be URL passed to capture");
|
||||
is(numCalls++, 0, "onDone should be called only once");
|
||||
ok(!thumbnailExists(url),
|
||||
"Capture failed so thumbnail should not be cached");
|
||||
next();
|
||||
},
|
||||
});
|
||||
yield new Promise(resolve => {
|
||||
bgAddPageThumbObserver(url).catch(function(err) {
|
||||
ok(true, "page-thumbnail error produced");
|
||||
resolve();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
|
@ -1,20 +0,0 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
function* runTests() {
|
||||
let url = "http://www.example.com/";
|
||||
ok(!thumbnailExists(url), "Thumbnail should not be cached yet.");
|
||||
|
||||
let capturePromise = new Promise(resolve => {
|
||||
bgAddPageThumbObserver(url).then(() => {
|
||||
ok(true, `page-thumbnail created for ${url}`);
|
||||
resolve();
|
||||
});
|
||||
});
|
||||
let capturedURL = yield bgCapture(url);
|
||||
is(capturedURL, url, "Captured URL should be URL passed to capture");
|
||||
yield capturePromise;
|
||||
|
||||
ok(thumbnailExists(url), "Thumbnail should be cached after capture");
|
||||
removeThumbnail(url);
|
||||
}
|
||||
|
|
@ -1,35 +0,0 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
function* runTests() {
|
||||
let numNotifications = 0;
|
||||
function observe(subject, topic, data) {
|
||||
is(topic, "page-thumbnail:create", "got expected topic");
|
||||
numNotifications += 1;
|
||||
}
|
||||
|
||||
Services.obs.addObserver(observe, "page-thumbnail:create", false);
|
||||
|
||||
let url = "http://example.com/";
|
||||
let file = thumbnailFile(url);
|
||||
ok(!file.exists(), "Thumbnail file should not already exist.");
|
||||
|
||||
let capturedURL = yield bgCaptureIfMissing(url);
|
||||
is(numNotifications, 1, "got notification of item being created.");
|
||||
is(capturedURL, url, "Captured URL should be URL passed to capture");
|
||||
ok(file.exists(url), "Thumbnail should be cached after capture");
|
||||
|
||||
let past = Date.now() - 1000000000;
|
||||
let pastFudge = past + 30000;
|
||||
file.lastModifiedTime = past;
|
||||
ok(file.lastModifiedTime < pastFudge, "Last modified time should stick!");
|
||||
capturedURL = yield bgCaptureIfMissing(url);
|
||||
is(numNotifications, 1, "still only 1 notification of item being created.");
|
||||
is(capturedURL, url, "Captured URL should be URL passed to second capture");
|
||||
ok(file.exists(), "Thumbnail should remain cached after second capture");
|
||||
ok(file.lastModifiedTime < pastFudge,
|
||||
"File should not have been overwritten");
|
||||
|
||||
file.remove(false);
|
||||
Services.obs.removeObserver(observe, "page-thumbnail:create");
|
||||
}
|
||||
|
|
@ -1,49 +0,0 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
function* runTests() {
|
||||
let crashObserver = bgAddCrashObserver();
|
||||
|
||||
// make a good capture first - this ensures we have the <browser>
|
||||
let goodUrl = bgTestPageURL();
|
||||
yield bgCapture(goodUrl);
|
||||
ok(thumbnailExists(goodUrl), "Thumbnail should be cached after capture");
|
||||
removeThumbnail(goodUrl);
|
||||
|
||||
// inject our content script.
|
||||
let mm = bgInjectCrashContentScript();
|
||||
|
||||
// queue up 2 captures - the first has a wait, so this is the one that
|
||||
// will die. The second one should immediately capture after the crash.
|
||||
let waitUrl = bgTestPageURL({ wait: 30000 });
|
||||
let sawWaitUrlCapture = false;
|
||||
bgCapture(waitUrl, { onDone: () => {
|
||||
sawWaitUrlCapture = true;
|
||||
ok(!thumbnailExists(waitUrl), "Thumbnail should not have been saved due to the crash");
|
||||
}});
|
||||
bgCapture(goodUrl, { onDone: () => {
|
||||
ok(sawWaitUrlCapture, "waitUrl capture should have finished first");
|
||||
ok(thumbnailExists(goodUrl), "We should have recovered and completed the 2nd capture after the crash");
|
||||
removeThumbnail(goodUrl);
|
||||
// Test done.
|
||||
ok(crashObserver.crashed, "Saw a crash from this test");
|
||||
next();
|
||||
}});
|
||||
let crashPromise = new Promise(resolve => {
|
||||
bgAddPageThumbObserver(waitUrl).catch(function(err) {
|
||||
ok(true, `page-thumbnail error thrown for ${waitUrl}`);
|
||||
resolve();
|
||||
});
|
||||
});
|
||||
let capturePromise = new Promise(resolve => {
|
||||
bgAddPageThumbObserver(goodUrl).then(() => {
|
||||
ok(true, `page-thumbnail created for ${goodUrl}`);
|
||||
resolve();
|
||||
});
|
||||
});
|
||||
|
||||
info("Crashing the thumbnail content process.");
|
||||
mm.sendAsyncMessage("thumbnails-test:crash");
|
||||
yield crashPromise;
|
||||
yield capturePromise;
|
||||
}
|
||||
|
|
@ -1,38 +0,0 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
function* runTests() {
|
||||
let crashObserver = bgAddCrashObserver();
|
||||
|
||||
// make a good capture first - this ensures we have the <browser>
|
||||
let goodUrl = bgTestPageURL();
|
||||
yield bgCapture(goodUrl);
|
||||
ok(thumbnailExists(goodUrl), "Thumbnail should be cached after capture");
|
||||
removeThumbnail(goodUrl);
|
||||
|
||||
// inject our content script.
|
||||
let mm = bgInjectCrashContentScript();
|
||||
|
||||
// the observer for the crashing process is basically async, so it's hard
|
||||
// to know when the <browser> has actually seen it. Easist is to just add
|
||||
// our own observer.
|
||||
Services.obs.addObserver(function onCrash() {
|
||||
Services.obs.removeObserver(onCrash, "oop-frameloader-crashed");
|
||||
// spin the event loop to ensure the BPT observer was called.
|
||||
executeSoon(function() {
|
||||
// Now queue another capture and ensure it recovers.
|
||||
bgCapture(goodUrl, { onDone: () => {
|
||||
ok(thumbnailExists(goodUrl), "We should have recovered and handled new capture requests");
|
||||
removeThumbnail(goodUrl);
|
||||
// Test done.
|
||||
ok(crashObserver.crashed, "Saw a crash from this test");
|
||||
next();
|
||||
}});
|
||||
});
|
||||
}, "oop-frameloader-crashed", false);
|
||||
|
||||
// Nothing is pending - crash the process.
|
||||
info("Crashing the thumbnail content process.");
|
||||
mm.sendAsyncMessage("thumbnails-test:crash");
|
||||
yield true;
|
||||
}
|
||||
|
|
@ -1,33 +0,0 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
function* runTests() {
|
||||
yield SpecialPowers.pushPrefEnv({
|
||||
set: [["dom.ipc.processCount", 1]]
|
||||
});
|
||||
|
||||
let url1 = "http://example.com/1";
|
||||
ok(!thumbnailExists(url1), "First file should not exist yet.");
|
||||
|
||||
let url2 = "http://example.com/2";
|
||||
ok(!thumbnailExists(url2), "Second file should not exist yet.");
|
||||
|
||||
let defaultTimeout = BackgroundPageThumbs._destroyBrowserTimeout;
|
||||
BackgroundPageThumbs._destroyBrowserTimeout = 1000;
|
||||
|
||||
yield bgCapture(url1);
|
||||
ok(thumbnailExists(url1), "First file should exist after capture.");
|
||||
removeThumbnail(url1);
|
||||
|
||||
yield wait(2000);
|
||||
is(BackgroundPageThumbs._thumbBrowser, undefined,
|
||||
"Thumb browser should be destroyed after timeout.");
|
||||
BackgroundPageThumbs._destroyBrowserTimeout = defaultTimeout;
|
||||
|
||||
yield bgCapture(url2);
|
||||
ok(thumbnailExists(url2), "Second file should exist after capture.");
|
||||
removeThumbnail(url2);
|
||||
|
||||
isnot(BackgroundPageThumbs._thumbBrowser, undefined,
|
||||
"Thumb browser should exist immediately after capture.");
|
||||
}
|
||||
|
|
@ -1,13 +0,0 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
function* runTests() {
|
||||
let url = "data:text/html,<script>try { alert('yo!'); } catch (e) {}</script>";
|
||||
ok(!thumbnailExists(url), "Thumbnail file should not already exist.");
|
||||
|
||||
let capturedURL = yield bgCapture(url);
|
||||
is(capturedURL, url, "Captured URL should be URL passed to capture.");
|
||||
ok(thumbnailExists(url),
|
||||
"Thumbnail file should exist even though it alerted.");
|
||||
removeThumbnail(url);
|
||||
}
|
||||
|
|
@ -1,21 +0,0 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
// the following tests attempt to display modal dialogs. The test just
|
||||
// relies on the fact that if the dialog was displayed the test will hang
|
||||
// and timeout. IOW - the tests would pass if the dialogs appear and are
|
||||
// manually closed by the user - so don't do that :) (obviously there is
|
||||
// noone available to do that when run via tbpl etc, so this should be safe,
|
||||
// and it's tricky to use the window-watcher to check a window *does not*
|
||||
// appear - how long should the watcher be active before assuming it's not
|
||||
// going to appear?)
|
||||
function* runTests() {
|
||||
let url = "http://mochi.test:8888/browser/toolkit/components/thumbnails/test/authenticate.sjs?user=anyone";
|
||||
ok(!thumbnailExists(url), "Thumbnail file should not already exist.");
|
||||
|
||||
let capturedURL = yield bgCapture(url);
|
||||
is(capturedURL, url, "Captured URL should be URL passed to capture.");
|
||||
ok(thumbnailExists(url),
|
||||
"Thumbnail file should exist even though it requires auth.");
|
||||
removeThumbnail(url);
|
||||
}
|
||||
|
|
@ -1,40 +0,0 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
function* runTests() {
|
||||
// Visit the test page in the browser and tell it to set a cookie.
|
||||
let url = bgTestPageURL({ setGreenCookie: true });
|
||||
let tab = yield BrowserTestUtils.openNewForegroundTab(gBrowser, url);
|
||||
let browser = tab.linkedBrowser;
|
||||
|
||||
// The root element of the page shouldn't be green yet.
|
||||
yield ContentTask.spawn(browser, null, function () {
|
||||
Assert.notEqual(content.document.documentElement.style.backgroundColor,
|
||||
"rgb(0, 255, 0)",
|
||||
"The page shouldn't be green yet.");
|
||||
});
|
||||
|
||||
// Cookie should be set now. Reload the page to verify. Its root element
|
||||
// will be green if the cookie's set.
|
||||
browser.reload();
|
||||
yield BrowserTestUtils.browserLoaded(browser);
|
||||
yield ContentTask.spawn(browser, null, function () {
|
||||
Assert.equal(content.document.documentElement.style.backgroundColor,
|
||||
"rgb(0, 255, 0)",
|
||||
"The page should be green now.");
|
||||
});
|
||||
|
||||
// Capture the page. Get the image data of the capture and verify it's not
|
||||
// green. (Checking only the first pixel suffices.)
|
||||
yield bgCapture(url);
|
||||
ok(thumbnailExists(url), "Thumbnail file should exist after capture.");
|
||||
|
||||
retrieveImageDataForURL(url, function ([r, g, b]) {
|
||||
isnot([r, g, b].toString(), [0, 255, 0].toString(),
|
||||
"The captured page should not be green.");
|
||||
gBrowser.removeTab(tab);
|
||||
removeThumbnail(url);
|
||||
next();
|
||||
});
|
||||
yield true;
|
||||
}
|
||||
|
|
@ -1,32 +0,0 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
// check that if a page captured in the background attempts to set a cookie,
|
||||
// that cookie is not saved for subsequent requests.
|
||||
function* runTests() {
|
||||
yield SpecialPowers.pushPrefEnv({
|
||||
set: [["privacy.usercontext.about_newtab_segregation.enabled", true]]
|
||||
});
|
||||
let url = bgTestPageURL({
|
||||
setRedCookie: true,
|
||||
iframe: bgTestPageURL({ setRedCookie: true}),
|
||||
xhr: bgTestPageURL({ setRedCookie: true})
|
||||
});
|
||||
ok(!thumbnailExists(url), "Thumbnail file should not exist before capture.");
|
||||
yield bgCapture(url);
|
||||
ok(thumbnailExists(url), "Thumbnail file should exist after capture.");
|
||||
removeThumbnail(url);
|
||||
// now load it up in a browser - it should *not* be red, otherwise the
|
||||
// cookie above was saved.
|
||||
let tab = yield BrowserTestUtils.openNewForegroundTab(gBrowser, url);
|
||||
let browser = tab.linkedBrowser;
|
||||
|
||||
// The root element of the page shouldn't be red.
|
||||
yield ContentTask.spawn(browser, null, function() {
|
||||
Assert.notEqual(content.document.documentElement.style.backgroundColor,
|
||||
"rgb(255, 0, 0)",
|
||||
"The page shouldn't be red.");
|
||||
});
|
||||
|
||||
gBrowser.removeTab(tab);
|
||||
}
|
||||
|
|
@ -1,31 +0,0 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
function* runTests() {
|
||||
let url = "http://example.com/1";
|
||||
ok(!thumbnailExists(url), "Thumbnail file should not already exist.");
|
||||
let numCallbacks = 0;
|
||||
let doneCallback = function(doneUrl) {
|
||||
is(doneUrl, url, "called back with correct url");
|
||||
numCallbacks += 1;
|
||||
// We will delete the file after the first callback, then check it
|
||||
// still doesn't exist on the second callback, which should give us
|
||||
// confidence that we didn't end up with 2 different captures happening
|
||||
// for the same url...
|
||||
if (numCallbacks == 1) {
|
||||
ok(thumbnailExists(url), "Thumbnail file should now exist.");
|
||||
removeThumbnail(url);
|
||||
return;
|
||||
}
|
||||
if (numCallbacks == 2) {
|
||||
ok(!thumbnailExists(url), "Thumbnail file should still be deleted.");
|
||||
// and that's all we expect, so we are done...
|
||||
next();
|
||||
return;
|
||||
}
|
||||
ok(false, "only expecting 2 callbacks");
|
||||
}
|
||||
BackgroundPageThumbs.capture(url, {onDone: doneCallback});
|
||||
BackgroundPageThumbs.capture(url, {onDone: doneCallback});
|
||||
yield true;
|
||||
}
|
||||
|
|
@ -1,38 +0,0 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
function* runTests() {
|
||||
let urls = [
|
||||
"http://www.example.com/0",
|
||||
"http://www.example.com/1",
|
||||
// an item that will timeout to ensure timeouts work and we resume.
|
||||
bgTestPageURL({ wait: 2002 }),
|
||||
"http://www.example.com/2",
|
||||
];
|
||||
dontExpireThumbnailURLs(urls);
|
||||
urls.forEach(url => {
|
||||
ok(!thumbnailExists(url), "Thumbnail should not exist yet: " + url);
|
||||
let isTimeoutTest = url.indexOf("wait") >= 0;
|
||||
BackgroundPageThumbs.capture(url, {
|
||||
timeout: isTimeoutTest ? 100 : 30000,
|
||||
onDone: function onDone(capturedURL) {
|
||||
ok(urls.length > 0, "onDone called, so URLs should still remain");
|
||||
is(capturedURL, urls.shift(),
|
||||
"Captured URL should be currently expected URL (i.e., " +
|
||||
"capture() callbacks should be called in the correct order)");
|
||||
if (isTimeoutTest) {
|
||||
ok(!thumbnailExists(capturedURL),
|
||||
"Thumbnail shouldn't exist for timed out capture");
|
||||
} else {
|
||||
ok(thumbnailExists(capturedURL),
|
||||
"Thumbnail should be cached after capture");
|
||||
removeThumbnail(url);
|
||||
}
|
||||
if (!urls.length)
|
||||
// Test done.
|
||||
next();
|
||||
},
|
||||
});
|
||||
});
|
||||
yield true;
|
||||
}
|
||||
|
|
@ -1,39 +0,0 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
function* runTests() {
|
||||
let finalURL = "http://example.com/redirected";
|
||||
let originalURL = bgTestPageURL({ redirect: finalURL });
|
||||
|
||||
ok(!thumbnailExists(originalURL),
|
||||
"Thumbnail file for original URL should not exist yet.");
|
||||
ok(!thumbnailExists(finalURL),
|
||||
"Thumbnail file for final URL should not exist yet.");
|
||||
|
||||
let captureOriginalPromise = new Promise(resolve => {
|
||||
bgAddPageThumbObserver(originalURL).then(() => {
|
||||
ok(true, `page-thumbnail created for ${originalURL}`);
|
||||
resolve();
|
||||
});
|
||||
});
|
||||
|
||||
let captureFinalPromise = new Promise(resolve => {
|
||||
bgAddPageThumbObserver(finalURL).then(() => {
|
||||
ok(true, `page-thumbnail created for ${finalURL}`);
|
||||
resolve();
|
||||
});
|
||||
});
|
||||
|
||||
let capturedURL = yield bgCapture(originalURL);
|
||||
is(capturedURL, originalURL,
|
||||
"Captured URL should be URL passed to capture");
|
||||
yield captureOriginalPromise;
|
||||
yield captureFinalPromise;
|
||||
ok(thumbnailExists(originalURL),
|
||||
"Thumbnail for original URL should be cached");
|
||||
ok(thumbnailExists(finalURL),
|
||||
"Thumbnail for final URL should be cached");
|
||||
|
||||
removeThumbnail(originalURL);
|
||||
removeThumbnail(finalURL);
|
||||
}
|
||||
|
|
@ -1,24 +0,0 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
function* runTests() {
|
||||
let url = bgTestPageURL({ wait: 30000 });
|
||||
ok(!thumbnailExists(url), "Thumbnail should not be cached already.");
|
||||
let numCalls = 0;
|
||||
BackgroundPageThumbs.capture(url, {
|
||||
timeout: 0,
|
||||
onDone: function onDone(capturedURL) {
|
||||
is(capturedURL, url, "Captured URL should be URL passed to capture");
|
||||
is(numCalls++, 0, "onDone should be called only once");
|
||||
ok(!thumbnailExists(url),
|
||||
"Capture timed out so thumbnail should not be cached");
|
||||
next();
|
||||
},
|
||||
});
|
||||
yield new Promise(resolve => {
|
||||
bgAddPageThumbObserver(url).catch(function(err) {
|
||||
ok(true, `page-thumbnail error thrown for ${url}`);
|
||||
resolve();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
|
@ -1,19 +0,0 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
/**
|
||||
* These tests ensure that capturing a sites's thumbnail, saving it and
|
||||
* retrieving it from the cache works.
|
||||
*/
|
||||
function* runTests() {
|
||||
// Create a tab that shows an error page.
|
||||
let tab = gBrowser.addTab("http://127.0.0.1:1/");
|
||||
let browser = tab.linkedBrowser;
|
||||
yield browser.addEventListener("DOMContentLoaded", function onLoad() {
|
||||
browser.removeEventListener("DOMContentLoaded", onLoad, false);
|
||||
PageThumbs.shouldStoreThumbnail(browser, (aResult) => {
|
||||
ok(!aResult, "we're not going to capture an error page");
|
||||
executeSoon(next);
|
||||
});
|
||||
}, false);
|
||||
}
|
||||
|
|
@ -1,29 +0,0 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
const URL = "http://mochi.test:8888/browser/toolkit/components/thumbnails/" +
|
||||
"test/background_red_scroll.html";
|
||||
|
||||
function isRedThumbnailFuzz(r, g, b, expectedR, expectedB, expectedG, aFuzz)
|
||||
{
|
||||
return (Math.abs(r - expectedR) <= aFuzz) &&
|
||||
(Math.abs(g - expectedG) <= aFuzz) &&
|
||||
(Math.abs(b - expectedB) <= aFuzz);
|
||||
}
|
||||
|
||||
// Test for black borders caused by scrollbars.
|
||||
function* runTests() {
|
||||
// Create a tab with a page with a red background and scrollbars.
|
||||
yield addTab(URL);
|
||||
yield captureAndCheckColor(255, 0, 0, "we have a red thumbnail");
|
||||
|
||||
// Check the thumbnail color of the bottom right pixel.
|
||||
yield whenFileExists(URL);
|
||||
yield retrieveImageDataForURL(URL, function (aData) {
|
||||
let [r, g, b] = [].slice.call(aData, -4);
|
||||
let fuzz = 2; // Windows 8 x64 blends with the scrollbar a bit.
|
||||
var message = "Expected red thumbnail rgb(255, 0, 0), got " + r + "," + g + "," + b;
|
||||
ok(isRedThumbnailFuzz(r, g, b, 255, 0, 0, fuzz), message);
|
||||
next();
|
||||
});
|
||||
}
|
||||
|
|
@ -1,42 +0,0 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
const URL = "http://mochi.test:8888/browser/toolkit/components/thumbnails/" +
|
||||
"test/background_red.html?" + Date.now();
|
||||
|
||||
// Test PageThumbs API function getThumbnailPath
|
||||
function* runTests() {
|
||||
|
||||
let path = PageThumbs.getThumbnailPath(URL);
|
||||
yield testIfExists(path, false, "Thumbnail file does not exist");
|
||||
|
||||
yield addVisitsAndRepopulateNewTabLinks(URL, next);
|
||||
yield createThumbnail(URL);
|
||||
|
||||
path = PageThumbs.getThumbnailPath(URL);
|
||||
let expectedPath = PageThumbsStorage.getFilePathForURL(URL);
|
||||
is(path, expectedPath, "Thumbnail file has correct path");
|
||||
|
||||
yield testIfExists(path, true, "Thumbnail file exists");
|
||||
|
||||
}
|
||||
|
||||
function createThumbnail(aURL) {
|
||||
addTab(aURL, function () {
|
||||
whenFileExists(aURL, function () {
|
||||
gBrowser.removeTab(gBrowser.selectedTab);
|
||||
next();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function testIfExists(aPath, aExpected, aMessage) {
|
||||
return OS.File.exists(aPath).then(
|
||||
function onSuccess(exists) {
|
||||
is(exists, aExpected, aMessage);
|
||||
},
|
||||
function onFailure(error) {
|
||||
ok(false, "OS.File.exists() failed " + error);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
|
@ -1,20 +0,0 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
/**
|
||||
* These tests ensure that capturing a sites's thumbnail, saving it and
|
||||
* retrieving it from the cache works.
|
||||
*/
|
||||
function* runTests() {
|
||||
// Create a tab with a red background.
|
||||
yield addTab("data:text/html,<body bgcolor=ff0000></body>");
|
||||
yield captureAndCheckColor(255, 0, 0, "we have a red thumbnail");
|
||||
|
||||
// Load a page with a green background.
|
||||
yield navigateTo("data:text/html,<body bgcolor=00ff00></body>");
|
||||
yield captureAndCheckColor(0, 255, 0, "we have a green thumbnail");
|
||||
|
||||
// Load a page with a blue background.
|
||||
yield navigateTo("data:text/html,<body bgcolor=0000ff></body>");
|
||||
yield captureAndCheckColor(0, 0, 255, "we have a blue thumbnail");
|
||||
}
|
||||
|
|
@ -1,97 +0,0 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
const URL = "http://mochi.test:8888/?t=" + Date.now();
|
||||
const URL1 = URL + "#1";
|
||||
const URL2 = URL + "#2";
|
||||
const URL3 = URL + "#3";
|
||||
|
||||
var tmp = {};
|
||||
Cc["@mozilla.org/moz/jssubscript-loader;1"]
|
||||
.getService(Ci.mozIJSSubScriptLoader)
|
||||
.loadSubScript("resource://gre/modules/PageThumbs.jsm", tmp);
|
||||
|
||||
const EXPIRATION_MIN_CHUNK_SIZE = 50;
|
||||
const {PageThumbsExpiration} = tmp;
|
||||
|
||||
function* runTests() {
|
||||
// Create dummy URLs.
|
||||
let dummyURLs = [];
|
||||
for (let i = 0; i < EXPIRATION_MIN_CHUNK_SIZE + 10; i++) {
|
||||
dummyURLs.push(URL + "#dummy" + i);
|
||||
}
|
||||
|
||||
// Make sure our thumbnails aren't expired too early.
|
||||
dontExpireThumbnailURLs([URL1, URL2, URL3].concat(dummyURLs));
|
||||
|
||||
// Create three thumbnails.
|
||||
yield createDummyThumbnail(URL1);
|
||||
ok(thumbnailExists(URL1), "first thumbnail created");
|
||||
|
||||
yield createDummyThumbnail(URL2);
|
||||
ok(thumbnailExists(URL2), "second thumbnail created");
|
||||
|
||||
yield createDummyThumbnail(URL3);
|
||||
ok(thumbnailExists(URL3), "third thumbnail created");
|
||||
|
||||
// Remove the third thumbnail.
|
||||
yield expireThumbnails([URL1, URL2]);
|
||||
ok(thumbnailExists(URL1), "first thumbnail still exists");
|
||||
ok(thumbnailExists(URL2), "second thumbnail still exists");
|
||||
ok(!thumbnailExists(URL3), "third thumbnail has been removed");
|
||||
|
||||
// Remove the second thumbnail.
|
||||
yield expireThumbnails([URL1]);
|
||||
ok(thumbnailExists(URL1), "first thumbnail still exists");
|
||||
ok(!thumbnailExists(URL2), "second thumbnail has been removed");
|
||||
|
||||
// Remove all thumbnails.
|
||||
yield expireThumbnails([]);
|
||||
ok(!thumbnailExists(URL1), "all thumbnails have been removed");
|
||||
|
||||
// Create some more files than the min chunk size.
|
||||
for (let url of dummyURLs) {
|
||||
yield createDummyThumbnail(url);
|
||||
}
|
||||
|
||||
ok(dummyURLs.every(thumbnailExists), "all dummy thumbnails created");
|
||||
|
||||
// Expire thumbnails and expect 10 remaining.
|
||||
yield expireThumbnails([]);
|
||||
let remainingURLs = dummyURLs.filter(thumbnailExists);
|
||||
is(remainingURLs.length, 10, "10 dummy thumbnails remaining");
|
||||
|
||||
// Expire thumbnails again. All should be gone by now.
|
||||
yield expireThumbnails([]);
|
||||
remainingURLs = remainingURLs.filter(thumbnailExists);
|
||||
is(remainingURLs.length, 0, "no dummy thumbnails remaining");
|
||||
}
|
||||
|
||||
function createDummyThumbnail(aURL) {
|
||||
info("Creating dummy thumbnail for " + aURL);
|
||||
let dummy = new Uint8Array(10);
|
||||
for (let i = 0; i < 10; ++i) {
|
||||
dummy[i] = i;
|
||||
}
|
||||
PageThumbsStorage.writeData(aURL, dummy).then(
|
||||
function onSuccess() {
|
||||
info("createDummyThumbnail succeeded");
|
||||
executeSoon(next);
|
||||
},
|
||||
function onFailure(error) {
|
||||
ok(false, "createDummyThumbnail failed " + error);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
function expireThumbnails(aKeep) {
|
||||
PageThumbsExpiration.expireThumbnails(aKeep).then(
|
||||
function onSuccess() {
|
||||
info("expireThumbnails succeeded");
|
||||
executeSoon(next);
|
||||
},
|
||||
function onFailure(error) {
|
||||
ok(false, "expireThumbnails failed " + error);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
|
@ -1,74 +0,0 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
const PREF_DISK_CACHE_SSL = "browser.cache.disk_cache_ssl";
|
||||
const URL = "://example.com/browser/toolkit/components/thumbnails/" +
|
||||
"test/privacy_cache_control.sjs";
|
||||
|
||||
function* runTests() {
|
||||
registerCleanupFunction(function () {
|
||||
Services.prefs.clearUserPref(PREF_DISK_CACHE_SSL);
|
||||
});
|
||||
|
||||
let positive = [
|
||||
// A normal HTTP page without any Cache-Control header.
|
||||
{scheme: "http", cacheControl: null, diskCacheSSL: false},
|
||||
|
||||
// A normal HTTP page with 'Cache-Control: private'.
|
||||
{scheme: "http", cacheControl: "private", diskCacheSSL: false},
|
||||
|
||||
// Capture HTTPS pages if browser.cache.disk_cache_ssl == true.
|
||||
{scheme: "https", cacheControl: null, diskCacheSSL: true},
|
||||
{scheme: "https", cacheControl: "public", diskCacheSSL: true},
|
||||
{scheme: "https", cacheControl: "private", diskCacheSSL: true}
|
||||
];
|
||||
|
||||
let negative = [
|
||||
// Never capture pages with 'Cache-Control: no-store'.
|
||||
{scheme: "http", cacheControl: "no-store", diskCacheSSL: false},
|
||||
{scheme: "http", cacheControl: "no-store", diskCacheSSL: true},
|
||||
{scheme: "https", cacheControl: "no-store", diskCacheSSL: false},
|
||||
{scheme: "https", cacheControl: "no-store", diskCacheSSL: true},
|
||||
|
||||
// Don't capture HTTPS pages by default.
|
||||
{scheme: "https", cacheControl: null, diskCacheSSL: false},
|
||||
{scheme: "https", cacheControl: "public", diskCacheSSL: false},
|
||||
{scheme: "https", cacheControl: "private", diskCacheSSL: false}
|
||||
];
|
||||
|
||||
yield checkCombinations(positive, true);
|
||||
yield checkCombinations(negative, false);
|
||||
}
|
||||
|
||||
function checkCombinations(aCombinations, aResult) {
|
||||
let combi = aCombinations.shift();
|
||||
if (!combi) {
|
||||
next();
|
||||
return;
|
||||
}
|
||||
|
||||
let url = combi.scheme + URL;
|
||||
if (combi.cacheControl)
|
||||
url += "?" + combi.cacheControl;
|
||||
Services.prefs.setBoolPref(PREF_DISK_CACHE_SSL, combi.diskCacheSSL);
|
||||
|
||||
// Add the test page as a top link so it has a chance to be thumbnailed
|
||||
addVisitsAndRepopulateNewTabLinks(url, _ => {
|
||||
testCombination(combi, url, aCombinations, aResult);
|
||||
});
|
||||
}
|
||||
|
||||
function testCombination(combi, url, aCombinations, aResult) {
|
||||
let tab = gBrowser.selectedTab = gBrowser.addTab(url);
|
||||
let browser = gBrowser.selectedBrowser;
|
||||
|
||||
whenLoaded(browser, () => {
|
||||
let msg = JSON.stringify(combi) + " == " + aResult;
|
||||
PageThumbs.shouldStoreThumbnail(browser, (aIsSafeSite) => {
|
||||
is(aIsSafeSite, aResult, msg);
|
||||
gBrowser.removeTab(tab);
|
||||
// Continue with the next combination.
|
||||
checkCombinations(aCombinations, aResult);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
|
@ -1,30 +0,0 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
const URL = "http://mochi.test:8888/browser/toolkit/components/thumbnails/" +
|
||||
"test/background_red_redirect.sjs";
|
||||
// loading URL will redirect us to...
|
||||
const FINAL_URL = "http://mochi.test:8888/browser/toolkit/components/" +
|
||||
"thumbnails/test/background_red.html";
|
||||
|
||||
/**
|
||||
* These tests ensure that we save and provide thumbnails for redirecting sites.
|
||||
*/
|
||||
function* runTests() {
|
||||
dontExpireThumbnailURLs([URL, FINAL_URL]);
|
||||
|
||||
// Kick off history by loading a tab first or the test fails in single mode.
|
||||
yield addTab(URL);
|
||||
gBrowser.removeTab(gBrowser.selectedTab);
|
||||
|
||||
// Create a tab, redirecting to a page with a red background.
|
||||
yield addTab(URL);
|
||||
yield captureAndCheckColor(255, 0, 0, "we have a red thumbnail");
|
||||
|
||||
// Wait until the referrer's thumbnail's file has been written.
|
||||
yield whenFileExists(URL);
|
||||
yield retrieveImageDataForURL(URL, function ([r, g, b]) {
|
||||
is("" + [r, g, b], "255,0,0", "referrer has a red thumbnail");
|
||||
next();
|
||||
});
|
||||
}
|
||||
|
|
@ -1,112 +0,0 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
const URL = "http://mochi.test:8888/";
|
||||
const URL_COPY = URL + "#copy";
|
||||
|
||||
XPCOMUtils.defineLazyGetter(this, "Sanitizer", function () {
|
||||
let tmp = {};
|
||||
Cc["@mozilla.org/moz/jssubscript-loader;1"]
|
||||
.getService(Ci.mozIJSSubScriptLoader)
|
||||
.loadSubScript("chrome://browser/content/sanitize.js", tmp);
|
||||
return tmp.Sanitizer;
|
||||
});
|
||||
|
||||
/**
|
||||
* These tests ensure that the thumbnail storage is working as intended.
|
||||
* Newly captured thumbnails should be saved as files and they should as well
|
||||
* be removed when the user sanitizes their history.
|
||||
*/
|
||||
function* runTests() {
|
||||
yield Task.spawn(function*() {
|
||||
dontExpireThumbnailURLs([URL, URL_COPY]);
|
||||
|
||||
yield promiseClearHistory();
|
||||
yield promiseAddVisitsAndRepopulateNewTabLinks(URL);
|
||||
yield promiseCreateThumbnail();
|
||||
|
||||
// Make sure Storage.copy() updates an existing file.
|
||||
yield PageThumbsStorage.copy(URL, URL_COPY);
|
||||
let copy = new FileUtils.File(PageThumbsStorage.getFilePathForURL(URL_COPY));
|
||||
let mtime = copy.lastModifiedTime -= 60;
|
||||
|
||||
yield PageThumbsStorage.copy(URL, URL_COPY);
|
||||
isnot(new FileUtils.File(PageThumbsStorage.getFilePathForURL(URL_COPY)).lastModifiedTime, mtime,
|
||||
"thumbnail file was updated");
|
||||
|
||||
let file = new FileUtils.File(PageThumbsStorage.getFilePathForURL(URL));
|
||||
let fileCopy = new FileUtils.File(PageThumbsStorage.getFilePathForURL(URL_COPY));
|
||||
|
||||
// Clear the browser history. Retry until the files are gone because Windows
|
||||
// locks them sometimes.
|
||||
info("Clearing history");
|
||||
while (file.exists() || fileCopy.exists()) {
|
||||
yield promiseClearHistory();
|
||||
}
|
||||
info("History is clear");
|
||||
|
||||
info("Repopulating");
|
||||
yield promiseAddVisitsAndRepopulateNewTabLinks(URL);
|
||||
yield promiseCreateThumbnail();
|
||||
|
||||
info("Clearing the last 10 minutes of browsing history");
|
||||
// Clear the last 10 minutes of browsing history.
|
||||
yield promiseClearHistory(true);
|
||||
|
||||
info("Attempt to clear file");
|
||||
// Retry until the file is gone because Windows locks it sometimes.
|
||||
yield promiseClearFile(file, URL);
|
||||
|
||||
info("Done");
|
||||
});
|
||||
}
|
||||
|
||||
var promiseClearFile = Task.async(function*(aFile, aURL) {
|
||||
if (!aFile.exists()) {
|
||||
return undefined;
|
||||
}
|
||||
// Re-add our URL to the history so that history observer's onDeleteURI()
|
||||
// is called again.
|
||||
yield PlacesTestUtils.addVisits(makeURI(aURL));
|
||||
yield promiseClearHistory(true);
|
||||
// Then retry.
|
||||
return promiseClearFile(aFile, aURL);
|
||||
});
|
||||
|
||||
function promiseClearHistory(aUseRange) {
|
||||
let s = new Sanitizer();
|
||||
s.prefDomain = "privacy.cpd.";
|
||||
|
||||
let prefs = gPrefService.getBranch(s.prefDomain);
|
||||
prefs.setBoolPref("history", true);
|
||||
prefs.setBoolPref("downloads", false);
|
||||
prefs.setBoolPref("cache", false);
|
||||
prefs.setBoolPref("cookies", false);
|
||||
prefs.setBoolPref("formdata", false);
|
||||
prefs.setBoolPref("offlineApps", false);
|
||||
prefs.setBoolPref("passwords", false);
|
||||
prefs.setBoolPref("sessions", false);
|
||||
prefs.setBoolPref("siteSettings", false);
|
||||
|
||||
if (aUseRange) {
|
||||
let usec = Date.now() * 1000;
|
||||
s.range = [usec - 10 * 60 * 1000 * 1000, usec];
|
||||
s.ignoreTimespan = false;
|
||||
}
|
||||
|
||||
return s.sanitize().then(() => {
|
||||
s.range = null;
|
||||
s.ignoreTimespan = true;
|
||||
});
|
||||
}
|
||||
|
||||
function promiseCreateThumbnail() {
|
||||
return new Promise(resolve => {
|
||||
addTab(URL, function () {
|
||||
whenFileExists(URL, function () {
|
||||
gBrowser.removeTab(gBrowser.selectedTab);
|
||||
resolve();
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
|
@ -1,102 +0,0 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
const URL = "http://mochi.test:8888/migration3";
|
||||
const URL2 = URL + "#2";
|
||||
const URL3 = URL + "#3";
|
||||
const THUMBNAIL_DIRECTORY = "thumbnails";
|
||||
const PREF_STORAGE_VERSION = "browser.pagethumbnails.storage_version";
|
||||
|
||||
var tmp = {};
|
||||
Cc["@mozilla.org/moz/jssubscript-loader;1"]
|
||||
.getService(Ci.mozIJSSubScriptLoader)
|
||||
.loadSubScript("resource://gre/modules/PageThumbs.jsm", tmp);
|
||||
var {PageThumbsStorageMigrator} = tmp;
|
||||
|
||||
XPCOMUtils.defineLazyServiceGetter(this, "gDirSvc",
|
||||
"@mozilla.org/file/directory_service;1", "nsIProperties");
|
||||
|
||||
/**
|
||||
* This test makes sure we correctly migrate to thumbnail storage version 3.
|
||||
* This means copying existing thumbnails from the roaming to the local profile
|
||||
* directory and should just apply to Linux.
|
||||
*/
|
||||
function* runTests() {
|
||||
// Prepare a local profile directory.
|
||||
let localProfile = FileUtils.getDir("ProfD", ["local-test"], true);
|
||||
changeLocation("ProfLD", localProfile);
|
||||
|
||||
let roaming = FileUtils.getDir("ProfD", [THUMBNAIL_DIRECTORY], true);
|
||||
|
||||
// Set up some data in the roaming profile.
|
||||
let name = PageThumbsStorage.getLeafNameForURL(URL);
|
||||
let file = FileUtils.getFile("ProfD", [THUMBNAIL_DIRECTORY, name]);
|
||||
writeDummyFile(file);
|
||||
|
||||
name = PageThumbsStorage.getLeafNameForURL(URL2);
|
||||
file = FileUtils.getFile("ProfD", [THUMBNAIL_DIRECTORY, name]);
|
||||
writeDummyFile(file);
|
||||
|
||||
name = PageThumbsStorage.getLeafNameForURL(URL3);
|
||||
file = FileUtils.getFile("ProfD", [THUMBNAIL_DIRECTORY, name]);
|
||||
writeDummyFile(file);
|
||||
|
||||
// Pretend to have one of the thumbnails
|
||||
// already in place at the new storage site.
|
||||
name = PageThumbsStorage.getLeafNameForURL(URL3);
|
||||
file = FileUtils.getFile("ProfLD", [THUMBNAIL_DIRECTORY, name]);
|
||||
writeDummyFile(file, "no-overwrite-plz");
|
||||
|
||||
// Kick off thumbnail storage migration.
|
||||
PageThumbsStorageMigrator.migrateToVersion3(localProfile.path);
|
||||
ok(true, "migration finished");
|
||||
|
||||
// Wait until the first thumbnail was moved to its new location.
|
||||
yield whenFileExists(URL);
|
||||
ok(true, "first thumbnail moved");
|
||||
|
||||
// Wait for the second thumbnail to be moved as well.
|
||||
yield whenFileExists(URL2);
|
||||
ok(true, "second thumbnail moved");
|
||||
|
||||
yield whenFileRemoved(roaming);
|
||||
ok(true, "roaming thumbnail directory removed");
|
||||
|
||||
// Check that our existing thumbnail wasn't overwritten.
|
||||
is(getFileContents(file), "no-overwrite-plz",
|
||||
"existing thumbnail was not overwritten");
|
||||
|
||||
// Sanity check: ensure that, until it is removed, deprecated
|
||||
// function |getFileForURL| points to the same path as
|
||||
// |getFilePathForURL|.
|
||||
if ("getFileForURL" in PageThumbsStorage) {
|
||||
file = PageThumbsStorage.getFileForURL(URL);
|
||||
is(file.path, PageThumbsStorage.getFilePathForURL(URL),
|
||||
"Deprecated getFileForURL and getFilePathForURL return the same path");
|
||||
}
|
||||
}
|
||||
|
||||
function changeLocation(aLocation, aNewDir) {
|
||||
let oldDir = gDirSvc.get(aLocation, Ci.nsILocalFile);
|
||||
gDirSvc.undefine(aLocation);
|
||||
gDirSvc.set(aLocation, aNewDir);
|
||||
|
||||
registerCleanupFunction(function () {
|
||||
gDirSvc.undefine(aLocation);
|
||||
gDirSvc.set(aLocation, oldDir);
|
||||
});
|
||||
}
|
||||
|
||||
function writeDummyFile(aFile, aContents) {
|
||||
let fos = FileUtils.openSafeFileOutputStream(aFile);
|
||||
let data = aContents || "dummy";
|
||||
fos.write(data, data.length);
|
||||
FileUtils.closeSafeFileOutputStream(fos);
|
||||
}
|
||||
|
||||
function getFileContents(aFile) {
|
||||
let istream = Cc["@mozilla.org/network/file-input-stream;1"]
|
||||
.createInstance(Ci.nsIFileInputStream);
|
||||
istream.init(aFile, FileUtils.MODE_RDONLY, FileUtils.PERMS_FILE, 0);
|
||||
return NetUtil.readInputStreamToString(istream, istream.available());
|
||||
}
|
||||
|
|
@ -1,169 +0,0 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
/**
|
||||
* These tests check the auto-update facility of the thumbnail service.
|
||||
*/
|
||||
|
||||
function* runTests() {
|
||||
// A "trampoline" - a generator that iterates over sub-iterators
|
||||
let tests = [
|
||||
simpleCaptureTest,
|
||||
capIfStaleErrorResponseUpdateTest,
|
||||
capIfStaleGoodResponseUpdateTest,
|
||||
regularCapErrorResponseUpdateTest,
|
||||
regularCapGoodResponseUpdateTest
|
||||
];
|
||||
for (let test of tests) {
|
||||
info("Running subtest " + test.name);
|
||||
for (let iterator of test())
|
||||
yield iterator;
|
||||
}
|
||||
}
|
||||
|
||||
function ensureThumbnailStale(url) {
|
||||
// We go behind the back of the thumbnail service and change the
|
||||
// mtime of the file to be in the past.
|
||||
let fname = PageThumbsStorage.getFilePathForURL(url);
|
||||
let file = Cc["@mozilla.org/file/local;1"].createInstance(Ci.nsIFile);
|
||||
file.initWithPath(fname);
|
||||
ok(file.exists(), fname + " should exist");
|
||||
// Set it as very stale...
|
||||
file.lastModifiedTime = Date.now() - 1000000000;
|
||||
}
|
||||
|
||||
function getThumbnailModifiedTime(url) {
|
||||
let fname = PageThumbsStorage.getFilePathForURL(url);
|
||||
let file = Cc["@mozilla.org/file/local;1"].createInstance(Ci.nsIFile);
|
||||
file.initWithPath(fname);
|
||||
return file.lastModifiedTime;
|
||||
}
|
||||
|
||||
// The tests!
|
||||
/* Check functionality of a normal captureAndStoreIfStale request */
|
||||
function* simpleCaptureTest() {
|
||||
let numNotifications = 0;
|
||||
const URL = "http://mochi.test:8888/browser/toolkit/components/thumbnails/test/thumbnails_update.sjs?simple";
|
||||
|
||||
function observe(subject, topic, data) {
|
||||
is(topic, "page-thumbnail:create", "got expected topic");
|
||||
is(data, URL, "data is our test URL");
|
||||
if (++numNotifications == 2) {
|
||||
// This is the final notification and signals test success...
|
||||
Services.obs.removeObserver(observe, "page-thumbnail:create");
|
||||
gBrowser.removeTab(gBrowser.selectedTab);
|
||||
next();
|
||||
}
|
||||
}
|
||||
|
||||
Services.obs.addObserver(observe, "page-thumbnail:create", false);
|
||||
// Create a tab - we don't care what the content is.
|
||||
yield addTab(URL);
|
||||
let browser = gBrowser.selectedBrowser;
|
||||
|
||||
// Capture the screenshot.
|
||||
PageThumbs.captureAndStore(browser, function () {
|
||||
// We've got a capture so should have seen the observer.
|
||||
is(numNotifications, 1, "got notification of item being created.");
|
||||
// The capture is now "fresh" - so requesting the URL should not cause
|
||||
// a new capture.
|
||||
PageThumbs.captureAndStoreIfStale(browser, function() {
|
||||
is(numNotifications, 1, "still only 1 notification of item being created.");
|
||||
|
||||
ensureThumbnailStale(URL);
|
||||
// Ask for it to be updated.
|
||||
PageThumbs.captureAndStoreIfStale(browser);
|
||||
// But it's async, so wait - our observer above will call next() when
|
||||
// the notification comes.
|
||||
});
|
||||
});
|
||||
yield undefined // wait for callbacks to call 'next'...
|
||||
}
|
||||
|
||||
/* Check functionality of captureAndStoreIfStale when there is an error response
|
||||
from the server.
|
||||
*/
|
||||
function* capIfStaleErrorResponseUpdateTest() {
|
||||
const URL = "http://mochi.test:8888/browser/toolkit/components/thumbnails/test/thumbnails_update.sjs?fail";
|
||||
yield addTab(URL);
|
||||
|
||||
yield captureAndCheckColor(0, 255, 0, "we have a green thumbnail");
|
||||
// update the thumbnail to be stale, then re-request it. The server will
|
||||
// return a 400 response and a red thumbnail.
|
||||
// The service should not save the thumbnail - so we (a) check the thumbnail
|
||||
// remains green and (b) check the mtime of the file is < now.
|
||||
ensureThumbnailStale(URL);
|
||||
yield navigateTo(URL);
|
||||
// now() returns a higher-precision value than the modified time of a file.
|
||||
// As we set the thumbnail very stale, allowing 1 second of "slop" here
|
||||
// works around this while still keeping the test valid.
|
||||
let now = Date.now() - 1000 ;
|
||||
PageThumbs.captureAndStoreIfStale(gBrowser.selectedBrowser, () => {
|
||||
ok(getThumbnailModifiedTime(URL) < now, "modified time should be < now");
|
||||
retrieveImageDataForURL(URL, function ([r, g, b]) {
|
||||
is("" + [r, g, b], "" + [0, 255, 0], "thumbnail is still green");
|
||||
gBrowser.removeTab(gBrowser.selectedTab);
|
||||
next();
|
||||
});
|
||||
});
|
||||
yield undefined; // wait for callback to call 'next'...
|
||||
}
|
||||
|
||||
/* Check functionality of captureAndStoreIfStale when there is a non-error
|
||||
response from the server. This test is somewhat redundant - although it is
|
||||
using a http:// URL instead of a data: url like most others.
|
||||
*/
|
||||
function* capIfStaleGoodResponseUpdateTest() {
|
||||
const URL = "http://mochi.test:8888/browser/toolkit/components/thumbnails/test/thumbnails_update.sjs?ok";
|
||||
yield addTab(URL);
|
||||
let browser = gBrowser.selectedBrowser;
|
||||
|
||||
yield captureAndCheckColor(0, 255, 0, "we have a green thumbnail");
|
||||
// update the thumbnail to be stale, then re-request it. The server will
|
||||
// return a 200 response and a red thumbnail - so that new thumbnail should
|
||||
// end up captured.
|
||||
ensureThumbnailStale(URL);
|
||||
yield navigateTo(URL);
|
||||
// now() returns a higher-precision value than the modified time of a file.
|
||||
// As we set the thumbnail very stale, allowing 1 second of "slop" here
|
||||
// works around this while still keeping the test valid.
|
||||
let now = Date.now() - 1000 ;
|
||||
PageThumbs.captureAndStoreIfStale(browser, () => {
|
||||
ok(getThumbnailModifiedTime(URL) >= now, "modified time should be >= now");
|
||||
// the captureAndStoreIfStale request saw a 200 response with the red body,
|
||||
// so we expect to see the red version here.
|
||||
retrieveImageDataForURL(URL, function ([r, g, b]) {
|
||||
is("" + [r, g, b], "" + [255, 0, 0], "thumbnail is now red");
|
||||
next();
|
||||
});
|
||||
});
|
||||
yield undefined; // wait for callback to call 'next'...
|
||||
}
|
||||
|
||||
/* Check functionality of captureAndStore when there is an error response
|
||||
from the server.
|
||||
*/
|
||||
function* regularCapErrorResponseUpdateTest() {
|
||||
const URL = "http://mochi.test:8888/browser/toolkit/components/thumbnails/test/thumbnails_update.sjs?fail";
|
||||
yield addTab(URL);
|
||||
yield captureAndCheckColor(0, 255, 0, "we have a green thumbnail");
|
||||
gBrowser.removeTab(gBrowser.selectedTab);
|
||||
// do it again - the server will return a 400, so the foreground service
|
||||
// should not update it.
|
||||
yield addTab(URL);
|
||||
yield captureAndCheckColor(0, 255, 0, "we still have a green thumbnail");
|
||||
}
|
||||
|
||||
/* Check functionality of captureAndStore when there is an OK response
|
||||
from the server.
|
||||
*/
|
||||
function* regularCapGoodResponseUpdateTest() {
|
||||
const URL = "http://mochi.test:8888/browser/toolkit/components/thumbnails/test/thumbnails_update.sjs?ok";
|
||||
yield addTab(URL);
|
||||
yield captureAndCheckColor(0, 255, 0, "we have a green thumbnail");
|
||||
gBrowser.removeTab(gBrowser.selectedTab);
|
||||
// do it again - the server will return a 200, so the foreground service
|
||||
// should update it.
|
||||
yield addTab(URL);
|
||||
yield captureAndCheckColor(255, 0, 0, "we now have a red thumbnail");
|
||||
}
|
||||
|
|
@ -1,356 +0,0 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
var tmp = {};
|
||||
Cu.import("resource://gre/modules/PageThumbs.jsm", tmp);
|
||||
Cu.import("resource://gre/modules/BackgroundPageThumbs.jsm", tmp);
|
||||
Cu.import("resource://gre/modules/NewTabUtils.jsm", tmp);
|
||||
Cu.import("resource:///modules/sessionstore/SessionStore.jsm", tmp);
|
||||
Cu.import("resource://gre/modules/FileUtils.jsm", tmp);
|
||||
Cu.import("resource://gre/modules/osfile.jsm", tmp);
|
||||
var {PageThumbs, BackgroundPageThumbs, NewTabUtils, PageThumbsStorage, SessionStore, FileUtils, OS} = tmp;
|
||||
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "PlacesTestUtils",
|
||||
"resource://testing-common/PlacesTestUtils.jsm");
|
||||
|
||||
var oldEnabledPref = Services.prefs.getBoolPref("browser.pagethumbnails.capturing_disabled");
|
||||
Services.prefs.setBoolPref("browser.pagethumbnails.capturing_disabled", false);
|
||||
|
||||
registerCleanupFunction(function () {
|
||||
while (gBrowser.tabs.length > 1)
|
||||
gBrowser.removeTab(gBrowser.tabs[1]);
|
||||
Services.prefs.setBoolPref("browser.pagethumbnails.capturing_disabled", oldEnabledPref)
|
||||
});
|
||||
|
||||
/**
|
||||
* Provide the default test function to start our test runner.
|
||||
*/
|
||||
function test() {
|
||||
TestRunner.run();
|
||||
}
|
||||
|
||||
/**
|
||||
* The test runner that controls the execution flow of our tests.
|
||||
*/
|
||||
var TestRunner = {
|
||||
/**
|
||||
* Starts the test runner.
|
||||
*/
|
||||
run: function () {
|
||||
waitForExplicitFinish();
|
||||
|
||||
SessionStore.promiseInitialized.then(function () {
|
||||
this._iter = runTests();
|
||||
if (this._iter) {
|
||||
this.next();
|
||||
} else {
|
||||
finish();
|
||||
}
|
||||
}.bind(this));
|
||||
},
|
||||
|
||||
/**
|
||||
* Runs the next available test or finishes if there's no test left.
|
||||
* @param aValue This value will be passed to the yielder via the runner's
|
||||
* iterator.
|
||||
*/
|
||||
next: function (aValue) {
|
||||
let obj = TestRunner._iter.next(aValue);
|
||||
if (obj.done) {
|
||||
finish();
|
||||
return;
|
||||
}
|
||||
|
||||
let value = obj.value || obj;
|
||||
if (value && typeof value.then == "function") {
|
||||
value.then(result => {
|
||||
next(result);
|
||||
}, error => {
|
||||
ok(false, error + "\n" + error.stack);
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Continues the current test execution.
|
||||
* @param aValue This value will be passed to the yielder via the runner's
|
||||
* iterator.
|
||||
*/
|
||||
function next(aValue) {
|
||||
TestRunner.next(aValue);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new tab with the given URI.
|
||||
* @param aURI The URI that's loaded in the tab.
|
||||
* @param aCallback The function to call when the tab has loaded.
|
||||
*/
|
||||
function addTab(aURI, aCallback) {
|
||||
let tab = gBrowser.selectedTab = gBrowser.addTab(aURI);
|
||||
whenLoaded(tab.linkedBrowser, aCallback);
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads a new URI into the currently selected tab.
|
||||
* @param aURI The URI to load.
|
||||
*/
|
||||
function navigateTo(aURI) {
|
||||
let browser = gBrowser.selectedBrowser;
|
||||
whenLoaded(browser);
|
||||
browser.loadURI(aURI);
|
||||
}
|
||||
|
||||
/**
|
||||
* Continues the current test execution when a load event for the given element
|
||||
* has been received.
|
||||
* @param aElement The DOM element to listen on.
|
||||
* @param aCallback The function to call when the load event was dispatched.
|
||||
*/
|
||||
function whenLoaded(aElement, aCallback = next) {
|
||||
aElement.addEventListener("load", function onLoad() {
|
||||
aElement.removeEventListener("load", onLoad, true);
|
||||
executeSoon(aCallback);
|
||||
}, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Captures a screenshot for the currently selected tab, stores it in the cache,
|
||||
* retrieves it from the cache and compares pixel color values.
|
||||
* @param aRed The red component's intensity.
|
||||
* @param aGreen The green component's intensity.
|
||||
* @param aBlue The blue component's intensity.
|
||||
* @param aMessage The info message to print when comparing the pixel color.
|
||||
*/
|
||||
function captureAndCheckColor(aRed, aGreen, aBlue, aMessage) {
|
||||
let browser = gBrowser.selectedBrowser;
|
||||
// We'll get oranges if the expiration filter removes the file during the
|
||||
// test.
|
||||
dontExpireThumbnailURLs([browser.currentURI.spec]);
|
||||
|
||||
// Capture the screenshot.
|
||||
PageThumbs.captureAndStore(browser, function () {
|
||||
retrieveImageDataForURL(browser.currentURI.spec, function ([r, g, b]) {
|
||||
is("" + [r, g, b], "" + [aRed, aGreen, aBlue], aMessage);
|
||||
next();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* For a given URL, loads the corresponding thumbnail
|
||||
* to a canvas and passes its image data to the callback.
|
||||
* Note, not compat with e10s!
|
||||
* @param aURL The url associated with the thumbnail.
|
||||
* @param aCallback The function to pass the image data to.
|
||||
*/
|
||||
function retrieveImageDataForURL(aURL, aCallback) {
|
||||
let width = 100, height = 100;
|
||||
let thumb = PageThumbs.getThumbnailURL(aURL, width, height);
|
||||
|
||||
let htmlns = "http://www.w3.org/1999/xhtml";
|
||||
let img = document.createElementNS(htmlns, "img");
|
||||
img.setAttribute("src", thumb);
|
||||
|
||||
whenLoaded(img, function () {
|
||||
let canvas = document.createElementNS(htmlns, "canvas");
|
||||
canvas.setAttribute("width", width);
|
||||
canvas.setAttribute("height", height);
|
||||
|
||||
// Draw the image to a canvas and compare the pixel color values.
|
||||
let ctx = canvas.getContext("2d");
|
||||
ctx.drawImage(img, 0, 0, width, height);
|
||||
let result = ctx.getImageData(0, 0, 100, 100).data;
|
||||
aCallback(result);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the file of the thumbnail with the given URL.
|
||||
* @param aURL The URL of the thumbnail.
|
||||
*/
|
||||
function thumbnailFile(aURL) {
|
||||
return new FileUtils.File(PageThumbsStorage.getFilePathForURL(aURL));
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if a thumbnail for the given URL exists.
|
||||
* @param aURL The url associated to the thumbnail.
|
||||
*/
|
||||
function thumbnailExists(aURL) {
|
||||
let file = thumbnailFile(aURL);
|
||||
return file.exists() && file.fileSize;
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes the thumbnail for the given URL.
|
||||
* @param aURL The URL associated with the thumbnail.
|
||||
*/
|
||||
function removeThumbnail(aURL) {
|
||||
let file = thumbnailFile(aURL);
|
||||
file.remove(false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Calls addVisits, and then forces the newtab module to repopulate its links.
|
||||
* See addVisits for parameter descriptions.
|
||||
*/
|
||||
function addVisitsAndRepopulateNewTabLinks(aPlaceInfo, aCallback) {
|
||||
PlacesTestUtils.addVisits(makeURI(aPlaceInfo)).then(() => {
|
||||
NewTabUtils.links.populateCache(aCallback, true);
|
||||
});
|
||||
}
|
||||
function promiseAddVisitsAndRepopulateNewTabLinks(aPlaceInfo) {
|
||||
return new Promise(resolve => addVisitsAndRepopulateNewTabLinks(aPlaceInfo, resolve));
|
||||
}
|
||||
|
||||
/**
|
||||
* Calls a given callback when the thumbnail for a given URL has been found
|
||||
* on disk. Keeps trying until the thumbnail has been created.
|
||||
*
|
||||
* @param aURL The URL of the thumbnail's page.
|
||||
* @param [optional] aCallback
|
||||
* Function to be invoked on completion.
|
||||
*/
|
||||
function whenFileExists(aURL, aCallback = next) {
|
||||
let callback = aCallback;
|
||||
if (!thumbnailExists(aURL)) {
|
||||
callback = () => whenFileExists(aURL, aCallback);
|
||||
}
|
||||
|
||||
executeSoon(callback);
|
||||
}
|
||||
|
||||
/**
|
||||
* Calls a given callback when the given file has been removed.
|
||||
* Keeps trying until the file is removed.
|
||||
*
|
||||
* @param aFile The file that is being removed
|
||||
* @param [optional] aCallback
|
||||
* Function to be invoked on completion.
|
||||
*/
|
||||
function whenFileRemoved(aFile, aCallback) {
|
||||
let callback = aCallback;
|
||||
if (aFile.exists()) {
|
||||
callback = () => whenFileRemoved(aFile, aCallback);
|
||||
}
|
||||
|
||||
executeSoon(callback || next);
|
||||
}
|
||||
|
||||
function wait(aMillis) {
|
||||
setTimeout(next, aMillis);
|
||||
}
|
||||
|
||||
/**
|
||||
* Makes sure that a given list of URLs is not implicitly expired.
|
||||
*
|
||||
* @param aURLs The list of URLs that should not be expired.
|
||||
*/
|
||||
function dontExpireThumbnailURLs(aURLs) {
|
||||
let dontExpireURLs = (cb) => cb(aURLs);
|
||||
PageThumbs.addExpirationFilter(dontExpireURLs);
|
||||
|
||||
registerCleanupFunction(function () {
|
||||
PageThumbs.removeExpirationFilter(dontExpireURLs);
|
||||
});
|
||||
}
|
||||
|
||||
function bgCapture(aURL, aOptions) {
|
||||
bgCaptureWithMethod("capture", aURL, aOptions);
|
||||
}
|
||||
|
||||
function bgCaptureIfMissing(aURL, aOptions) {
|
||||
bgCaptureWithMethod("captureIfMissing", aURL, aOptions);
|
||||
}
|
||||
|
||||
function bgCaptureWithMethod(aMethodName, aURL, aOptions = {}) {
|
||||
// We'll get oranges if the expiration filter removes the file during the
|
||||
// test.
|
||||
dontExpireThumbnailURLs([aURL]);
|
||||
if (!aOptions.onDone)
|
||||
aOptions.onDone = next;
|
||||
BackgroundPageThumbs[aMethodName](aURL, aOptions);
|
||||
}
|
||||
|
||||
function bgTestPageURL(aOpts = {}) {
|
||||
let TEST_PAGE_URL = "http://mochi.test:8888/browser/toolkit/components/thumbnails/test/thumbnails_background.sjs";
|
||||
return TEST_PAGE_URL + "?" + encodeURIComponent(JSON.stringify(aOpts));
|
||||
}
|
||||
|
||||
function bgAddPageThumbObserver(url) {
|
||||
return new Promise((resolve, reject) => {
|
||||
function observe(subject, topic, data) { // jshint ignore:line
|
||||
if (data === url) {
|
||||
switch (topic) {
|
||||
case "page-thumbnail:create":
|
||||
resolve();
|
||||
break;
|
||||
case "page-thumbnail:error":
|
||||
reject(new Error("page-thumbnail:error"));
|
||||
break;
|
||||
}
|
||||
Services.obs.removeObserver(observe, "page-thumbnail:create");
|
||||
Services.obs.removeObserver(observe, "page-thumbnail:error");
|
||||
}
|
||||
}
|
||||
Services.obs.addObserver(observe, "page-thumbnail:create", false);
|
||||
Services.obs.addObserver(observe, "page-thumbnail:error", false);
|
||||
});
|
||||
}
|
||||
|
||||
function bgAddCrashObserver() {
|
||||
let crashed = false;
|
||||
Services.obs.addObserver(function crashObserver(subject, topic, data) {
|
||||
is(topic, 'ipc:content-shutdown', 'Received correct observer topic.');
|
||||
ok(subject instanceof Components.interfaces.nsIPropertyBag2,
|
||||
'Subject implements nsIPropertyBag2.');
|
||||
// we might see this called as the process terminates due to previous tests.
|
||||
// We are only looking for "abnormal" exits...
|
||||
if (!subject.hasKey("abnormal")) {
|
||||
info("This is a normal termination and isn't the one we are looking for...");
|
||||
return;
|
||||
}
|
||||
Services.obs.removeObserver(crashObserver, 'ipc:content-shutdown');
|
||||
crashed = true;
|
||||
|
||||
var dumpID;
|
||||
if ('nsICrashReporter' in Components.interfaces) {
|
||||
dumpID = subject.getPropertyAsAString('dumpID');
|
||||
ok(dumpID, "dumpID is present and not an empty string");
|
||||
}
|
||||
|
||||
if (dumpID) {
|
||||
var minidumpDirectory = getMinidumpDirectory();
|
||||
removeFile(minidumpDirectory, dumpID + '.dmp');
|
||||
removeFile(minidumpDirectory, dumpID + '.extra');
|
||||
}
|
||||
}, 'ipc:content-shutdown', false);
|
||||
return {
|
||||
get crashed() {
|
||||
return crashed;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
function bgInjectCrashContentScript() {
|
||||
const TEST_CONTENT_HELPER = "chrome://mochitests/content/browser/toolkit/components/thumbnails/test/thumbnails_crash_content_helper.js";
|
||||
let thumbnailBrowser = BackgroundPageThumbs._thumbBrowser;
|
||||
let mm = thumbnailBrowser.messageManager;
|
||||
mm.loadFrameScript(TEST_CONTENT_HELPER, false);
|
||||
return mm;
|
||||
}
|
||||
|
||||
function getMinidumpDirectory() {
|
||||
var dir = Services.dirsvc.get('ProfD', Components.interfaces.nsIFile);
|
||||
dir.append("minidumps");
|
||||
return dir;
|
||||
}
|
||||
|
||||
function removeFile(directory, filename) {
|
||||
var file = directory.clone();
|
||||
file.append(filename);
|
||||
if (file.exists()) {
|
||||
file.remove(false);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,16 +0,0 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/
|
||||
*/
|
||||
|
||||
function handleRequest(aRequest, aResponse) {
|
||||
// Set HTTP Status
|
||||
aResponse.setStatusLine(aRequest.httpVersion, 200, "OK");
|
||||
|
||||
// Set Cache-Control header.
|
||||
let value = aRequest.queryString;
|
||||
if (value)
|
||||
aResponse.setHeader("Cache-Control", value);
|
||||
|
||||
// Set the response body.
|
||||
aResponse.write("<!DOCTYPE html><html><body></body></html>");
|
||||
}
|
||||
|
|
@ -1,25 +0,0 @@
|
|||
// tests to check that moz-page-thumb URLs correctly resolve as file:// URLS
|
||||
"use strict";
|
||||
|
||||
const Cu = Components.utils;
|
||||
const Cc = Components.classes;
|
||||
const Cr = Components.results;
|
||||
const Ci = Components.interfaces;
|
||||
|
||||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
|
||||
// need profile so that PageThumbsStorage can resolve the path to the underlying file
|
||||
do_get_profile();
|
||||
|
||||
function run_test() {
|
||||
// first check the protocol handler implements the correct interface
|
||||
let handler = Services.io.getProtocolHandler("moz-page-thumb");
|
||||
ok(handler instanceof Ci.nsISubstitutingProtocolHandler,
|
||||
"moz-page-thumb handler provides substituting interface");
|
||||
|
||||
// then check that the file URL resolution works
|
||||
let uri = Services.io.newURI("moz-page-thumb://thumbnail/?url=http%3A%2F%2Fwww.mozilla.org%2F",
|
||||
null, null);
|
||||
ok(uri instanceof Ci.nsIFileURL, "moz-page-thumb:// is a FileURL");
|
||||
ok(uri.file, "This moz-page-thumb:// object is backed by a file");
|
||||
}
|
||||
|
|
@ -1,79 +0,0 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
// The timer never fires if it's not declared and set to this variable outside
|
||||
// handleRequest, as if it's getting GC'ed when handleRequest's scope goes away.
|
||||
// Shouldn't the timer thread hold a strong reference to it?
|
||||
var timer;
|
||||
|
||||
function handleRequest(req, resp) {
|
||||
resp.processAsync();
|
||||
resp.setHeader("Cache-Control", "no-cache, no-store", false);
|
||||
resp.setHeader("Content-Type", "text/html;charset=utf-8", false);
|
||||
|
||||
let opts = {};
|
||||
try {
|
||||
opts = JSON.parse(decodeURIComponent(req.queryString));
|
||||
}
|
||||
catch (err) {}
|
||||
|
||||
let setCookieScript = "";
|
||||
if (opts.setRedCookie) {
|
||||
resp.setHeader("Set-Cookie", "red", false);
|
||||
setCookieScript = '<script>document.cookie="red";</script>';
|
||||
}
|
||||
|
||||
if (opts.setGreenCookie) {
|
||||
resp.setHeader("Set-Cookie", "green", false);
|
||||
setCookieScript = '<script>document.cookie="green";</script>';
|
||||
}
|
||||
|
||||
if (opts.iframe) {
|
||||
setCookieScript += '<iframe src="' + opts.iframe + '" />';
|
||||
}
|
||||
|
||||
if (opts.xhr) {
|
||||
setCookieScript += `
|
||||
<script>
|
||||
var req = new XMLHttpRequest();
|
||||
req.open("GET", "${opts.xhr}", true);
|
||||
req.send();
|
||||
</script>
|
||||
`;
|
||||
}
|
||||
|
||||
if (req.hasHeader("Cookie") &&
|
||||
req.getHeader("Cookie").split(";").indexOf("red") >= 0) {
|
||||
resp.write('<html style="background: #f00;">' + setCookieScript + '</html>');
|
||||
resp.finish();
|
||||
return;
|
||||
}
|
||||
|
||||
if (req.hasHeader("Cookie") &&
|
||||
req.getHeader("Cookie").split(";").indexOf("green") >= 0) {
|
||||
resp.write('<html style="background: #0f0;">' + setCookieScript + '</html>');
|
||||
resp.finish();
|
||||
return;
|
||||
}
|
||||
|
||||
if (opts.redirect) {
|
||||
resp.setHeader("Location", opts.redirect);
|
||||
resp.setStatusLine(null, 303, null);
|
||||
resp.finish();
|
||||
return;
|
||||
}
|
||||
|
||||
if (opts.wait) {
|
||||
resp.write("Waiting " + opts.wait + " ms... ");
|
||||
timer = Components.classes["@mozilla.org/timer;1"].
|
||||
createInstance(Components.interfaces.nsITimer);
|
||||
timer.init(function ding() {
|
||||
resp.write("OK!");
|
||||
resp.finish();
|
||||
}, opts.wait, Components.interfaces.nsITimer.TYPE_ONE_SHOT);
|
||||
return;
|
||||
}
|
||||
|
||||
resp.write("<pre>" + JSON.stringify(opts, undefined, 2) + "</pre>" + setCookieScript);
|
||||
resp.finish();
|
||||
}
|
||||
|
|
@ -1,31 +0,0 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
var Cu = Components.utils;
|
||||
|
||||
// Ideally we would use CrashTestUtils.jsm, but that's only available for
|
||||
// xpcshell tests - so we just copy a ctypes crasher from it.
|
||||
Cu.import("resource://gre/modules/ctypes.jsm");
|
||||
var crash = function() { // this will crash when called.
|
||||
let zero = new ctypes.intptr_t(8);
|
||||
let badptr = ctypes.cast(zero, ctypes.PointerType(ctypes.int32_t));
|
||||
badptr.contents
|
||||
};
|
||||
|
||||
|
||||
var TestHelper = {
|
||||
init: function() {
|
||||
addMessageListener("thumbnails-test:crash", this);
|
||||
},
|
||||
|
||||
receiveMessage: function(msg) {
|
||||
switch (msg.name) {
|
||||
case "thumbnails-test:crash":
|
||||
privateNoteIntentionalCrash();
|
||||
crash();
|
||||
break;
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
TestHelper.init();
|
||||
|
|
@ -1,56 +0,0 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
// This server-side script is used for browser_thumbnails_update. One of the
|
||||
// main things it must do in all cases is ensure a Cache-Control: no-store
|
||||
// header, so the foreground capture doesn't interfere with the testing.
|
||||
|
||||
// If the querystring is "simple", then all it does it return some content -
|
||||
// it doesn't really matter what that content is.
|
||||
|
||||
// Otherwise, its main role is that it must return different *content* for the
|
||||
// second request than it did for the first.
|
||||
// Also, it should be able to return an error response when requested for the
|
||||
// second response.
|
||||
// So the basic tests will be to grab the thumbnail, then request it to be
|
||||
// grabbed again:
|
||||
// * If the second request succeeded, the new thumbnail should exist.
|
||||
// * If the second request is an error, the new thumbnail should be ignored.
|
||||
|
||||
function handleRequest(aRequest, aResponse) {
|
||||
aResponse.setHeader("Content-Type", "text/html;charset=utf-8", false);
|
||||
// we want to disable gBrowserThumbnails on-load capture for these responses,
|
||||
// so set as a "no-store" response.
|
||||
aResponse.setHeader("Cache-Control", "no-store");
|
||||
|
||||
// for the simple test - just return some content.
|
||||
if (aRequest.queryString == "simple") {
|
||||
aResponse.write("<html><body></body></html>");
|
||||
aResponse.setStatusLine(aRequest.httpVersion, 200, "Its simply OK");
|
||||
return;
|
||||
}
|
||||
|
||||
// it's one of the more complex tests where the first request for the given
|
||||
// URL must return different content than the second, and possibly an error
|
||||
// response for the second
|
||||
let doneError = getState(aRequest.queryString);
|
||||
if (!doneError) {
|
||||
// first request - return a response with a green body and 200 response.
|
||||
aResponse.setStatusLine(aRequest.httpVersion, 200, "OK - It's green");
|
||||
aResponse.write("<html><body bgcolor=00ff00></body></html>");
|
||||
// set the state so the next request does the "second request" thing below.
|
||||
setState(aRequest.queryString, "yep");
|
||||
} else {
|
||||
// second request - this will be done by the b/g service.
|
||||
// We always return a red background, but depending on the query string we
|
||||
// return either a 200 or 401 response.
|
||||
if (aRequest.queryString == "fail")
|
||||
aResponse.setStatusLine(aRequest.httpVersion, 401, "Oh no you don't");
|
||||
else
|
||||
aResponse.setStatusLine(aRequest.httpVersion, 200, "OK - It's red");
|
||||
aResponse.write("<html><body bgcolor=ff0000></body></html>");
|
||||
// reset the error state incase this ends up being reused for the
|
||||
// same url and querystring.
|
||||
setState(aRequest.queryString, "");
|
||||
}
|
||||
}
|
||||
|
|
@ -1,6 +0,0 @@
|
|||
[DEFAULT]
|
||||
head =
|
||||
tail =
|
||||
|
||||
[test_thumbnails_interfaces.js]
|
||||
skip-if = os == 'android' # xpcom interface not packaged
|
||||
Loading…
Add table
Add a link
Reference in a new issue