mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-10 20:05:49 +00:00
Merge mozilla-central to mozilla-inbound
This commit is contained in:
commit
53eeadbacf
@ -1318,6 +1318,7 @@ pref("services.sync.prefs.sync.security.OCSP.require", true);
|
||||
pref("services.sync.prefs.sync.security.default_personal_cert", true);
|
||||
pref("services.sync.prefs.sync.security.tls.version.min", true);
|
||||
pref("services.sync.prefs.sync.security.tls.version.max", true);
|
||||
pref("services.sync.prefs.sync.services.sync.syncedTabs.showRemoteIcons", true);
|
||||
pref("services.sync.prefs.sync.signon.rememberSignons", true);
|
||||
pref("services.sync.prefs.sync.spellchecker.dictionary", true);
|
||||
pref("services.sync.prefs.sync.xpinstall.whitelist.required", true);
|
||||
@ -1328,6 +1329,12 @@ pref("services.sync.syncedTabsUIRefresh", true);
|
||||
pref("services.sync.syncedTabsUIRefresh", false);
|
||||
#endif
|
||||
|
||||
// A preference that controls whether we should show the icon for a remote tab.
|
||||
// This pref has no UI but exists because some people may be concerned that
|
||||
// fetching these icons to show remote tabs may leak information about that
|
||||
// user's tabs and bookmarks. Note this pref is also synced.
|
||||
pref("services.sync.syncedTabs.showRemoteIcons", true);
|
||||
|
||||
// Developer edition preferences
|
||||
#ifdef MOZ_DEV_EDITION
|
||||
sticky_pref("lightweightThemes.selectedThemeID", "firefox-devedition@mozilla.org");
|
||||
|
@ -19,6 +19,7 @@ support-files =
|
||||
browser_star_hsts.sjs
|
||||
browser_tab_dragdrop2_frame1.xul
|
||||
browser_web_channel.html
|
||||
browser_web_channel_iframe.html
|
||||
bug592338.html
|
||||
bug792517-2.html
|
||||
bug792517.html
|
||||
|
@ -6,6 +6,8 @@
|
||||
</head>
|
||||
<body>
|
||||
<script>
|
||||
var IFRAME_SRC_ROOT = "http://mochi.test:8888/browser/browser/base/content/test/general/browser_web_channel_iframe.html";
|
||||
|
||||
window.onload = function() {
|
||||
var testName = window.location.search.replace(/^\?/, "");
|
||||
|
||||
@ -19,6 +21,21 @@
|
||||
case "multichannel":
|
||||
test_multichannel();
|
||||
break;
|
||||
case "iframe":
|
||||
test_iframe();
|
||||
break;
|
||||
case "iframe_pre_redirect":
|
||||
test_iframe_pre_redirect();
|
||||
break;
|
||||
case "unsolicited":
|
||||
test_unsolicited();
|
||||
break;
|
||||
case "bubbles":
|
||||
test_bubbles();
|
||||
break;
|
||||
default:
|
||||
throw new Error(`INVALID TEST NAME ${testName}`);
|
||||
break;
|
||||
}
|
||||
};
|
||||
|
||||
@ -84,6 +101,67 @@
|
||||
window.dispatchEvent(event1);
|
||||
window.dispatchEvent(event2);
|
||||
}
|
||||
|
||||
function test_iframe() {
|
||||
// Note that this message is the response to the message sent
|
||||
// by the iframe! This is bad, as this page is *not* trusted.
|
||||
window.addEventListener("WebChannelMessageToContent", function(e) {
|
||||
// the test parent will fail if the echo message is received.
|
||||
echoEventToChannel(e, "echo");
|
||||
});
|
||||
|
||||
// only attach the iframe for the iframe test to avoid
|
||||
// interfering with other tests.
|
||||
var iframe = document.createElement("iframe");
|
||||
iframe.setAttribute("src", IFRAME_SRC_ROOT + "?iframe");
|
||||
document.body.appendChild(iframe);
|
||||
}
|
||||
|
||||
function test_iframe_pre_redirect() {
|
||||
var iframe = document.createElement("iframe");
|
||||
iframe.setAttribute("src", IFRAME_SRC_ROOT + "?iframe_pre_redirect");
|
||||
document.body.appendChild(iframe);
|
||||
}
|
||||
|
||||
function test_unsolicited() {
|
||||
// echo any unsolicted events back to chrome.
|
||||
window.addEventListener("WebChannelMessageToContent", function(e) {
|
||||
echoEventToChannel(e, "echo");
|
||||
}, true);
|
||||
}
|
||||
|
||||
function test_bubbles() {
|
||||
var event = new window.CustomEvent("WebChannelMessageToChrome", {
|
||||
detail: {
|
||||
id: "not_a_window",
|
||||
message: {
|
||||
command: "start"
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
var nonWindowTarget = document.getElementById("not_a_window");
|
||||
|
||||
nonWindowTarget.addEventListener("WebChannelMessageToContent", function(e) {
|
||||
echoEventToChannel(e, "not_a_window");
|
||||
}, true);
|
||||
|
||||
|
||||
nonWindowTarget.dispatchEvent(event);
|
||||
}
|
||||
|
||||
function echoEventToChannel(e, channelId) {
|
||||
var echoedEvent = new window.CustomEvent("WebChannelMessageToChrome", {
|
||||
detail: {
|
||||
id: channelId,
|
||||
message: e.detail.message,
|
||||
}
|
||||
});
|
||||
|
||||
e.target.dispatchEvent(echoedEvent);
|
||||
}
|
||||
</script>
|
||||
|
||||
<div id="not_a_window"></div>
|
||||
</body>
|
||||
</html>
|
||||
|
@ -10,6 +10,9 @@ XPCOMUtils.defineLazyModuleGetter(this, "WebChannel",
|
||||
|
||||
const HTTP_PATH = "http://example.com";
|
||||
const HTTP_ENDPOINT = "/browser/browser/base/content/test/general/browser_web_channel.html";
|
||||
const HTTP_MISMATCH_PATH = "http://example.org";
|
||||
const HTTP_IFRAME_PATH = "http://mochi.test:8888";
|
||||
const HTTP_REDIRECTED_IFRAME_PATH = "http://example.org";
|
||||
|
||||
// Keep this synced with /mobile/android/tests/browser/robocop/testWebChannel.js
|
||||
// as much as possible. (We only have that since we can't run browser chrome
|
||||
@ -60,6 +63,104 @@ var gTests = [
|
||||
});
|
||||
}
|
||||
},
|
||||
{
|
||||
desc: "WebChannel two way communication in an iframe",
|
||||
run: function* () {
|
||||
let parentChannel = new WebChannel("echo", Services.io.newURI(HTTP_PATH, null, null));
|
||||
let iframeChannel = new WebChannel("twoway", Services.io.newURI(HTTP_IFRAME_PATH, null, null));
|
||||
let promiseTestDone = new Promise(function (resolve, reject) {
|
||||
parentChannel.listen(function (id, message, sender) {
|
||||
reject(new Error("WebChannel message incorrectly sent to parent"));
|
||||
});
|
||||
|
||||
iframeChannel.listen(function (id, message, sender) {
|
||||
is(id, "twoway");
|
||||
ok(message.command);
|
||||
|
||||
if (message.command === "one") {
|
||||
iframeChannel.send({ data: { nested: true } }, sender);
|
||||
}
|
||||
|
||||
if (message.command === "two") {
|
||||
is(message.detail.data.nested, true);
|
||||
resolve();
|
||||
}
|
||||
});
|
||||
});
|
||||
yield BrowserTestUtils.withNewTab({
|
||||
gBrowser: gBrowser,
|
||||
url: HTTP_PATH + HTTP_ENDPOINT + "?iframe"
|
||||
}, function* () {
|
||||
yield promiseTestDone;
|
||||
parentChannel.stopListening();
|
||||
iframeChannel.stopListening();
|
||||
});
|
||||
}
|
||||
},
|
||||
{
|
||||
desc: "WebChannel response to a redirected iframe",
|
||||
run: function* () {
|
||||
/**
|
||||
* This test checks that WebChannel responses are only sent
|
||||
* to an iframe if the iframe has not redirected to another origin.
|
||||
* Test flow:
|
||||
* 1. create a page, embed an iframe on origin A.
|
||||
* 2. the iframe sends a message `redirecting`, then redirects to
|
||||
* origin B.
|
||||
* 3. the iframe at origin B is set up to echo any messages back to the
|
||||
* test parent.
|
||||
* 4. the test parent receives the `redirecting` message from origin A.
|
||||
* the test parent creates a new channel with origin B.
|
||||
* 5. when origin B is ready, it sends a `loaded` message to the test
|
||||
* parent, letting the test parent know origin B is ready to echo
|
||||
* messages.
|
||||
* 5. the test parent tries to send a response to origin A. If the
|
||||
* WebChannel does not perform a valid origin check, the response
|
||||
* will be received by origin B. If the WebChannel does perform
|
||||
* a valid origin check, the response will not be sent.
|
||||
* 6. the test parent sends a `done` message to origin B, which origin
|
||||
* B echoes back. If the response to origin A is not echoed but
|
||||
* the message to origin B is, then hooray, the test passes.
|
||||
*/
|
||||
|
||||
let preRedirectChannel = new WebChannel("pre_redirect", Services.io.newURI(HTTP_IFRAME_PATH, null, null));
|
||||
let postRedirectChannel = new WebChannel("post_redirect", Services.io.newURI(HTTP_REDIRECTED_IFRAME_PATH, null, null));
|
||||
|
||||
let promiseTestDone = new Promise(function (resolve, reject) {
|
||||
preRedirectChannel.listen(function (id, message, preRedirectSender) {
|
||||
if (message.command === "redirecting") {
|
||||
|
||||
postRedirectChannel.listen(function (id, message, postRedirectSender) {
|
||||
is(id, "post_redirect");
|
||||
isnot(message.command, "no_response_expected");
|
||||
|
||||
if (message.command === "loaded") {
|
||||
// The message should not be received on the preRedirectChannel
|
||||
// because the target window has redirected.
|
||||
preRedirectChannel.send({ command: "no_response_expected" }, preRedirectSender);
|
||||
postRedirectChannel.send({ command: "done" }, postRedirectSender);
|
||||
} else if (message.command === "done") {
|
||||
resolve();
|
||||
} else {
|
||||
reject(new Error(`Unexpected command ${message.command}`));
|
||||
}
|
||||
});
|
||||
} else {
|
||||
reject(new Error(`Unexpected command ${message.command}`));
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
yield BrowserTestUtils.withNewTab({
|
||||
gBrowser: gBrowser,
|
||||
url: HTTP_PATH + HTTP_ENDPOINT + "?iframe_pre_redirect"
|
||||
}, function* () {
|
||||
yield promiseTestDone;
|
||||
preRedirectChannel.stopListening();
|
||||
postRedirectChannel.stopListening();
|
||||
});
|
||||
}
|
||||
},
|
||||
{
|
||||
desc: "WebChannel multichannel",
|
||||
run: function* () {
|
||||
@ -76,7 +177,157 @@ var gTests = [
|
||||
tab = gBrowser.addTab(HTTP_PATH + HTTP_ENDPOINT + "?multichannel");
|
||||
});
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
desc: "WebChannel unsolicited send, using system principal",
|
||||
run: function* () {
|
||||
let channel = new WebChannel("echo", Services.io.newURI(HTTP_PATH, null, null));
|
||||
|
||||
// an unsolicted message is sent from Chrome->Content which is then
|
||||
// echoed back. If the echo is received here, then the content
|
||||
// received the message.
|
||||
let messagePromise = new Promise(function (resolve, reject) {
|
||||
channel.listen(function (id, message, sender) {
|
||||
is(id, "echo");
|
||||
is(message.command, "unsolicited");
|
||||
|
||||
resolve()
|
||||
});
|
||||
});
|
||||
|
||||
yield BrowserTestUtils.withNewTab({
|
||||
gBrowser,
|
||||
url: HTTP_PATH + HTTP_ENDPOINT + "?unsolicited"
|
||||
}, function* (targetBrowser) {
|
||||
channel.send({ command: "unsolicited" }, {
|
||||
browser: targetBrowser,
|
||||
principal: Services.scriptSecurityManager.getSystemPrincipal()
|
||||
});
|
||||
yield messagePromise;
|
||||
channel.stopListening();
|
||||
});
|
||||
}
|
||||
},
|
||||
{
|
||||
desc: "WebChannel unsolicited send, using target origin's principal",
|
||||
run: function* () {
|
||||
let targetURI = Services.io.newURI(HTTP_PATH, null, null);
|
||||
let channel = new WebChannel("echo", targetURI);
|
||||
|
||||
// an unsolicted message is sent from Chrome->Content which is then
|
||||
// echoed back. If the echo is received here, then the content
|
||||
// received the message.
|
||||
let messagePromise = new Promise(function (resolve, reject) {
|
||||
channel.listen(function (id, message, sender) {
|
||||
is(id, "echo");
|
||||
is(message.command, "unsolicited");
|
||||
|
||||
resolve();
|
||||
});
|
||||
});
|
||||
|
||||
yield BrowserTestUtils.withNewTab({
|
||||
gBrowser,
|
||||
url: HTTP_PATH + HTTP_ENDPOINT + "?unsolicited"
|
||||
}, function* (targetBrowser) {
|
||||
|
||||
channel.send({ command: "unsolicited" }, {
|
||||
browser: targetBrowser,
|
||||
principal: Services.scriptSecurityManager.getNoAppCodebasePrincipal(targetURI)
|
||||
});
|
||||
|
||||
yield messagePromise;
|
||||
channel.stopListening();
|
||||
});
|
||||
}
|
||||
},
|
||||
{
|
||||
desc: "WebChannel unsolicited send with principal mismatch",
|
||||
run: function* () {
|
||||
let targetURI = Services.io.newURI(HTTP_PATH, null, null);
|
||||
let channel = new WebChannel("echo", targetURI);
|
||||
|
||||
// two unsolicited messages are sent from Chrome->Content. The first,
|
||||
// `unsolicited_no_response_expected` is sent to the wrong principal
|
||||
// and should not be echoed back. The second, `done`, is sent to the
|
||||
// correct principal and should be echoed back.
|
||||
let messagePromise = new Promise(function (resolve, reject) {
|
||||
channel.listen(function (id, message, sender) {
|
||||
is(id, "echo");
|
||||
|
||||
if (message.command === "done") {
|
||||
resolve();
|
||||
} else {
|
||||
reject(new Error(`Unexpected command ${message.command}`));
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
yield BrowserTestUtils.withNewTab({
|
||||
gBrowser: gBrowser,
|
||||
url: HTTP_PATH + HTTP_ENDPOINT + "?unsolicited"
|
||||
}, function* (targetBrowser) {
|
||||
|
||||
let mismatchURI = Services.io.newURI(HTTP_MISMATCH_PATH, null, null);
|
||||
let mismatchPrincipal = Services.scriptSecurityManager.getNoAppCodebasePrincipal(mismatchURI);
|
||||
|
||||
// send a message to the wrong principal. It should not be delivered
|
||||
// to content, and should not be echoed back.
|
||||
channel.send({ command: "unsolicited_no_response_expected" }, {
|
||||
browser: targetBrowser,
|
||||
principal: mismatchPrincipal
|
||||
});
|
||||
|
||||
let targetPrincipal = Services.scriptSecurityManager.getNoAppCodebasePrincipal(targetURI);
|
||||
|
||||
// send the `done` message to the correct principal. It
|
||||
// should be echoed back.
|
||||
channel.send({ command: "done" }, {
|
||||
browser: targetBrowser,
|
||||
principal: targetPrincipal
|
||||
});
|
||||
|
||||
yield messagePromise;
|
||||
channel.stopListening();
|
||||
});
|
||||
}
|
||||
},
|
||||
{
|
||||
desc: "WebChannel non-window target",
|
||||
run: function* () {
|
||||
/**
|
||||
* This test ensures messages can be received from and responses
|
||||
* sent to non-window elements.
|
||||
*
|
||||
* First wait for the non-window element to send a "start" message.
|
||||
* Then send the non-window element a "done" message.
|
||||
* The non-window element will echo the "done" message back, if it
|
||||
* receives the message.
|
||||
* Listen for the response. If received, good to go!
|
||||
*/
|
||||
let channel = new WebChannel("not_a_window", Services.io.newURI(HTTP_PATH, null, null));
|
||||
|
||||
let testDonePromise = new Promise(function (resolve, reject) {
|
||||
channel.listen(function (id, message, sender) {
|
||||
if (message.command === "start") {
|
||||
channel.send({ command: "done" }, sender);
|
||||
} else if (message.command === "done") {
|
||||
resolve();
|
||||
} else {
|
||||
reject(new Error(`Unexpected command ${message.command}`));
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
yield BrowserTestUtils.withNewTab({
|
||||
gBrowser,
|
||||
url: HTTP_PATH + HTTP_ENDPOINT + "?bubbles"
|
||||
}, function* () {
|
||||
yield testDonePromise;
|
||||
channel.stopListening();
|
||||
});
|
||||
}
|
||||
},
|
||||
]; // gTests
|
||||
|
||||
function test() {
|
||||
|
@ -0,0 +1,97 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>web_channel_test (iframe)</title>
|
||||
</head>
|
||||
<body>
|
||||
<script>
|
||||
var REDIRECTED_IFRAME_SRC_ROOT = "http://example.org/browser/browser/base/content/test/general/browser_web_channel_iframe.html";
|
||||
|
||||
window.onload = function() {
|
||||
var testName = window.location.search.replace(/^\?/, "");
|
||||
switch(testName) {
|
||||
case "iframe":
|
||||
test_iframe();
|
||||
break;
|
||||
case "iframe_pre_redirect":
|
||||
test_iframe_pre_redirect();
|
||||
break;
|
||||
case "iframe_post_redirect":
|
||||
test_iframe_post_redirect();
|
||||
break;
|
||||
default:
|
||||
throw new Error(`INVALID TEST NAME ${testName}`);
|
||||
break;
|
||||
}
|
||||
};
|
||||
|
||||
function test_iframe() {
|
||||
var firstMessage = new window.CustomEvent("WebChannelMessageToChrome", {
|
||||
detail: {
|
||||
id: "twoway",
|
||||
message: {
|
||||
command: "one",
|
||||
},
|
||||
}
|
||||
});
|
||||
|
||||
window.addEventListener("WebChannelMessageToContent", function(e) {
|
||||
var secondMessage = new window.CustomEvent("WebChannelMessageToChrome", {
|
||||
detail: {
|
||||
id: "twoway",
|
||||
message: {
|
||||
command: "two",
|
||||
detail: e.detail.message,
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
if (!e.detail.message.error) {
|
||||
window.dispatchEvent(secondMessage);
|
||||
}
|
||||
}, true);
|
||||
|
||||
window.dispatchEvent(firstMessage);
|
||||
}
|
||||
|
||||
|
||||
function test_iframe_pre_redirect() {
|
||||
var firstMessage = new window.CustomEvent("WebChannelMessageToChrome", {
|
||||
detail: {
|
||||
id: "pre_redirect",
|
||||
message: {
|
||||
command: "redirecting",
|
||||
},
|
||||
},
|
||||
});
|
||||
window.dispatchEvent(firstMessage);
|
||||
document.location = REDIRECTED_IFRAME_SRC_ROOT + "?iframe_post_redirect";
|
||||
}
|
||||
|
||||
function test_iframe_post_redirect() {
|
||||
window.addEventListener("WebChannelMessageToContent", function(e) {
|
||||
var echoMessage = new window.CustomEvent("WebChannelMessageToChrome", {
|
||||
detail: {
|
||||
id: "post_redirect",
|
||||
message: e.detail.message,
|
||||
},
|
||||
});
|
||||
|
||||
window.dispatchEvent(echoMessage);
|
||||
}, true);
|
||||
|
||||
// Let the test parent know the page has loaded and is ready to echo events
|
||||
var loadedMessage = new window.CustomEvent("WebChannelMessageToChrome", {
|
||||
detail: {
|
||||
id: "post_redirect",
|
||||
message: {
|
||||
command: "loaded",
|
||||
},
|
||||
},
|
||||
});
|
||||
window.dispatchEvent(loadedMessage);
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
1720
devtools/client/webconsole/jsterm.js
Normal file
1720
devtools/client/webconsole/jsterm.js
Normal file
File diff suppressed because it is too large
Load Diff
@ -10,6 +10,7 @@ DevToolsModules(
|
||||
'console-commands.js',
|
||||
'console-output.js',
|
||||
'hudservice.js',
|
||||
'jsterm.js',
|
||||
'panel.js',
|
||||
'webconsole.js',
|
||||
)
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -62,8 +62,11 @@ let SyncedTabsInternal = {
|
||||
},
|
||||
|
||||
/* Make a "tab" record. Returns a promise */
|
||||
_makeTab: Task.async(function* (client, tab, url) {
|
||||
let icon = tab.icon;
|
||||
_makeTab: Task.async(function* (client, tab, url, showRemoteIcons) {
|
||||
let icon;
|
||||
if (showRemoteIcons) {
|
||||
icon = tab.icon;
|
||||
}
|
||||
if (!icon) {
|
||||
try {
|
||||
icon = (yield PlacesUtils.promiseFaviconLinkUrl(url)).spec;
|
||||
@ -108,6 +111,9 @@ let SyncedTabsInternal = {
|
||||
return result;
|
||||
}
|
||||
|
||||
// A boolean that controls whether we should show the icon from the remote tab.
|
||||
const showRemoteIcons = Preferences.get("services.sync.syncedTabs.showRemoteIcons", true);
|
||||
|
||||
let engine = Weave.Service.engineManager.get("tabs");
|
||||
|
||||
let seenURLs = new Set();
|
||||
@ -134,7 +140,7 @@ let SyncedTabsInternal = {
|
||||
if (!url || seenURLs.has(url)) {
|
||||
continue;
|
||||
}
|
||||
let tabRepr = yield this._makeTab(client, tab, url);
|
||||
let tabRepr = yield this._makeTab(client, tab, url, showRemoteIcons);
|
||||
if (filter && !this._tabMatchesFilter(tabRepr, filter)) {
|
||||
continue;
|
||||
}
|
||||
|
@ -184,7 +184,9 @@ TabStore.prototype = {
|
||||
allTabs.push({
|
||||
title: current.title || "",
|
||||
urlHistory: urls,
|
||||
icon: tabState.attributes && tabState.attributes.image || "",
|
||||
icon: tabState.image ||
|
||||
(tabState.attributes && tabState.attributes.image) ||
|
||||
"",
|
||||
lastUsed: Math.floor((tabState.lastAccessed || 0) / 1000),
|
||||
});
|
||||
}
|
||||
|
@ -7,6 +7,9 @@ Cu.import("resource://services-sync/main.js");
|
||||
Cu.import("resource://services-sync/SyncedTabs.jsm");
|
||||
Cu.import("resource://gre/modules/Log.jsm");
|
||||
|
||||
const faviconService = Cc["@mozilla.org/browser/favicon-service;1"]
|
||||
.getService(Ci.nsIFaviconService);
|
||||
|
||||
Log.repository.getLogger("Sync.RemoteTabs").addAppender(new Log.DumpAppender());
|
||||
|
||||
// A mock "Tabs" engine which the SyncedTabs module will use instead of the real
|
||||
@ -79,6 +82,7 @@ add_task(function* test_clientWithTabs() {
|
||||
tabs: [
|
||||
{
|
||||
urlHistory: ["http://foo.com/"],
|
||||
icon: "http://foo.com/favicon",
|
||||
}],
|
||||
},
|
||||
guid_mobile: {
|
||||
@ -92,10 +96,34 @@ add_task(function* test_clientWithTabs() {
|
||||
clients.sort((a, b) => { return a.name.localeCompare(b.name);});
|
||||
equal(clients[0].tabs.length, 1);
|
||||
equal(clients[0].tabs[0].url, "http://foo.com/");
|
||||
equal(clients[0].tabs[0].icon, "http://foo.com/favicon");
|
||||
// second client has no tabs.
|
||||
equal(clients[1].tabs.length, 0);
|
||||
});
|
||||
|
||||
add_task(function* test_clientWithTabsIconsDisabled() {
|
||||
Services.prefs.setBoolPref("services.sync.syncedTabs.showRemoteIcons", false);
|
||||
yield configureClients({
|
||||
guid_desktop: {
|
||||
clientName: "My Desktop",
|
||||
tabs: [
|
||||
{
|
||||
urlHistory: ["http://foo.com/"],
|
||||
icon: "http://foo.com/favicon",
|
||||
}],
|
||||
},
|
||||
});
|
||||
|
||||
let clients = yield SyncedTabs.getTabClients();
|
||||
equal(clients.length, 1);
|
||||
clients.sort((a, b) => { return a.name.localeCompare(b.name);});
|
||||
equal(clients[0].tabs.length, 1);
|
||||
equal(clients[0].tabs[0].url, "http://foo.com/");
|
||||
// expect the default favicon due to the pref being false.
|
||||
equal(clients[0].tabs[0].icon, faviconService.defaultFavicon.spec);
|
||||
Services.prefs.clearUserPref("services.sync.syncedTabs.showRemoteIcons");
|
||||
});
|
||||
|
||||
add_task(function* test_filter() {
|
||||
// Nothing matches.
|
||||
yield configureClients({
|
||||
|
@ -63,7 +63,11 @@ function ensureItems() {
|
||||
return _items;
|
||||
}
|
||||
|
||||
// An observer to invalidate _items.
|
||||
// A preference used to disable the showing of icons in remote tab records.
|
||||
const PREF_SHOW_REMOTE_ICONS = "services.sync.syncedTabs.showRemoteIcons";
|
||||
let showRemoteIcons;
|
||||
|
||||
// An observer to invalidate _items and watch for changed prefs.
|
||||
function observe(subject, topic, data) {
|
||||
switch (topic) {
|
||||
case "weave:engine:sync:finish":
|
||||
@ -80,6 +84,16 @@ function observe(subject, topic, data) {
|
||||
_items = null;
|
||||
break;
|
||||
|
||||
case "nsPref:changed":
|
||||
if (data == PREF_SHOW_REMOTE_ICONS) {
|
||||
try {
|
||||
showRemoteIcons = Services.prefs.getBoolPref(PREF_SHOW_REMOTE_ICONS);
|
||||
} catch(_) {
|
||||
showRemoteIcons = true; // no such pref - default is to show the icons.
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@ -88,6 +102,10 @@ function observe(subject, topic, data) {
|
||||
Services.obs.addObserver(observe, "weave:engine:sync:finish", false);
|
||||
Services.obs.addObserver(observe, "weave:service:start-over", false);
|
||||
|
||||
// Observe the pref for showing remote icons and prime our bool that reflects its value.
|
||||
Services.prefs.addObserver(PREF_SHOW_REMOTE_ICONS, observe, false);
|
||||
observe(null, "nsPref:changed", PREF_SHOW_REMOTE_ICONS);
|
||||
|
||||
// This public object is a static singleton.
|
||||
this.PlacesRemoteTabsAutocompleteProvider = {
|
||||
// a promise that resolves with an array of matching remote tabs.
|
||||
@ -105,10 +123,10 @@ this.PlacesRemoteTabsAutocompleteProvider = {
|
||||
if (url.match(re) || (title && title.match(re))) {
|
||||
// lookup the client record.
|
||||
let client = clients.get(clientId);
|
||||
let icon = showRemoteIcons ? tab.icon : null;
|
||||
// create the record we return for auto-complete.
|
||||
let record = {
|
||||
url, title,
|
||||
icon: tab.icon,
|
||||
url, title, icon,
|
||||
deviceClass: Weave.Service.clientsEngine.isMobile(clientId) ? "mobile" : "desktop",
|
||||
deviceName: client.clientName,
|
||||
};
|
||||
|
@ -54,6 +54,7 @@ function makeRemoteTabMatch(url, deviceName, extra = {}) {
|
||||
uri: makeActionURI("remotetab", {url, deviceName}),
|
||||
title: extra.title || url,
|
||||
style: [ "action" ],
|
||||
icon: extra.icon,
|
||||
}
|
||||
}
|
||||
|
||||
@ -115,12 +116,39 @@ add_task(function* test_maximal() {
|
||||
matches: [ makeSearchMatch("ex", { heuristic: true }),
|
||||
makeRemoteTabMatch("http://example.com/", "My Phone",
|
||||
{ title: "An Example",
|
||||
icon: "moz-anno:favicon:http://favicon"
|
||||
icon: "moz-anno:favicon:http://favicon/"
|
||||
}),
|
||||
],
|
||||
});
|
||||
});
|
||||
|
||||
add_task(function* test_noShowIcons() {
|
||||
Services.prefs.setBoolPref("services.sync.syncedTabs.showRemoteIcons", false);
|
||||
configureEngine({
|
||||
guid_mobile: {
|
||||
clientName: "My Phone",
|
||||
tabs: [{
|
||||
urlHistory: ["http://example.com/"],
|
||||
title: "An Example",
|
||||
icon: "http://favicon",
|
||||
}],
|
||||
}
|
||||
});
|
||||
|
||||
yield check_autocomplete({
|
||||
search: "ex",
|
||||
searchParam: "enable-actions",
|
||||
matches: [ makeSearchMatch("ex", { heuristic: true }),
|
||||
makeRemoteTabMatch("http://example.com/", "My Phone",
|
||||
{ title: "An Example",
|
||||
// expecting the default favicon due to that pref.
|
||||
icon: PlacesUtils.favicons.defaultFavicon.spec,
|
||||
}),
|
||||
],
|
||||
});
|
||||
Services.prefs.clearUserPref("services.sync.syncedTabs.showRemoteIcons");
|
||||
});
|
||||
|
||||
add_task(function* test_matches_title() {
|
||||
// URL doesn't match search expression, should still match the title.
|
||||
configureEngine({
|
||||
|
@ -61,6 +61,7 @@ add_task(function test_web_channel_broker_listener() {
|
||||
deliver: function(data, sender) {
|
||||
do_check_eq(data.id, VALID_WEB_CHANNEL_ID);
|
||||
do_check_eq(data.message.command, "hello");
|
||||
do_check_neq(sender, undefined);
|
||||
WebChannelBroker.unregisterChannel(channel);
|
||||
resolve();
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user