author | Wes Kocher <wkocher@mozilla.com> |
Tue, 02 Sep 2014 19:28:14 -0700 | |
changeset 203126 | e58842c764dd10913e29f54e3cecd7654499a830 |
parent 203112 | 0b63b2b7733f241f6b12b745b989337375ee3caf (current diff) |
parent 203125 | 2dd9b2f2ef8fa99d631a4897027e0cf33f0e15e4 (diff) |
child 203127 | 5e9826980be5999a66f6c3f8c9d2a95762fa6788 |
child 203134 | fc096d338bc411a2084f4e1b429d3738ca5a395f |
child 203221 | 53ab51cc4eb0a8b475ff1e8e1db8e59688c8b97e |
child 203328 | 413f70cd2040ae387a0a50fdd4f996b1cdd230e4 |
push id | 27421 |
push user | kwierso@gmail.com |
push date | Wed, 03 Sep 2014 02:33:37 +0000 |
treeherder | mozilla-central@e58842c764dd [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
reviewers | merge |
milestone | 35.0a1 |
first release with | nightly linux32
e58842c764dd
/
35.0a1
/
20140903030206
/
files
nightly linux64
e58842c764dd
/
35.0a1
/
20140903030206
/
files
nightly mac
e58842c764dd
/
35.0a1
/
20140903030206
/
files
nightly win32
e58842c764dd
/
35.0a1
/
20140903030206
/
files
nightly win64
e58842c764dd
/
35.0a1
/
20140903030206
/
files
|
last release without | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
releases | nightly linux32
35.0a1
/
20140903030206
/
pushlog to previous
nightly linux64
35.0a1
/
20140903030206
/
pushlog to previous
nightly mac
35.0a1
/
20140903030206
/
pushlog to previous
nightly win32
35.0a1
/
20140903030206
/
pushlog to previous
nightly win64
35.0a1
/
20140903030206
/
pushlog to previous
|
browser/themes/linux/social/chat-icons.png | file | annotate | diff | comparison | revisions | |
browser/themes/osx/social/chat-icons.png | file | annotate | diff | comparison | revisions | |
browser/themes/osx/social/chat-icons@2x.png | file | annotate | diff | comparison | revisions | |
browser/themes/windows/social/chat-icons.png | file | annotate | diff | comparison | revisions |
--- a/browser/app/profile/firefox.js +++ b/browser/app/profile/firefox.js @@ -1577,18 +1577,22 @@ pref("shumway.disabled", true); // The maximum amount of decoded image data we'll willingly keep around (we // might keep around more than this, but we'll try to get down to this value). // (This is intentionally on the high side; see bug 746055.) pref("image.mem.max_decoded_image_kb", 256000); // Enable by default development builds up until early beta #ifdef EARLY_BETA_OR_EARLIER pref("loop.enabled", true); +pref("loop.throttled", false); #else -pref("loop.enabled", false); +pref("loop.enabled", true); +pref("loop.throttled", true); +pref("loop.soft_start_ticket_number", -1); +pref("loop.soft_start_hostname", "soft-start.loop-dev.stage.mozaws.net"); #endif pref("loop.server", "https://loop.services.mozilla.com"); pref("loop.seenToS", "unseen"); pref("loop.legal.ToS_url", "https://accounts.firefox.com/legal/terms"); pref("loop.legal.privacy_url", "https://www.mozilla.org/privacy/"); pref("loop.do_not_disturb", false); pref("loop.ringtone", "chrome://browser/content/loop/shared/sounds/Firefox-Long.ogg");
--- a/browser/base/content/browser-loop.js +++ b/browser/base/content/browser-loop.js @@ -44,16 +44,22 @@ XPCOMUtils.defineLazyModuleGetter(this, if (!Services.prefs.getBoolPref("loop.enabled")) { this.toolbarButton.node.hidden = true; return; } // Add observer notifications before the service is initialized Services.obs.addObserver(this, "loop-status-changed", false); + // If we're throttled, check to see if it's our turn to be unthrottled + if (Services.prefs.getBoolPref("loop.throttled")) { + this.toolbarButton.node.hidden = true; + MozLoopService.checkSoftStart(this.toolbarButton.node); + return; + } MozLoopService.initialize(); this.updateToolbarState(); }, uninit: function() { Services.obs.removeObserver(this, "loop-status-changed"); },
--- a/browser/base/content/socialchat.xml +++ b/browser/base/content/socialchat.xml @@ -132,17 +132,19 @@ PopupNotifications._reshowNotifications(this.content.popupnotificationanchor, this.content); ]]></body> </method> <method name="swapDocShells"> <parameter name="aTarget"/> <body><![CDATA[ - aTarget.setAttribute('label', this.contentDocument.title); + aTarget.setAttribute("label", this.contentDocument.title); + if (this.getAttribute("dark") == "true") + aTarget.setAttribute("dark", "true"); aTarget.src = this.src; aTarget.content.setAttribute("origin", this.content.getAttribute("origin")); aTarget.content.popupnotificationanchor.className = this.content.popupnotificationanchor.className; this.content.swapDocShells(aTarget.content); ]]></body> </method> <method name="onTitlebarClick">
--- a/browser/components/loop/MozLoopService.jsm +++ b/browser/components/loop/MozLoopService.jsm @@ -5,16 +5,21 @@ "use strict"; const { classes: Cc, interfaces: Ci, utils: Cu } = Components; // Invalid auth token as per // https://github.com/mozilla-services/loop-server/blob/45787d34108e2f0d87d74d4ddf4ff0dbab23501c/loop/errno.json#L6 const INVALID_AUTH_TOKEN = 110; +// Ticket numbers are 24 bits in length. +// The highest valid ticket number is 16777214 (2^24 - 2), so that a "now +// serving" number of 2^24 - 1 is greater than it. +const MAX_SOFT_START_TICKET_NUMBER = 16777214; + Cu.import("resource://gre/modules/Services.jsm"); Cu.import("resource://gre/modules/XPCOMUtils.jsm"); Cu.import("resource://gre/modules/Promise.jsm"); Cu.import("resource://gre/modules/osfile.jsm", this); Cu.import("resource://gre/modules/Task.jsm"); Cu.import("resource://gre/modules/FxAccountsOAuthClient.jsm"); this.EXPORTED_SYMBOLS = ["MozLoopService"]; @@ -44,16 +49,21 @@ XPCOMUtils.defineLazyModuleGetter(this, XPCOMUtils.defineLazyModuleGetter(this, "MozLoopPushHandler", "resource:///modules/loop/MozLoopPushHandler.jsm"); XPCOMUtils.defineLazyServiceGetter(this, "uuidgen", "@mozilla.org/uuid-generator;1", "nsIUUIDGenerator"); +XPCOMUtils.defineLazyServiceGetter(this, "gDNSService", + "@mozilla.org/network/dns-service;1", + "nsIDNSService"); + + // The current deferred for the registration process. This is set if in progress // or the registration was successful. This is null if a registration attempt was // unsuccessful. let gRegisteredDeferred = null; let gPushHandler = null; let gHawkClient = null; let gRegisteredLoopServer = false; let gLocalizedStrings = null; @@ -449,16 +459,18 @@ let MozLoopServiceInternal = { // in about:blank and then get lost. // Sadly we can't use chatbox.promiseChatLoaded() as promise chaining // involves event loop spins, which means it might be too late. // Have we already done it? if (chatbox.contentWindow.navigator.mozLoop) { return; } + chatbox.setAttribute("dark", true); + chatbox.addEventListener("DOMContentLoaded", function loaded(event) { if (event.target != chatbox.contentDocument) { return; } chatbox.removeEventListener("DOMContentLoaded", loaded, true); let window = chatbox.contentWindow; injectLoopAPI(window); @@ -627,51 +639,157 @@ this.MozLoopService = { resetFxA: function() { gFxAOAuthClientPromise = null; gFxAOAuthClient = null; gFxAOAuthTokenData = null; }, #endif + _DNSService: gDNSService, + set initializeTimerFunc(value) { gInitializeTimerFunc = value; }, /** * Initialized the loop service, and starts registration with the * push and loop servers. */ initialize: function() { // Don't do anything if loop is not enabled. - if (!Services.prefs.getBoolPref("loop.enabled")) { + if (!Services.prefs.getBoolPref("loop.enabled") || + Services.prefs.getBoolPref("loop.throttled")) { return; } // If expiresTime is in the future then kick-off registration. if (MozLoopServiceInternal.urlExpiryTimeIsInFuture()) { gInitializeTimerFunc(); } }, /** + * If we're operating the service in "soft start" mode, and this browser + * isn't already activated, check whether it's time for it to become active. + * If so, activate the loop service. + * + * @param {Object} buttonNode DOM node representing the Loop button -- if we + * change from inactive to active, we need this + * in order to unhide the Loop button. + * @param {Function} doneCb [optional] Callback that is called when the + * check has completed. + */ + checkSoftStart(buttonNode, doneCb) { + if (!Services.prefs.getBoolPref("loop.throttled")) { + if (typeof(doneCb) == "function") { + doneCb(new Error("Throttling is not active")); + } + return; + } + + if (Services.io.offline) { + if (typeof(doneCb) == "function") { + doneCb(new Error("Cannot check soft-start value: browser is offline")); + } + return; + } + + let ticket = Services.prefs.getIntPref("loop.soft_start_ticket_number"); + if (!ticket || ticket > MAX_SOFT_START_TICKET_NUMBER || ticket < 0) { + // Ticket value isn't valid (probably isn't set up yet) -- pick a random + // number from 1 to MAX_SOFT_START_TICKET_NUMBER, inclusive, and write it + // into prefs. + ticket = Math.floor(Math.random() * MAX_SOFT_START_TICKET_NUMBER) + 1; + // Floating point numbers can be imprecise, so we need to deal with + // the case that Math.random() effectively rounds to 1.0 + if (ticket > MAX_SOFT_START_TICKET_NUMBER) { + ticket = MAX_SOFT_START_TICKET_NUMBER; + } + Services.prefs.setIntPref("loop.soft_start_ticket_number", ticket); + } + + let onLookupComplete = (request, record, status) => { + // We don't bother checking errors -- if the DNS query fails, + // we just don't activate this time around. We'll check again on + // next startup. + if (!Components.isSuccessCode(status)) { + if (typeof(doneCb) == "function") { + doneCb(new Error("Error in DNS Lookup: " + status)); + } + return; + } + + let address = record.getNextAddrAsString().split("."); + if (address.length != 4) { + if (typeof(doneCb) == "function") { + doneCb(new Error("Invalid IP address")); + } + return; + } + + if (address[0] != 127) { + if (typeof(doneCb) == "function") { + doneCb(new Error("Throttling IP address is not on localhost subnet")); + } + return + } + + // Can't use bitwise operations here because JS treats all bitwise + // operations as 32-bit *signed* integers. + let now_serving = ((parseInt(address[1]) * 0x10000) + + (parseInt(address[2]) * 0x100) + + parseInt(address[3])); + + if (now_serving > ticket) { + // Hot diggity! It's our turn! Activate the service. + console.log("MozLoopService: Activating Loop via soft-start"); + Services.prefs.setBoolPref("loop.throttled", false); + buttonNode.hidden = false; + this.initialize(); + } + if (typeof(doneCb) == "function") { + doneCb(null); + } + }; + + // We use DNS to propagate the slow-start value, since it has well-known + // scaling properties. Ideally, this would use something more semantic, + // like a TXT record; but we don't support TXT in our DNS resolution (see + // Bug 14328), so we instead treat the lowest 24 bits of the IP address + // corresponding to our "slow start DNS name" as a 24-bit integer. To + // ensure that these addresses aren't routable, the highest 8 bits must + // be "127" (reserved for localhost). + let host = Services.prefs.getCharPref("loop.soft_start_hostname"); + let task = this._DNSService.asyncResolve(host, + this._DNSService.RESOLVE_DISABLE_IPV6, + onLookupComplete, + Services.tm.mainThread); + }, + + + /** * Starts registration of Loop with the push server, and then will register * with the Loop server. It will return early if already registered. * * @param {Object} mockPushHandler Optional, test-only mock push handler. Used * to allow mocking of the MozLoopPushHandler. * @returns {Promise} a promise that is resolved with no params on completion, or * rejected with an error code or string. */ register: function(mockPushHandler) { // Don't do anything if loop is not enabled. if (!Services.prefs.getBoolPref("loop.enabled")) { throw new Error("Loop is not enabled"); } + if (Services.prefs.getBoolPref("loop.throttled")) { + throw new Error("Loop is disabled by the soft-start mechanism"); + } + return MozLoopServiceInternal.promiseRegisteredWithServers(mockPushHandler); }, /** * Used to note a call url expiry time. If the time is later than the current * latest expiry time, then the stored expiry time is increased. For times * sooner, this function is a no-op; this ensures we always have the latest * expiry time for a url.
--- a/browser/components/loop/test/mochitest/browser.ini +++ b/browser/components/loop/test/mochitest/browser.ini @@ -7,11 +7,12 @@ support-files = [browser_CardDavImporter.js] [browser_fxa_login.js] skip-if = !debug [browser_loop_fxa_server.js] [browser_LoopContacts.js] [browser_mozLoop_appVersionInfo.js] [browser_mozLoop_prefs.js] [browser_mozLoop_doNotDisturb.js] +[browser_mozLoop_softStart.js] skip-if = buildapp == 'mulet' [browser_toolbarbutton.js] [browser_mozLoop_pluralStrings.js]
new file mode 100644 --- /dev/null +++ b/browser/components/loop/test/mochitest/browser_mozLoop_softStart.js @@ -0,0 +1,130 @@ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +const SOFT_START_HOSTNAME = "soft-start.example.invalid"; + +let MockDNSService = { + RESOLVE_DISABLE_IPV6: 32, + nowServing: 0, + resultCode: 0, + ipFirstOctet: 127, + + getNowServingAddress: function() { + let ip = this.ipFirstOctet + "." + + ((this.nowServing >>> 16) & 0xFF) + "." + + ((this.nowServing >>> 8) & 0xFF) + "." + + ((this.nowServing) & 0xFF); + info("Using 'now serving' of " + this.nowServing + " (" + ip + ")"); + return ip; + }, + + asyncResolve: function(host, flags, callback) { + let mds = this; + Assert.equal(flags, this.RESOLVE_DISABLE_IPV6, + "AAAA lookup should be disabled"); + Assert.equal(host, SOFT_START_HOSTNAME, + "Configured hostname should be used"); + callback(null, + {getNextAddrAsString: mds.getNowServingAddress.bind(mds)}, + this.resultCode); + } +}; + +// We need an unfrozen copy of the LoopService so we can monkeypatch it. +let LoopService = {}; +for (var prop in MozLoopService) { + if (MozLoopService.hasOwnProperty(prop)) { + LoopService[prop] = MozLoopService[prop]; + } +} +LoopService._DNSService = MockDNSService; + +let MockButton = { + hidden: true +}; + +let runCheck = function(expectError) { + return new Promise((resolve, reject) => { + LoopService.checkSoftStart(MockButton, error => { + if ((!!error) != (!!expectError)) { + reject(error); + } else { + resolve(error); + } + }) + }); +} + +add_task(function* test_mozLoop_softStart() { + // Set associated variables to proper values + Services.prefs.setBoolPref("loop.throttled", true); + Services.prefs.setCharPref("loop.soft_start_hostname", SOFT_START_HOSTNAME); + Services.prefs.setIntPref("loop.soft_start_ticket_number", -1); + + let throttled; + let ticket; + + info("Ensure that we pick a valid ticket number."); + yield runCheck(); + throttled = Services.prefs.getBoolPref("loop.throttled"); + ticket = Services.prefs.getIntPref("loop.soft_start_ticket_number"); + Assert.equal(MockButton.hidden, true, "Button should still be hidden"); + Assert.equal(throttled, true, "Feature should still be throttled"); + Assert.notEqual(ticket, -1, "Ticket should be changed"); + Assert.ok((ticket < 16777214 && ticket > 0), "Ticket should be in range"); + + // Try some "interesting" ticket numbers + for (ticket of [1, 256, 65535, 10000000, 16777214]) { + MockButton.hidden = true; + Services.prefs.setBoolPref("loop.throttled", true); + Services.prefs.setBoolPref("loop.soft_start", true); + Services.prefs.setIntPref("loop.soft_start_ticket_number", ticket); + + info("Ensure that we don't activate when the now serving " + + "number is less than our value."); + MockDNSService.nowServing = ticket - 1; + yield runCheck(); + throttled = Services.prefs.getBoolPref("loop.throttled"); + Assert.equal(MockButton.hidden, true, "Button should still be hidden"); + Assert.equal(throttled, true, "Feature should still be throttled"); + + info("Ensure that we don't activate when the now serving " + + "number is equal to our value"); + MockDNSService.nowServing = ticket; + yield runCheck(); + throttled = Services.prefs.getBoolPref("loop.throttled"); + Assert.equal(MockButton.hidden, true, "Button should still be hidden"); + Assert.equal(throttled, true, "Feature should still be throttled"); + + info("Ensure that we *do* activate when the now serving " + + "number is greater than our value"); + MockDNSService.nowServing = ticket + 1; + yield runCheck(); + throttled = Services.prefs.getBoolPref("loop.throttled"); + Assert.equal(MockButton.hidden, false, "Button should not be hidden"); + Assert.equal(throttled, false, "Feature should be unthrottled"); + } + + info("Check DNS error behavior"); + MockDNSService.nowServing = 0; + MockDNSService.resultCode = 0x80000000; + Services.prefs.setBoolPref("loop.throttled", true); + Services.prefs.setBoolPref("loop.soft_start", true); + MockButton.hidden = true; + yield runCheck(true); + throttled = Services.prefs.getBoolPref("loop.throttled"); + Assert.equal(MockButton.hidden, true, "Button should be hidden"); + Assert.equal(throttled, true, "Feature should be throttled"); + + info("Check DNS misconfiguration behavior"); + MockDNSService.nowServing = ticket + 1; + MockDNSService.resultCode = 0; + MockDNSService.ipFirstOctet = 6; + Services.prefs.setBoolPref("loop.throttled", true); + Services.prefs.setBoolPref("loop.soft_start", true); + MockButton.hidden = true; + yield runCheck(true); + throttled = Services.prefs.getBoolPref("loop.throttled"); + Assert.equal(MockButton.hidden, true, "Button should be hidden"); + Assert.equal(throttled, true, "Feature should be throttled"); +});
--- a/browser/themes/linux/jar.mn +++ b/browser/themes/linux/jar.mn @@ -151,17 +151,17 @@ browser.jar: skin/classic/browser/preferences/in-content/icons.png (../shared/incontentprefs/icons.png) skin/classic/browser/preferences/in-content/icons@2x.png (../shared/incontentprefs/icons@2x.png) skin/classic/browser/preferences/applications.css (preferences/applications.css) skin/classic/browser/preferences/aboutPermissions.css (preferences/aboutPermissions.css) skin/classic/browser/social/services-16.png (social/services-16.png) skin/classic/browser/social/services-64.png (social/services-64.png) skin/classic/browser/social/share-button.png (social/share-button.png) skin/classic/browser/social/share-button-active.png (social/share-button-active.png) - skin/classic/browser/social/chat-icons.png (social/chat-icons.png) + skin/classic/browser/social/chat-icons.svg (../shared/social/chat-icons.svg) skin/classic/browser/social/gear_default.png (../shared/social/gear_default.png) skin/classic/browser/social/gear_clicked.png (../shared/social/gear_clicked.png) skin/classic/browser/tabbrowser/alltabs.png (tabbrowser/alltabs.png) skin/classic/browser/tabbrowser/alltabs-inverted.png (tabbrowser/alltabs-inverted.png) skin/classic/browser/tabbrowser/connecting.png (tabbrowser/connecting.png) skin/classic/browser/tabbrowser/loading.png (tabbrowser/loading.png) skin/classic/browser/tabbrowser/tab-active-middle.png (tabbrowser/tab-active-middle.png) skin/classic/browser/tabbrowser/tab-arrow-left.png (tabbrowser/tab-arrow-left.png)
deleted file mode 100644 index cc895f93c29f2b3601ddd1af3bf3a9a042eda15c..0000000000000000000000000000000000000000 GIT binary patch literal 0 Hc$@<O00001
--- a/browser/themes/osx/jar.mn +++ b/browser/themes/osx/jar.mn @@ -255,18 +255,17 @@ browser.jar: skin/classic/browser/preferences/in-content/icons.png (../shared/incontentprefs/icons.png) skin/classic/browser/preferences/in-content/icons@2x.png (../shared/incontentprefs/icons@2x.png) skin/classic/browser/preferences/applications.css (preferences/applications.css) skin/classic/browser/preferences/aboutPermissions.css (preferences/aboutPermissions.css) skin/classic/browser/social/services-16.png (social/services-16.png) skin/classic/browser/social/services-16@2x.png (social/services-16@2x.png) skin/classic/browser/social/services-64.png (social/services-64.png) skin/classic/browser/social/services-64@2x.png (social/services-64@2x.png) - skin/classic/browser/social/chat-icons.png (social/chat-icons.png) - skin/classic/browser/social/chat-icons@2x.png (social/chat-icons@2x.png) + skin/classic/browser/social/chat-icons.svg (../shared/social/chat-icons.svg) skin/classic/browser/social/gear_default.png (../shared/social/gear_default.png) skin/classic/browser/social/gear_clicked.png (../shared/social/gear_clicked.png) skin/classic/browser/tabbrowser/alltabs-box-bkgnd-icon.png (tabbrowser/alltabs-box-bkgnd-icon.png) skin/classic/browser/tabbrowser/alltabs-box-bkgnd-icon-inverted.png (tabbrowser/alltabs-box-bkgnd-icon-inverted.png) skin/classic/browser/tabbrowser/alltabs-box-bkgnd-icon-inverted@2x.png (tabbrowser/alltabs-box-bkgnd-icon-inverted@2x.png) skin/classic/browser/tabbrowser/newtab.png (tabbrowser/newtab.png) skin/classic/browser/tabbrowser/newtab@2x.png (tabbrowser/newtab@2x.png) skin/classic/browser/tabbrowser/newtab-inverted.png (tabbrowser/newtab-inverted.png)
deleted file mode 100644 index cc895f93c29f2b3601ddd1af3bf3a9a042eda15c..0000000000000000000000000000000000000000 GIT binary patch literal 0 Hc$@<O00001
deleted file mode 100644 index 4afab888b14686c8856f651928f20bc6776f92aa..0000000000000000000000000000000000000000 GIT binary patch literal 0 Hc$@<O00001
new file mode 100644 --- /dev/null +++ b/browser/themes/shared/social/chat-icons.svg @@ -0,0 +1,45 @@ +<?xml version="1.0"?> +<!-- This Source Code Form is subject to the terms of the Mozilla Public + - 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/. --> +<svg xmlns="http://www.w3.org/2000/svg" + xmlns:xlink="http://www.w3.org/1999/xlink" + x="0px" y="0px" + viewBox="-3 -3 16 16" + enable-background="new 0 0 16 16" + xml:space="preserve"> +<style> +use:not(:target) { + display: none; +} + +use { + fill: #c1c1c1; +} + +use[id$="-active"] { + fill: #c1c1c1; +} + +use[id$="-disabled"] { + fill: #c1c1c1; +} +</style> +<defs> + <polygon id="close-shape" fill-rule="evenodd" clip-rule="evenodd" points="10,1.717 8.336,0.049 5.024,3.369 1.663,0 0,1.668 + 3.36,5.037 0.098,8.307 1.762,9.975 5.025,6.705 8.311,10 9.975,8.332 6.688,5.037"/> + <path id="dropdown-shape" fill-rule="evenodd" clip-rule="evenodd" d="M9,3L4.984,7L1,3H9z"/> + <polygon id="expand-shape" fill-rule="evenodd" clip-rule="evenodd" points="10,0 4.838,0 6.506,1.669 0,8.175 1.825,10 8.331,3.494 + 10,5.162"/> + <rect id="minimize-shape" y="3.6" fill-rule="evenodd" clip-rule="evenodd" width="10" height="2.8"/> +</defs> +<use id="close" xlink:href="#close-shape"/> +<use id="close-active" xlink:href="#close-shape"/> +<use id="close-disabled" xlink:href="#close-shape"/> +<use id="expand" xlink:href="#expand-shape"/> +<use id="expand-active" xlink:href="#expand-shape"/> +<use id="expand-disabled" xlink:href="#expand-shape"/> +<use id="minimize" xlink:href="#minimize-shape"/> +<use id="minimize-active" xlink:href="#minimize-shape"/> +<use id="minimize-disabled" xlink:href="#minimize-shape"/> +</svg>
--- a/browser/themes/shared/social/chat.inc.css +++ b/browser/themes/shared/social/chat.inc.css @@ -42,150 +42,80 @@ max-height: 16px; max-width: 16px; padding: 0; } .chat-toolbarbutton { -moz-appearance: none; border: none; - padding: 0; + padding: 0 3px; margin: 0; background: none; - width: 16px; +} + +.chat-toolbarbutton:hover { + background-color: rgba(255,255,255,.35); +} + +.chat-toolbarbutton:hover:active { + background-color: rgba(255,255,255,.5); } .chat-toolbarbutton > .toolbarbutton-text { display: none; } .chat-toolbarbutton > .toolbarbutton-icon { - width: inherit; + width: 16px; + height: 16px; } .chat-close-button { - list-style-image: url('chrome://browser/skin/social/chat-icons.png'); - -moz-image-region: rect(0, 16px, 16px, 0); + list-style-image: url("chrome://browser/skin/social/chat-icons.svg#close"); } -.chat-close-button:hover { - -moz-image-region: rect(0, 32px, 16px, 16px); -} - -.chat-close-button:hover:active { - -moz-image-region: rect(0, 48px, 16px, 32px); +.chat-close-button:-moz-any(:hover,:hover:active) { + list-style-image: url("chrome://browser/skin/social/chat-icons.svg#close-active"); } .chat-minimize-button { - list-style-image: url('chrome://browser/skin/social/chat-icons.png'); - -moz-image-region: rect(16px, 16px, 32px, 0); + list-style-image: url("chrome://browser/skin/social/chat-icons.svg#minimize"); } -.chat-minimize-button:hover { - -moz-image-region: rect(16px, 32px, 32px, 16px); -} - -.chat-minimize-button:hover:active { - -moz-image-region: rect(16px, 48px, 32px, 32px); +.chat-minimize-button:-moz-any(:hover,:hover:active) { + list-style-image: url("chrome://browser/skin/social/chat-icons.svg#minimize-active"); } .chat-swap-button { - list-style-image: url('chrome://browser/skin/social/chat-icons.png'); - -moz-image-region: rect(48px, 16px, 64px, 0); + list-style-image: url("chrome://browser/skin/social/chat-icons.svg#expand"); + transform: rotate(180deg); } -.chat-swap-button:hover { - -moz-image-region: rect(48px, 32px, 64px, 16px); -} - -.chat-swap-button:hover:active { - -moz-image-region: rect(48px, 48px, 64px, 32px); +.chat-swap-button:-moz-any(:hover,:hover:active) { + list-style-image: url("chrome://browser/skin/social/chat-icons.svg#expand-active"); } chatbar > chatbox > .chat-titlebar > .chat-swap-button { - list-style-image: url('chrome://browser/skin/social/chat-icons.png'); - -moz-image-region: rect(32px, 16px, 48px, 0); -} - -chatbar > chatbox > .chat-titlebar > .chat-swap-button:hover { - -moz-image-region: rect(32px, 32px, 48px, 16px); -} - -chatbar > chatbox > .chat-titlebar > .chat-swap-button:hover:active { - -moz-image-region: rect(32px, 48px, 48px, 32px); -} - -@media (min-resolution: 2dppx) { - .chat-close-button { - list-style-image: url('chrome://browser/skin/social/chat-icons@2x.png'); - -moz-image-region: rect(0, 32px, 32px, 0); - } - - .chat-close-button:hover { - -moz-image-region: rect(0, 64px, 32px, 32px); - } - - .chat-close-button:hover:active { - -moz-image-region: rect(0, 96px, 32px, 64px); - } - - .chat-minimize-button { - list-style-image: url('chrome://browser/skin/social/chat-icons@2x.png'); - -moz-image-region: rect(32px, 32px, 64px, 0); - } - - .chat-minimize-button:hover { - -moz-image-region: rect(32px, 64px, 64px, 32px); - } - - .chat-minimize-button:hover:active { - -moz-image-region: rect(32px, 96px, 64px, 64px); - } - - .chat-swap-button { - list-style-image: url('chrome://browser/skin/social/chat-icons@2x.png'); - -moz-image-region: rect(96px, 32px, 128px, 0); - } - - .chat-swap-button:hover { - -moz-image-region: rect(96px, 64px, 128px, 32px); - } - - .chat-swap-button:hover:active { - -moz-image-region: rect(96px, 96px, 128px, 64px); - } - - chatbar > chatbox > .chat-titlebar > .chat-swap-button { - list-style-image: url('chrome://browser/skin/social/chat-icons@2x.png'); - -moz-image-region: rect(64px, 32px, 96px, 0); - } - - chatbar > chatbox > .chat-titlebar > .chat-swap-button:hover { - -moz-image-region: rect(64px, 64px, 96px, 32px); - } - - chatbar > chatbox > .chat-titlebar > .chat-swap-button:hover:active { - -moz-image-region: rect(64px, 96px, 96px, 64px); - } + transform: none; } .chat-title { font-weight: bold; color: black; text-shadow: none; cursor: inherit; } .chat-titlebar { - height: 20px; - min-height: 20px; + height: 30px; + min-height: 30px; width: 100%; margin: 0; - padding: 2px; - -moz-padding-start: 6px; + padding: 7px 6px; border: none; border-bottom: 1px solid #ccc; cursor: pointer; } .chat-titlebar > .notification-anchor-icon { margin-left: 2px; margin-right: 2px; @@ -197,16 +127,28 @@ chatbar > chatbox > .chat-titlebar > .ch .chat-titlebar[activity] { background-image: radial-gradient(ellipse closest-side at center, rgb(255,255,255), rgba(255,255,255,0)); background-repeat: no-repeat; background-size: 100% 20px; background-position: 0 -10px; } +chatbox[dark=true] > .chat-titlebar, +chatbox[dark=true] > .chat-titlebar[selected] { + border-bottom: none; + background-color: #000; + background-image: none; +} + +chatbox[dark=true] > .chat-titlebar > hbox > .chat-title { + font-weight: normal; + color: #c1c1c1; +} + .chat-frame { padding: 0; margin: 0; overflow: hidden; } .chatbar-button { list-style-image: url("chrome://browser/skin/social/services-16.png");
--- a/browser/themes/windows/jar.mn +++ b/browser/themes/windows/jar.mn @@ -177,17 +177,17 @@ browser.jar: * skin/classic/browser/preferences/in-content/preferences.css (preferences/in-content/preferences.css) skin/classic/browser/preferences/in-content/favicon.ico (../shared/incontentprefs/favicon.ico) skin/classic/browser/preferences/in-content/icons.png (../shared/incontentprefs/icons.png) skin/classic/browser/preferences/in-content/icons@2x.png (../shared/incontentprefs/icons@2x.png) skin/classic/browser/preferences/applications.css (preferences/applications.css) skin/classic/browser/preferences/aboutPermissions.css (preferences/aboutPermissions.css) skin/classic/browser/social/services-16.png (social/services-16.png) skin/classic/browser/social/services-64.png (social/services-64.png) - skin/classic/browser/social/chat-icons.png (social/chat-icons.png) + skin/classic/browser/social/chat-icons.svg (../shared/social/chat-icons.svg) skin/classic/browser/social/gear_default.png (../shared/social/gear_default.png) skin/classic/browser/social/gear_clicked.png (../shared/social/gear_clicked.png) skin/classic/browser/tabbrowser/newtab.png (tabbrowser/newtab.png) skin/classic/browser/tabbrowser/newtab-inverted.png (tabbrowser/newtab-inverted.png) skin/classic/browser/tabbrowser/connecting.png (tabbrowser/connecting.png) skin/classic/browser/tabbrowser/loading.png (tabbrowser/loading.png) skin/classic/browser/tabbrowser/tab-active-middle.png (tabbrowser/tab-active-middle.png) skin/classic/browser/tabbrowser/tab-active-middle@2x.png (tabbrowser/tab-active-middle@2x.png) @@ -596,17 +596,17 @@ browser.jar: * skin/classic/aero/browser/preferences/in-content/preferences.css (preferences/in-content/preferences.css) skin/classic/aero/browser/preferences/in-content/favicon.ico (../shared/incontentprefs/favicon.ico) skin/classic/aero/browser/preferences/in-content/icons.png (../shared/incontentprefs/icons.png) skin/classic/aero/browser/preferences/in-content/icons@2x.png (../shared/incontentprefs/icons@2x.png) skin/classic/aero/browser/preferences/applications.css (preferences/applications.css) skin/classic/aero/browser/preferences/aboutPermissions.css (preferences/aboutPermissions.css) skin/classic/aero/browser/social/services-16.png (social/services-16.png) skin/classic/aero/browser/social/services-64.png (social/services-64.png) - skin/classic/aero/browser/social/chat-icons.png (social/chat-icons.png) + skin/classic/aero/browser/social/chat-icons.svg (../shared/social/chat-icons.svg) skin/classic/aero/browser/social/gear_default.png (../shared/social/gear_default.png) skin/classic/aero/browser/social/gear_clicked.png (../shared/social/gear_clicked.png) skin/classic/aero/browser/tabbrowser/newtab.png (tabbrowser/newtab.png) skin/classic/aero/browser/tabbrowser/newtab-inverted.png (tabbrowser/newtab-inverted.png) skin/classic/aero/browser/tabbrowser/connecting.png (tabbrowser/connecting.png) skin/classic/aero/browser/tabbrowser/loading.png (tabbrowser/loading.png) skin/classic/aero/browser/tabbrowser/tab-active-middle.png (tabbrowser/tab-active-middle.png) skin/classic/aero/browser/tabbrowser/tab-active-middle@2x.png (tabbrowser/tab-active-middle@2x.png)
deleted file mode 100644 index cc895f93c29f2b3601ddd1af3bf3a9a042eda15c..0000000000000000000000000000000000000000 GIT binary patch literal 0 Hc$@<O00001
--- a/dom/events/EventStateManager.cpp +++ b/dom/events/EventStateManager.cpp @@ -2699,16 +2699,25 @@ EventStateManager::PostHandleEvent(nsPre if (mouseEvent->button == WidgetMouseEvent::eLeftButton && !sNormalLMouseEventInProcess) { // We got a mouseup event while a mousedown event was being processed. // Make sure that the capturing content is cleared. nsIPresShell::SetCapturingContent(nullptr, 0); break; } + // For remote content, capture the event in the parent process at the + // <xul:browser remote> element. This will ensure that subsequent mousemove/mouseup + // events will continue to be dispatched to this element and therefore forwarded + // to the child. + if (dispatchedToContentProcess && !nsIPresShell::GetCapturingContent()) { + nsIContent* content = mCurrentTarget ? mCurrentTarget->GetContent() : nullptr; + nsIPresShell::SetCapturingContent(content, 0); + } + nsCOMPtr<nsIContent> activeContent; if (nsEventStatus_eConsumeNoDefault != *aStatus) { nsCOMPtr<nsIContent> newFocus; bool suppressBlur = false; if (mCurrentTarget) { mCurrentTarget->GetContentForEvent(aEvent, getter_AddRefs(newFocus)); const nsStyleUserInterface* ui = mCurrentTarget->StyleUserInterface(); activeContent = mCurrentTarget->GetContent();
--- a/mobile/android/base/MediaCastingBar.java +++ b/mobile/android/base/MediaCastingBar.java @@ -43,17 +43,17 @@ public class MediaCastingBar extends Rel mMediaPlay = (ImageButton) content.findViewById(R.id.media_play); mMediaPlay.setOnClickListener(this); mMediaPause = (ImageButton) content.findViewById(R.id.media_pause); mMediaPause.setOnClickListener(this); mMediaStop = (ImageButton) content.findViewById(R.id.media_stop); mMediaStop.setOnClickListener(this); - mCastingTo = (TextView) content.findViewById(R.id.media_casting_to); + mCastingTo = (TextView) content.findViewById(R.id.media_sending_to); // Capture clicks on the rest of the view to prevent them from // leaking into other views positioned below. content.setOnClickListener(this); mInflated = true; }
--- a/mobile/android/base/locales/en-US/android_strings.dtd +++ b/mobile/android/base/locales/en-US/android_strings.dtd @@ -296,19 +296,19 @@ size. --> <!-- Localization note (find_text, find_prev, find_next, find_close) : These strings are used as alternate text for accessibility. They are not visible in the UI. --> <!ENTITY find_text "Find in Page"> <!ENTITY find_prev "Previous"> <!ENTITY find_next "Next"> <!ENTITY find_close "Close"> -<!-- Localization note (media_casting_to, media_play, media_pause, media_stop) : These strings are used +<!-- Localization note (media_sending_to, media_play, media_pause, media_stop) : These strings are used as alternate text for accessibility. They are not visible in the UI. --> -<!ENTITY media_casting_to "Casting to Device"> +<!ENTITY media_sending_to "Sending to Device"> <!ENTITY media_play "Play"> <!ENTITY media_pause "Pause"> <!ENTITY media_stop "Stop"> <!ENTITY contextmenu_open_new_tab "Open in New Tab"> <!ENTITY contextmenu_open_private_tab "Open in Private Tab"> <!ENTITY contextmenu_remove "Remove"> <!ENTITY contextmenu_add_to_launcher "Add to Home Screen">
--- a/mobile/android/base/resources/layout/media_casting.xml +++ b/mobile/android/base/resources/layout/media_casting.xml @@ -14,28 +14,28 @@ <ImageButton android:id="@+id/media_pause" style="@style/FindBar.ImageButton" android:contentDescription="@string/media_pause" android:src="@drawable/media_bar_pause"/> </RelativeLayout> - <TextView android:id="@+id/media_casting_to" + <TextView android:id="@+id/media_sending_to" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginLeft="5dip" android:layout_marginRight="5dip" android:layout_alignParentLeft="true" android:layout_toLeftOf="@id/media_controls" android:layout_centerVertical="true" android:singleLine="true" android:ellipsize="end" android:textColor="#FFFFFFFF" - android:contentDescription="@string/media_casting_to"/> + android:contentDescription="@string/media_sending_to"/> <ImageButton android:id="@+id/media_stop" style="@style/FindBar.ImageButton" android:contentDescription="@string/media_stop" android:layout_alignParentRight="true" android:src="@drawable/media_bar_stop"/> </merge>
--- a/mobile/android/base/strings.xml.in +++ b/mobile/android/base/strings.xml.in @@ -100,17 +100,17 @@ <string name="page">&page;</string> <string name="tools">&tools;</string> <string name="find_text">&find_text;</string> <string name="find_prev">&find_prev;</string> <string name="find_next">&find_next;</string> <string name="find_close">&find_close;</string> - <string name="media_casting_to">&media_casting_to;</string> + <string name="media_sending_to">&media_sending_to;</string> <string name="media_play">&media_play;</string> <string name="media_pause">&media_pause;</string> <string name="media_stop">&media_stop;</string> <string name="overlay_share_send_other">&overlay_share_send_other;</string> <string name="overlay_share_label">&overlay_share_label;</string> <string name="overlay_share_bookmark_btn_label">&overlay_share_bookmark_btn_label;</string> <string name="overlay_share_reading_list_btn_label">&overlay_share_reading_list_btn_label;</string>
--- a/mobile/android/base/tests/robocop_head.js +++ b/mobile/android/base/tests/robocop_head.js @@ -1162,17 +1162,17 @@ function JavaBridge(obj) { }; JavaBridge.prototype = { _Services: Components.utils.import( "resource://gre/modules/Services.jsm", {}).Services, _sendMessageToJava: Components.utils.import( - "resource://gre/modules/Messaging.jsm", {}).sendMessageToJava, + "resource://gre/modules/Messaging.jsm", {}).Messaging.sendRequest, _sendMessage: function (innerType, args) { this._sendMessageToJava({ type: this._EVENT_TYPE, innerType: innerType, method: args[0], args: Array.prototype.slice.call(args, 1), });
--- a/mobile/android/base/tests/roboextender/robocop_home_banner.html +++ b/mobile/android/base/tests/roboextender/robocop_home_banner.html @@ -16,30 +16,30 @@ function start() { } var messageId; function addMessage() { messageId = Home.banner.add({ text: TEXT, onclick: function() { - sendMessageToJava({ type: "TestHomeBanner:MessageClicked" }); + Messaging.sendRequest({ type: "TestHomeBanner:MessageClicked" }); }, onshown: function() { - sendMessageToJava({ type: "TestHomeBanner:MessageShown" }); + Messaging.sendRequest({ type: "TestHomeBanner:MessageShown" }); }, ondismiss: function() { - sendMessageToJava({ type: "TestHomeBanner:MessageDismissed" }); + Messaging.sendRequest({ type: "TestHomeBanner:MessageDismissed" }); } }); - sendMessageToJava({ type: "TestHomeBanner:MessageAdded" }); + Messaging.sendRequest({ type: "TestHomeBanner:MessageAdded" }); } function removeMessage() { Home.banner.remove(messageId); - sendMessageToJava({ type: "TestHomeBanner:MessageRemoved" }); + Messaging.sendRequest({ type: "TestHomeBanner:MessageRemoved" }); } </script> </head> <body onload="start();"> </body> </html>
--- a/mobile/android/base/tests/roboextender/testSelectionHandler.html +++ b/mobile/android/base/tests/roboextender/testSelectionHandler.html @@ -208,17 +208,17 @@ function testCloseSelection() { } /* ================================================================================= * * After finish of all selection tests, wrap up and go home. * */ function finishTests() { - sendMessageToJava({ + Messaging.sendRequest({ type: "Robocop:testSelectionHandler", result: true, msg: "Done!", done: true }); } /* ============================== Utility functions ======================
--- a/mobile/android/base/tests/testEventDispatcher.js +++ b/mobile/android/base/tests/testEventDispatcher.js @@ -23,17 +23,17 @@ function send_test_message(type) { // Make a copy let outerObject = JSON.parse(JSON.stringify(innerObject)); outerObject.type = type; outerObject.object = innerObject; outerObject.objectArray = [null, innerObject]; - sendMessageToJava(outerObject); + Messaging.sendRequest(outerObject); } function send_message_for_response(type, response) { sendMessageToJava({ type: type, response: response, }, (success, error) => { if (response === "success") {
--- a/mobile/android/base/tests/testGeckoRequest.js +++ b/mobile/android/base/tests/testGeckoRequest.js @@ -3,38 +3,38 @@ Components.utils.import("resource://gre/ let java = new JavaBridge(this); do_register_cleanup(() => { java.disconnect(); }); do_test_pending(); function add_request_listener(message) { - RequestService.addListener(function (data) { + Messaging.addListener(function (data) { return { result: data + "bar" }; }, message); } function add_exception_listener(message) { - RequestService.addListener(function (data) { + Messaging.addListener(function (data) { throw "error!"; }, message); } function add_second_request_listener(message) { let exceptionCaught = false; try { - RequestService.addListener(() => {}, message); + Messaging.addListener(() => {}, message); } catch (e) { exceptionCaught = true; } do_check_true(exceptionCaught); } function remove_request_listener(message) { - RequestService.removeListener(message); + Messaging.removeListener(message); } function finish_test() { do_test_finished(); }
--- a/mobile/android/base/util/NativeEventListener.java +++ b/mobile/android/base/util/NativeEventListener.java @@ -10,14 +10,14 @@ import org.mozilla.gecko.mozglue.Robocop @RobocopTarget public interface NativeEventListener { /** * Handles a message sent from Gecko. * * @param event The name of the event being sent. * @param message The message data. * @param callback The callback interface for this message. A callback is provided only if the - * originating sendMessageToJava call included a callback argument; otherwise, + * originating Messaging.sendRequest call included a callback argument; otherwise, * callback will be null. All listeners for a given event are given the same * callback object, and exactly one listener must handle the callback. */ void handleMessage(String event, NativeJSObject message, EventCallback callback); }
--- a/mobile/android/chrome/content/CastingApps.js +++ b/mobile/android/chrome/content/CastingApps.js @@ -57,17 +57,17 @@ var CastingApps = { SimpleServiceDiscovery.registerTarget(rokuTarget); SimpleServiceDiscovery.registerTarget(fireflyTarget); SimpleServiceDiscovery.registerTarget(mediaPlayerTarget); // Search for devices continuously every 120 seconds SimpleServiceDiscovery.search(120 * 1000); this._castMenuId = NativeWindow.contextmenus.add( - Strings.browser.GetStringFromName("contextmenu.castToScreen"), + Strings.browser.GetStringFromName("contextmenu.sendToDevice"), this.filterCast, this.handleContextMenu.bind(this) ); Services.obs.addObserver(this, "Casting:Play", false); Services.obs.addObserver(this, "Casting:Pause", false); Services.obs.addObserver(this, "Casting:Stop", false); Services.obs.addObserver(this, "Casting:Mirror", false); @@ -424,24 +424,24 @@ var CastingApps = { } // We check for two state here: // 1. The video is actively being cast // 2. The video is allowed to be cast and is currently playing // Both states have the same action: Show the cast page action if (aVideo.mozIsCasting) { this.pageAction.id = PageActions.add({ - title: Strings.browser.GetStringFromName("contextmenu.castToScreen"), + title: Strings.browser.GetStringFromName("contextmenu.sendToDevice"), icon: "drawable://casting_active", clickCallback: this.pageAction.click, important: true }); } else if (aVideo.mozAllowCasting) { this.pageAction.id = PageActions.add({ - title: Strings.browser.GetStringFromName("contextmenu.castToScreen"), + title: Strings.browser.GetStringFromName("contextmenu.sendToDevice"), icon: "drawable://casting", clickCallback: this.pageAction.click, important: true }); } }, prompt: function(aCallback, aFilterFunc) { @@ -458,17 +458,17 @@ var CastingApps = { } }); if (items.length == 0) { return; } let prompt = new Prompt({ - title: Strings.browser.GetStringFromName("casting.prompt") + title: Strings.browser.GetStringFromName("casting.sendToDevice") }).setSingleChoiceItems(items).show(function(data) { let selected = data.button; let service = selected == -1 ? null : filteredServices[selected]; if (aCallback) aCallback(service); }); }, @@ -558,27 +558,27 @@ var CastingApps = { // RemoteMedia callback API methods onRemoteMediaStart: function(aRemoteMedia) { if (!this.session) { return; } aRemoteMedia.load(this.session.data); - sendMessageToJava({ type: "Casting:Started", device: this.session.service.friendlyName }); + Messaging.sendRequest({ type: "Casting:Started", device: this.session.service.friendlyName }); let video = this.session.videoRef.get(); if (video) { this._sendEventToVideo(video, { active: true }); this._updatePageAction(video); } }, onRemoteMediaStop: function(aRemoteMedia) { - sendMessageToJava({ type: "Casting:Stopped" }); + Messaging.sendRequest({ type: "Casting:Stopped" }); this._shutdown(); }, onRemoteMediaStatus: function(aRemoteMedia) { if (!this.session) { return; }
--- a/mobile/android/chrome/content/PermissionsHelper.js +++ b/mobile/android/chrome/content/PermissionsHelper.js @@ -83,17 +83,17 @@ var PermissionsHelper = { this._currentPermissions = permissions; let host; try { host = uri.host; } catch(e) { host = uri.spec; } - sendMessageToJava({ + Messaging.sendRequest({ type: "Permissions:Data", host: host, permissions: permissions }); break; case "Permissions:Clear": // An array of the indices of the permissions we want to clear
--- a/mobile/android/chrome/content/SelectionHandler.js +++ b/mobile/android/chrome/content/SelectionHandler.js @@ -193,40 +193,40 @@ var SelectionHandler = { } else { Cu.reportError("Ignored \"TextSelection:Position\" message during invalid selection status"); } break; } case "TextSelection:Get": - sendMessageToJava({ + Messaging.sendRequest({ type: "TextSelection:Data", requestId: aData, text: this._getSelectedText() }); break; } }, // Ignore selectionChange notifications during handle dragging, disable dynamic // IME text compositions (autoSuggest, autoCorrect, etc) _startDraggingHandles: function sh_startDraggingHandles() { if (!this._draggingHandles) { this._draggingHandles = true; - sendMessageToJava({ type: "TextSelection:DraggingHandle", dragging: true }); + Messaging.sendRequest({ type: "TextSelection:DraggingHandle", dragging: true }); } }, // Act on selectionChange notifications when not dragging handles, allow dynamic // IME text compositions (autoSuggest, autoCorrect, etc) _stopDraggingHandles: function sh_stopDraggingHandles() { if (this._draggingHandles) { this._draggingHandles = false; - sendMessageToJava({ type: "TextSelection:DraggingHandle", dragging: false }); + Messaging.sendRequest({ type: "TextSelection:DraggingHandle", dragging: false }); } }, handleEvent: function sh_handleEvent(aEvent) { switch (aEvent.type) { case "scroll": // Maintain position when top-level document is scrolled this._positionHandlesOnChange(); @@ -336,17 +336,17 @@ var SelectionHandler = { scroll.Y + aOptions.y, positions)) { this._closeSelection(); return false; } // Determine position and show handles, open actionbar this._positionHandles(positions); - sendMessageToJava({ + Messaging.sendRequest({ type: "TextSelection:ShowHandles", handles: [this.HANDLE_TYPE_START, this.HANDLE_TYPE_END] }); this._updateMenu(); return true; }, /* @@ -541,17 +541,17 @@ var SelectionHandler = { order: this._getValue(action, "order", 0) }; actions.push(a); } } actions.sort((a, b) => b.order - a.order); - sendMessageToJava({ + Messaging.sendRequest({ type: "TextSelection:Update", actions: actions }); }, /* * Actionbar methods. */ @@ -712,17 +712,17 @@ var SelectionHandler = { BrowserApp.deck.addEventListener("keyup", this, false); BrowserApp.deck.addEventListener("compositionupdate", this, false); BrowserApp.deck.addEventListener("compositionend", this, false); this._activeType = this.TYPE_CURSOR; // Determine position and show caret, open actionbar this._positionHandles(); - sendMessageToJava({ + Messaging.sendRequest({ type: "TextSelection:ShowHandles", handles: [this.HANDLE_TYPE_MIDDLE] }); this._updateMenu(); return true; }, @@ -926,17 +926,17 @@ var SelectionHandler = { NativeWindow.toast.show(Strings.browser.GetStringFromName("selectionHelper.textCopied"), "short"); } this._closeSelection(); }, shareSelection: function sh_shareSelection() { let selectedText = this._getSelectedText(); if (selectedText.length) { - sendMessageToJava({ + Messaging.sendRequest({ type: "Share:Text", text: selectedText }); } this._closeSelection(); }, searchSelection: function sh_searchSelection() { @@ -995,17 +995,17 @@ var SelectionHandler = { selection.collapseToStart(); } } }, _deactivate: function sh_deactivate() { this._stopDraggingHandles(); // Hide handle/caret, close actionbar - sendMessageToJava({ type: "TextSelection:HideHandles" }); + Messaging.sendRequest({ type: "TextSelection:HideHandles" }); this._removeObservers(); // Only observed for caret positioning if (this._activeType == this.TYPE_CURSOR) { Services.obs.removeObserver(this, "TextSelection:UpdateCaretPos"); BrowserApp.deck.removeEventListener("keyup", this); BrowserApp.deck.removeEventListener("compositionupdate", this); @@ -1151,17 +1151,17 @@ var SelectionHandler = { // Position handles, allow for re-position, in case user drags handle // to invalid position, then releases, we can put it back where it started // positions is an array of objects with data about handle positions, // which we get from _getHandlePositions. _positionHandles: function sh_positionHandles(positions) { if (!positions) { positions = this._getHandlePositions(this._getScrollPos()); } - sendMessageToJava({ + Messaging.sendRequest({ type: "TextSelection:PositionHandles", positions: positions, rtl: this._isRTL }); this._prevHandlePositions = positions; // Text state transitions (text <--> no text) will affect selection context and actionbar display let currTargetElementHasText = (this._targetElement.textLength > 0);
--- a/mobile/android/chrome/content/ZoomHelper.js +++ b/mobile/android/chrome/content/ZoomHelper.js @@ -32,23 +32,23 @@ var ZoomHelper = { rect.type = "Browser:ZoomToRect"; rect.x = Math.max(viewport.cssPageLeft, rect.x - fudge + leftAdjustment); rect.y = Math.max(topPos, viewport.cssPageTop); rect.w = viewport.cssWidth; rect.h = viewport.cssHeight; rect.animate = false; - sendMessageToJava(rect); + Messaging.sendRequest(rect); BrowserApp.selectedTab._mReflozPoint = null; }, zoomOut: function() { BrowserEventHandler.resetMaxLineBoxWidth(); - sendMessageToJava({ type: "Browser:ZoomToPageWidth" }); + Messaging.sendRequest({ type: "Browser:ZoomToPageWidth" }); }, isRectZoomedIn: function(aRect, aViewport) { // This function checks to see if the area of the rect visible in the // viewport (i.e. the "overlapArea" variable below) is approximately // the max area of the rect we can show. It also checks that the rect // is actually on-screen by testing the left and right edges of the rect. // In effect, this tells us whether or not zooming in to this rect @@ -140,11 +140,11 @@ var ZoomHelper = { rect.y = cssTapY - (rect.h / 2); } } if (rect.w > viewport.cssWidth || rect.h > viewport.cssHeight) { BrowserEventHandler.resetMaxLineBoxWidth(); } - sendMessageToJava(rect); + Messaging.sendRequest(rect); }, };
--- a/mobile/android/chrome/content/aboutFeedback.js +++ b/mobile/android/chrome/content/aboutFeedback.js @@ -43,17 +43,17 @@ function init() { updateActiveSection(aEvent.state ? aEvent.state.section : "intro") }, false); // Fill "Last visited site" input with most recent history entry URL. Services.obs.addObserver(function observer(aSubject, aTopic, aData) { document.getElementById("last-url").value = aData; }, "Feedback:LastUrl", false); - sendMessageToJava({ type: "Feedback:LastUrl" }); + Messaging.sendRequest({ type: "Feedback:LastUrl" }); } function uninit() { Services.obs.removeObserver(this, "Feedback:LastUrl"); } function switchSection(aSection) { history.pushState({ section: aSection }, aSection); @@ -61,25 +61,25 @@ function switchSection(aSection) { } function updateActiveSection(aSection) { document.querySelector("section[active]").removeAttribute("active"); document.getElementById(aSection).setAttribute("active", true); } function openPlayStore() { - sendMessageToJava({ type: "Feedback:OpenPlayStore" }); + Messaging.sendRequest({ type: "Feedback:OpenPlayStore" }); window.close(); } function maybeLater() { window.close(); - sendMessageToJava({ type: "Feedback:MaybeLater" }); + Messaging.sendRequest({ type: "Feedback:MaybeLater" }); } function sendFeedback(aEvent) { // Prevent the page from reloading. aEvent.preventDefault(); let section = history.state.section;
--- a/mobile/android/chrome/content/aboutHealthReport.js +++ b/mobile/android/chrome/content/aboutHealthReport.js @@ -83,17 +83,17 @@ let healthReportWrapper = { this.injectData("prefs", prefs); } catch (e) { this.reportFailure(this.ERROR_PREFS_FAILED); } }, refreshPayload: function () { console.log("AboutHealthReport: page requested fresh payload."); - sendMessageToJava({ + Messaging.sendRequest({ type: EVENT_HEALTH_REQUEST, }); }, updatePayload: function (data) { healthReportWrapper.injectData("payload", data); // Data is supposed to be a string, so the length should be // defined. Just in case, we do this after injecting the data. @@ -115,25 +115,25 @@ let healthReportWrapper = { }; let iframe = document.getElementById("remote-report"); iframe.contentWindow.postMessage(data, reportUrl); }, showSettings: function () { console.log("AboutHealthReport: showing settings."); - sendMessageToJava({ + Messaging.sendRequest({ type: "Settings:Show", resource: "preferences_vendor", }); }, launchUpdater: function () { console.log("AboutHealthReport: launching updater."); - sendMessageToJava({ + Messaging.sendRequest({ type: "Updater:Launch", }); }, handleRemoteCommand: function (evt) { switch (evt.detail.command) { case "DisableDataSubmission": this.onOptOut();
--- a/mobile/android/chrome/content/aboutReader.js +++ b/mobile/android/chrome/content/aboutReader.js @@ -1,14 +1,15 @@ /* This Source Code Form is subject to the terms of the Mozilla Public * 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/. */ let Ci = Components.interfaces, Cc = Components.classes, Cu = Components.utils; +Cu.import("resource://gre/modules/Messaging.jsm"); Cu.import("resource://gre/modules/Services.jsm") Cu.import("resource://gre/modules/XPCOMUtils.jsm"); XPCOMUtils.defineLazyModuleGetter(this, "UITelemetry", "resource://gre/modules/UITelemetry.jsm"); XPCOMUtils.defineLazyGetter(window, "gChromeWin", function () window.QueryInterface(Ci.nsIInterfaceRequestor) @@ -303,17 +304,17 @@ AboutReader.prototype = { if (this._isReadingListItem == 1) { classes.add("on"); } else { classes.remove("on"); } }, _requestReadingListStatus: function Reader_requestReadingListStatus() { - gChromeWin.sendMessageToJava({ + Messaging.sendRequest({ type: "Reader:ListStatusRequest", url: this._article.url }); }, _onReaderToggle: function Reader_onToggle() { if (!this._article) return; @@ -330,17 +331,17 @@ AboutReader.prototype = { if (success) { result = gChromeWin.Reader.READER_ADD_SUCCESS; UITelemetry.addEvent("save.1", "button", uptime, "reader"); } let json = JSON.stringify({ fromAboutReader: true, url: this._article.url }); Services.obs.notifyObservers(null, "Reader:Add", json); - gChromeWin.sendMessageToJava({ + Messaging.sendRequest({ type: "Reader:Added", result: result, title: this._article.title, url: this._article.url, length: this._article.length, excerpt: this._article.excerpt }); }.bind(this)); @@ -354,17 +355,17 @@ AboutReader.prototype = { UITelemetry.addEvent("unsave.1", "button", null, "reader"); } }, _onShare: function Reader_onShare() { if (!this._article) return; - gChromeWin.sendMessageToJava({ + Messaging.sendRequest({ type: "Reader:Share", url: this._article.url, title: this._article.title }); UITelemetry.addEvent("share.1", "list", null); }, @@ -519,24 +520,24 @@ AboutReader.prototype = { } }, _toggleToolbarVisibility: function Reader_toggleToolbarVisibility() { this._setToolbarVisibility(!this._getToolbarVisibility()); }, _setBrowserToolbarVisiblity: function Reader_setBrowserToolbarVisiblity(visible) { - gChromeWin.sendMessageToJava({ + Messaging.sendRequest({ type: "BrowserToolbar:Visibility", visible: visible }); }, _setSystemUIVisibility: function Reader_setSystemUIVisibility(visible) { - gChromeWin.sendMessageToJava({ + Messaging.sendRequest({ type: "SystemUI:Visibility", visible: visible }); }, _loadFromURL: function Reader_loadFromURL(url) { this._showProgressDelayed(); @@ -555,17 +556,17 @@ AboutReader.prototype = { if (article) this._showContent(article); else this._showError(gStrings.GetStringFromName("aboutReader.loadError")); }.bind(this)); }, _requestFavicon: function Reader_requestFavicon() { - gChromeWin.sendMessageToJava({ + Messaging.sendRequest({ type: "Reader:FaviconRequest", url: this._article.url }); }, _loadFavicon: function Reader_loadFavicon(url, faviconUrl) { if (this._article.url !== url) return;
--- a/mobile/android/chrome/content/browser.js +++ b/mobile/android/chrome/content/browser.js @@ -22,17 +22,17 @@ Cu.import("resource://gre/modules/UITele #ifdef ACCESSIBILITY Cu.import("resource://gre/modules/accessibility/AccessFu.jsm"); #endif XPCOMUtils.defineLazyModuleGetter(this, "PluralForm", "resource://gre/modules/PluralForm.jsm"); -XPCOMUtils.defineLazyModuleGetter(this, "sendMessageToJava", +XPCOMUtils.defineLazyModuleGetter(this, "Messaging", "resource://gre/modules/Messaging.jsm"); XPCOMUtils.defineLazyModuleGetter(this, "DebuggerServer", "resource://gre/modules/devtools/dbg-server.jsm"); XPCOMUtils.defineLazyModuleGetter(this, "UserAgentOverrides", "resource://gre/modules/UserAgentOverrides.jsm"); @@ -301,17 +301,17 @@ var BrowserApp = { window.QueryInterface(Ci.nsIDOMChromeWindow).browserDOMWindow = new nsBrowserAccess(); dump("zerdatime " + Date.now() + " - browser chrome startup finished."); this.deck = document.getElementById("browsers"); this.deck.addEventListener("DOMContentLoaded", function BrowserApp_delayedStartup() { try { BrowserApp.deck.removeEventListener("DOMContentLoaded", BrowserApp_delayedStartup, false); Services.obs.notifyObservers(window, "browser-delayed-startup-finished", ""); - sendMessageToJava({ type: "Gecko:DelayedStartup" }); + Messaging.sendRequest({ type: "Gecko:DelayedStartup" }); // Queue up some other performance-impacting initializations Services.tm.mainThread.dispatch(function() { // Init LoginManager Cc["@mozilla.org/login-manager;1"].getService(Ci.nsILoginManager); }, Ci.nsIThread.DISPATCH_NORMAL); #ifdef MOZ_SAFE_BROWSING @@ -361,29 +361,29 @@ var BrowserApp = { Services.obs.addObserver(this, "Webapps:AutoUninstall", false); Services.obs.addObserver(this, "sessionstore-state-purge-complete", false); function showFullScreenWarning() { NativeWindow.toast.show(Strings.browser.GetStringFromName("alertFullScreenToast"), "short"); } window.addEventListener("fullscreen", function() { - sendMessageToJava({ + Messaging.sendRequest({ type: window.fullScreen ? "ToggleChrome:Show" : "ToggleChrome:Hide" }); }, false); window.addEventListener("mozfullscreenchange", function(e) { // This event gets fired on the document and its entire ancestor chain // of documents. When enabling fullscreen, it is fired on the top-level // document first and goes down; when disabling the order is reversed // (per spec). This means the last event on enabling will be for the innermost // document, which will have mozFullScreenElement set correctly. let doc = e.target; - sendMessageToJava({ + Messaging.sendRequest({ type: doc.mozFullScreen ? "DOMFullScreen:Start" : "DOMFullScreen:Stop", rootElement: (doc.mozFullScreen && doc.mozFullScreenElement == doc.documentElement) }); if (doc.mozFullScreen) showFullScreenWarning(); }, false); @@ -456,17 +456,17 @@ var BrowserApp = { if (this.isGuest) { // Disable extension installs Services.prefs.setIntPref("extensions.enabledScopes", 1); Services.prefs.setIntPref("extensions.autoDisableScopes", 1); Services.prefs.setBoolPref("xpinstall.enabled", false); } // notify java that gecko has loaded - sendMessageToJava({ type: "Gecko:Ready" }); + Messaging.sendRequest({ type: "Gecko:Ready" }); }, get _startupStatus() { delete this._startupStatus; let savedMilestone = null; try { savedMilestone = Services.prefs.getCharPref("browser.startup.homepage_override.mstone"); @@ -482,17 +482,17 @@ var BrowserApp = { return this._startupStatus; }, /** * Pass this a locale string, such as "fr" or "es_ES". */ setLocale: function (locale) { console.log("browser.js: requesting locale set: " + locale); - sendMessageToJava({ type: "Locale:Set", locale: locale }); + Messaging.sendRequest({ type: "Locale:Set", locale: locale }); }, _initRuntime: function(status, url, callback) { let sandbox = {}; Services.scriptloader.loadSubScript("chrome://browser/content/WebappRT.js", sandbox); window.WebappRT = sandbox.WebappRT; WebappRT.init(status, url, callback); }, @@ -627,42 +627,42 @@ var BrowserApp = { }); NativeWindow.contextmenus.add(Strings.browser.GetStringFromName("contextmenu.addToContacts"), NativeWindow.contextmenus._disableInGuest(NativeWindow.contextmenus.emailLinkContext), function(aTarget) { UITelemetry.addEvent("action.1", "contextmenu", null, "web_contact_email"); let url = NativeWindow.contextmenus._getLinkURL(aTarget); - sendMessageToJava({ + Messaging.sendRequest({ type: "Contact:Add", email: url }); }); NativeWindow.contextmenus.add(Strings.browser.GetStringFromName("contextmenu.addToContacts"), NativeWindow.contextmenus._disableInGuest(NativeWindow.contextmenus.phoneNumberLinkContext), function(aTarget) { UITelemetry.addEvent("action.1", "contextmenu", null, "web_contact_phone"); let url = NativeWindow.contextmenus._getLinkURL(aTarget); - sendMessageToJava({ + Messaging.sendRequest({ type: "Contact:Add", phone: url }); }); NativeWindow.contextmenus.add(Strings.browser.GetStringFromName("contextmenu.bookmarkLink"), NativeWindow.contextmenus._disableInGuest(NativeWindow.contextmenus.linkBookmarkableContext), function(aTarget) { UITelemetry.addEvent("action.1", "contextmenu", null, "web_bookmark"); let url = NativeWindow.contextmenus._getLinkURL(aTarget); let title = aTarget.textContent || aTarget.title || url; - sendMessageToJava({ + Messaging.sendRequest({ type: "Bookmark:Insert", url: url, title: title }); }); NativeWindow.contextmenus.add(Strings.browser.GetStringFromName("contextmenu.playMedia"), NativeWindow.contextmenus.mediaContext("media-paused"), @@ -768,17 +768,17 @@ var BrowserApp = { }); NativeWindow.contextmenus.add(Strings.browser.GetStringFromName("contextmenu.setImageAs"), NativeWindow.contextmenus._disableInGuest(NativeWindow.contextmenus.imageSaveableContext), function(aTarget) { UITelemetry.addEvent("action.1", "contextmenu", null, "web_background_image"); let src = aTarget.src; - sendMessageToJava({ + Messaging.sendRequest({ type: "Image:SetAs", url: src }); }); NativeWindow.contextmenus.add( function(aTarget) { if (aTarget instanceof HTMLVideoElement) { @@ -958,17 +958,17 @@ var BrowserApp = { try { aBrowser.loadURIWithFlags(aURI, flags, referrerURI, charset, postData); } catch(e) { if (tab) { let message = { type: "Content:LoadError", tabID: tab.id }; - sendMessageToJava(message); + Messaging.sendRequest(message); dump("Handled load error: " + e) } } }, addTab: function addTab(aURI, aParams) { aParams = aParams || {}; @@ -1005,17 +1005,17 @@ var BrowserApp = { Cu.reportError("Error trying to close tab (tab doesn't exist)"); return; } let message = { type: "Tab:Close", tabID: aTab.id }; - sendMessageToJava(message); + Messaging.sendRequest(message); }, _loadWebapp: function(aMessage) { this._initRuntime(this._startupStatus, aMessage.url, aUrl => { this.manifestUrl = aMessage.url; this.addTab(aUrl, { title: aMessage.name }); }); @@ -1075,17 +1075,17 @@ var BrowserApp = { // There's nothing to do if the tab is already selected if (aTab == this.selectedTab) return; let message = { type: "Tab:Select", tabID: aTab.id }; - sendMessageToJava(message); + Messaging.sendRequest(message); }, /** * Gets an open tab with the given URL. * * @param aURL URL to look for * @return the tab with the given URL, or null if no such tab exists */ @@ -1318,17 +1318,17 @@ var BrowserApp = { pref.type = "string"; pref.value = pref.value.toString(); break; } prefs.push(pref); } - sendMessageToJava({ + Messaging.sendRequest({ type: "Preferences:Data", requestId: aRequestId, // opaque request identifier, can be any string/int/whatever preferences: prefs }); }, setPreferences: function setPreferences(aPref) { let json = JSON.parse(aPref); @@ -1424,26 +1424,26 @@ var BrowserApp = { promises.push(Sanitizer.clearItem("sessions")); break; default: promises.push(Sanitizer.clearItem(key)); } } Promise.all(promises).then(function() { - sendMessageToJava({ + Messaging.sendRequest({ type: "Sanitize:Finished", success: true }); if (callback) { callback(); } }).catch(function(err) { - sendMessageToJava({ + Messaging.sendRequest({ type: "Sanitize:Finished", error: err, success: false }); if (callback) { callback(); } @@ -1616,17 +1616,17 @@ var BrowserApp = { // perform a keyword search on the selected tab. this.selectedTab.userSearch = aData; // Don't store queries in private browsing mode. let isPrivate = PrivateBrowsingUtils.isWindowPrivate(this.selectedTab.browser.contentWindow); let query = isPrivate ? "" : aData; let engine = aSubject.QueryInterface(Ci.nsISearchEngine); - sendMessageToJava({ + Messaging.sendRequest({ type: "Search:Keyword", identifier: engine.identifier, name: engine.name, query: query }); break; case "Browser:Quit": @@ -1677,21 +1677,21 @@ var BrowserApp = { case "FormHistory:Init": { // Force creation/upgrade of formhistory.sqlite FormHistory.count({}); Services.obs.removeObserver(this, "FormHistory:Init"); break; } case "sessionstore-state-purge-complete": - sendMessageToJava({ type: "Session:StatePurged" }); + Messaging.sendRequest({ type: "Session:StatePurged" }); break; case "gather-telemetry": - sendMessageToJava({ type: "Telemetry:Gather" }); + Messaging.sendRequest({ type: "Telemetry:Gather" }); break; case "Viewport:FixedMarginsChanged": gViewportMargins = JSON.parse(aData); this.selectedTab.updateViewportSize(gScreenWidth); break; case "nsPref:changed": @@ -1866,25 +1866,25 @@ var NativeWindow = { Services.obs.removeObserver(this, "Menu:Clicked"); Services.obs.removeObserver(this, "Doorhanger:Reply"); Services.obs.removeObserver(this, "Toast:Click", false); Services.obs.removeObserver(this, "Toast:Hidden", false); this.contextmenus.uninit(); }, loadDex: function(zipFile, implClass) { - sendMessageToJava({ + Messaging.sendRequest({ type: "Dex:Load", zipfile: zipFile, impl: implClass || "Main" }); }, unloadDex: function(zipFile) { - sendMessageToJava({ + Messaging.sendRequest({ type: "Dex:Unload", zipfile: zipFile }); }, toast: { _callbacks: {}, show: function(aMessage, aDuration, aOptions) { @@ -1908,17 +1908,17 @@ var NativeWindow = { // If the caller specified a button, make sure we convert any chrome urls // to jar:jar urls so that the frontend can show them msg.button.icon = resolveGeckoURI(aOptions.button.icon); }; this._callbacks[msg.button.id] = aOptions.button.callback; } - sendMessageToJava(msg); + Messaging.sendRequest(msg); } }, menu: { _callbacks: [], _menuId: 1, toolsMenuID: -1, add: function() { @@ -1933,31 +1933,31 @@ var NativeWindow = { }; } else { throw "Incorrect number of parameters"; } options.type = "Menu:Add"; options.id = this._menuId; - sendMessageToJava(options); + Messaging.sendRequest(options); this._callbacks[this._menuId] = options.callback; this._menuId++; return this._menuId - 1; }, remove: function(aId) { - sendMessageToJava({ type: "Menu:Remove", id: aId }); + Messaging.sendRequest({ type: "Menu:Remove", id: aId }); }, update: function(aId, aOptions) { if (!aOptions) return; - sendMessageToJava({ + Messaging.sendRequest({ type: "Menu:Update", id: aId, options: aOptions }); } }, doorhanger: { @@ -1997,21 +1997,21 @@ var NativeWindow = { type: "Doorhanger:Add", message: aMessage, value: aValue, buttons: aButtons, // use the current tab if none is provided tabID: aTabID || BrowserApp.selectedTab.id, options: aOptions || {} }; - sendMessageToJava(json); + Messaging.sendRequest(json); }, hide: function(aValue, aTabID) { - sendMessageToJava({ + Messaging.sendRequest({ type: "Doorhanger:Remove", value: aValue, tabID: aTabID }); } }, observe: function(aSubject, aTopic, aData) { @@ -3191,17 +3191,17 @@ Tab.prototype = { external: ("external" in aParams) ? aParams.external : false, selected: ("selected" in aParams) ? aParams.selected : true, title: truncate(title, MAX_TITLE_LENGTH), delayLoad: aParams.delayLoad || false, desktopMode: this.desktopMode, isPrivate: isPrivate, stub: stub }; - sendMessageToJava(message); + Messaging.sendRequest(message); this.overscrollController = new OverscrollController(this); } this.browser.contentWindow.controllers.insertControllerAt(0, this.overscrollController); let flags = Ci.nsIWebProgress.NOTIFY_STATE_ALL | Ci.nsIWebProgress.NOTIFY_LOCATION | @@ -3255,17 +3255,17 @@ Tab.prototype = { try { this.browser.loadURIWithFlags(aURL, flags, referrerURI, charset, postData); } catch(e) { let message = { type: "Content:LoadError", tabID: this.id }; - sendMessageToJava(message); + Messaging.sendRequest(message); dump("Handled load error: " + e); } } }, /** * Retrieves the font size in twips for a given element. */ @@ -3346,17 +3346,17 @@ Tab.prototype = { /** * Reloads the tab with the desktop mode setting. */ reloadWithMode: function (aDesktopMode) { // Set desktop mode for tab and send change to Java if (this.desktopMode != aDesktopMode) { this.desktopMode = aDesktopMode; - sendMessageToJava({ + Messaging.sendRequest({ type: "DesktopMode:Changed", desktopMode: aDesktopMode, tabID: this.id }); } // Only reload the page for http/https schemes let currentURI = this.browser.currentURI; @@ -3775,17 +3775,17 @@ Tab.prototype = { let errorType = ""; if (docURI.startsWith("about:certerror")) errorType = "certerror"; else if (docURI.startsWith("about:blocked")) errorType = "blocked" else if (docURI.startsWith("about:neterror")) errorType = "neterror"; - sendMessageToJava({ + Messaging.sendRequest({ type: "DOMContentLoaded", tabID: this.id, bgColor: backgroundColor, errorType: errorType, metadata: this.metatags }); this.metatags = null; @@ -3886,17 +3886,17 @@ Tab.prototype = { } let json = { type: "Link:Favicon", tabID: this.id, href: resolveGeckoURI(target.href), size: maxSize }; - sendMessageToJava(json); + Messaging.sendRequest(json); } else if (list.indexOf("[alternate]") != -1 && aEvent.type == "DOMLinkAdded") { let type = target.type.toLowerCase().replace(/^\s+|\s*(?:;.*)?$/g, ""); let isFeed = (type == "application/rss+xml" || type == "application/atom+xml"); if (!isFeed) return; try { @@ -3906,17 +3906,17 @@ Tab.prototype = { if (!this.browser.feeds) this.browser.feeds = []; this.browser.feeds.push({ href: target.href, title: target.title, type: type }); let json = { type: "Link:Feed", tabID: this.id }; - sendMessageToJava(json); + Messaging.sendRequest(json); } catch (e) {} } else if (list.indexOf("[search]" != -1) && aEvent.type == "DOMLinkAdded") { let type = target.type && target.type.toLowerCase(); // Replace all starting or trailing spaces or spaces before "*;" globally w/ "". type = type.replace(/^\s+|\s*(?:;.*)?$/g, ""); // Check that type matches opensearch. @@ -3960,47 +3960,47 @@ Tab.prototype = { // Broadcast message that this tab contains search engines that should be visible. let newEngineMessage = { type: "Link:OpenSearch", tabID: this.id, visible: true }; - sendMessageToJava(newEngineMessage); + Messaging.sendRequest(newEngineMessage); } } break; } case "DOMTitleChanged": { if (!aEvent.isTrusted) return; // ignore on frames and other documents if (aEvent.originalTarget != this.browser.contentDocument) return; - sendMessageToJava({ + Messaging.sendRequest({ type: "DOMTitleChanged", tabID: this.id, title: truncate(aEvent.target.title, MAX_TITLE_LENGTH) }); break; } case "DOMWindowClose": { if (!aEvent.isTrusted) return; // Find the relevant tab, and close it from Java if (this.browser.contentWindow == aEvent.target) { aEvent.preventDefault(); - sendMessageToJava({ + Messaging.sendRequest({ type: "Tab:Close", tabID: this.id }); } break; } case "DOMWillOpenModalDialog": { @@ -4060,17 +4060,17 @@ Tab.prototype = { break; } case "pageshow": { // only send pageshow for the top-level document if (aEvent.originalTarget.defaultView != this.browser.contentWindow) return; - sendMessageToJava({ + Messaging.sendRequest({ type: "Content:PageShow", tabID: this.id }); if (!aEvent.persisted && Services.prefs.getBoolPref("browser.ui.linkify.phone")) { if (!this._linkifier) this._linkifier = new Linkifier(); this._linkifier.linkifyNumbers(this.browser.contentWindow.document); @@ -4107,17 +4107,17 @@ Tab.prototype = { } else { this.readerActive = true; } return; } this.savedArticle = article; - sendMessageToJava({ + Messaging.sendRequest({ type: "Content:ReaderEnabled", tabID: this.id }); if(this.readerActive) this.readerActive = false; if(!this.readerEnabled) @@ -4171,17 +4171,17 @@ Tab.prototype = { let message = { type: "Content:StateChange", tabID: this.id, uri: truncate(uri, MAX_URI_LENGTH), state: aStateFlags, restoring: restoring, success: success }; - sendMessageToJava(message); + Messaging.sendRequest(message); } }, onLocationChange: function(aWebProgress, aRequest, aLocationURI, aFlags) { let contentWin = aWebProgress.DOMWindow; // Browser webapps may load content inside iframes that can not reach across the app/frame boundary // i.e. even though the page is loaded in an iframe window.top != webapp @@ -4253,17 +4253,17 @@ Tab.prototype = { tabID: this.id, uri: truncate(fixedURI.spec, MAX_URI_LENGTH), userSearch: this.userSearch || "", baseDomain: baseDomain, contentType: (contentType ? contentType : ""), sameDocument: sameDocument }; - sendMessageToJava(message); + Messaging.sendRequest(message); // The search term is only valid for this location change event, so reset it here. this.userSearch = ""; if (!sameDocument) { // XXX This code assumes that this is the earliest hook we have at which // browser.contentDocument is changed to the new document we're loading @@ -4295,17 +4295,17 @@ Tab.prototype = { let identity = IdentityHandler.checkIdentity(aState, this.browser); let message = { type: "Content:SecurityChange", tabID: this.id, identity: identity }; - sendMessageToJava(message); + Messaging.sendRequest(message); }, onProgressChange: function(aWebProgress, aRequest, aCurSelfProgress, aMaxSelfProgress, aCurTotalProgress, aMaxTotalProgress) { }, onStatusChange: function(aBrowser, aWebProgress, aRequest, aStatus, aMessage) { }, @@ -4322,17 +4322,17 @@ Tab.prototype = { if ("url" in aParams) message.url = aParams.url; if ("index" in aParams) message.index = aParams.index; if ("numEntries" in aParams) message.numEntries = aParams.numEntries; } - sendMessageToJava(message); + Messaging.sendRequest(message); }, _getGeckoZoom: function() { let res = {x: {}, y: {}}; let cwu = this.browser.contentWindow.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIDOMWindowUtils); cwu.getResolution(res.x, res.y); let zoom = res.x.value * window.devicePixelRatio; return zoom; @@ -4559,17 +4559,17 @@ Tab.prototype = { this.lastPageSizeAfterViewportRemeasure = { width: viewport.pageRight - viewport.pageLeft, height: viewport.pageBottom - viewport.pageTop }; }, sendViewportMetadata: function sendViewportMetadata() { let metadata = this.metadata; - sendMessageToJava({ + Messaging.sendRequest({ type: "Tab:ViewportMetadata", allowZoom: metadata.allowZoom, allowDoubleTapZoom: metadata.allowDoubleTapZoom, defaultZoom: metadata.defaultZoom || window.devicePixelRatio, minZoom: metadata.minZoom || 0, maxZoom: metadata.maxZoom || 0, isRTL: metadata.isRTL, tabID: this.id @@ -4777,17 +4777,17 @@ var BrowserEventHandler = { if (this._scrollableElement != null) { // Discard if it's the top-level scrollable, we let Java handle this // The top-level scrollable is the body in quirks mode and the html element // in standards mode let doc = BrowserApp.selectedBrowser.contentDocument; let rootScrollable = (doc.compatMode === "BackCompat" ? doc.body : doc.documentElement); if (this._scrollableElement != rootScrollable) { - sendMessageToJava({ type: "Panning:Override" }); + Messaging.sendRequest({ type: "Panning:Override" }); } } } if (!ElementTouchHelper.isElementClickable(closest, null, false)) closest = ElementTouchHelper.elementFromPoint(aEvent.changedTouches[0].screenX, aEvent.changedTouches[0].screenY); if (!closest) @@ -4817,17 +4817,17 @@ var BrowserEventHandler = { observe: function(aSubject, aTopic, aData) { if (aTopic == "dom-touch-listener-added") { let tab = BrowserApp.getTabForWindow(aSubject.top); if (!tab || tab.hasTouchListener) return; tab.hasTouchListener = true; - sendMessageToJava({ + Messaging.sendRequest({ type: "Tab:HasTouchListener", tabID: tab.id }); return; } else if (aTopic == "nsPref:changed") { if (aData == "browser.zoom.reflowOnZoom") { this.updateReflozPref(); } @@ -4867,30 +4867,30 @@ var BrowserEventHandler = { if (this._firstScrollEvent) { while (this._scrollableElement != null && !this._elementCanScroll(this._scrollableElement, x, y)) this._scrollableElement = this._findScrollableElement(this._scrollableElement, false); let doc = BrowserApp.selectedBrowser.contentDocument; if (this._scrollableElement == null || this._scrollableElement == doc.documentElement) { - sendMessageToJava({ type: "Panning:CancelOverride" }); + Messaging.sendRequest({ type: "Panning:CancelOverride" }); return; } this._firstScrollEvent = false; } // Scroll the scrollable element if (this._elementCanScroll(this._scrollableElement, x, y)) { this._scrollElementBy(this._scrollableElement, x, y); - sendMessageToJava({ type: "Gesture:ScrollAck", scrolled: true }); + Messaging.sendRequest({ type: "Gesture:ScrollAck", scrolled: true }); SelectionHandler.subdocumentScrolled(this._scrollableElement); } else { - sendMessageToJava({ type: "Gesture:ScrollAck", scrolled: false }); + Messaging.sendRequest({ type: "Gesture:ScrollAck", scrolled: false }); } break; } case "Gesture:CancelTouch": this._cancelTapHighlight(); break; @@ -5796,17 +5796,17 @@ var FormAssistant = { let suggestions = autoCompleteSuggestions.concat(listSuggestions); // Return false if there are no suggestions to show if (!suggestions.length) { aCallback(false); return; } - sendMessageToJava({ + Messaging.sendRequest({ type: "FormAssist:AutoComplete", suggestions: suggestions, rect: ElementTouchHelper.getBoundingContentRect(aElement) }); // Keep track of input element so we can fill it in if the user // selects an autocomplete suggestion this._currentInputElement = aElement; @@ -5831,27 +5831,27 @@ var FormAssistant = { }, // Sends a validation message and position data for an element to the Java UI. // Returns true if there's a validation message to show, false otherwise. _showValidationMessage: function _sendValidationMessage(aElement) { if (!this._isValidateable(aElement)) return false; - sendMessageToJava({ + Messaging.sendRequest({ type: "FormAssist:ValidationMessage", validationMessage: aElement.validationMessage, rect: ElementTouchHelper.getBoundingContentRect(aElement) }); return true; }, _hideFormAssistPopup: function _hideFormAssistPopup() { - sendMessageToJava({ type: "FormAssist:Hide" }); + Messaging.sendRequest({ type: "FormAssist:Hide" }); } }; /** * An object to watch for Gecko status changes -- add-on installs, pref changes * -- and reflect them back to Java. */ let HealthReportStatusListener = { @@ -5912,17 +5912,17 @@ let HealthReportStatusListener = { case this.PREF_BLOCKLIST_ENABLED: response.value = Services.prefs.getBoolPref(aData); break; default: console.log("Unexpected pref in HealthReportStatusListener: " + aData); return; } - sendMessageToJava(response); + Messaging.sendRequest(response); break; } }, MILLISECONDS_PER_DAY: 24 * 60 * 60 * 1000, COPY_FIELDS: [ "blocklistState", @@ -5971,17 +5971,17 @@ let HealthReportStatusListener = { return o; }, notifyJava: function (aAddon, aNeedsRestart, aAction="Addons:Change") { let json = this.jsonForAddon(aAddon); if (this._shouldIgnore(aAddon)) { json.ignore = true; } - sendMessageToJava({ type: aAction, id: aAddon.id, json: json }); + Messaging.sendRequest({ type: aAction, id: aAddon.id, json: json }); }, // Add-on listeners. onEnabling: function (aAddon, aNeedsRestart) { this.notifyJava(aAddon, aNeedsRestart); }, onDisabling: function (aAddon, aNeedsRestart) { this.notifyJava(aAddon, aNeedsRestart); @@ -6034,17 +6034,17 @@ let HealthReportStatusListener = { jsonP[pref] = { pref: pref, value: Services.prefs.getCharPref(pref), isUserSet: Services.prefs.prefHasUserValue(pref), }; } console.log("Sending snapshot message."); - sendMessageToJava({ + Messaging.sendRequest({ type: "HealthReport:Snapshot", json: { addons: jsonA, prefs: jsonP, }, }); }.bind(this)); }, @@ -6688,17 +6688,17 @@ var CharacterEncoding = { }, sendState: function sendState() { let showCharEncoding = "false"; try { showCharEncoding = Services.prefs.getComplexValue("browser.menu.showCharacterEncoding", Ci.nsIPrefLocalizedString).data; } catch (e) { /* Optional */ } - sendMessageToJava({ + Messaging.sendRequest({ type: "CharEncoding:State", visible: showCharEncoding }); }, getEncoding: function getEncoding() { function infoToCharset(info) { return { code: info.value, title: info.label }; @@ -6722,17 +6722,17 @@ var CharacterEncoding = { for (let i = 0; i < charsetCount; i++) { if (this._charsets[i].code === docCharset) { selected = i; break; } } - sendMessageToJava({ + Messaging.sendRequest({ type: "CharEncoding:Data", charsets: this._charsets, selected: selected }); }, setEncoding: function setEncoding(aEncoding) { let browser = BrowserApp.selectedBrowser; @@ -6934,17 +6934,17 @@ OverscrollController.prototype = { return (this.tab.getViewport().y == 0); }, isCommandEnabled : function isCommandEnabled(aCommand) { return this.supportsCommand(aCommand); }, doCommand : function doCommand(aCommand){ - sendMessageToJava({ type: "ToggleChrome:Focus" }); + Messaging.sendRequest({ type: "ToggleChrome:Focus" }); }, onEvent : function onEvent(aEvent) { } }; var SearchEngines = { _contextMenuId: null, PREF_SUGGEST_ENABLED: "browser.search.suggest.enabled", @@ -7028,17 +7028,17 @@ var SearchEngines = { // the default engine because we only show suggestions for the default engine in the UI. let engine = Services.search.defaultEngine; if (engine.supportsResponseType("application/x-suggestions+json")) { suggestEngine = engine.name; suggestTemplate = engine.getSubmission("__searchTerms__", "application/x-suggestions+json").uri.spec; } // By convention, the currently configured default engine is at position zero in searchEngines. - sendMessageToJava({ + Messaging.sendRequest({ type: "SearchEngines:Data", searchEngines: searchEngines, suggest: { engine: suggestEngine, template: suggestTemplate, enabled: Services.prefs.getBoolPref(this.PREF_SUGGEST_ENABLED), prompted: Services.prefs.getBoolPref(this.PREF_SUGGEST_PROMPTED) } @@ -7112,17 +7112,17 @@ var SearchEngines = { if (engines.length < 1) { // Broadcast message that there are no more add-able search engines. let newEngineMessage = { type: "Link:OpenSearch", tabID: tab.id, visible: false }; - sendMessageToJava(newEngineMessage); + Messaging.sendRequest(newEngineMessage); } }).bind(this)); }, addOpenSearchEngine: function addOpenSearchEngine(engine) { Services.search.addEngine(engine.url, Ci.nsISearchEngine.DATA_XML, engine.iconURL, false, { onSuccess: function() { // Display a toast confirming addition of new search engine. @@ -7407,23 +7407,23 @@ let Reader = { Services.obs.addObserver(this, "Reader:Add", false); Services.obs.addObserver(this, "Reader:Remove", false); Services.prefs.addObserver("reader.parse-on-load.", this, false); }, pageAction: { readerModeCallback: function(){ - sendMessageToJava({ + Messaging.sendRequest({ type: "Reader:Click", }); }, readerModeActiveCallback: function(){ - sendMessageToJava({ + Messaging.sendRequest({ type: "Reader:LongClick", }); UITelemetry.addEvent("save.1", "pageaction", null, "reader"); }, }, updatePageAction: function(tab) { @@ -7487,17 +7487,17 @@ let Reader = { } else { throw new Error("Reader:Add requires a tabID or an URL as argument"); } let sendResult = function(result, article) { article = article || {}; this.log("Reader:Add success=" + result + ", url=" + url + ", title=" + article.title + ", excerpt=" + article.excerpt); - sendMessageToJava({ + Messaging.sendRequest({ type: "Reader:Added", result: result, title: truncate(article.title, MAX_TITLE_LENGTH), url: truncate(url, MAX_URI_LENGTH), length: article.length, excerpt: article.excerpt }); }.bind(this); @@ -7535,17 +7535,17 @@ let Reader = { if (!("url" in args)) { throw new Error("Reader:Remove requires URL as an argument"); } this.removeArticleFromCache(args.url, function(success) { this.log("Reader:Remove success=" + success + ", url=" + args.url); if (success && args.notify) { - sendMessageToJava({ + Messaging.sendRequest({ type: "Reader:Removed", url: args.url }); } }.bind(this)); break; } @@ -8180,17 +8180,17 @@ var Distribution = { for (let key in localizeablePrefsOverrides) { try { let value = localizeablePrefsOverrides[key]; localizedString.data = "data:text/plain," + key + "=" + value; defaults.setComplexValue(key, Ci.nsIPrefLocalizedString, localizedString); } catch (e) { /* ignore bad prefs and move on */ } } - sendMessageToJava({ type: "Distribution:Set:OK" }); + Messaging.sendRequest({ type: "Distribution:Set:OK" }); }, // aFile is an nsIFile // aCallback takes the parsed JSON object as a parameter readJSON: function dc_readJSON(aFile, aCallback) { Task.spawn(function() { let bytes = yield OS.File.read(aFile.path); let raw = new TextDecoder().decode(bytes) || "";
--- a/mobile/android/components/ContentDispatchChooser.js +++ b/mobile/android/components/ContentDispatchChooser.js @@ -59,17 +59,17 @@ ContentDispatchChooser.prototype = button: { label: searchText, callback: function() { let message = { type: "Intent:Open", url: "market://search?q=" + aURI.scheme, }; - sendMessageToJava(message); + Messaging.sendRequest(message); } } }); } } }, };
--- a/mobile/android/components/SessionStore.js +++ b/mobile/android/components/SessionStore.js @@ -12,17 +12,17 @@ Cu.import("resource://gre/modules/Servic #ifdef MOZ_CRASHREPORTER XPCOMUtils.defineLazyServiceGetter(this, "CrashReporter", "@mozilla.org/xre/app-info;1", "nsICrashReporter"); #endif XPCOMUtils.defineLazyModuleGetter(this, "Task", "resource://gre/modules/Task.jsm"); XPCOMUtils.defineLazyModuleGetter(this, "OS", "resource://gre/modules/osfile.jsm"); -XPCOMUtils.defineLazyModuleGetter(this, "sendMessageToJava", "resource://gre/modules/Messaging.jsm"); +XPCOMUtils.defineLazyModuleGetter(this, "Messaging", "resource://gre/modules/Messaging.jsm"); XPCOMUtils.defineLazyModuleGetter(this, "PrivateBrowsingUtils", "resource://gre/modules/PrivateBrowsingUtils.jsm"); function dump(a) { Services.console.logStringMessage(a); } // ----------------------------------------------------------------------- // Session Store @@ -139,17 +139,17 @@ SessionStore.prototype = { if (window.BrowserApp.tabs.length == 0) { window.BrowserApp.addTab("about:home", { selected: true }); } // Let Java know we're done restoring tabs so tabs added after this can be animated - sendMessageToJava({ + Messaging.sendRequest({ type: "Session:RestoreEnd" }); }.bind(this) }; Services.obs.addObserver(restoreCleanup, "sessionstore-windows-restored", false); // Do a restore, triggered by Java let data = JSON.parse(aData); @@ -449,17 +449,17 @@ SessionStore.prototype = { } } // Write only non-private data to disk this._writeFile(this._sessionFile, JSON.stringify(normalData), aAsync); // If we have private data, send it to Java; otherwise, send null to // indicate that there is no private data - sendMessageToJava({ + Messaging.sendRequest({ type: "PrivateBrowsing:Data", session: (privateData.windows.length > 0 && privateData.windows[0].tabs.length > 0) ? JSON.stringify(privateData) : null }); this._lastSaveTime = Date.now(); }, _getCurrentState: function ss_getCurrentState() { @@ -938,17 +938,17 @@ SessionStore.prototype = { // Get the url and title for the last entry in the session history. let lastEntry = tab.entries[tab.entries.length - 1]; return { url: lastEntry.url, title: lastEntry.title || "" }; }); - sendMessageToJava({ + Messaging.sendRequest({ type: "ClosedTabs:Data", tabs: tabs }); }, getTabValue: function ss_getTabValue(aTab, aKey) { let browser = aTab.browser; let data = browser.__SS_extdata || {};
--- a/mobile/android/components/TabSource.js +++ b/mobile/android/components/TabSource.js @@ -7,17 +7,17 @@ const { classes: Cc, interfaces: Ci, manager: Cm, utils: Cu, results: Cr } = Components; Cu.import("resource://gre/modules/Services.jsm"); Cu.import("resource://gre/modules/XPCOMUtils.jsm"); XPCOMUtils.defineLazyModuleGetter(this, "Prompt", "resource://gre/modules/Prompt.jsm"); -XPCOMUtils.defineLazyModuleGetter(this, "sendMessageToJava", +XPCOMUtils.defineLazyModuleGetter(this, "Messaging", "resource://gre/modules/Messaging.jsm"); function TabSource() { } TabSource.prototype = { classID: Components.ID("{5850c76e-b916-4218-b99a-31f004e0a7e7}"), classDescription: "Fennec Tab Source", @@ -67,25 +67,25 @@ TabSource.prototype = { return tabs[result].browser.contentWindow; }, notifyStreamStart: function(window) { let app = Services.wm.getMostRecentWindow("navigator:browser").BrowserApp; let tabs = app.tabs; for (var i in tabs) { if (tabs[i].browser.contentWindow == window) { - sendMessageToJava({ type: "Tab:StreamStart", tabID: tabs[i].id }); + Messaging.sendRequest({ type: "Tab:StreamStart", tabID: tabs[i].id }); } } }, notifyStreamStop: function(window) { let app = Services.wm.getMostRecentWindow("navigator:browser").BrowserApp; let tabs = app.tabs; for (let i in tabs) { if (tabs[i].browser.contentWindow == window) { - sendMessageToJava({ type: "Tab:StreamStop", tabID: tabs[i].id }); + Messaging.sendRequest({ type: "Tab:StreamStop", tabID: tabs[i].id }); } } } }; this.NSGetFactory = XPCOMUtils.generateNSGetFactory([TabSource]);
--- a/mobile/android/locales/en-US/chrome/browser.properties +++ b/mobile/android/locales/en-US/chrome/browser.properties @@ -206,17 +206,19 @@ password.dontSave=Don't save # This is not a string to translate. If users frequently use the "Character Encoding" # menu, set this to "true". Otherwise, you can leave it as "false". browser.menu.showCharacterEncoding=false # Text Selection selectionHelper.textCopied=Text copied to clipboard # Casting -casting.prompt=Cast to Device +# LOCALIZATION NOTE (casting.sendToDevice): Label that will be used in the +# dialog/prompt. +casting.sendToDevice=Send to Device casting.mirrorTab=Mirror Tab casting.mirrorTabStop=Stop Mirror # Context menu contextmenu.openInNewTab=Open Link in New Tab contextmenu.openInPrivateTab=Open Link in Private Tab contextmenu.addToReadingList=Add to Reading List contextmenu.share=Share @@ -242,17 +244,19 @@ contextmenu.playMedia=Play contextmenu.pauseMedia=Pause contextmenu.shareMedia=Share Video contextmenu.showControls2=Show Controls contextmenu.mute=Mute contextmenu.unmute=Unmute contextmenu.saveVideo=Save Video contextmenu.saveAudio=Save Audio contextmenu.addToContacts=Add to Contacts -contextmenu.castToScreen=Cast to Screen +# LOCALIZATION NOTE (contextmenu.sendToDevice): +# The label that will be used in the contextmenu and the pageaction +contextmenu.sendToDevice=Send to Device contextmenu.copy=Copy contextmenu.cut=Cut contextmenu.selectAll=Select All contextmenu.paste=Paste contextmenu.call=Call @@ -379,9 +383,9 @@ browser.menu.context.mailto = Mail # "Subscribe to page" prompts created in FeedHandler.js feedHandler.chooseFeed=Choose feed feedHandler.subscribeWith=Subscribe with # LOCALIZATION NOTE (nativeWindow.deprecated): # This string is shown in the console when someone uses deprecated NativeWindow apis. # %1$S=name of the api that's deprecated, %2$S=New API to use. This may be a url to # a file they should import or the name of an api. -nativeWindow.deprecated=%S is deprecated. Please use %S instead \ No newline at end of file +nativeWindow.deprecated=%S is deprecated. Please use %S instead
--- a/mobile/android/modules/Accounts.jsm +++ b/mobile/android/modules/Accounts.jsm @@ -67,14 +67,14 @@ let Accounts = Object.freeze({ * * Optional extras are passed, as a JSON string, to the Firefox * Account Getting Started activity in the extras bundle of the * activity launch intent, under the key "extras". * * There is no return value from this method. */ launchSetup: function (extras) { - sendMessageToJava({ + Messaging.sendRequest({ type: "Accounts:Create", extras: extras, }); }, });
--- a/mobile/android/modules/HelperApps.jsm +++ b/mobile/android/modules/HelperApps.jsm @@ -6,16 +6,19 @@ const { classes: Cc, interfaces: Ci, utils: Cu, results: Cr } = Components; Cu.import("resource://gre/modules/XPCOMUtils.jsm"); Cu.import("resource://gre/modules/Services.jsm"); XPCOMUtils.defineLazyModuleGetter(this, "Prompt", "resource://gre/modules/Prompt.jsm"); +XPCOMUtils.defineLazyModuleGetter(this, "Messaging", + "resource://gre/modules/Messaging.jsm"); + XPCOMUtils.defineLazyModuleGetter(this, "sendMessageToJava", "resource://gre/modules/Messaging.jsm"); XPCOMUtils.defineLazyGetter(this, "ContentAreaUtils", function() { let ContentAreaUtils = {}; Services.scriptloader.loadSubScript("chrome://global/content/contentAreaUtils.js", ContentAreaUtils); return ContentAreaUtils; }); @@ -147,17 +150,17 @@ var HelperApps = { sendMessageToJava(msg, function(data) { callback(parseData(data)); }); } }, launchUri: function launchUri(uri) { let msg = this._getMessage("Intent:Open", uri); - sendMessageToJava(msg); + Messaging.sendRequest(msg); }, _parseApps: function _parseApps(appInfo) { // appInfo -> {apps: [app1Label, app1Default, app1PackageName, app1ActivityName, app2Label, app2Defaut, ...]} // see GeckoAppShell.java getHandlersForIntent function for details const numAttr = 4; // 4 elements per ResolveInfo: label, default, package name, activity name. let apps = []; @@ -197,17 +200,17 @@ var HelperApps = { callback(data); }); } else { let msg = this._getMessage("Intent:Open", uri, { packageName: app.packageName, className: app.activityName }); - sendMessageToJava(msg); + Messaging.sendRequest(msg); } }, _sendMessageSync: function(msg) { let res = null; sendMessageToJava(msg, function(data) { res = data; });
--- a/mobile/android/modules/Home.jsm +++ b/mobile/android/modules/Home.jsm @@ -89,17 +89,17 @@ let HomeBanner = (function () { totalWeight += message.weight; message.totalWeight = totalWeight; } let threshold = Math.random() * totalWeight; for (let key in _messages) { let message = _messages[key]; if (threshold < message.totalWeight) { - sendMessageToJava({ + Messaging.sendRequest({ type: "HomeBanner:Data", id: message.id, text: message.text, iconURI: message.iconURI }); return; } } @@ -209,17 +209,17 @@ let HomePanels = (function () { try { panels.push(_generatePanel(id)); } catch(e) { Cu.reportError("Home.panels: Invalid options, panel.id = " + id + ": " + e); } } } - sendMessageToJava({ + Messaging.sendRequest({ type: "HomePanels:Data", panels: panels, requestId: requestId }); }, "HomePanels:Authenticate": function handlePanelsAuthenticate(id) { // Generate panel options to get auth handler. @@ -424,35 +424,35 @@ let HomePanels = (function () { _assertPanelExists(id); delete _registeredPanels[id]; }, install: function(id) { _assertPanelExists(id); - sendMessageToJava({ + Messaging.sendRequest({ type: "HomePanels:Install", panel: _generatePanel(id) }); }, uninstall: function(id) { _assertPanelExists(id); - sendMessageToJava({ + Messaging.sendRequest({ type: "HomePanels:Uninstall", id: id }); }, update: function(id) { _assertPanelExists(id); - sendMessageToJava({ + Messaging.sendRequest({ type: "HomePanels:Update", panel: _generatePanel(id) }); }, setAuthenticated: function(id, isAuthenticated) { _assertPanelExists(id);
--- a/mobile/android/modules/HomeProvider.jsm +++ b/mobile/android/modules/HomeProvider.jsm @@ -295,17 +295,17 @@ function refreshDataset(datasetId) { if (gRefreshTimers[datasetId]) { return; } let timer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer); timer.initWithCallback(function(timer) { delete gRefreshTimers[datasetId]; - sendMessageToJava({ + Messaging.sendRequest({ type: "HomePanels:RefreshDataset", datasetId: datasetId }); }, 100, Ci.nsITimer.TYPE_ONE_SHOT); gRefreshTimers[datasetId] = timer; }
--- a/mobile/android/modules/Messaging.jsm +++ b/mobile/android/modules/Messaging.jsm @@ -4,74 +4,51 @@ "use strict" const { classes: Cc, interfaces: Ci, utils: Cu } = Components; Cu.import("resource://gre/modules/Services.jsm"); Cu.import("resource://gre/modules/XPCOMUtils.jsm"); Cu.import("resource://gre/modules/Task.jsm"); -this.EXPORTED_SYMBOLS = ["sendMessageToJava", "RequestService"]; +this.EXPORTED_SYMBOLS = ["sendMessageToJava", "Messaging"]; XPCOMUtils.defineLazyServiceGetter(this, "uuidgen", "@mozilla.org/uuid-generator;1", "nsIUUIDGenerator"); function sendMessageToJava(aMessage, aCallback) { - if (aCallback) { - let id = uuidgen.generateUUID().toString(); - let obs = { - observe: function(aSubject, aTopic, aData) { - let data = JSON.parse(aData); - if (data.__guid__ != id) { - return; - } - - Services.obs.removeObserver(obs, aMessage.type + ":Response", false); + Cu.reportError("sendMessageToJava is deprecated. Use Messaging API instead."); - if (data.status === "cancel") { - // No Java-side listeners handled our callback. - return; - } - - aCallback(data.status === "success" ? data.response : null, - data.status === "error" ? data.response : null); - } - } - - aMessage.__guid__ = id; - Services.obs.addObserver(obs, aMessage.type + ":Response", false); - } - - return Services.androidBridge.handleGeckoMessage(aMessage); + Messaging.sendRequest(aMessage, aCallback); } -let RequestService = { +let Messaging = { /** * Add a listener for the given message. * * Only one request listener can be registered for a given message. * * Example usage: - * RequestService.addListener({ + * Messaging.addListener({ * // aMessage is the message name. * // aData is data sent from Java with the request. * // The return value is used to respond to the request. The return * // type *must* be an instance of Object. * onRequest: function (aMessage, aData) { * if (aData == "foo") { * return { response: "bar" }; * } * return {}; * } * }, "Demo:Request"); * * The listener may also be a generator function, useful for performing a * task asynchronously. For example: - * RequestService.addListener({ + * Messaging.addListener({ * onRequest: function* (aMessage, aData) { * yield new Promise(resolve => setTimeout(resolve, 2000)); * return { response: "bar" }; * } * }, "Demo:Request"); * * @param aListener Listener object with an onRequest function (see example * usage above). @@ -84,16 +61,51 @@ let RequestService = { /** * Removes a listener for a given message. * * @param aMessage The event to stop listening for. */ removeListener: function (aMessage) { requestHandler.removeListener(aMessage); }, + + /** + * Sends a request to Java. + * + * @param aMessage Message to send; must be an object with a "type" property + * @param aCallback Callback function, required if this request expects a response. + */ + sendRequest: function (aMessage, aCallback) { + if (aCallback) { + let id = uuidgen.generateUUID().toString(); + let obs = { + observe: function(aSubject, aTopic, aData) { + let data = JSON.parse(aData); + if (data.__guid__ != id) { + return; + } + + Services.obs.removeObserver(obs, aMessage.type + ":Response", false); + + if (data.status === "cancel") { + // No Java-side listeners handled our callback. + return; + } + + aCallback(data.status === "success" ? data.response : null, + data.status === "error" ? data.response : null); + } + } + + aMessage.__guid__ = id; + Services.obs.addObserver(obs, aMessage.type + ":Response", false); + } + + return Services.androidBridge.handleGeckoMessage(aMessage); + }, }; let requestHandler = { _listeners: {}, addListener: function (aListener, aMessage) { if (aMessage in this._listeners) { throw new Error("Error in addListener: A listener already exists for message " + aMessage); @@ -130,14 +142,14 @@ let requestHandler = { if (typeof result !== "object" || result === null) { throw new Error("Gecko request listener did not return an object"); } response = result; } catch (e) { Cu.reportError(e); } - sendMessageToJava({ + Messaging.sendRequest({ type: "Gecko:Request" + wrapper.id, response: response }); }) };
--- a/mobile/android/modules/NetErrorHelper.jsm +++ b/mobile/android/modules/NetErrorHelper.jsm @@ -96,17 +96,17 @@ handlers.wifi = { UITelemetry.addEvent("neterror.1", "button", "wifitoggle"); // Show indeterminate progress while we wait for the network. node.disabled = true; node.classList.add("inProgress"); this.node = Cu.getWeakReference(node); Services.obs.addObserver(this, "network:link-status-changed", true); - sendMessageToJava({ + Messaging.sendRequest({ type: "Wifi:Enable" }); }, observe: function(subject, topic, data) { let node = this.node.get(); if (!node) { return;
--- a/mobile/android/modules/OrderedBroadcast.jsm +++ b/mobile/android/modules/OrderedBroadcast.jsm @@ -65,16 +65,16 @@ function sendOrderedBroadcast(action, to // This is called from within a notified observer, so we don't // need to take special pains to catch exceptions. theCallback(theData, theToken, theAction); }, }; Services.obs.addObserver(observer, responseEvent, false); - sendMessageToJava({ + Messaging.sendRequest({ type: "OrderedBroadcast:Send", action: action, responseEvent: responseEvent, token: { callbackId: callbackId, data: token || null }, permission: permission, }); };
--- a/mobile/android/modules/PageActions.jsm +++ b/mobile/android/modules/PageActions.jsm @@ -62,17 +62,17 @@ var PageActions = { if (this._items[aData].longClickCallback) { this._items[aData].longClickCallback(); } } }, add: function(aOptions) { let id = uuidgen.generateUUID().toString(); - sendMessageToJava({ + Messaging.sendRequest({ type: "PageActions:Add", id: id, title: aOptions.title, icon: resolveGeckoURI(aOptions.icon), important: "important" in aOptions ? aOptions.important : false }); this._items[id] = { @@ -80,17 +80,17 @@ var PageActions = { longClickCallback: aOptions.longClickCallback }; this._maybeInit(); return id; }, remove: function(id) { - sendMessageToJava({ + Messaging.sendRequest({ type: "PageActions:Remove", id: id }); delete this._items[id]; this._maybeUninit(); } }
--- a/mobile/android/modules/SharedPreferences.jsm +++ b/mobile/android/modules/SharedPreferences.jsm @@ -71,17 +71,17 @@ function SharedPreferencesImpl(options = this._scope = options.scope; this._profileName = options.profileName; this._branch = options.branch; this._observers = {}; } SharedPreferencesImpl.prototype = Object.freeze({ _set: function _set(prefs) { - sendMessageToJava({ + Messaging.sendRequest({ type: "SharedPreferences:Set", preferences: prefs, scope: this._scope, profileName: this._profileName, branch: this._branch, }); }, @@ -201,17 +201,17 @@ SharedPreferencesImpl.prototype = Object }, _installAndroidListener: function _installAndroidListener() { if (this._listening) return; this._listening = true; Services.obs.addObserver(this, "SharedPreferences:Changed", false); - sendMessageToJava({ + Messaging.sendRequest({ type: "SharedPreferences:Observe", enable: true, scope: this._scope, profileName: this._profileName, branch: this._branch, }); }, @@ -238,17 +238,17 @@ SharedPreferencesImpl.prototype = Object }, _uninstallAndroidListener: function _uninstallAndroidListener() { if (!this._listening) return; this._listening = false; Services.obs.removeObserver(this, "SharedPreferences:Changed"); - sendMessageToJava({ + Messaging.sendRequest({ type: "SharedPreferences:Observe", enable: false, scope: this._scope, profileName: this._profileName, branch: this._branch, }); }, });
--- a/mobile/android/modules/WebappManager.jsm +++ b/mobile/android/modules/WebappManager.jsm @@ -17,16 +17,17 @@ Cu.import("resource://gre/modules/NetUti Cu.import("resource://gre/modules/FileUtils.jsm"); Cu.import("resource://gre/modules/DOMRequestHelper.jsm"); Cu.import("resource://gre/modules/Webapps.jsm"); Cu.import("resource://gre/modules/osfile.jsm"); Cu.import("resource://gre/modules/Promise.jsm"); Cu.import("resource://gre/modules/Task.jsm"); XPCOMUtils.defineLazyModuleGetter(this, "Notifications", "resource://gre/modules/Notifications.jsm"); +XPCOMUtils.defineLazyModuleGetter(this, "Messaging", "resource://gre/modules/Messaging.jsm"); XPCOMUtils.defineLazyModuleGetter(this, "sendMessageToJava", "resource://gre/modules/Messaging.jsm"); XPCOMUtils.defineLazyModuleGetter(this, "PluralForm", "resource://gre/modules/PluralForm.jsm"); XPCOMUtils.defineLazyGetter(this, "Strings", function() { return Services.strings.createBundle("chrome://browser/locale/webapp.properties"); }); /** @@ -188,33 +189,33 @@ this.WebappManager = { this._postInstall(aData.profilePath, aManifest, aData.app.origin, aData.app.apkPackageName, aData.app.manifestURL); }).bind(this)); }); }, _postInstall: function(aProfilePath, aNewManifest, aOrigin, aApkPackageName, aManifestURL) { // aOrigin may now point to the app: url that hosts this app. - sendMessageToJava({ + Messaging.sendRequest({ type: "Webapps:Postinstall", apkPackageName: aApkPackageName, origin: aOrigin, }); }, askUninstall: function(aData) { // Android does not currently support automatic uninstalling of apps. // See bug 1019054. DOMApplicationRegistry.denyUninstall(aData, "NOT_SUPPORTED"); }, launch: function({ apkPackageName }) { debug("launch: " + apkPackageName); - sendMessageToJava({ + Messaging.sendRequest({ type: "Webapps:Launch", packageName: apkPackageName, }); }, uninstall: Task.async(function*(aData, aMessageManager) { debug("uninstall: " + aData.manifestURL); @@ -231,17 +232,17 @@ this.WebappManager = { throw new Error("app not found in registry"); } // If the APK is installed, then _getAPKVersions will return a version // for it, so we can use that function to determine its install status. let apkVersions = yield this._getAPKVersions([ app.apkPackageName ]); if (app.apkPackageName in apkVersions) { debug("APK is installed; requesting uninstallation"); - sendMessageToJava({ + Messaging.sendRequest({ type: "Webapps:UninstallApk", apkPackageName: app.apkPackageName, }); // We don't need to call DOMApplicationRegistry.doUninstall at this point, // because the APK uninstall listener will call autoUninstall once the APK // is uninstalled; and if the user cancels the APK uninstallation, then we // shouldn't remove the app from the registry anyway.
--- a/mobile/android/search/java/org/mozilla/search/providers/SearchEngineManager.java +++ b/mobile/android/search/java/org/mozilla/search/providers/SearchEngineManager.java @@ -81,19 +81,25 @@ public class SearchEngineManager impleme * @param callback a SearchEngineCallback to be called after successfully looking * up the search engine. This will run on the UI thread. */ private void getEngineFromPrefs(final SearchEngineCallback callback) { final AsyncTask<Void, Void, SearchEngine> task = new AsyncTask<Void, Void, SearchEngine>() { @Override protected SearchEngine doInBackground(Void... params) { String identifier = GeckoSharedPrefs.forApp(context).getString(SearchPreferenceActivity.PREF_SEARCH_ENGINE_KEY, null); - if (TextUtils.isEmpty(identifier)) { - identifier = context.getResources().getString(R.string.default_engine_identifier); + if (!TextUtils.isEmpty(identifier)) { + try { + return createEngine(identifier); + } catch (IllegalArgumentException e) { + Log.e(LOG_TAG, "Exception creating search engine from pref. Falling back to default engine.", e); + } } + + identifier = context.getResources().getString(R.string.default_engine_identifier); return createEngine(identifier); } @Override protected void onPostExecute(SearchEngine engine) { // Only touch engine on the main thread. SearchEngineManager.this.engine = engine; if (callback != null) {
--- a/testing/profiles/prefs_general.js +++ b/testing/profiles/prefs_general.js @@ -237,12 +237,13 @@ user_pref("browser.aboutHomeSnippets.upd user_pref("dom.mozApps.debug", true); // Don't fetch or send directory tiles data from real servers user_pref("browser.newtabpage.directory.source", 'data:application/json,{"testing":1}'); user_pref("browser.newtabpage.directory.ping", ""); // Enable Loop user_pref("loop.enabled", true); +user_pref("loop.throttled", false); // Ensure UITour won't hit the network user_pref("browser.uitour.pinnedTabUrl", "http://%(server)s/uitour-dummy/pinnedTab"); user_pref("browser.uitour.url", "http://%(server)s/uitour-dummy/tour");
--- a/toolkit/components/thumbnails/PageThumbsProtocol.js +++ b/toolkit/components/thumbnails/PageThumbsProtocol.js @@ -47,16 +47,17 @@ Protocol.prototype = { */ get defaultPort() -1, /** * The flags specific to this protocol implementation. */ get protocolFlags() { return Ci.nsIProtocolHandler.URI_DANGEROUS_TO_LOAD | + Ci.nsIProtocolHandler.URI_IS_LOCAL_RESOURCE | Ci.nsIProtocolHandler.URI_NORELATIVE | Ci.nsIProtocolHandler.URI_NOAUTH; }, /** * Creates a new URI object that is suitable for loading by this protocol. * @param aSpec The URI string in UTF8 encoding. * @param aOriginCharset The charset of the document from which the URI originated.