mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Merge m-c to inbound, a=merge
This commit is contained in:
commit
7b3f9b8da9
@ -15,7 +15,7 @@
|
||||
<project name="platform_build" path="build" remote="b2g" revision="8d83715f08b7849f16a0dfc88f78d5c3a89c0a54">
|
||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="d2e5c49440bf8410ae747b15c0dd11c54053ef3e"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="994ff1537c2d7ca4d1658806c50f3ceba1053f9b"/>
|
||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="e9e2923fd6cab93cf88b4b9ada82225e44fe6635"/>
|
||||
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
|
||||
|
@ -15,7 +15,7 @@
|
||||
<project name="platform_build" path="build" remote="b2g" revision="8d83715f08b7849f16a0dfc88f78d5c3a89c0a54">
|
||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="d2e5c49440bf8410ae747b15c0dd11c54053ef3e"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="994ff1537c2d7ca4d1658806c50f3ceba1053f9b"/>
|
||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="e9e2923fd6cab93cf88b4b9ada82225e44fe6635"/>
|
||||
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
|
||||
|
@ -19,7 +19,7 @@
|
||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="d2e5c49440bf8410ae747b15c0dd11c54053ef3e"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="994ff1537c2d7ca4d1658806c50f3ceba1053f9b"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="e9e2923fd6cab93cf88b4b9ada82225e44fe6635"/>
|
||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
|
||||
<project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="27eb2f04e149fc2c9976d881b1b5984bbe7ee089"/>
|
||||
|
@ -17,7 +17,7 @@
|
||||
</project>
|
||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
|
||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="d2e5c49440bf8410ae747b15c0dd11c54053ef3e"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="994ff1537c2d7ca4d1658806c50f3ceba1053f9b"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="e9e2923fd6cab93cf88b4b9ada82225e44fe6635"/>
|
||||
<project name="moztt" path="external/moztt" remote="b2g" revision="f5d65f5b17d9766d7925aefd0486a1e526ae9bf0"/>
|
||||
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="fb28def18ceb2516c460c4bd5825d2dc656c7818"/>
|
||||
|
@ -15,7 +15,7 @@
|
||||
<project name="platform_build" path="build" remote="b2g" revision="8d83715f08b7849f16a0dfc88f78d5c3a89c0a54">
|
||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="d2e5c49440bf8410ae747b15c0dd11c54053ef3e"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="994ff1537c2d7ca4d1658806c50f3ceba1053f9b"/>
|
||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="e9e2923fd6cab93cf88b4b9ada82225e44fe6635"/>
|
||||
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
|
||||
|
@ -15,7 +15,7 @@
|
||||
<project name="platform_build" path="build" remote="b2g" revision="c9d4fe680662ee44a4bdea42ae00366f5df399cf">
|
||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="d2e5c49440bf8410ae747b15c0dd11c54053ef3e"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="994ff1537c2d7ca4d1658806c50f3ceba1053f9b"/>
|
||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="e9e2923fd6cab93cf88b4b9ada82225e44fe6635"/>
|
||||
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
|
||||
|
@ -19,7 +19,7 @@
|
||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="d2e5c49440bf8410ae747b15c0dd11c54053ef3e"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="994ff1537c2d7ca4d1658806c50f3ceba1053f9b"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="e9e2923fd6cab93cf88b4b9ada82225e44fe6635"/>
|
||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
|
||||
<project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="27eb2f04e149fc2c9976d881b1b5984bbe7ee089"/>
|
||||
|
@ -15,7 +15,7 @@
|
||||
<project name="platform_build" path="build" remote="b2g" revision="8d83715f08b7849f16a0dfc88f78d5c3a89c0a54">
|
||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="d2e5c49440bf8410ae747b15c0dd11c54053ef3e"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="994ff1537c2d7ca4d1658806c50f3ceba1053f9b"/>
|
||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="e9e2923fd6cab93cf88b4b9ada82225e44fe6635"/>
|
||||
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
|
||||
|
@ -1,9 +1,9 @@
|
||||
{
|
||||
"git": {
|
||||
"git_revision": "d2e5c49440bf8410ae747b15c0dd11c54053ef3e",
|
||||
"git_revision": "994ff1537c2d7ca4d1658806c50f3ceba1053f9b",
|
||||
"remote": "https://git.mozilla.org/releases/gaia.git",
|
||||
"branch": ""
|
||||
},
|
||||
"revision": "4b08f8a2624bc83d1f839f79b4969671417c42d6",
|
||||
"revision": "9090c80639ae3689dddbefb8a76ba82c1268b63a",
|
||||
"repo_path": "integration/gaia-central"
|
||||
}
|
||||
|
@ -17,7 +17,7 @@
|
||||
</project>
|
||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
|
||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="d2e5c49440bf8410ae747b15c0dd11c54053ef3e"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="994ff1537c2d7ca4d1658806c50f3ceba1053f9b"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="e9e2923fd6cab93cf88b4b9ada82225e44fe6635"/>
|
||||
<project name="moztt" path="external/moztt" remote="b2g" revision="f5d65f5b17d9766d7925aefd0486a1e526ae9bf0"/>
|
||||
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="fb28def18ceb2516c460c4bd5825d2dc656c7818"/>
|
||||
|
@ -15,7 +15,7 @@
|
||||
<project name="platform_build" path="build" remote="b2g" revision="c9d4fe680662ee44a4bdea42ae00366f5df399cf">
|
||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="d2e5c49440bf8410ae747b15c0dd11c54053ef3e"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="994ff1537c2d7ca4d1658806c50f3ceba1053f9b"/>
|
||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="e9e2923fd6cab93cf88b4b9ada82225e44fe6635"/>
|
||||
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
|
||||
|
@ -269,7 +269,7 @@ var gTests = [
|
||||
|
||||
let indicator = promiseIndicatorWindow();
|
||||
yield promiseMessage("ok", () => {
|
||||
PopupNotifications.panel.firstChild.button.click();
|
||||
activateSecondaryAction(kActionAlways);
|
||||
});
|
||||
expectObserverCalled("getUserMedia:response:allow");
|
||||
expectObserverCalled("recording-device-events");
|
||||
@ -279,6 +279,13 @@ var gTests = [
|
||||
yield indicator;
|
||||
yield checkSharingUI({video: true, audio: true});
|
||||
|
||||
let Perms = Services.perms;
|
||||
let uri = Services.io.newURI("https://example.com/", null, null);
|
||||
is(Perms.testExactPermission(uri, "microphone"), Perms.ALLOW_ACTION,
|
||||
"microphone persistently allowed");
|
||||
is(Perms.testExactPermission(uri, "camera"), Perms.ALLOW_ACTION,
|
||||
"camera persistently allowed");
|
||||
|
||||
yield promiseNotificationShown(PopupNotifications.getNotification("webRTC-sharingDevices"));
|
||||
activateSecondaryAction(kActionDeny);
|
||||
|
||||
@ -296,6 +303,12 @@ var gTests = [
|
||||
expectNoObserverCalled();
|
||||
yield checkNotSharing();
|
||||
|
||||
// The persistent permissions for the frame should have been removed.
|
||||
is(Perms.testExactPermission(uri, "microphone"), Perms.UNKNOWN_ACTION,
|
||||
"microphone not persistently allowed");
|
||||
is(Perms.testExactPermission(uri, "camera"), Perms.UNKNOWN_ACTION,
|
||||
"camera not persistently allowed");
|
||||
|
||||
// the stream is already closed, but this will do some cleanup anyway
|
||||
yield closeStream(global, true);
|
||||
}
|
||||
|
@ -39,12 +39,12 @@ file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
allowevents="true"
|
||||
xbl:inherits="tooltiptext=inputtooltiptext,value,type,maxlength,disabled,size,readonly,placeholder,tabindex,accesskey"/>
|
||||
</xul:hbox>
|
||||
<xul:dropmarker anonid="historydropmarker"
|
||||
class="autocomplete-history-dropmarker urlbar-history-dropmarker"
|
||||
allowevents="true"
|
||||
xbl:inherits="open,enablehistory,parentfocused=focused"/>
|
||||
<children includes="hbox"/>
|
||||
</xul:hbox>
|
||||
<xul:dropmarker anonid="historydropmarker"
|
||||
class="autocomplete-history-dropmarker urlbar-history-dropmarker"
|
||||
allowevents="true"
|
||||
xbl:inherits="open,enablehistory,parentfocused=focused"/>
|
||||
<xul:popupset anonid="popupset"
|
||||
class="autocomplete-result-popupset"/>
|
||||
<children includes="toolbarbutton"/>
|
||||
|
@ -68,14 +68,11 @@
|
||||
// Make sure we rebuild the popup in onpopupshowing
|
||||
this._needToBuildPopup = true;
|
||||
|
||||
var os =
|
||||
Components.classes["@mozilla.org/observer-service;1"]
|
||||
.getService(Components.interfaces.nsIObserverService);
|
||||
os.addObserver(this, "browser-search-engine-modified", false);
|
||||
Services.obs.addObserver(this, "browser-search-engine-modified", false);
|
||||
|
||||
this._initialized = true;
|
||||
|
||||
this.searchService.init((function search_init_cb(aStatus) {
|
||||
Services.search.init((function search_init_cb(aStatus) {
|
||||
// Bail out if the binding's been destroyed
|
||||
if (!this._initialized)
|
||||
return;
|
||||
@ -98,9 +95,7 @@
|
||||
if (this._initialized) {
|
||||
this._initialized = false;
|
||||
|
||||
var os = Components.classes["@mozilla.org/observer-service;1"]
|
||||
.getService(Components.interfaces.nsIObserverService);
|
||||
os.removeObserver(this, "browser-search-engine-modified");
|
||||
Services.obs.removeObserver(this, "browser-search-engine-modified");
|
||||
}
|
||||
|
||||
// Make sure to break the cycle from _textbox to us. Otherwise we leak
|
||||
@ -120,7 +115,6 @@
|
||||
<field name="_textboxInitialized">false</field>
|
||||
<field name="_textbox">document.getAnonymousElementByAttribute(this,
|
||||
"anonid", "searchbar-textbox");</field>
|
||||
<field name="_ss">null</field>
|
||||
<field name="_engines">null</field>
|
||||
<field name="FormHistory" readonly="true">
|
||||
(Components.utils.import("resource://gre/modules/FormHistory.jsm", {})).FormHistory;
|
||||
@ -132,19 +126,19 @@
|
||||
<property name="engines" readonly="true">
|
||||
<getter><![CDATA[
|
||||
if (!this._engines)
|
||||
this._engines = this.searchService.getVisibleEngines();
|
||||
this._engines = Services.search.getVisibleEngines();
|
||||
return this._engines;
|
||||
]]></getter>
|
||||
</property>
|
||||
|
||||
<property name="currentEngine">
|
||||
<setter><![CDATA[
|
||||
let ss = this.searchService;
|
||||
let ss = Services.search;
|
||||
ss.defaultEngine = ss.currentEngine = val;
|
||||
return val;
|
||||
]]></setter>
|
||||
<getter><![CDATA[
|
||||
var currentEngine = this.searchService.currentEngine;
|
||||
var currentEngine = Services.search.currentEngine;
|
||||
// Return a dummy engine if there is no currentEngine
|
||||
return currentEngine || {name: "", uri: null};
|
||||
]]></getter>
|
||||
@ -155,18 +149,6 @@
|
||||
<property name="textbox" readonly="true"
|
||||
onget="return this._textbox;"/>
|
||||
|
||||
<property name="searchService" readonly="true">
|
||||
<getter><![CDATA[
|
||||
if (!this._ss) {
|
||||
const nsIBSS = Components.interfaces.nsIBrowserSearchService;
|
||||
this._ss =
|
||||
Components.classes["@mozilla.org/browser/search-service;1"]
|
||||
.getService(nsIBSS);
|
||||
}
|
||||
return this._ss;
|
||||
]]></getter>
|
||||
</property>
|
||||
|
||||
<property name="value" onget="return this._textbox.value;"
|
||||
onset="return this._textbox.value = val;"/>
|
||||
|
||||
@ -366,7 +348,7 @@
|
||||
where = whereToOpenLink(aEvent, false, true);
|
||||
}
|
||||
else {
|
||||
var newTabPref = textBox._prefBranch.getBoolPref("browser.search.openintab");
|
||||
var newTabPref = Services.prefs.getBoolPref("browser.search.openintab");
|
||||
if (((aEvent instanceof KeyboardEvent) && aEvent.altKey) ^ newTabPref)
|
||||
where = "tab";
|
||||
if ((aEvent instanceof MouseEvent) &&
|
||||
@ -456,18 +438,15 @@
|
||||
if (target.engine) {
|
||||
this.currentEngine = target.engine;
|
||||
} else if (target.classList.contains("addengine-item")) {
|
||||
var searchService =
|
||||
Components.classes["@mozilla.org/browser/search-service;1"]
|
||||
.getService(Components.interfaces.nsIBrowserSearchService);
|
||||
// We only detect OpenSearch files
|
||||
var type = Components.interfaces.nsISearchEngine.DATA_XML;
|
||||
var type = Ci.nsISearchEngine.DATA_XML;
|
||||
// Select the installed engine if the installation succeeds
|
||||
var installCallback = {
|
||||
onSuccess: engine => this.currentEngine = engine
|
||||
}
|
||||
searchService.addEngine(target.getAttribute("uri"), type,
|
||||
target.getAttribute("src"), false,
|
||||
installCallback);
|
||||
Services.search.addEngine(target.getAttribute("uri"), type,
|
||||
target.getAttribute("src"), false,
|
||||
installCallback);
|
||||
}
|
||||
else
|
||||
return;
|
||||
@ -559,13 +538,10 @@
|
||||
|
||||
// Initialize fields
|
||||
this._stringBundle = document.getBindingParent(this)._stringBundle;
|
||||
this._prefBranch =
|
||||
Components.classes["@mozilla.org/preferences-service;1"]
|
||||
.getService(Components.interfaces.nsIPrefBranch);
|
||||
this._suggestEnabled =
|
||||
this._prefBranch.getBoolPref("browser.search.suggest.enabled");
|
||||
Services.prefs.getBoolPref("browser.search.suggest.enabled");
|
||||
|
||||
if (this._prefBranch.getBoolPref("browser.urlbar.clickSelectsAll"))
|
||||
if (Services.prefs.getBoolPref("browser.urlbar.clickSelectsAll"))
|
||||
this.setAttribute("clickSelectsAll", true);
|
||||
|
||||
// Add items to context menu and attach controller to handle them
|
||||
@ -637,15 +613,11 @@
|
||||
document.getBindingParent(this)._textboxInitialized = true;
|
||||
|
||||
// Add observer for suggest preference
|
||||
var prefs = Components.classes["@mozilla.org/preferences-service;1"]
|
||||
.getService(Components.interfaces.nsIPrefBranch);
|
||||
prefs.addObserver("browser.search.suggest.enabled", this, false);
|
||||
Services.prefs.addObserver("browser.search.suggest.enabled", this, false);
|
||||
]]></constructor>
|
||||
|
||||
<destructor><![CDATA[
|
||||
var prefs = Components.classes["@mozilla.org/preferences-service;1"]
|
||||
.getService(Components.interfaces.nsIPrefBranch);
|
||||
prefs.removeObserver("browser.search.suggest.enabled", this);
|
||||
Services.prefs.removeObserver("browser.search.suggest.enabled", this);
|
||||
|
||||
// Because XBL and the customize toolbar code interacts poorly,
|
||||
// there may not be anything to remove here
|
||||
@ -655,7 +627,6 @@
|
||||
]]></destructor>
|
||||
|
||||
<field name="_stringBundle"/>
|
||||
<field name="_prefBranch"/>
|
||||
<field name="_suggestMenuItem"/>
|
||||
<field name="_suggestEnabled"/>
|
||||
|
||||
@ -698,7 +669,7 @@
|
||||
}
|
||||
|
||||
popup.mInput = this;
|
||||
popup.view = this.controller.QueryInterface(Components.interfaces.nsITreeView);
|
||||
popup.view = this.controller.QueryInterface(Ci.nsITreeView);
|
||||
popup.invalidate();
|
||||
|
||||
popup.showCommentColumn = this.showCommentColumn;
|
||||
@ -730,7 +701,7 @@
|
||||
<body><![CDATA[
|
||||
if (aTopic == "nsPref:changed") {
|
||||
this._suggestEnabled =
|
||||
this._prefBranch.getBoolPref("browser.search.suggest.enabled");
|
||||
Services.prefs.getBoolPref("browser.search.suggest.enabled");
|
||||
this._suggestMenuItem.setAttribute("checked", this._suggestEnabled);
|
||||
}
|
||||
]]></body>
|
||||
@ -756,7 +727,7 @@
|
||||
|
||||
let engine;
|
||||
let oneOff = this.selectedButton;
|
||||
if (oneOff) {
|
||||
if (oneOff && !this.selectionFromMouseOver) {
|
||||
if (!oneOff.engine) {
|
||||
oneOff.doCommand();
|
||||
this.mEnterEvent = null;
|
||||
@ -778,6 +749,9 @@
|
||||
<field name="_selectedButton"/>
|
||||
<property name="selectedButton" onget="return this._selectedButton;">
|
||||
<setter><![CDATA[
|
||||
// Set to true from the mouseover handler right after this setter call.
|
||||
this.selectionFromMouseOver = false;
|
||||
|
||||
if (this._selectedButton)
|
||||
this._selectedButton.removeAttribute("selected");
|
||||
|
||||
@ -974,8 +948,8 @@
|
||||
case "cmd_togglesuggest":
|
||||
// The pref observer will update _suggestEnabled and the menu
|
||||
// checkmark.
|
||||
this._self._prefBranch.setBoolPref("browser.search.suggest.enabled",
|
||||
!this._self._suggestEnabled);
|
||||
Services.prefs.setBoolPref("browser.search.suggest.enabled",
|
||||
!this._self._suggestEnabled);
|
||||
break;
|
||||
default:
|
||||
// do nothing with unrecognized command
|
||||
@ -1169,6 +1143,10 @@
|
||||
let isOneOffSelected =
|
||||
this.selectedButton &&
|
||||
this.selectedButton.classList.contains("searchbar-engine-one-off-item");
|
||||
// Typing de-selects the settings or opensearch buttons at the bottom
|
||||
// of the search panel, as typing shows the user intends to search.
|
||||
if (this.selectedButton && !isOneOffSelected)
|
||||
this.selectedButton = null;
|
||||
if (textbox.value) {
|
||||
self.removeAttribute("showonlysettings");
|
||||
groupText = headerSearchText.previousSibling.value +
|
||||
@ -1232,10 +1210,6 @@
|
||||
while (list.firstChild)
|
||||
list.firstChild.remove();
|
||||
|
||||
// Avoid setting the selection based on mouse events before
|
||||
// the 'popupshown' event has fired.
|
||||
this._ignoreMouseEvents = true;
|
||||
|
||||
let Preferences =
|
||||
Cu.import("resource://gre/modules/Preferences.jsm", {}).Preferences;
|
||||
let pref = Preferences.get("browser.search.hiddenOneOffs");
|
||||
@ -1327,10 +1301,6 @@
|
||||
}
|
||||
]]></handler>
|
||||
|
||||
<handler event="popupshown"><![CDATA[
|
||||
this._ignoreMouseEvents = false;
|
||||
]]></handler>
|
||||
|
||||
<handler event="mousedown"><![CDATA[
|
||||
// Required to receive click events from the buttons on Linux.
|
||||
event.preventDefault();
|
||||
@ -1341,17 +1311,14 @@
|
||||
if (target.localName != "button")
|
||||
return;
|
||||
|
||||
// We ignore mouse events between the popupshowing and popupshown
|
||||
// events to avoid selecting the button that happens to be under the
|
||||
// mouse when the panel opens.
|
||||
if (this._ignoreMouseEvents)
|
||||
return;
|
||||
|
||||
if ((target.classList.contains("searchbar-engine-one-off-item") &&
|
||||
!target.classList.contains("dummy")) ||
|
||||
target.classList.contains("addengine-item") ||
|
||||
target.classList.contains("search-setting-button"))
|
||||
document.getElementById("searchbar").textbox.selectedButton = target;
|
||||
target.classList.contains("search-setting-button")) {
|
||||
let textbox = document.getElementById("searchbar").textbox;
|
||||
textbox.selectedButton = target;
|
||||
textbox.selectionFromMouseOver = true;
|
||||
}
|
||||
]]></handler>
|
||||
|
||||
<handler event="mouseout"><![CDATA[
|
||||
|
@ -138,4 +138,7 @@ add_task(function* test_text() {
|
||||
info("Closing search panel");
|
||||
EventUtils.synthesizeKey("VK_ESCAPE", {});
|
||||
yield promise;
|
||||
|
||||
// Move the cursor out of the panel area to avoid messing with other tests.
|
||||
yield synthesizeNativeMouseMove(searchbar);
|
||||
});
|
||||
|
@ -152,6 +152,23 @@ add_task(function* test_arrows() {
|
||||
"the textfield value should be back to initial value");
|
||||
});
|
||||
|
||||
add_task(function* test_typing_clears_button_selection() {
|
||||
is(Services.focus.focusedElement, textbox.inputField,
|
||||
"the search bar should be focused"); // from the previous test.
|
||||
ok(!textbox.selectedButton, "no button should be selected");
|
||||
|
||||
EventUtils.synthesizeKey("VK_UP", {});
|
||||
is(textbox.selectedButton.getAttribute("anonid"), "search-settings",
|
||||
"the settings item should be selected");
|
||||
|
||||
// Type a character.
|
||||
EventUtils.synthesizeKey("a", {});
|
||||
ok(!textbox.selectedButton, "the settings item should be de-selected");
|
||||
|
||||
// Remove the character.
|
||||
EventUtils.synthesizeKey("VK_BACK_SPACE", {});
|
||||
});
|
||||
|
||||
add_task(function* test_tab() {
|
||||
is(Services.focus.focusedElement, textbox.inputField,
|
||||
"the search bar should be focused"); // from the previous test.
|
||||
|
@ -338,9 +338,16 @@ var NetMonitorController = {
|
||||
let inspector = function() {
|
||||
let predicate = i => i.value === requestId;
|
||||
request = NetMonitorView.RequestsMenu.getItemForPredicate(predicate);
|
||||
if (!request) {
|
||||
// Reset filters so that the request is visible.
|
||||
NetMonitorView.RequestsMenu.filterOn("all");
|
||||
request = NetMonitorView.RequestsMenu.getItemForPredicate(predicate);
|
||||
}
|
||||
|
||||
// If the request was found, select it. Otherwise this function will be
|
||||
// called again once new requests arrive.
|
||||
if (request) {
|
||||
window.off(EVENTS.REQUEST_ADDED, inspector);
|
||||
NetMonitorView.RequestsMenu.filterOn("all");
|
||||
NetMonitorView.RequestsMenu.selectedItem = request;
|
||||
deferred.resolve();
|
||||
}
|
||||
|
@ -328,6 +328,7 @@ skip-if = e10s # Bug 1042253 - webconsole e10s tests (Linux debug timeout)
|
||||
[browser_webconsole_live_filtering_on_search_strings.js]
|
||||
[browser_webconsole_message_node_id.js]
|
||||
[browser_webconsole_netlogging.js]
|
||||
[browser_webconsole_netlogging_reset_filter.js]
|
||||
[browser_webconsole_notifications.js]
|
||||
[browser_webconsole_open-links-without-callback.js]
|
||||
[browser_webconsole_promise.js]
|
||||
|
@ -0,0 +1,91 @@
|
||||
/* 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/. */
|
||||
|
||||
// Tests that network log messages bring up the network panel and select the
|
||||
// right request even if it was previously filtered off.
|
||||
|
||||
"use strict";
|
||||
|
||||
const TEST_FILE_URI = "http://example.com/browser/browser/" +
|
||||
"devtools/webconsole/test/test-network.html";
|
||||
const TEST_URI = "data:text/html;charset=utf8,<p>test file URI";
|
||||
|
||||
let hud;
|
||||
|
||||
let test = asyncTest(function* () {
|
||||
let requests = [];
|
||||
let { browser } = yield loadTab(TEST_URI);
|
||||
|
||||
yield pushPrefEnv();
|
||||
hud = yield openConsole();
|
||||
hud.jsterm.clearOutput();
|
||||
|
||||
HUDService.lastFinishedRequest.callback = request => requests.push(request);
|
||||
|
||||
let loaded = loadBrowser(browser);
|
||||
content.location = TEST_FILE_URI;
|
||||
yield loaded;
|
||||
|
||||
yield testMessages();
|
||||
let htmlRequest = requests.find(e => e.request.url.endsWith("html"));
|
||||
ok(htmlRequest, "htmlRequest was a html");
|
||||
|
||||
yield hud.ui.openNetworkPanel(htmlRequest.actor);
|
||||
let toolbox = gDevTools.getToolbox(hud.target);
|
||||
is(toolbox.currentToolId, "netmonitor", "Network panel was opened");
|
||||
|
||||
let panel = toolbox.getCurrentPanel();
|
||||
let selected = panel.panelWin.NetMonitorView.RequestsMenu.selectedItem;
|
||||
is(selected.attachment.method, htmlRequest.request.method,
|
||||
"The correct request is selected");
|
||||
is(selected.attachment.url, htmlRequest.request.url,
|
||||
"The correct request is definitely selected");
|
||||
|
||||
// Filter out the HTML request.
|
||||
panel.panelWin.NetMonitorView.RequestsMenu.filterOn("js");
|
||||
|
||||
yield toolbox.selectTool("webconsole");
|
||||
is(toolbox.currentToolId, "webconsole", "Web console was selected");
|
||||
yield hud.ui.openNetworkPanel(htmlRequest.actor);
|
||||
|
||||
panel.panelWin.NetMonitorView.RequestsMenu.selectedItem;
|
||||
is(selected.attachment.method, htmlRequest.request.method,
|
||||
"The correct request is selected");
|
||||
is(selected.attachment.url, htmlRequest.request.url,
|
||||
"The correct request is definitely selected");
|
||||
|
||||
// All tests are done. Shutdown.
|
||||
HUDService.lastFinishedRequest.callback = null;
|
||||
htmlRequest = browser = requests = hud = null;
|
||||
});
|
||||
|
||||
function testMessages() {
|
||||
return waitForMessages({
|
||||
webconsole: hud,
|
||||
messages: [{
|
||||
text: "running network console logging tests",
|
||||
category: CATEGORY_WEBDEV,
|
||||
severity: SEVERITY_LOG,
|
||||
},
|
||||
{
|
||||
text: "test-network.html",
|
||||
category: CATEGORY_NETWORK,
|
||||
severity: SEVERITY_LOG,
|
||||
},
|
||||
{
|
||||
text: "testscript.js",
|
||||
category: CATEGORY_NETWORK,
|
||||
severity: SEVERITY_LOG,
|
||||
}],
|
||||
});
|
||||
}
|
||||
|
||||
function pushPrefEnv() {
|
||||
let deferred = promise.defer();
|
||||
let options = {
|
||||
set: [["devtools.webconsole.filter.networkinfo", true]]
|
||||
};
|
||||
SpecialPowers.pushPrefEnv(options, deferred.resolve);
|
||||
return deferred.promise;
|
||||
}
|
@ -393,7 +393,16 @@ function prompt(aBrowser, aRequest) {
|
||||
allowedDevices.push(videoDevices[0].deviceIndex);
|
||||
if (audioDevices.length && micPerm == perms.ALLOW_ACTION)
|
||||
allowedDevices.push(audioDevices[0].deviceIndex);
|
||||
let mm = this.browser.messageManager;
|
||||
|
||||
// Remember on which URIs we found persistent permissions so that we
|
||||
// can remove them if the user clicks 'Stop Sharing'. There's no
|
||||
// other way for the stop sharing code to know the hostnames of frames
|
||||
// using devices until bug 1066082 is fixed.
|
||||
let browser = this.browser;
|
||||
browser._devicePermissionURIs = browser._devicePermissionURIs || [];
|
||||
browser._devicePermissionURIs.push(uri);
|
||||
|
||||
let mm = browser.messageManager;
|
||||
mm.sendAsyncMessage("webrtc:Allow", {callID: aRequest.callID,
|
||||
windowID: aRequest.windowID,
|
||||
devices: allowedDevices});
|
||||
@ -534,6 +543,13 @@ function prompt(aBrowser, aRequest) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (aRemember) {
|
||||
// Remember on which URIs we set persistent permissions so that we
|
||||
// can remove them if the user clicks 'Stop Sharing'.
|
||||
aBrowser._devicePermissionURIs = aBrowser._devicePermissionURIs || [];
|
||||
aBrowser._devicePermissionURIs.push(uri);
|
||||
}
|
||||
|
||||
let mm = notification.browser.messageManager;
|
||||
mm.sendAsyncMessage("webrtc:Allow", {callID: aRequest.callID,
|
||||
windowID: aRequest.windowID,
|
||||
@ -862,15 +878,17 @@ function updateBrowserSpecificIndicator(aBrowser, aState) {
|
||||
label: stringBundle.getString("getUserMedia.stopSharing.label"),
|
||||
accessKey: stringBundle.getString("getUserMedia.stopSharing.accesskey"),
|
||||
callback: function () {
|
||||
let uri = Services.io.newURI(aState.documentURI, null, null);
|
||||
let uris = aBrowser._devicePermissionURIs || [];
|
||||
uris = uris.concat(Services.io.newURI(aState.documentURI, null, null));
|
||||
let perms = Services.perms;
|
||||
if (aState.camera &&
|
||||
perms.testExactPermission(uri, "camera") == perms.ALLOW_ACTION)
|
||||
perms.remove(uri, "camera");
|
||||
if (aState.microphone &&
|
||||
perms.testExactPermission(uri, "microphone") == perms.ALLOW_ACTION)
|
||||
perms.remove(uri, "microphone");
|
||||
|
||||
for (let uri of uris) {
|
||||
if (aState.camera &&
|
||||
perms.testExactPermission(uri, "camera") == perms.ALLOW_ACTION)
|
||||
perms.remove(uri, "camera");
|
||||
if (aState.microphone &&
|
||||
perms.testExactPermission(uri, "microphone") == perms.ALLOW_ACTION)
|
||||
perms.remove(uri, "microphone");
|
||||
}
|
||||
let mm = notification.browser.messageManager;
|
||||
mm.sendAsyncMessage("webrtc:StopSharing", windowId);
|
||||
}
|
||||
@ -902,12 +920,13 @@ function updateBrowserSpecificIndicator(aBrowser, aState) {
|
||||
anchorId, mainAction, secondaryActions, options);
|
||||
}
|
||||
else {
|
||||
removeBrowserNotification(aBrowser,"webRTC-sharingDevices");
|
||||
removeBrowserNotification(aBrowser, "webRTC-sharingDevices");
|
||||
aBrowser._devicePermissionURIs = null;
|
||||
}
|
||||
|
||||
// Now handle the screen sharing indicator.
|
||||
if (!aState.screen) {
|
||||
removeBrowserNotification(aBrowser,"webRTC-sharingScreen");
|
||||
removeBrowserNotification(aBrowser, "webRTC-sharingScreen");
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -890,6 +890,11 @@ toolbarbutton[constrain-size="true"][cui-areatype="toolbar"] > .toolbarbutton-ba
|
||||
|
||||
.urlbar-history-dropmarker {
|
||||
-moz-appearance: toolbarbutton-dropdown;
|
||||
transition: opacity 0.15s ease;
|
||||
}
|
||||
|
||||
#urlbar:not(:hover) > .urlbar-textbox-container > .urlbar-history-dropmarker {
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
#urlbar-container {
|
||||
|
@ -1699,6 +1699,11 @@ toolbarbutton[constrain-size="true"][cui-areatype="toolbar"] > .toolbarbutton-ba
|
||||
padding: 0 3px;
|
||||
list-style-image: var(--urlbar-dropmarker-url);
|
||||
-moz-image-region: var(--urlbar-dropmarker-region);
|
||||
transition: opacity 0.15s ease;
|
||||
}
|
||||
|
||||
#urlbar:not(:hover) > .urlbar-textbox-container > .urlbar-history-dropmarker {
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
.urlbar-history-dropmarker[open="true"],
|
||||
|
@ -1476,6 +1476,11 @@ html|*.urlbar-input:-moz-lwtheme::-moz-placeholder,
|
||||
width: auto;
|
||||
list-style-image: var(--urlbar-dropmarker-url);
|
||||
-moz-image-region: var(--urlbar-dropmarker-region);
|
||||
transition: opacity 0.15s ease;
|
||||
}
|
||||
|
||||
#urlbar:not(:hover) > .urlbar-textbox-container > .urlbar-history-dropmarker {
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
.urlbar-history-dropmarker:hover {
|
||||
|
@ -28,25 +28,14 @@ BluetoothDaemonA2dpModule::SetNotificationHandler(
|
||||
sNotificationHandler = aNotificationHandler;
|
||||
}
|
||||
|
||||
nsresult
|
||||
BluetoothDaemonA2dpModule::Send(DaemonSocketPDU* aPDU,
|
||||
BluetoothA2dpResultHandler* aRes)
|
||||
{
|
||||
nsRefPtr<BluetoothA2dpResultHandler> res(aRes);
|
||||
nsresult rv = Send(aPDU, static_cast<void*>(res.get()));
|
||||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
}
|
||||
unused << res.forget(); // Keep reference for response
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void
|
||||
BluetoothDaemonA2dpModule::HandleSvc(const DaemonSocketPDUHeader& aHeader,
|
||||
DaemonSocketPDU& aPDU, void* aUserData)
|
||||
DaemonSocketPDU& aPDU,
|
||||
DaemonSocketResultHandler* aRes)
|
||||
{
|
||||
static void (BluetoothDaemonA2dpModule::* const HandleOp[])(
|
||||
const DaemonSocketPDUHeader&, DaemonSocketPDU&, void*) = {
|
||||
const DaemonSocketPDUHeader&, DaemonSocketPDU&,
|
||||
DaemonSocketResultHandler*) = {
|
||||
[0] = &BluetoothDaemonA2dpModule::HandleRsp,
|
||||
[1] = &BluetoothDaemonA2dpModule::HandleNtf
|
||||
};
|
||||
@ -56,7 +45,7 @@ BluetoothDaemonA2dpModule::HandleSvc(const DaemonSocketPDUHeader& aHeader,
|
||||
// negate twice to map bit to 0/1
|
||||
unsigned int isNtf = !!(aHeader.mOpcode & 0x80);
|
||||
|
||||
(this->*(HandleOp[isNtf]))(aHeader, aPDU, aUserData);
|
||||
(this->*(HandleOp[isNtf]))(aHeader, aPDU, aRes);
|
||||
}
|
||||
|
||||
// Commands
|
||||
@ -139,7 +128,7 @@ BluetoothDaemonA2dpModule::DisconnectRsp(
|
||||
void
|
||||
BluetoothDaemonA2dpModule::HandleRsp(
|
||||
const DaemonSocketPDUHeader& aHeader, DaemonSocketPDU& aPDU,
|
||||
void* aUserData)
|
||||
DaemonSocketResultHandler* aRes)
|
||||
{
|
||||
static void (BluetoothDaemonA2dpModule::* const HandleRsp[])(
|
||||
const DaemonSocketPDUHeader&,
|
||||
@ -158,8 +147,7 @@ BluetoothDaemonA2dpModule::HandleRsp(
|
||||
}
|
||||
|
||||
nsRefPtr<BluetoothA2dpResultHandler> res =
|
||||
already_AddRefed<BluetoothA2dpResultHandler>(
|
||||
static_cast<BluetoothA2dpResultHandler*>(aUserData));
|
||||
static_cast<BluetoothA2dpResultHandler*>(aRes);
|
||||
|
||||
if (!res) {
|
||||
return; // Return early if no result handler has been set for response
|
||||
@ -315,7 +303,7 @@ BluetoothDaemonA2dpModule::AudioConfigNtf(
|
||||
void
|
||||
BluetoothDaemonA2dpModule::HandleNtf(
|
||||
const DaemonSocketPDUHeader& aHeader, DaemonSocketPDU& aPDU,
|
||||
void* aUserData)
|
||||
DaemonSocketResultHandler* aRes)
|
||||
{
|
||||
static void (BluetoothDaemonA2dpModule::* const HandleNtf[])(
|
||||
const DaemonSocketPDUHeader&, DaemonSocketPDU&) = {
|
||||
|
@ -15,6 +15,7 @@ BEGIN_BLUETOOTH_NAMESPACE
|
||||
|
||||
using mozilla::ipc::DaemonSocketPDU;
|
||||
using mozilla::ipc::DaemonSocketPDUHeader;
|
||||
using mozilla::ipc::DaemonSocketResultHandler;
|
||||
|
||||
class BluetoothSetupResultHandler;
|
||||
|
||||
@ -33,7 +34,8 @@ public:
|
||||
|
||||
static const int MAX_NUM_CLIENTS;
|
||||
|
||||
virtual nsresult Send(DaemonSocketPDU* aPDU, void* aUserData) = 0;
|
||||
virtual nsresult Send(DaemonSocketPDU* aPDU,
|
||||
DaemonSocketResultHandler* aRes) = 0;
|
||||
|
||||
virtual nsresult RegisterModule(uint8_t aId, uint8_t aMode,
|
||||
uint32_t aMaxNumClients,
|
||||
@ -55,11 +57,8 @@ public:
|
||||
BluetoothA2dpResultHandler* aRes);
|
||||
|
||||
protected:
|
||||
nsresult Send(DaemonSocketPDU* aPDU,
|
||||
BluetoothA2dpResultHandler* aRes);
|
||||
|
||||
void HandleSvc(const DaemonSocketPDUHeader& aHeader,
|
||||
DaemonSocketPDU& aPDU, void* aUserData);
|
||||
DaemonSocketPDU& aPDU, DaemonSocketResultHandler* aRes);
|
||||
|
||||
//
|
||||
// Responses
|
||||
@ -87,7 +86,7 @@ protected:
|
||||
|
||||
void HandleRsp(const DaemonSocketPDUHeader& aHeader,
|
||||
DaemonSocketPDU& aPDU,
|
||||
void* aUserData);
|
||||
DaemonSocketResultHandler* aRes);
|
||||
|
||||
//
|
||||
// Notifications
|
||||
@ -125,7 +124,7 @@ protected:
|
||||
|
||||
void HandleNtf(const DaemonSocketPDUHeader& aHeader,
|
||||
DaemonSocketPDU& aPDU,
|
||||
void* aUserData);
|
||||
DaemonSocketResultHandler* aRes);
|
||||
|
||||
static BluetoothA2dpNotificationHandler* sNotificationHandler;
|
||||
};
|
||||
@ -142,15 +141,15 @@ public:
|
||||
|
||||
void Init(
|
||||
BluetoothA2dpNotificationHandler* aNotificationHandler,
|
||||
BluetoothA2dpResultHandler* aRes);
|
||||
void Cleanup(BluetoothA2dpResultHandler* aRes);
|
||||
BluetoothA2dpResultHandler* aRes) override;
|
||||
void Cleanup(BluetoothA2dpResultHandler* aRes) override;
|
||||
|
||||
/* Connect / Disconnect */
|
||||
|
||||
void Connect(const nsAString& aBdAddr,
|
||||
BluetoothA2dpResultHandler* aRes);
|
||||
BluetoothA2dpResultHandler* aRes) override;
|
||||
void Disconnect(const nsAString& aBdAddr,
|
||||
BluetoothA2dpResultHandler* aRes);
|
||||
BluetoothA2dpResultHandler* aRes) override;
|
||||
|
||||
private:
|
||||
void DispatchError(BluetoothA2dpResultHandler* aRes,
|
||||
|
@ -28,25 +28,14 @@ BluetoothDaemonAvrcpModule::SetNotificationHandler(
|
||||
sNotificationHandler = aNotificationHandler;
|
||||
}
|
||||
|
||||
nsresult
|
||||
BluetoothDaemonAvrcpModule::Send(DaemonSocketPDU* aPDU,
|
||||
BluetoothAvrcpResultHandler* aRes)
|
||||
{
|
||||
nsRefPtr<BluetoothAvrcpResultHandler> res(aRes);
|
||||
nsresult rv = Send(aPDU, static_cast<void*>(res.get()));
|
||||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
}
|
||||
unused << res.forget(); // Keep reference for response
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void
|
||||
BluetoothDaemonAvrcpModule::HandleSvc(const DaemonSocketPDUHeader& aHeader,
|
||||
DaemonSocketPDU& aPDU, void* aUserData)
|
||||
DaemonSocketPDU& aPDU,
|
||||
DaemonSocketResultHandler* aRes)
|
||||
{
|
||||
static void (BluetoothDaemonAvrcpModule::* const HandleOp[])(
|
||||
const DaemonSocketPDUHeader&, DaemonSocketPDU&, void*) = {
|
||||
const DaemonSocketPDUHeader&, DaemonSocketPDU&,
|
||||
DaemonSocketResultHandler*) = {
|
||||
[0] = &BluetoothDaemonAvrcpModule::HandleRsp,
|
||||
[1] = &BluetoothDaemonAvrcpModule::HandleNtf
|
||||
};
|
||||
@ -55,7 +44,7 @@ BluetoothDaemonAvrcpModule::HandleSvc(const DaemonSocketPDUHeader& aHeader,
|
||||
|
||||
unsigned int isNtf = !!(aHeader.mOpcode & 0x80);
|
||||
|
||||
(this->*(HandleOp[isNtf]))(aHeader, aPDU, aUserData);
|
||||
(this->*(HandleOp[isNtf]))(aHeader, aPDU, aRes);
|
||||
}
|
||||
|
||||
// Commands
|
||||
@ -421,7 +410,7 @@ BluetoothDaemonAvrcpModule::SetVolumeRsp(
|
||||
void
|
||||
BluetoothDaemonAvrcpModule::HandleRsp(
|
||||
const DaemonSocketPDUHeader& aHeader, DaemonSocketPDU& aPDU,
|
||||
void* aUserData)
|
||||
DaemonSocketResultHandler* aRes)
|
||||
{
|
||||
static void (BluetoothDaemonAvrcpModule::* const HandleRsp[])(
|
||||
const DaemonSocketPDUHeader&,
|
||||
@ -459,8 +448,7 @@ BluetoothDaemonAvrcpModule::HandleRsp(
|
||||
}
|
||||
|
||||
nsRefPtr<BluetoothAvrcpResultHandler> res =
|
||||
already_AddRefed<BluetoothAvrcpResultHandler>(
|
||||
static_cast<BluetoothAvrcpResultHandler*>(aUserData));
|
||||
static_cast<BluetoothAvrcpResultHandler*>(aRes);
|
||||
|
||||
if (!res) {
|
||||
return; // Return early if no result handler has been set for response
|
||||
@ -792,7 +780,7 @@ BluetoothDaemonAvrcpModule::PassthroughCmdNtf(
|
||||
void
|
||||
BluetoothDaemonAvrcpModule::HandleNtf(
|
||||
const DaemonSocketPDUHeader& aHeader, DaemonSocketPDU& aPDU,
|
||||
void* aUserData)
|
||||
DaemonSocketResultHandler* aRes)
|
||||
{
|
||||
static void (BluetoothDaemonAvrcpModule::* const HandleNtf[])(
|
||||
const DaemonSocketPDUHeader&, DaemonSocketPDU&) = {
|
||||
|
@ -15,6 +15,7 @@ BEGIN_BLUETOOTH_NAMESPACE
|
||||
|
||||
using mozilla::ipc::DaemonSocketPDU;
|
||||
using mozilla::ipc::DaemonSocketPDUHeader;
|
||||
using mozilla::ipc::DaemonSocketResultHandler;
|
||||
|
||||
class BluetoothSetupResultHandler;
|
||||
|
||||
@ -65,7 +66,8 @@ public:
|
||||
|
||||
static const int MAX_NUM_CLIENTS;
|
||||
|
||||
virtual nsresult Send(DaemonSocketPDU* aPDU, void* aUserData) = 0;
|
||||
virtual nsresult Send(DaemonSocketPDU* aPDU,
|
||||
DaemonSocketResultHandler* aRes) = 0;
|
||||
|
||||
virtual nsresult RegisterModule(uint8_t aId, uint8_t aMode,
|
||||
uint32_t aMaxNumClients,
|
||||
@ -119,11 +121,8 @@ public:
|
||||
nsresult SetVolumeCmd(uint8_t aVolume, BluetoothAvrcpResultHandler* aRes);
|
||||
|
||||
protected:
|
||||
nsresult Send(DaemonSocketPDU* aPDU,
|
||||
BluetoothAvrcpResultHandler* aRes);
|
||||
|
||||
void HandleSvc(const DaemonSocketPDUHeader& aHeader,
|
||||
DaemonSocketPDU& aPDU, void* aUserData);
|
||||
DaemonSocketPDU& aPDU, DaemonSocketResultHandler* aRes);
|
||||
|
||||
//
|
||||
// Responses
|
||||
@ -183,7 +182,7 @@ protected:
|
||||
|
||||
void HandleRsp(const DaemonSocketPDUHeader& aHeader,
|
||||
DaemonSocketPDU& aPDU,
|
||||
void* aUserData);
|
||||
DaemonSocketResultHandler* aRes);
|
||||
|
||||
//
|
||||
// Notifications
|
||||
@ -293,7 +292,7 @@ protected:
|
||||
|
||||
void HandleNtf(const DaemonSocketPDUHeader& aHeader,
|
||||
DaemonSocketPDU& aPDU,
|
||||
void* aUserData);
|
||||
DaemonSocketResultHandler* aRes);
|
||||
|
||||
static BluetoothAvrcpNotificationHandler* sNotificationHandler;
|
||||
};
|
||||
|
@ -28,25 +28,14 @@ BluetoothDaemonGattModule::SetNotificationHandler(
|
||||
sNotificationHandler = aNotificationHandler;
|
||||
}
|
||||
|
||||
nsresult
|
||||
BluetoothDaemonGattModule::Send(DaemonSocketPDU* aPDU,
|
||||
BluetoothGattResultHandler* aRes)
|
||||
{
|
||||
nsRefPtr<BluetoothGattResultHandler> res(aRes);
|
||||
nsresult rv = Send(aPDU, static_cast<void*>(res.get()));
|
||||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
}
|
||||
unused << res.forget(); // Keep reference for response
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void
|
||||
BluetoothDaemonGattModule::HandleSvc(const DaemonSocketPDUHeader& aHeader,
|
||||
DaemonSocketPDU& aPDU, void* aUserData)
|
||||
DaemonSocketPDU& aPDU,
|
||||
DaemonSocketResultHandler* aRes)
|
||||
{
|
||||
static void (BluetoothDaemonGattModule::* const HandleOp[])(
|
||||
const DaemonSocketPDUHeader&, DaemonSocketPDU&, void*) = {
|
||||
const DaemonSocketPDUHeader&, DaemonSocketPDU&,
|
||||
DaemonSocketResultHandler*) = {
|
||||
[0] = &BluetoothDaemonGattModule::HandleRsp,
|
||||
[1] = &BluetoothDaemonGattModule::HandleNtf
|
||||
};
|
||||
@ -56,7 +45,7 @@ BluetoothDaemonGattModule::HandleSvc(const DaemonSocketPDUHeader& aHeader,
|
||||
// Negate twice to map bit to 0/1
|
||||
unsigned long isNtf = !!(aHeader.mOpcode & 0x80);
|
||||
|
||||
(this->*(HandleOp[isNtf]))(aHeader, aPDU, aUserData);
|
||||
(this->*(HandleOp[isNtf]))(aHeader, aPDU, aRes);
|
||||
}
|
||||
|
||||
// Commands
|
||||
@ -1405,7 +1394,7 @@ BluetoothDaemonGattModule::ServerSendResponseRsp(
|
||||
void
|
||||
BluetoothDaemonGattModule::HandleRsp(
|
||||
const DaemonSocketPDUHeader& aHeader, DaemonSocketPDU& aPDU,
|
||||
void* aUserData)
|
||||
DaemonSocketResultHandler* aRes)
|
||||
{
|
||||
static void (BluetoothDaemonGattModule::* const HandleRsp[])(
|
||||
const DaemonSocketPDUHeader&,
|
||||
@ -1493,8 +1482,7 @@ BluetoothDaemonGattModule::HandleRsp(
|
||||
}
|
||||
|
||||
nsRefPtr<BluetoothGattResultHandler> res =
|
||||
already_AddRefed<BluetoothGattResultHandler>(
|
||||
static_cast<BluetoothGattResultHandler*>(aUserData));
|
||||
static_cast<BluetoothGattResultHandler*>(aRes);
|
||||
|
||||
if (!res) {
|
||||
return;
|
||||
@ -2152,7 +2140,7 @@ BluetoothDaemonGattModule::ServerResponseConfirmationNtf(
|
||||
void
|
||||
BluetoothDaemonGattModule::HandleNtf(
|
||||
const DaemonSocketPDUHeader& aHeader, DaemonSocketPDU& aPDU,
|
||||
void* aUserData)
|
||||
DaemonSocketResultHandler* aRes)
|
||||
{
|
||||
static void (BluetoothDaemonGattModule::* const HandleNtf[])(
|
||||
const DaemonSocketPDUHeader&, DaemonSocketPDU&) = {
|
||||
|
@ -15,6 +15,7 @@ BEGIN_BLUETOOTH_NAMESPACE
|
||||
|
||||
using mozilla::ipc::DaemonSocketPDU;
|
||||
using mozilla::ipc::DaemonSocketPDUHeader;
|
||||
using mozilla::ipc::DaemonSocketResultHandler;
|
||||
|
||||
class BluetoothSetupResultHandler;
|
||||
|
||||
@ -67,7 +68,8 @@ public:
|
||||
|
||||
static const int MAX_NUM_CLIENTS;
|
||||
|
||||
virtual nsresult Send(DaemonSocketPDU* aPDU, void* aUserData) = 0;
|
||||
virtual nsresult Send(DaemonSocketPDU* aPDU,
|
||||
DaemonSocketResultHandler* aRes) = 0;
|
||||
|
||||
virtual nsresult RegisterModule(uint8_t aId, uint8_t aMode,
|
||||
uint32_t aMaxNumClients,
|
||||
@ -300,11 +302,8 @@ public:
|
||||
// TODO: Add L support
|
||||
|
||||
protected:
|
||||
nsresult Send(DaemonSocketPDU* aPDU,
|
||||
BluetoothGattResultHandler* aRes);
|
||||
|
||||
void HandleSvc(const DaemonSocketPDUHeader& aHeader,
|
||||
DaemonSocketPDU& aPDU, void* aUserData);
|
||||
DaemonSocketPDU& aPDU, DaemonSocketResultHandler* aRes);
|
||||
|
||||
//
|
||||
// Responses
|
||||
@ -471,7 +470,7 @@ protected:
|
||||
|
||||
void HandleRsp(const DaemonSocketPDUHeader& aHeader,
|
||||
DaemonSocketPDU& aPDU,
|
||||
void* aUserData);
|
||||
DaemonSocketResultHandler* aRes);
|
||||
|
||||
//
|
||||
// Notifications
|
||||
@ -770,7 +769,7 @@ protected:
|
||||
|
||||
void HandleNtf(const DaemonSocketPDUHeader& aHeader,
|
||||
DaemonSocketPDU& aPDU,
|
||||
void* aUserData);
|
||||
DaemonSocketResultHandler* aRes);
|
||||
|
||||
static BluetoothGattNotificationHandler* sNotificationHandler;
|
||||
};
|
||||
@ -786,81 +785,81 @@ public:
|
||||
~BluetoothDaemonGattInterface();
|
||||
|
||||
void Init(BluetoothGattNotificationHandler* aNotificationHandler,
|
||||
BluetoothGattResultHandler* aRes);
|
||||
void Cleanup(BluetoothGattResultHandler* aRes);
|
||||
BluetoothGattResultHandler* aRes) override;
|
||||
void Cleanup(BluetoothGattResultHandler* aRes) override;
|
||||
|
||||
/* Register / Unregister */
|
||||
void RegisterClient(const BluetoothUuid& aUuid,
|
||||
BluetoothGattResultHandler* aRes);
|
||||
BluetoothGattResultHandler* aRes) override;
|
||||
void UnregisterClient(int aClientIf,
|
||||
BluetoothGattResultHandler* aRes);
|
||||
BluetoothGattResultHandler* aRes) override;
|
||||
|
||||
/* Start / Stop LE Scan */
|
||||
void Scan(int aClientIf, bool aStart,
|
||||
BluetoothGattResultHandler* aRes);
|
||||
BluetoothGattResultHandler* aRes) override;
|
||||
|
||||
/* Connect / Disconnect */
|
||||
void Connect(int aClientIf,
|
||||
const nsAString& aBdAddr,
|
||||
bool aIsDirect, /* auto connect */
|
||||
BluetoothTransport aTransport,
|
||||
BluetoothGattResultHandler* aRes);
|
||||
BluetoothGattResultHandler* aRes) override;
|
||||
void Disconnect(int aClientIf,
|
||||
const nsAString& aBdAddr,
|
||||
int aConnId,
|
||||
BluetoothGattResultHandler* aRes);
|
||||
BluetoothGattResultHandler* aRes) override;
|
||||
|
||||
/* Start / Stop advertisements to listen for incoming connections */
|
||||
void Listen(int aClientIf,
|
||||
bool aIsStart,
|
||||
BluetoothGattResultHandler* aRes);
|
||||
BluetoothGattResultHandler* aRes) override;
|
||||
|
||||
/* Clear the attribute cache for a given device*/
|
||||
void Refresh(int aClientIf,
|
||||
const nsAString& aBdAddr,
|
||||
BluetoothGattResultHandler* aRes);
|
||||
BluetoothGattResultHandler* aRes) override;
|
||||
|
||||
/* Enumerate Attributes */
|
||||
void SearchService(int aConnId,
|
||||
bool aSearchAll,
|
||||
const BluetoothUuid& aUuid,
|
||||
BluetoothGattResultHandler* aRes);
|
||||
BluetoothGattResultHandler* aRes) override;
|
||||
void GetIncludedService(int aConnId,
|
||||
const BluetoothGattServiceId& aServiceId,
|
||||
bool aFirst,
|
||||
const BluetoothGattServiceId& aStartServiceId,
|
||||
BluetoothGattResultHandler* aRes);
|
||||
BluetoothGattResultHandler* aRes) override;
|
||||
void GetCharacteristic(int aConnId,
|
||||
const BluetoothGattServiceId& aServiceId,
|
||||
bool aFirst,
|
||||
const BluetoothGattId& aStartCharId,
|
||||
BluetoothGattResultHandler* aRes);
|
||||
BluetoothGattResultHandler* aRes) override;
|
||||
void GetDescriptor(int aConnId,
|
||||
const BluetoothGattServiceId& aServiceId,
|
||||
const BluetoothGattId& aCharId,
|
||||
bool aFirst,
|
||||
const BluetoothGattId& aDescriptorId,
|
||||
BluetoothGattResultHandler* aRes);
|
||||
BluetoothGattResultHandler* aRes) override;
|
||||
|
||||
/* Read / Write An Attribute */
|
||||
void ReadCharacteristic(int aConnId,
|
||||
const BluetoothGattServiceId& aServiceId,
|
||||
const BluetoothGattId& aCharId,
|
||||
BluetoothGattAuthReq aAuthReq,
|
||||
BluetoothGattResultHandler* aRes);
|
||||
BluetoothGattResultHandler* aRes) override;
|
||||
void WriteCharacteristic(int aConnId,
|
||||
const BluetoothGattServiceId& aServiceId,
|
||||
const BluetoothGattId& aCharId,
|
||||
BluetoothGattWriteType aWriteType,
|
||||
BluetoothGattAuthReq aAuthReq,
|
||||
const nsTArray<uint8_t>& aValue,
|
||||
BluetoothGattResultHandler* aRes);
|
||||
BluetoothGattResultHandler* aRes) override;
|
||||
void ReadDescriptor(int aConnId,
|
||||
const BluetoothGattServiceId& aServiceId,
|
||||
const BluetoothGattId& aCharId,
|
||||
const BluetoothGattId& aDescriptorId,
|
||||
BluetoothGattAuthReq aAuthReq,
|
||||
BluetoothGattResultHandler* aRes);
|
||||
BluetoothGattResultHandler* aRes) override;
|
||||
void WriteDescriptor(int aConnId,
|
||||
const BluetoothGattServiceId& aServiceId,
|
||||
const BluetoothGattId& aCharId,
|
||||
@ -868,12 +867,12 @@ public:
|
||||
BluetoothGattWriteType aWriteType,
|
||||
BluetoothGattAuthReq aAuthReq,
|
||||
const nsTArray<uint8_t>& aValue,
|
||||
BluetoothGattResultHandler* aRes);
|
||||
BluetoothGattResultHandler* aRes) override;
|
||||
|
||||
/* Execute / Abort Prepared Write*/
|
||||
void ExecuteWrite(int aConnId,
|
||||
int aIsExecute,
|
||||
BluetoothGattResultHandler* aRes);
|
||||
BluetoothGattResultHandler* aRes) override;
|
||||
|
||||
|
||||
/* Register / Deregister Characteristic Notifications or Indications */
|
||||
@ -881,19 +880,19 @@ public:
|
||||
const nsAString& aBdAddr,
|
||||
const BluetoothGattServiceId& aServiceId,
|
||||
const BluetoothGattId& aCharId,
|
||||
BluetoothGattResultHandler* aRes);
|
||||
BluetoothGattResultHandler* aRes) override;
|
||||
void DeregisterNotification(int aClientIf,
|
||||
const nsAString& aBdAddr,
|
||||
const BluetoothGattServiceId& aServiceId,
|
||||
const BluetoothGattId& aCharId,
|
||||
BluetoothGattResultHandler* aRes);
|
||||
BluetoothGattResultHandler* aRes) override;
|
||||
|
||||
void ReadRemoteRssi(int aClientIf,
|
||||
const nsAString& aBdAddr,
|
||||
BluetoothGattResultHandler* aRes);
|
||||
BluetoothGattResultHandler* aRes) override;
|
||||
|
||||
void GetDeviceType(const nsAString& aBdAddr,
|
||||
BluetoothGattResultHandler* aRes);
|
||||
BluetoothGattResultHandler* aRes) override;
|
||||
|
||||
/* Set advertising data or scan response data */
|
||||
void SetAdvData(int aServerIf,
|
||||
@ -906,61 +905,61 @@ public:
|
||||
uint16_t aManufacturerLen, char* aManufacturerData,
|
||||
uint16_t aServiceDataLen, char* aServiceData,
|
||||
uint16_t aServiceUuidLen, char* aServiceUuid,
|
||||
BluetoothGattResultHandler* aRes);
|
||||
BluetoothGattResultHandler* aRes) override;
|
||||
|
||||
void TestCommand(int aCommand,
|
||||
const BluetoothGattTestParam& aTestParam,
|
||||
BluetoothGattResultHandler* aRes);
|
||||
BluetoothGattResultHandler* aRes) override;
|
||||
|
||||
/* Register / Unregister */
|
||||
void RegisterServer(const BluetoothUuid& aUuid,
|
||||
BluetoothGattResultHandler* aRes);
|
||||
BluetoothGattResultHandler* aRes) override;
|
||||
void UnregisterServer(int aServerIf,
|
||||
BluetoothGattResultHandler* aRes);
|
||||
BluetoothGattResultHandler* aRes) override;
|
||||
|
||||
/* Connect / Disconnect */
|
||||
void ConnectPeripheral(int aServerIf,
|
||||
const nsAString& aBdAddr,
|
||||
bool aIsDirect, /* auto connect */
|
||||
BluetoothTransport aTransport,
|
||||
BluetoothGattResultHandler* aRes);
|
||||
BluetoothGattResultHandler* aRes) override;
|
||||
void DisconnectPeripheral(int aServerIf,
|
||||
const nsAString& aBdAddr,
|
||||
int aConnId,
|
||||
BluetoothGattResultHandler* aRes);
|
||||
BluetoothGattResultHandler* aRes) override;
|
||||
|
||||
/* Add a services / a characteristic / a descriptor */
|
||||
void AddService(int aServerIf,
|
||||
const BluetoothGattServiceId& aServiceId,
|
||||
int aNumHandles,
|
||||
BluetoothGattResultHandler* aRes);
|
||||
BluetoothGattResultHandler* aRes) override;
|
||||
void AddIncludedService(int aServerIf,
|
||||
int aServiceHandle,
|
||||
int aIncludedServiceHandle,
|
||||
BluetoothGattResultHandler* aRes);
|
||||
BluetoothGattResultHandler* aRes) override;
|
||||
void AddCharacteristic(int aServerIf,
|
||||
int aServiceHandle,
|
||||
const BluetoothUuid& aUuid,
|
||||
BluetoothGattCharProp aProperties,
|
||||
BluetoothGattAttrPerm aPermissions,
|
||||
BluetoothGattResultHandler* aRes);
|
||||
BluetoothGattResultHandler* aRes) override;
|
||||
void AddDescriptor(int aServerIf,
|
||||
int aServiceHandle,
|
||||
const BluetoothUuid& aUuid,
|
||||
BluetoothGattAttrPerm aPermissions,
|
||||
BluetoothGattResultHandler* aRes);
|
||||
BluetoothGattResultHandler* aRes) override;
|
||||
|
||||
/* Start / Stop / Delete a service */
|
||||
void StartService(int aServerIf,
|
||||
int aServiceHandle,
|
||||
BluetoothTransport aTransport,
|
||||
BluetoothGattResultHandler* aRes);
|
||||
BluetoothGattResultHandler* aRes) override;
|
||||
void StopService(int aServerIf,
|
||||
int aServiceHandle,
|
||||
BluetoothGattResultHandler* aRes);
|
||||
BluetoothGattResultHandler* aRes) override;
|
||||
void DeleteService(int aServerIf,
|
||||
int aServiceHandle,
|
||||
BluetoothGattResultHandler* aRes);
|
||||
BluetoothGattResultHandler* aRes) override;
|
||||
|
||||
/* Send an indication or a notification */
|
||||
void SendIndication(
|
||||
@ -969,14 +968,14 @@ public:
|
||||
int aConnId,
|
||||
const nsTArray<uint8_t>& aValue,
|
||||
bool aConfirm, /* true: indication, false: notification */
|
||||
BluetoothGattResultHandler* aRes);
|
||||
BluetoothGattResultHandler* aRes) override;
|
||||
|
||||
/* Send a response for an incoming indication */
|
||||
void SendResponse(int aConnId,
|
||||
int aTransId,
|
||||
BluetoothGattStatus aStatus,
|
||||
const BluetoothGattResponse& aResponse,
|
||||
BluetoothGattResultHandler* aRes);
|
||||
BluetoothGattResultHandler* aRes) override;
|
||||
|
||||
private:
|
||||
void DispatchError(BluetoothGattResultHandler* aRes,
|
||||
|
@ -31,25 +31,14 @@ BluetoothDaemonHandsfreeModule::SetNotificationHandler(
|
||||
sNotificationHandler = aNotificationHandler;
|
||||
}
|
||||
|
||||
nsresult
|
||||
BluetoothDaemonHandsfreeModule::Send(DaemonSocketPDU* aPDU,
|
||||
BluetoothHandsfreeResultHandler* aRes)
|
||||
{
|
||||
nsRefPtr<BluetoothHandsfreeResultHandler> res(aRes);
|
||||
nsresult rv = Send(aPDU, static_cast<void*>(res.get()));
|
||||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
}
|
||||
unused << res.forget(); // Keep reference for response
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void
|
||||
BluetoothDaemonHandsfreeModule::HandleSvc(
|
||||
const DaemonSocketPDUHeader& aHeader, DaemonSocketPDU& aPDU, void* aUserData)
|
||||
const DaemonSocketPDUHeader& aHeader, DaemonSocketPDU& aPDU,
|
||||
DaemonSocketResultHandler* aRes)
|
||||
{
|
||||
static void (BluetoothDaemonHandsfreeModule::* const HandleOp[])(
|
||||
const DaemonSocketPDUHeader&, DaemonSocketPDU&, void*) = {
|
||||
const DaemonSocketPDUHeader&, DaemonSocketPDU&,
|
||||
DaemonSocketResultHandler*) = {
|
||||
[0] = &BluetoothDaemonHandsfreeModule::HandleRsp,
|
||||
[1] = &BluetoothDaemonHandsfreeModule::HandleNtf
|
||||
};
|
||||
@ -59,7 +48,7 @@ BluetoothDaemonHandsfreeModule::HandleSvc(
|
||||
// Negate twice to map bit to 0/1
|
||||
unsigned long isNtf = !!(aHeader.mOpcode & 0x80);
|
||||
|
||||
(this->*(HandleOp[isNtf]))(aHeader, aPDU, aUserData);
|
||||
(this->*(HandleOp[isNtf]))(aHeader, aPDU, aRes);
|
||||
}
|
||||
|
||||
// Commands
|
||||
@ -679,7 +668,7 @@ BluetoothDaemonHandsfreeModule::ConfigureWbsRsp(
|
||||
void
|
||||
BluetoothDaemonHandsfreeModule::HandleRsp(
|
||||
const DaemonSocketPDUHeader& aHeader, DaemonSocketPDU& aPDU,
|
||||
void* aUserData)
|
||||
DaemonSocketResultHandler* aRes)
|
||||
{
|
||||
static void (BluetoothDaemonHandsfreeModule::* const HandleRsp[])(
|
||||
const DaemonSocketPDUHeader&,
|
||||
@ -727,8 +716,7 @@ BluetoothDaemonHandsfreeModule::HandleRsp(
|
||||
}
|
||||
|
||||
nsRefPtr<BluetoothHandsfreeResultHandler> res =
|
||||
already_AddRefed<BluetoothHandsfreeResultHandler>(
|
||||
static_cast<BluetoothHandsfreeResultHandler*>(aUserData));
|
||||
static_cast<BluetoothHandsfreeResultHandler*>(aRes);
|
||||
|
||||
if (!res) {
|
||||
return; // Return early if no result handler has been set for response
|
||||
@ -1463,7 +1451,7 @@ BluetoothDaemonHandsfreeModule::WbsNtf(
|
||||
void
|
||||
BluetoothDaemonHandsfreeModule::HandleNtf(
|
||||
const DaemonSocketPDUHeader& aHeader, DaemonSocketPDU& aPDU,
|
||||
void* aUserData)
|
||||
DaemonSocketResultHandler* aRes)
|
||||
{
|
||||
static void (BluetoothDaemonHandsfreeModule::* const HandleNtf[])(
|
||||
const DaemonSocketPDUHeader&, DaemonSocketPDU&) = {
|
||||
|
@ -15,6 +15,7 @@ BEGIN_BLUETOOTH_NAMESPACE
|
||||
|
||||
using mozilla::ipc::DaemonSocketPDU;
|
||||
using mozilla::ipc::DaemonSocketPDUHeader;
|
||||
using mozilla::ipc::DaemonSocketResultHandler;
|
||||
|
||||
class BluetoothSetupResultHandler;
|
||||
|
||||
@ -44,7 +45,8 @@ public:
|
||||
OPCODE_CONFIGURE_WBS = 0x0f
|
||||
};
|
||||
|
||||
virtual nsresult Send(DaemonSocketPDU* aPDU, void* aUserData) = 0;
|
||||
virtual nsresult Send(DaemonSocketPDU* aPDU,
|
||||
DaemonSocketResultHandler* aRes) = 0;
|
||||
|
||||
virtual nsresult RegisterModule(uint8_t aId, uint8_t aMode,
|
||||
uint32_t aMaxNumClients,
|
||||
@ -128,11 +130,9 @@ public:
|
||||
BluetoothHandsfreeResultHandler* aRes);
|
||||
|
||||
protected:
|
||||
nsresult Send(DaemonSocketPDU* aPDU,
|
||||
BluetoothHandsfreeResultHandler* aRes);
|
||||
|
||||
void HandleSvc(const DaemonSocketPDUHeader& aHeader,
|
||||
DaemonSocketPDU& aPDU, void* aUserData);
|
||||
DaemonSocketPDU& aPDU,
|
||||
DaemonSocketResultHandler* aRes);
|
||||
|
||||
//
|
||||
// Responses
|
||||
@ -212,7 +212,7 @@ protected:
|
||||
|
||||
void HandleRsp(const DaemonSocketPDUHeader& aHeader,
|
||||
DaemonSocketPDU& aPDU,
|
||||
void* aUserData);
|
||||
DaemonSocketResultHandler* aRes);
|
||||
|
||||
//
|
||||
// Notifications
|
||||
@ -369,7 +369,7 @@ protected:
|
||||
|
||||
void HandleNtf(const DaemonSocketPDUHeader& aHeader,
|
||||
DaemonSocketPDU& aPDU,
|
||||
void* aUserData);
|
||||
DaemonSocketResultHandler* aRes);
|
||||
|
||||
static BluetoothHandsfreeNotificationHandler* sNotificationHandler;
|
||||
#if ANDROID_VERSION < 21
|
||||
@ -400,39 +400,39 @@ public:
|
||||
|
||||
void Init(
|
||||
BluetoothHandsfreeNotificationHandler* aNotificationHandler,
|
||||
int aMaxNumClients, BluetoothHandsfreeResultHandler* aRes);
|
||||
void Cleanup(BluetoothHandsfreeResultHandler* aRes);
|
||||
int aMaxNumClients, BluetoothHandsfreeResultHandler* aRes) override;
|
||||
void Cleanup(BluetoothHandsfreeResultHandler* aRes) override;
|
||||
|
||||
/* Connect / Disconnect */
|
||||
|
||||
void Connect(const nsAString& aBdAddr,
|
||||
BluetoothHandsfreeResultHandler* aRes);
|
||||
BluetoothHandsfreeResultHandler* aRes) override;
|
||||
void Disconnect(const nsAString& aBdAddr,
|
||||
BluetoothHandsfreeResultHandler* aRes);
|
||||
BluetoothHandsfreeResultHandler* aRes) override;
|
||||
void ConnectAudio(const nsAString& aBdAddr,
|
||||
BluetoothHandsfreeResultHandler* aRes);
|
||||
BluetoothHandsfreeResultHandler* aRes) override;
|
||||
void DisconnectAudio(const nsAString& aBdAddr,
|
||||
BluetoothHandsfreeResultHandler* aRes);
|
||||
BluetoothHandsfreeResultHandler* aRes) override;
|
||||
|
||||
/* Voice Recognition */
|
||||
|
||||
void StartVoiceRecognition(const nsAString& aBdAddr,
|
||||
BluetoothHandsfreeResultHandler* aRes);
|
||||
BluetoothHandsfreeResultHandler* aRes) override;
|
||||
void StopVoiceRecognition(const nsAString& aBdAddr,
|
||||
BluetoothHandsfreeResultHandler* aRes);
|
||||
BluetoothHandsfreeResultHandler* aRes) override;
|
||||
|
||||
/* Volume */
|
||||
|
||||
void VolumeControl(BluetoothHandsfreeVolumeType aType, int aVolume,
|
||||
const nsAString& aBdAddr,
|
||||
BluetoothHandsfreeResultHandler* aRes);
|
||||
BluetoothHandsfreeResultHandler* aRes) override;
|
||||
|
||||
/* Device status */
|
||||
|
||||
void DeviceStatusNotification(BluetoothHandsfreeNetworkState aNtkState,
|
||||
BluetoothHandsfreeServiceType aSvcType,
|
||||
int aSignal, int aBattChg,
|
||||
BluetoothHandsfreeResultHandler* aRes);
|
||||
BluetoothHandsfreeResultHandler* aRes) override;
|
||||
|
||||
/* Responses */
|
||||
|
||||
@ -442,12 +442,12 @@ public:
|
||||
BluetoothHandsfreeCallState aCallSetupState,
|
||||
int aSignal, int aRoam, int aBattChg,
|
||||
const nsAString& aBdAddr,
|
||||
BluetoothHandsfreeResultHandler* aRes);
|
||||
BluetoothHandsfreeResultHandler* aRes) override;
|
||||
void FormattedAtResponse(const char* aRsp, const nsAString& aBdAddr,
|
||||
BluetoothHandsfreeResultHandler* aRes);
|
||||
BluetoothHandsfreeResultHandler* aRes) override;
|
||||
void AtResponse(BluetoothHandsfreeAtResponse aResponseCode, int aErrorCode,
|
||||
const nsAString& aBdAddr,
|
||||
BluetoothHandsfreeResultHandler* aRes);
|
||||
BluetoothHandsfreeResultHandler* aRes) override;
|
||||
void ClccResponse(int aIndex, BluetoothHandsfreeCallDirection aDir,
|
||||
BluetoothHandsfreeCallState aState,
|
||||
BluetoothHandsfreeCallMode aMode,
|
||||
@ -455,7 +455,7 @@ public:
|
||||
const nsAString& aNumber,
|
||||
BluetoothHandsfreeCallAddressType aType,
|
||||
const nsAString& aBdAddr,
|
||||
BluetoothHandsfreeResultHandler* aRes);
|
||||
BluetoothHandsfreeResultHandler* aRes) override;
|
||||
|
||||
/* Phone State */
|
||||
|
||||
@ -463,12 +463,12 @@ public:
|
||||
BluetoothHandsfreeCallState aCallSetupState,
|
||||
const nsAString& aNumber,
|
||||
BluetoothHandsfreeCallAddressType aType,
|
||||
BluetoothHandsfreeResultHandler* aRes);
|
||||
BluetoothHandsfreeResultHandler* aRes) override;
|
||||
|
||||
/* Wide Band Speech */
|
||||
void ConfigureWbs(const nsAString& aBdAddr,
|
||||
BluetoothHandsfreeWbsConfig aConfig,
|
||||
BluetoothHandsfreeResultHandler* aRes);
|
||||
BluetoothHandsfreeResultHandler* aRes) override;
|
||||
|
||||
private:
|
||||
void DispatchError(BluetoothHandsfreeResultHandler* aRes,
|
||||
|
@ -34,7 +34,8 @@ static const int sRetryInterval = 100; // ms
|
||||
class BluetoothDaemonSetupModule
|
||||
{
|
||||
public:
|
||||
virtual nsresult Send(DaemonSocketPDU* aPDU, void* aUserData) = 0;
|
||||
virtual nsresult Send(DaemonSocketPDU* aPDU,
|
||||
DaemonSocketResultHandler* aRes) = 0;
|
||||
|
||||
// Commands
|
||||
//
|
||||
@ -107,7 +108,7 @@ protected:
|
||||
// Called to handle PDUs with Service field equal to 0x00, which
|
||||
// contains internal operations for setup and configuration.
|
||||
void HandleSvc(const DaemonSocketPDUHeader& aHeader,
|
||||
DaemonSocketPDU& aPDU, void* aUserData)
|
||||
DaemonSocketPDU& aPDU, DaemonSocketResultHandler* aRes)
|
||||
{
|
||||
static void (BluetoothDaemonSetupModule::* const HandleRsp[])(
|
||||
const DaemonSocketPDUHeader&,
|
||||
@ -125,27 +126,15 @@ protected:
|
||||
}
|
||||
|
||||
nsRefPtr<BluetoothSetupResultHandler> res =
|
||||
already_AddRefed<BluetoothSetupResultHandler>(
|
||||
static_cast<BluetoothSetupResultHandler*>(aUserData));
|
||||
static_cast<BluetoothSetupResultHandler*>(aRes);
|
||||
|
||||
if (!res) {
|
||||
if (!aRes) {
|
||||
return; // Return early if no result handler has been set
|
||||
}
|
||||
|
||||
(this->*(HandleRsp[aHeader.mOpcode]))(aHeader, aPDU, res);
|
||||
}
|
||||
|
||||
nsresult Send(DaemonSocketPDU* aPDU, BluetoothSetupResultHandler* aRes)
|
||||
{
|
||||
nsRefPtr<BluetoothSetupResultHandler> res(aRes);
|
||||
nsresult rv = Send(aPDU, static_cast<void*>(res.get()));
|
||||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
}
|
||||
unused << res.forget(); // Keep reference for response
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
// Responses
|
||||
@ -211,7 +200,8 @@ public:
|
||||
|
||||
static const int MAX_NUM_CLIENTS;
|
||||
|
||||
virtual nsresult Send(DaemonSocketPDU* aPDU, void* aUserData) = 0;
|
||||
virtual nsresult Send(DaemonSocketPDU* aPDU,
|
||||
DaemonSocketResultHandler* aRes) = 0;
|
||||
|
||||
nsresult EnableCmd(BluetoothResultHandler* aRes)
|
||||
{
|
||||
@ -600,28 +590,18 @@ public:
|
||||
protected:
|
||||
|
||||
void HandleSvc(const DaemonSocketPDUHeader& aHeader,
|
||||
DaemonSocketPDU& aPDU, void* aUserData)
|
||||
DaemonSocketPDU& aPDU, DaemonSocketResultHandler* aRes)
|
||||
{
|
||||
static void (BluetoothDaemonCoreModule::* const HandleOp[])(
|
||||
const DaemonSocketPDUHeader&, DaemonSocketPDU&, void*) = {
|
||||
const DaemonSocketPDUHeader&, DaemonSocketPDU&,
|
||||
DaemonSocketResultHandler*) = {
|
||||
[0] = &BluetoothDaemonCoreModule::HandleRsp,
|
||||
[1] = &BluetoothDaemonCoreModule::HandleNtf
|
||||
};
|
||||
|
||||
MOZ_ASSERT(!NS_IsMainThread());
|
||||
|
||||
(this->*(HandleOp[!!(aHeader.mOpcode & 0x80)]))(aHeader, aPDU, aUserData);
|
||||
}
|
||||
|
||||
nsresult Send(DaemonSocketPDU* aPDU, BluetoothResultHandler* aRes)
|
||||
{
|
||||
nsRefPtr<BluetoothResultHandler> res(aRes);
|
||||
nsresult rv = Send(aPDU, static_cast<void*>(res.get()));
|
||||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
}
|
||||
unused << res.forget(); // Keep reference for response
|
||||
return NS_OK;
|
||||
(this->*(HandleOp[!!(aHeader.mOpcode & 0x80)]))(aHeader, aPDU, aRes);
|
||||
}
|
||||
|
||||
private:
|
||||
@ -825,7 +805,7 @@ private:
|
||||
}
|
||||
|
||||
void HandleRsp(const DaemonSocketPDUHeader& aHeader,
|
||||
DaemonSocketPDU& aPDU, void* aUserData)
|
||||
DaemonSocketPDU& aPDU, DaemonSocketResultHandler* aRes)
|
||||
{
|
||||
static void (BluetoothDaemonCoreModule::* const HandleRsp[])(
|
||||
const DaemonSocketPDUHeader&,
|
||||
@ -862,8 +842,7 @@ private:
|
||||
}
|
||||
|
||||
nsRefPtr<BluetoothResultHandler> res =
|
||||
already_AddRefed<BluetoothResultHandler>(
|
||||
static_cast<BluetoothResultHandler*>(aUserData));
|
||||
static_cast<BluetoothResultHandler*>(aRes);
|
||||
|
||||
if (!res) {
|
||||
return; // Return early if no result handler has been set for response
|
||||
@ -1345,7 +1324,7 @@ private:
|
||||
}
|
||||
|
||||
void HandleNtf(const DaemonSocketPDUHeader& aHeader,
|
||||
DaemonSocketPDU& aPDU, void* aUserData)
|
||||
DaemonSocketPDU& aPDU, DaemonSocketResultHandler* aRes)
|
||||
{
|
||||
static void (BluetoothDaemonCoreModule::* const HandleNtf[])(
|
||||
const DaemonSocketPDUHeader&, DaemonSocketPDU&) = {
|
||||
@ -1453,35 +1432,44 @@ public:
|
||||
// Outgoing PDUs
|
||||
//
|
||||
|
||||
nsresult Send(DaemonSocketPDU* aPDU, void* aUserData) override;
|
||||
nsresult Send(DaemonSocketPDU* aPDU,
|
||||
DaemonSocketResultHandler* aRes) override;
|
||||
|
||||
void StoreUserData(const DaemonSocketPDU& aPDU) override;
|
||||
void StoreResultHandler(const DaemonSocketPDU& aPDU) override;
|
||||
|
||||
// Incoming PUDs
|
||||
//
|
||||
|
||||
void Handle(DaemonSocketPDU& aPDU) override;
|
||||
|
||||
void* FetchUserData(const DaemonSocketPDUHeader& aHeader);
|
||||
already_AddRefed<DaemonSocketResultHandler> FetchResultHandler(
|
||||
const DaemonSocketPDUHeader& aHeader);
|
||||
|
||||
private:
|
||||
void HandleSetupSvc(const DaemonSocketPDUHeader& aHeader,
|
||||
DaemonSocketPDU& aPDU, void* aUserData);
|
||||
DaemonSocketPDU& aPDU,
|
||||
DaemonSocketResultHandler* aRes);
|
||||
void HandleCoreSvc(const DaemonSocketPDUHeader& aHeader,
|
||||
DaemonSocketPDU& aPDU, void* aUserData);
|
||||
DaemonSocketPDU& aPDU,
|
||||
DaemonSocketResultHandler* aRes);
|
||||
void HandleSocketSvc(const DaemonSocketPDUHeader& aHeader,
|
||||
DaemonSocketPDU& aPDU, void* aUserData);
|
||||
DaemonSocketPDU& aPDU,
|
||||
DaemonSocketResultHandler* aRes);
|
||||
void HandleHandsfreeSvc(const DaemonSocketPDUHeader& aHeader,
|
||||
DaemonSocketPDU& aPDU, void* aUserData);
|
||||
DaemonSocketPDU& aPDU,
|
||||
DaemonSocketResultHandler* aRes);
|
||||
void HandleA2dpSvc(const DaemonSocketPDUHeader& aHeader,
|
||||
DaemonSocketPDU& aPDU, void* aUserData);
|
||||
DaemonSocketPDU& aPDU,
|
||||
DaemonSocketResultHandler* aUserData);
|
||||
void HandleAvrcpSvc(const DaemonSocketPDUHeader& aHeader,
|
||||
DaemonSocketPDU& aPDU, void* aUserData);
|
||||
DaemonSocketPDU& aPDU,
|
||||
DaemonSocketResultHandler* aRes);
|
||||
void HandleGattSvc(const DaemonSocketPDUHeader& aHeader,
|
||||
DaemonSocketPDU& aPDU, void* aUserData);
|
||||
DaemonSocketPDU& aPDU,
|
||||
DaemonSocketResultHandler* aRes);
|
||||
|
||||
DaemonSocket* mConnection;
|
||||
nsTArray<void*> mUserDataQ;
|
||||
nsTArray<nsRefPtr<DaemonSocketResultHandler>> mResQ;
|
||||
};
|
||||
|
||||
BluetoothDaemonProtocol::BluetoothDaemonProtocol()
|
||||
@ -1510,13 +1498,14 @@ BluetoothDaemonProtocol::UnregisterModule(uint8_t aId,
|
||||
}
|
||||
|
||||
nsresult
|
||||
BluetoothDaemonProtocol::Send(DaemonSocketPDU* aPDU, void* aUserData)
|
||||
BluetoothDaemonProtocol::Send(DaemonSocketPDU* aPDU,
|
||||
DaemonSocketResultHandler* aRes)
|
||||
{
|
||||
MOZ_ASSERT(mConnection);
|
||||
MOZ_ASSERT(aPDU);
|
||||
|
||||
aPDU->SetConsumer(this);
|
||||
aPDU->SetUserData(aUserData);
|
||||
aPDU->SetResultHandler(aRes);
|
||||
aPDU->UpdateHeader();
|
||||
|
||||
if (mConnection->GetConnectionStatus() == SOCKET_DISCONNECTED) {
|
||||
@ -1532,64 +1521,65 @@ BluetoothDaemonProtocol::Send(DaemonSocketPDU* aPDU, void* aUserData)
|
||||
void
|
||||
BluetoothDaemonProtocol::HandleSetupSvc(
|
||||
const DaemonSocketPDUHeader& aHeader, DaemonSocketPDU& aPDU,
|
||||
void* aUserData)
|
||||
DaemonSocketResultHandler* aRes)
|
||||
{
|
||||
BluetoothDaemonSetupModule::HandleSvc(aHeader, aPDU, aUserData);
|
||||
BluetoothDaemonSetupModule::HandleSvc(aHeader, aPDU, aRes);
|
||||
}
|
||||
|
||||
void
|
||||
BluetoothDaemonProtocol::HandleCoreSvc(
|
||||
const DaemonSocketPDUHeader& aHeader, DaemonSocketPDU& aPDU,
|
||||
void* aUserData)
|
||||
DaemonSocketResultHandler* aRes)
|
||||
{
|
||||
BluetoothDaemonCoreModule::HandleSvc(aHeader, aPDU, aUserData);
|
||||
BluetoothDaemonCoreModule::HandleSvc(aHeader, aPDU, aRes);
|
||||
}
|
||||
|
||||
void
|
||||
BluetoothDaemonProtocol::HandleSocketSvc(
|
||||
const DaemonSocketPDUHeader& aHeader, DaemonSocketPDU& aPDU,
|
||||
void* aUserData)
|
||||
DaemonSocketResultHandler* aRes)
|
||||
{
|
||||
BluetoothDaemonSocketModule::HandleSvc(aHeader, aPDU, aUserData);
|
||||
BluetoothDaemonSocketModule::HandleSvc(aHeader, aPDU, aRes);
|
||||
}
|
||||
|
||||
void
|
||||
BluetoothDaemonProtocol::HandleHandsfreeSvc(
|
||||
const DaemonSocketPDUHeader& aHeader, DaemonSocketPDU& aPDU,
|
||||
void* aUserData)
|
||||
DaemonSocketResultHandler* aRes)
|
||||
{
|
||||
BluetoothDaemonHandsfreeModule::HandleSvc(aHeader, aPDU, aUserData);
|
||||
BluetoothDaemonHandsfreeModule::HandleSvc(aHeader, aPDU, aRes);
|
||||
}
|
||||
|
||||
void
|
||||
BluetoothDaemonProtocol::HandleA2dpSvc(
|
||||
const DaemonSocketPDUHeader& aHeader, DaemonSocketPDU& aPDU,
|
||||
void* aUserData)
|
||||
DaemonSocketResultHandler* aRes)
|
||||
{
|
||||
BluetoothDaemonA2dpModule::HandleSvc(aHeader, aPDU, aUserData);
|
||||
BluetoothDaemonA2dpModule::HandleSvc(aHeader, aPDU, aRes);
|
||||
}
|
||||
|
||||
void
|
||||
BluetoothDaemonProtocol::HandleAvrcpSvc(
|
||||
const DaemonSocketPDUHeader& aHeader, DaemonSocketPDU& aPDU,
|
||||
void* aUserData)
|
||||
DaemonSocketResultHandler* aRes)
|
||||
{
|
||||
BluetoothDaemonAvrcpModule::HandleSvc(aHeader, aPDU, aUserData);
|
||||
BluetoothDaemonAvrcpModule::HandleSvc(aHeader, aPDU, aRes);
|
||||
}
|
||||
|
||||
void
|
||||
BluetoothDaemonProtocol::HandleGattSvc(
|
||||
const DaemonSocketPDUHeader& aHeader, DaemonSocketPDU& aPDU,
|
||||
void* aUserData)
|
||||
DaemonSocketResultHandler* aRes)
|
||||
{
|
||||
BluetoothDaemonGattModule::HandleSvc(aHeader, aPDU, aUserData);
|
||||
BluetoothDaemonGattModule::HandleSvc(aHeader, aPDU, aRes);
|
||||
}
|
||||
|
||||
void
|
||||
BluetoothDaemonProtocol::Handle(DaemonSocketPDU& aPDU)
|
||||
{
|
||||
static void (BluetoothDaemonProtocol::* const HandleSvc[])(
|
||||
const DaemonSocketPDUHeader&, DaemonSocketPDU&, void*) = {
|
||||
const DaemonSocketPDUHeader&, DaemonSocketPDU&,
|
||||
DaemonSocketResultHandler*) = {
|
||||
[0x00] = &BluetoothDaemonProtocol::HandleSetupSvc,
|
||||
[0x01] = &BluetoothDaemonProtocol::HandleCoreSvc,
|
||||
[0x02] = &BluetoothDaemonProtocol::HandleSocketSvc,
|
||||
@ -1614,19 +1604,22 @@ BluetoothDaemonProtocol::Handle(DaemonSocketPDU& aPDU)
|
||||
return;
|
||||
}
|
||||
|
||||
(this->*(HandleSvc[header.mService]))(header, aPDU, FetchUserData(header));
|
||||
nsRefPtr<DaemonSocketResultHandler> res = FetchResultHandler(header);
|
||||
|
||||
(this->*(HandleSvc[header.mService]))(header, aPDU, res);
|
||||
}
|
||||
|
||||
void
|
||||
BluetoothDaemonProtocol::StoreUserData(const DaemonSocketPDU& aPDU)
|
||||
BluetoothDaemonProtocol::StoreResultHandler(const DaemonSocketPDU& aPDU)
|
||||
{
|
||||
MOZ_ASSERT(!NS_IsMainThread());
|
||||
|
||||
mUserDataQ.AppendElement(aPDU.GetUserData());
|
||||
mResQ.AppendElement(aPDU.GetResultHandler());
|
||||
}
|
||||
|
||||
void*
|
||||
BluetoothDaemonProtocol::FetchUserData(const DaemonSocketPDUHeader& aHeader)
|
||||
already_AddRefed<DaemonSocketResultHandler>
|
||||
BluetoothDaemonProtocol::FetchResultHandler(
|
||||
const DaemonSocketPDUHeader& aHeader)
|
||||
{
|
||||
MOZ_ASSERT(!NS_IsMainThread());
|
||||
|
||||
@ -1634,10 +1627,10 @@ BluetoothDaemonProtocol::FetchUserData(const DaemonSocketPDUHeader& aHeader)
|
||||
return nullptr; // Ignore notifications
|
||||
}
|
||||
|
||||
void* userData = mUserDataQ.ElementAt(0);
|
||||
mUserDataQ.RemoveElementAt(0);
|
||||
nsRefPtr<DaemonSocketResultHandler> userData = mResQ.ElementAt(0);
|
||||
mResQ.RemoveElementAt(0);
|
||||
|
||||
return userData;
|
||||
return userData.forget();
|
||||
}
|
||||
|
||||
//
|
||||
|
@ -46,80 +46,82 @@ public:
|
||||
static BluetoothDaemonInterface* GetInstance();
|
||||
|
||||
void Init(BluetoothNotificationHandler* aNotificationHandler,
|
||||
BluetoothResultHandler* aRes);
|
||||
void Cleanup(BluetoothResultHandler* aRes);
|
||||
BluetoothResultHandler* aRes) override;
|
||||
void Cleanup(BluetoothResultHandler* aRes) override;
|
||||
|
||||
void Enable(BluetoothResultHandler* aRes);
|
||||
void Disable(BluetoothResultHandler* aRes);
|
||||
void Enable(BluetoothResultHandler* aRes) override;
|
||||
void Disable(BluetoothResultHandler* aRes) override;
|
||||
|
||||
/* Adapter Properties */
|
||||
|
||||
void GetAdapterProperties(BluetoothResultHandler* aRes);
|
||||
void GetAdapterProperties(BluetoothResultHandler* aRes) override;
|
||||
void GetAdapterProperty(const nsAString& aName,
|
||||
BluetoothResultHandler* aRes);
|
||||
BluetoothResultHandler* aRes) override;
|
||||
void SetAdapterProperty(const BluetoothNamedValue& aProperty,
|
||||
BluetoothResultHandler* aRes);
|
||||
BluetoothResultHandler* aRes) override;
|
||||
|
||||
/* Remote Device Properties */
|
||||
|
||||
void GetRemoteDeviceProperties(const nsAString& aRemoteAddr,
|
||||
BluetoothResultHandler* aRes);
|
||||
BluetoothResultHandler* aRes) override;
|
||||
void GetRemoteDeviceProperty(const nsAString& aRemoteAddr,
|
||||
const nsAString& aName,
|
||||
BluetoothResultHandler* aRes);
|
||||
BluetoothResultHandler* aRes) override;
|
||||
void SetRemoteDeviceProperty(const nsAString& aRemoteAddr,
|
||||
const BluetoothNamedValue& aProperty,
|
||||
BluetoothResultHandler* aRes);
|
||||
BluetoothResultHandler* aRes) override;
|
||||
|
||||
/* Remote Services */
|
||||
|
||||
void GetRemoteServiceRecord(const nsAString& aRemoteAddr,
|
||||
const uint8_t aUuid[16],
|
||||
BluetoothResultHandler* aRes);
|
||||
BluetoothResultHandler* aRes) override;
|
||||
void GetRemoteServices(const nsAString& aRemoteAddr,
|
||||
BluetoothResultHandler* aRes);
|
||||
BluetoothResultHandler* aRes) override;
|
||||
|
||||
/* Discovery */
|
||||
|
||||
void StartDiscovery(BluetoothResultHandler* aRes);
|
||||
void CancelDiscovery(BluetoothResultHandler* aRes);
|
||||
void StartDiscovery(BluetoothResultHandler* aRes) override;
|
||||
void CancelDiscovery(BluetoothResultHandler* aRes) override;
|
||||
|
||||
/* Bonds */
|
||||
|
||||
void CreateBond(const nsAString& aBdAddr, BluetoothTransport aTransport,
|
||||
BluetoothResultHandler* aRes);
|
||||
void RemoveBond(const nsAString& aBdAddr, BluetoothResultHandler* aRes);
|
||||
void CancelBond(const nsAString& aBdAddr, BluetoothResultHandler* aRes);
|
||||
BluetoothResultHandler* aRes) override;
|
||||
void RemoveBond(const nsAString& aBdAddr,
|
||||
BluetoothResultHandler* aRes) override;
|
||||
void CancelBond(const nsAString& aBdAddr,
|
||||
BluetoothResultHandler* aRes) override;
|
||||
|
||||
/* Connection */
|
||||
|
||||
void GetConnectionState(const nsAString& aBdAddr,
|
||||
BluetoothResultHandler* aRes);
|
||||
BluetoothResultHandler* aRes) override;
|
||||
|
||||
/* Authentication */
|
||||
|
||||
void PinReply(const nsAString& aBdAddr, bool aAccept,
|
||||
const nsAString& aPinCode,
|
||||
BluetoothResultHandler* aRes);
|
||||
BluetoothResultHandler* aRes) override;
|
||||
|
||||
void SspReply(const nsAString& aBdAddr, BluetoothSspVariant aVariant,
|
||||
bool aAccept, uint32_t aPasskey,
|
||||
BluetoothResultHandler* aRes);
|
||||
BluetoothResultHandler* aRes) override;
|
||||
|
||||
/* DUT Mode */
|
||||
|
||||
void DutModeConfigure(bool aEnable, BluetoothResultHandler* aRes);
|
||||
void DutModeSend(uint16_t aOpcode, uint8_t* aBuf, uint8_t aLen,
|
||||
BluetoothResultHandler* aRes);
|
||||
BluetoothResultHandler* aRes) override;
|
||||
|
||||
/* LE Mode */
|
||||
|
||||
void LeTestMode(uint16_t aOpcode, uint8_t* aBuf, uint8_t aLen,
|
||||
BluetoothResultHandler* aRes);
|
||||
BluetoothResultHandler* aRes) override;
|
||||
|
||||
/* Energy Information */
|
||||
|
||||
void ReadEnergyInfo(BluetoothResultHandler* aRes);
|
||||
void ReadEnergyInfo(BluetoothResultHandler* aRes) override;
|
||||
|
||||
/* Profile Interfaces */
|
||||
|
||||
|
@ -8,14 +8,14 @@
|
||||
#define mozilla_dom_bluetooth_bluedroid_BluetoothDaemonSetupInterface_h
|
||||
|
||||
#include "BluetoothCommon.h"
|
||||
#include "mozilla/ipc/DaemonSocketMessageHandlers.h"
|
||||
|
||||
BEGIN_BLUETOOTH_NAMESPACE
|
||||
|
||||
class BluetoothSetupResultHandler
|
||||
: public mozilla::ipc::DaemonSocketResultHandler
|
||||
{
|
||||
public:
|
||||
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(BluetoothSetupResultHandler)
|
||||
|
||||
virtual void OnError(BluetoothStatus aStatus);
|
||||
virtual void RegisterModule();
|
||||
virtual void UnregisterModule();
|
||||
|
@ -160,7 +160,7 @@ BluetoothDaemonSocketModule::CloseCmd(BluetoothSocketResultHandler* aRes)
|
||||
void
|
||||
BluetoothDaemonSocketModule::HandleSvc(const DaemonSocketPDUHeader& aHeader,
|
||||
DaemonSocketPDU& aPDU,
|
||||
void* aUserData)
|
||||
DaemonSocketResultHandler* aRes)
|
||||
{
|
||||
static void (BluetoothDaemonSocketModule::* const HandleRsp[])(
|
||||
const DaemonSocketPDUHeader&,
|
||||
@ -177,8 +177,7 @@ BluetoothDaemonSocketModule::HandleSvc(const DaemonSocketPDUHeader& aHeader,
|
||||
}
|
||||
|
||||
nsRefPtr<BluetoothSocketResultHandler> res =
|
||||
already_AddRefed<BluetoothSocketResultHandler>(
|
||||
static_cast<BluetoothSocketResultHandler*>(aUserData));
|
||||
static_cast<BluetoothSocketResultHandler*>(aRes);
|
||||
|
||||
if (!res) {
|
||||
return; // Return early if no result handler has been set
|
||||
@ -187,19 +186,6 @@ BluetoothDaemonSocketModule::HandleSvc(const DaemonSocketPDUHeader& aHeader,
|
||||
(this->*(HandleRsp[aHeader.mOpcode]))(aHeader, aPDU, res);
|
||||
}
|
||||
|
||||
nsresult
|
||||
BluetoothDaemonSocketModule::Send(DaemonSocketPDU* aPDU,
|
||||
BluetoothSocketResultHandler* aRes)
|
||||
{
|
||||
nsRefPtr<BluetoothSocketResultHandler> res(aRes);
|
||||
nsresult rv = Send(aPDU, static_cast<void*>(res.get()));
|
||||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
}
|
||||
unused << res.forget(); // Keep reference for response
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
uint8_t
|
||||
BluetoothDaemonSocketModule::SocketFlags(bool aEncrypt, bool aAuth)
|
||||
{
|
||||
|
@ -15,13 +15,15 @@ BEGIN_BLUETOOTH_NAMESPACE
|
||||
|
||||
using mozilla::ipc::DaemonSocketPDU;
|
||||
using mozilla::ipc::DaemonSocketPDUHeader;
|
||||
using mozilla::ipc::DaemonSocketResultHandler;
|
||||
|
||||
class BluetoothDaemonSocketModule
|
||||
{
|
||||
public:
|
||||
static const int MAX_NUM_CLIENTS;
|
||||
|
||||
virtual nsresult Send(DaemonSocketPDU* aPDU, void* aUserData) = 0;
|
||||
virtual nsresult Send(DaemonSocketPDU* aPDU,
|
||||
DaemonSocketResultHandler* aRes) = 0;
|
||||
|
||||
// Commands
|
||||
//
|
||||
@ -45,9 +47,7 @@ public:
|
||||
protected:
|
||||
|
||||
void HandleSvc(const DaemonSocketPDUHeader& aHeader,
|
||||
DaemonSocketPDU& aPDU, void* aUserData);
|
||||
|
||||
nsresult Send(DaemonSocketPDU* aPDU, BluetoothSocketResultHandler* aRes);
|
||||
DaemonSocketPDU& aPDU, DaemonSocketResultHandler* aRes);
|
||||
|
||||
private:
|
||||
class AcceptWatcher;
|
||||
@ -100,17 +100,17 @@ public:
|
||||
const nsAString& aServiceName,
|
||||
const uint8_t aServiceUuid[16],
|
||||
int aChannel, bool aEncrypt, bool aAuth,
|
||||
BluetoothSocketResultHandler* aRes);
|
||||
BluetoothSocketResultHandler* aRes) override;
|
||||
|
||||
void Connect(const nsAString& aBdAddr,
|
||||
BluetoothSocketType aType,
|
||||
const uint8_t aUuid[16],
|
||||
int aChannel, bool aEncrypt, bool aAuth,
|
||||
BluetoothSocketResultHandler* aRes);
|
||||
BluetoothSocketResultHandler* aRes) override;
|
||||
|
||||
void Accept(int aFd, BluetoothSocketResultHandler* aRes);
|
||||
void Accept(int aFd, BluetoothSocketResultHandler* aRes) override;
|
||||
|
||||
void Close(BluetoothSocketResultHandler* aRes);
|
||||
void Close(BluetoothSocketResultHandler* aRes) override;
|
||||
|
||||
private:
|
||||
void DispatchError(BluetoothSocketResultHandler* aRes,
|
||||
|
@ -1399,9 +1399,7 @@ BluetoothHfpManager::ConnectionStateNotification(
|
||||
|
||||
} else if (aState == HFP_CONNECTION_STATE_CONNECTED) {
|
||||
// Once RFCOMM is connected, enable NREC before each new SLC connection
|
||||
mNrecEnabled = HFP_NREC_STARTED;
|
||||
NotifyConnectionStateChanged(
|
||||
NS_LITERAL_STRING(BLUETOOTH_HFP_NREC_STATUS_CHANGED_ID));
|
||||
NRECNotification(HFP_NREC_STARTED, mDeviceAddress);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1478,6 +1476,12 @@ BluetoothHfpManager::DtmfNotification(char aDtmf, const nsAString& aBdAddress)
|
||||
NotifyDialer(NS_ConvertUTF8toUTF16(message));
|
||||
}
|
||||
|
||||
/**
|
||||
* NREC status will be set when:
|
||||
* 1. Get an AT command from HF device.
|
||||
* (Bluetooth HFP spec v1.6 merely defines for the "Disable" part.)
|
||||
* 2. Once RFCOMM is connected, enable NREC before each new SLC connection.
|
||||
*/
|
||||
void
|
||||
BluetoothHfpManager::NRECNotification(BluetoothHandsfreeNRECState aNrec,
|
||||
const nsAString& aBdAddr)
|
||||
@ -1488,7 +1492,6 @@ BluetoothHfpManager::NRECNotification(BluetoothHandsfreeNRECState aNrec,
|
||||
nsCOMPtr<nsIObserverService> obs = services::GetObserverService();
|
||||
NS_ENSURE_TRUE_VOID(obs);
|
||||
|
||||
// Set NREC status once getting AT command
|
||||
mNrecEnabled = static_cast<bool>(aNrec);
|
||||
|
||||
// Notify audio manager
|
||||
|
@ -9,6 +9,7 @@
|
||||
|
||||
#include "BluetoothCommon.h"
|
||||
#include "mozilla/dom/bluetooth/BluetoothTypes.h"
|
||||
#include "mozilla/ipc/DaemonSocketMessageHandlers.h"
|
||||
|
||||
BEGIN_BLUETOOTH_NAMESPACE
|
||||
|
||||
@ -17,10 +18,9 @@ BEGIN_BLUETOOTH_NAMESPACE
|
||||
//
|
||||
|
||||
class BluetoothSocketResultHandler
|
||||
: public mozilla::ipc::DaemonSocketResultHandler
|
||||
{
|
||||
public:
|
||||
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(BluetoothSocketResultHandler)
|
||||
|
||||
virtual void OnError(BluetoothStatus aStatus)
|
||||
{
|
||||
BT_WARNING("Received error code %d", (int)aStatus);
|
||||
@ -155,10 +155,9 @@ protected:
|
||||
};
|
||||
|
||||
class BluetoothHandsfreeResultHandler
|
||||
: public mozilla::ipc::DaemonSocketResultHandler
|
||||
{
|
||||
public:
|
||||
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(BluetoothHandsfreeResultHandler)
|
||||
|
||||
virtual void OnError(BluetoothStatus aStatus)
|
||||
{
|
||||
BT_WARNING("Received error code %d", (int)aStatus);
|
||||
@ -303,10 +302,9 @@ protected:
|
||||
};
|
||||
|
||||
class BluetoothA2dpResultHandler
|
||||
: public mozilla::ipc::DaemonSocketResultHandler
|
||||
{
|
||||
public:
|
||||
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(BluetoothA2dpResultHandler)
|
||||
|
||||
virtual void OnError(BluetoothStatus aStatus)
|
||||
{
|
||||
BT_WARNING("Received error code %d", (int)aStatus);
|
||||
@ -406,10 +404,9 @@ protected:
|
||||
};
|
||||
|
||||
class BluetoothAvrcpResultHandler
|
||||
: public mozilla::ipc::DaemonSocketResultHandler
|
||||
{
|
||||
public:
|
||||
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(BluetoothAvrcpResultHandler)
|
||||
|
||||
virtual void OnError(BluetoothStatus aStatus)
|
||||
{
|
||||
BT_WARNING("Received error code %d", (int)aStatus);
|
||||
@ -720,10 +717,9 @@ protected:
|
||||
};
|
||||
|
||||
class BluetoothGattResultHandler
|
||||
: public mozilla::ipc::DaemonSocketResultHandler
|
||||
{
|
||||
public:
|
||||
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(BluetoothGattResultHandler)
|
||||
|
||||
virtual void OnError(BluetoothStatus aStatus)
|
||||
{
|
||||
BT_WARNING("Received error code %d", (int)aStatus);
|
||||
@ -1048,10 +1044,9 @@ protected:
|
||||
};
|
||||
|
||||
class BluetoothResultHandler
|
||||
: public mozilla::ipc::DaemonSocketResultHandler
|
||||
{
|
||||
public:
|
||||
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(BluetoothResultHandler)
|
||||
|
||||
virtual void OnError(BluetoothStatus aStatus)
|
||||
{
|
||||
BT_LOGR("Received error code %d", aStatus);
|
||||
|
@ -23,7 +23,7 @@ public:
|
||||
virtual ~DaemonSocketIOConsumer();
|
||||
|
||||
virtual void Handle(DaemonSocketPDU& aPDU) = 0;
|
||||
virtual void StoreUserData(const DaemonSocketPDU& aPDU) = 0;
|
||||
virtual void StoreResultHandler(const DaemonSocketPDU& aPDU) = 0;
|
||||
|
||||
protected:
|
||||
DaemonSocketIOConsumer();
|
||||
|
40
ipc/hal/DaemonSocketMessageHandlers.h
Normal file
40
ipc/hal/DaemonSocketMessageHandlers.h
Normal file
@ -0,0 +1,40 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* 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/. */
|
||||
|
||||
/*
|
||||
* Message handlers
|
||||
*
|
||||
* This file contains base classes for message handling.
|
||||
*/
|
||||
|
||||
#ifndef mozilla_ipc_DaemonSocketMessageHandlers_h
|
||||
#define mozilla_ipc_DaemonSocketMessageHandlers_h
|
||||
|
||||
#include "nsISupportsImpl.h" // for ref-counting
|
||||
|
||||
namespace mozilla {
|
||||
namespace ipc {
|
||||
|
||||
/**
|
||||
* |DaemonSocketResultHandler| is the base class for all protocol-specific
|
||||
* result handlers. It currently only manages the reference counting.
|
||||
*/
|
||||
class DaemonSocketResultHandler
|
||||
{
|
||||
public:
|
||||
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(DaemonSocketResultHandler);
|
||||
|
||||
protected:
|
||||
DaemonSocketResultHandler()
|
||||
{ }
|
||||
virtual ~DaemonSocketResultHandler()
|
||||
{ }
|
||||
};
|
||||
|
||||
} // namespace ipc
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // mozilla_ipc_DaemonSocketMessageHandlers_h
|
@ -29,9 +29,8 @@ namespace ipc {
|
||||
//
|
||||
|
||||
DaemonSocketPDU::DaemonSocketPDU(uint8_t aService, uint8_t aOpcode,
|
||||
uint16_t aPayloadSize)
|
||||
uint16_t aPayloadSize)
|
||||
: mConsumer(nullptr)
|
||||
, mUserData(nullptr)
|
||||
{
|
||||
MOZ_COUNT_CTOR_INHERITED(DaemonSocketPDU, UnixSocketIOBuffer);
|
||||
|
||||
@ -51,7 +50,6 @@ DaemonSocketPDU::DaemonSocketPDU(uint8_t aService, uint8_t aOpcode,
|
||||
|
||||
DaemonSocketPDU::DaemonSocketPDU(size_t aPayloadSize)
|
||||
: mConsumer(nullptr)
|
||||
, mUserData(nullptr)
|
||||
{
|
||||
MOZ_COUNT_CTOR_INHERITED(DaemonSocketPDU, UnixSocketIOBuffer);
|
||||
|
||||
@ -102,8 +100,8 @@ DaemonSocketPDU::Send(int aFd)
|
||||
|
||||
if (mConsumer) {
|
||||
// We successfully sent a PDU, now store the
|
||||
// result runnable in the consumer.
|
||||
mConsumer->StoreUserData(*this);
|
||||
// result handler in the consumer.
|
||||
mConsumer->StoreResultHandler(*this);
|
||||
}
|
||||
|
||||
return res;
|
||||
|
@ -9,6 +9,7 @@
|
||||
|
||||
#include "mozilla/FileUtils.h"
|
||||
#include "mozilla/ipc/SocketBase.h"
|
||||
#include "mozilla/ipc/DaemonSocketMessageHandlers.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace ipc {
|
||||
@ -55,14 +56,14 @@ public:
|
||||
mConsumer = aConsumer;
|
||||
}
|
||||
|
||||
void SetUserData(void* aUserData)
|
||||
void SetResultHandler(DaemonSocketResultHandler* aRes)
|
||||
{
|
||||
mUserData = aUserData;
|
||||
mRes = aRes;
|
||||
}
|
||||
|
||||
void* GetUserData() const
|
||||
DaemonSocketResultHandler* GetResultHandler() const
|
||||
{
|
||||
return mUserData;
|
||||
return mRes;
|
||||
}
|
||||
|
||||
void GetHeader(uint8_t& aService, uint8_t& aOpcode,
|
||||
@ -80,7 +81,7 @@ private:
|
||||
void OnError(const char* aFunction, int aErrno);
|
||||
|
||||
DaemonSocketIOConsumer* mConsumer;
|
||||
void* mUserData;
|
||||
nsRefPtr<DaemonSocketResultHandler> mRes;
|
||||
ScopedClose mReceivedFd;
|
||||
};
|
||||
|
||||
|
@ -9,6 +9,7 @@ EXPORTS.mozilla.ipc += [
|
||||
'DaemonSocket.h',
|
||||
'DaemonSocketConnector.h',
|
||||
'DaemonSocketConsumer.h',
|
||||
'DaemonSocketMessageHandlers.h',
|
||||
'DaemonSocketPDU.h',
|
||||
'DaemonSocketPDUHelpers.h'
|
||||
]
|
||||
|
254
mobile/android/base/AccountsHelper.java
Normal file
254
mobile/android/base/AccountsHelper.java
Normal file
@ -0,0 +1,254 @@
|
||||
/* -*- Mode: Java; c-basic-offset: 4; tab-width: 20; indent-tabs-mode: nil; -*-
|
||||
* 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/. */
|
||||
|
||||
package org.mozilla.gecko;
|
||||
|
||||
import android.accounts.Account;
|
||||
import android.accounts.AccountManager;
|
||||
import android.accounts.AccountManagerCallback;
|
||||
import android.accounts.AccountManagerFuture;
|
||||
import android.accounts.AuthenticatorException;
|
||||
import android.accounts.OperationCanceledException;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.util.Log;
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
import org.mozilla.gecko.fxa.FirefoxAccounts;
|
||||
import org.mozilla.gecko.fxa.FxAccountConstants;
|
||||
import org.mozilla.gecko.fxa.authenticator.AndroidFxAccount;
|
||||
import org.mozilla.gecko.fxa.login.Engaged;
|
||||
import org.mozilla.gecko.fxa.login.State;
|
||||
import org.mozilla.gecko.sync.Utils;
|
||||
import org.mozilla.gecko.sync.setup.SyncAccounts;
|
||||
import org.mozilla.gecko.util.EventCallback;
|
||||
import org.mozilla.gecko.util.NativeEventListener;
|
||||
import org.mozilla.gecko.util.NativeJSObject;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.net.URISyntaxException;
|
||||
import java.security.GeneralSecurityException;
|
||||
|
||||
/**
|
||||
* Helper class to manage Android Accounts corresponding to Firefox Accounts.
|
||||
*/
|
||||
public class AccountsHelper implements NativeEventListener {
|
||||
public static final String LOGTAG = "GeckoAccounts";
|
||||
|
||||
protected final Context mContext;
|
||||
protected final GeckoProfile mProfile;
|
||||
|
||||
public AccountsHelper(Context context, GeckoProfile profile) {
|
||||
mContext = context;
|
||||
mProfile = profile;
|
||||
|
||||
EventDispatcher dispatcher = EventDispatcher.getInstance();
|
||||
if (dispatcher == null) {
|
||||
Log.e(LOGTAG, "Gecko event dispatcher must not be null", new RuntimeException());
|
||||
return;
|
||||
}
|
||||
dispatcher.registerGeckoThreadListener(this,
|
||||
"Accounts:CreateFirefoxAccountFromJSON",
|
||||
"Accounts:UpdateFirefoxAccountFromJSON",
|
||||
"Accounts:Create",
|
||||
"Accounts:DeleteFirefoxAccount",
|
||||
"Accounts:Exist");
|
||||
}
|
||||
|
||||
public synchronized void uninit() {
|
||||
EventDispatcher dispatcher = EventDispatcher.getInstance();
|
||||
if (dispatcher == null) {
|
||||
Log.e(LOGTAG, "Gecko event dispatcher must not be null", new RuntimeException());
|
||||
return;
|
||||
}
|
||||
dispatcher.unregisterGeckoThreadListener(this,
|
||||
"Accounts:CreateFirefoxAccountFromJSON",
|
||||
"Accounts:UpdateFirefoxAccountFromJSON",
|
||||
"Accounts:Create",
|
||||
"Accounts:DeleteFirefoxAccount",
|
||||
"Accounts:Exist");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleMessage(String event, NativeJSObject message, final EventCallback callback) {
|
||||
if ("Accounts:CreateFirefoxAccountFromJSON".equals(event)) {
|
||||
AndroidFxAccount fxAccount = null;
|
||||
try {
|
||||
final NativeJSObject json = message.getObject("json");
|
||||
final String email = json.getString("email");
|
||||
final String uid = json.getString("uid");
|
||||
final boolean verified = json.optBoolean("verified", false);
|
||||
final byte[] unwrapkB = Utils.hex2Byte(json.getString("unwrapBKey"));
|
||||
final byte[] sessionToken = Utils.hex2Byte(json.getString("sessionToken"));
|
||||
final byte[] keyFetchToken = Utils.hex2Byte(json.getString("keyFetchToken"));
|
||||
final String authServerEndpoint =
|
||||
json.optString("authServerEndpoint", FxAccountConstants.DEFAULT_AUTH_SERVER_ENDPOINT);
|
||||
final String tokenServerEndpoint =
|
||||
json.optString("tokenServerEndpoint", FxAccountConstants.DEFAULT_TOKEN_SERVER_ENDPOINT);
|
||||
final String profileServerEndpoint =
|
||||
json.optString("profileServerEndpoint", FxAccountConstants.DEFAULT_PROFILE_SERVER_ENDPOINT);
|
||||
// TODO: handle choose what to Sync.
|
||||
State state = new Engaged(email, uid, verified, unwrapkB, sessionToken, keyFetchToken);
|
||||
fxAccount = AndroidFxAccount.addAndroidAccount(mContext,
|
||||
email,
|
||||
mProfile.getName(),
|
||||
authServerEndpoint,
|
||||
tokenServerEndpoint,
|
||||
profileServerEndpoint,
|
||||
state,
|
||||
AndroidFxAccount.DEFAULT_AUTHORITIES_TO_SYNC_AUTOMATICALLY_MAP);
|
||||
} catch (URISyntaxException | GeneralSecurityException | UnsupportedEncodingException e) {
|
||||
Log.w(LOGTAG, "Got exception creating Firefox Account from JSON; ignoring.", e);
|
||||
if (callback != null) {
|
||||
callback.sendError("Could not create Firefox Account from JSON: " + e.toString());
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (callback != null) {
|
||||
callback.sendSuccess(fxAccount != null);
|
||||
}
|
||||
|
||||
} else if ("Accounts:UpdateFirefoxAccountFromJSON".equals(event)) {
|
||||
try {
|
||||
final Account account = FirefoxAccounts.getFirefoxAccount(mContext);
|
||||
if (account == null) {
|
||||
if (callback != null) {
|
||||
callback.sendError("Could not update Firefox Account since none exists");
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
final NativeJSObject json = message.getObject("json");
|
||||
final String email = json.getString("email");
|
||||
final String uid = json.getString("uid");
|
||||
|
||||
// Protect against cross-connecting accounts.
|
||||
if (account.name == null || !account.name.equals(email)) {
|
||||
final String errorMessage = "Cannot update Firefox Account from JSON: datum has different email address!";
|
||||
Log.e(LOGTAG, errorMessage);
|
||||
if (callback != null) {
|
||||
callback.sendError(errorMessage);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
final boolean verified = json.optBoolean("verified", false);
|
||||
final byte[] unwrapkB = Utils.hex2Byte(json.getString("unwrapBKey"));
|
||||
final byte[] sessionToken = Utils.hex2Byte(json.getString("sessionToken"));
|
||||
final byte[] keyFetchToken = Utils.hex2Byte(json.getString("keyFetchToken"));
|
||||
final State state = new Engaged(email, uid, verified, unwrapkB, sessionToken, keyFetchToken);
|
||||
|
||||
final AndroidFxAccount fxAccount = new AndroidFxAccount(mContext, account);
|
||||
fxAccount.setState(state);
|
||||
|
||||
if (callback != null) {
|
||||
callback.sendSuccess(true);
|
||||
}
|
||||
} catch (NativeJSObject.InvalidPropertyException e) {
|
||||
Log.w(LOGTAG, "Got exception updating Firefox Account from JSON; ignoring.", e);
|
||||
if (callback != null) {
|
||||
callback.sendError("Could not update Firefox Account from JSON: " + e.toString());
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
} else if ("Accounts:Create".equals(event)) {
|
||||
// Do exactly the same thing as if you tapped 'Sync' in Settings.
|
||||
final Intent intent = new Intent(FxAccountConstants.ACTION_FXA_GET_STARTED);
|
||||
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||
final NativeJSObject extras = message.optObject("extras", null);
|
||||
if (extras != null) {
|
||||
intent.putExtra("extras", extras.toString());
|
||||
}
|
||||
mContext.startActivity(intent);
|
||||
|
||||
} else if ("Accounts:DeleteFirefoxAccount".equals(event)) {
|
||||
try {
|
||||
final Account account = FirefoxAccounts.getFirefoxAccount(mContext);
|
||||
if (account == null) {
|
||||
Log.w(LOGTAG, "Could not delete Firefox Account since none exists!");
|
||||
if (callback != null) {
|
||||
callback.sendError("Could not delete Firefox Account since none exists");
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
final AccountManagerCallback<Boolean> accountManagerCallback = new AccountManagerCallback<Boolean>() {
|
||||
@Override
|
||||
public void run(AccountManagerFuture<Boolean> future) {
|
||||
try {
|
||||
final boolean result = future.getResult();
|
||||
Log.i(LOGTAG, "Account named like " + Utils.obfuscateEmail(account.name) + " removed: " + result);
|
||||
if (callback != null) {
|
||||
callback.sendSuccess(result);
|
||||
}
|
||||
} catch (OperationCanceledException | IOException | AuthenticatorException e) {
|
||||
if (callback != null) {
|
||||
callback.sendError("Could not delete Firefox Account: " + e.toString());
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
AccountManager.get(mContext).removeAccount(account, accountManagerCallback, null);
|
||||
} catch (Exception e) {
|
||||
Log.w(LOGTAG, "Got exception updating Firefox Account from JSON; ignoring.", e);
|
||||
if (callback != null) {
|
||||
callback.sendError("Could not update Firefox Account from JSON: " + e.toString());
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
} else if ("Accounts:Exist".equals(event)) {
|
||||
if (callback == null) {
|
||||
Log.w(LOGTAG, "Accounts:Exist requires a callback");
|
||||
return;
|
||||
}
|
||||
|
||||
final String kind = message.optString("kind", null);
|
||||
final JSONObject response = new JSONObject();
|
||||
|
||||
try {
|
||||
if ("any".equals(kind)) {
|
||||
response.put("exists", SyncAccounts.syncAccountsExist(mContext) ||
|
||||
FirefoxAccounts.firefoxAccountsExist(mContext));
|
||||
callback.sendSuccess(response);
|
||||
} else if ("fxa".equals(kind)) {
|
||||
final Account account = FirefoxAccounts.getFirefoxAccount(mContext);
|
||||
response.put("exists", account != null);
|
||||
if (account != null) {
|
||||
response.put("email", account.name);
|
||||
// We should always be able to extract the server endpoints.
|
||||
final AndroidFxAccount fxAccount = new AndroidFxAccount(mContext, account);
|
||||
response.put("authServerEndpoint", fxAccount.getAccountServerURI());
|
||||
response.put("profileServerEndpoint", fxAccount.getProfileServerURI());
|
||||
response.put("tokenServerEndpoint", fxAccount.getTokenServerURI());
|
||||
try {
|
||||
// It is possible for the state fetch to fail and us to not be able to provide a UID.
|
||||
// Long term, the UID (and verification flag) will be attached to the Android account
|
||||
// user data and not the internal state representation.
|
||||
final State state = fxAccount.getState();
|
||||
response.put("uid", state.uid);
|
||||
} catch (Exception e) {
|
||||
Log.w(LOGTAG, "Got exception extracting account UID; ignoring.", e);
|
||||
}
|
||||
}
|
||||
|
||||
callback.sendSuccess(response);
|
||||
} else if ("sync11".equals(kind)) {
|
||||
response.put("exists", SyncAccounts.syncAccountsExist(mContext));
|
||||
callback.sendSuccess(response);
|
||||
} else {
|
||||
callback.sendError("Could not query account existence: unknown kind.");
|
||||
}
|
||||
} catch (JSONException e) {
|
||||
Log.w(LOGTAG, "Got exception querying account existence; ignoring.", e);
|
||||
callback.sendError("Could not query account existence: " + e.toString());
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -24,12 +24,6 @@ import org.mozilla.gecko.favicons.LoadFaviconTask;
|
||||
import org.mozilla.gecko.favicons.OnFaviconLoadedListener;
|
||||
import org.mozilla.gecko.favicons.decoders.IconDirectoryEntry;
|
||||
import org.mozilla.gecko.firstrun.FirstrunPane;
|
||||
import org.mozilla.gecko.fxa.FirefoxAccounts;
|
||||
import org.mozilla.gecko.fxa.FxAccountConstants;
|
||||
import org.mozilla.gecko.fxa.activities.FxAccountGetStartedActivity;
|
||||
import org.mozilla.gecko.fxa.authenticator.AndroidFxAccount;
|
||||
import org.mozilla.gecko.fxa.login.Engaged;
|
||||
import org.mozilla.gecko.fxa.login.State;
|
||||
import org.mozilla.gecko.gfx.BitmapUtils;
|
||||
import org.mozilla.gecko.gfx.DynamicToolbarAnimator;
|
||||
import org.mozilla.gecko.gfx.ImmutableViewportMetrics;
|
||||
@ -57,9 +51,7 @@ import org.mozilla.gecko.preferences.GeckoPreferences;
|
||||
import org.mozilla.gecko.prompts.Prompt;
|
||||
import org.mozilla.gecko.prompts.PromptListItem;
|
||||
import org.mozilla.gecko.restrictions.Restriction;
|
||||
import org.mozilla.gecko.sync.Utils;
|
||||
import org.mozilla.gecko.sync.repositories.android.FennecTabsRepository;
|
||||
import org.mozilla.gecko.sync.setup.SyncAccounts;
|
||||
import org.mozilla.gecko.tabqueue.TabQueueHelper;
|
||||
import org.mozilla.gecko.tabqueue.TabQueuePrompt;
|
||||
import org.mozilla.gecko.tabs.TabHistoryController;
|
||||
@ -262,6 +254,8 @@ public class BrowserApp extends GeckoApp
|
||||
|
||||
private ReadingListHelper mReadingListHelper;
|
||||
|
||||
private AccountsHelper mAccountsHelper;
|
||||
|
||||
// The tab to be selected on editing mode exit.
|
||||
private Integer mTargetTabForEditingMode;
|
||||
|
||||
@ -839,12 +833,9 @@ public class BrowserApp extends GeckoApp
|
||||
"Menu:Update",
|
||||
"LightweightTheme:Update",
|
||||
"Search:Keyword",
|
||||
"Prompt:ShowTop",
|
||||
"Accounts:Exist");
|
||||
"Prompt:ShowTop");
|
||||
|
||||
EventDispatcher.getInstance().registerGeckoThreadListener((NativeEventListener)this,
|
||||
"Accounts:Create",
|
||||
"Accounts:CreateFirefoxAccountFromJSON",
|
||||
"CharEncoding:Data",
|
||||
"CharEncoding:State",
|
||||
"Favicon:CacheLoad",
|
||||
@ -872,6 +863,7 @@ public class BrowserApp extends GeckoApp
|
||||
mOrderedBroadcastHelper = new OrderedBroadcastHelper(appContext);
|
||||
mBrowserHealthReporter = new BrowserHealthReporter();
|
||||
mReadingListHelper = new ReadingListHelper(appContext, getProfile(), this);
|
||||
mAccountsHelper = new AccountsHelper(appContext, getProfile());
|
||||
|
||||
if (AppConstants.MOZ_ANDROID_BEAM) {
|
||||
NfcAdapter nfc = NfcAdapter.getDefaultAdapter(this);
|
||||
@ -1415,6 +1407,12 @@ public class BrowserApp extends GeckoApp
|
||||
mReadingListHelper.uninit();
|
||||
mReadingListHelper = null;
|
||||
}
|
||||
|
||||
if (mAccountsHelper != null) {
|
||||
mAccountsHelper.uninit();
|
||||
mAccountsHelper = null;
|
||||
}
|
||||
|
||||
if (mZoomedView != null) {
|
||||
mZoomedView.destroy();
|
||||
}
|
||||
@ -1424,12 +1422,9 @@ public class BrowserApp extends GeckoApp
|
||||
"Menu:Update",
|
||||
"LightweightTheme:Update",
|
||||
"Search:Keyword",
|
||||
"Prompt:ShowTop",
|
||||
"Accounts:Exist");
|
||||
"Prompt:ShowTop");
|
||||
|
||||
EventDispatcher.getInstance().unregisterGeckoThreadListener((NativeEventListener) this,
|
||||
"Accounts:Create",
|
||||
"Accounts:CreateFirefoxAccountFromJSON",
|
||||
"CharEncoding:Data",
|
||||
"CharEncoding:State",
|
||||
"Favicon:CacheLoad",
|
||||
@ -1688,53 +1683,7 @@ public class BrowserApp extends GeckoApp
|
||||
@Override
|
||||
public void handleMessage(final String event, final NativeJSObject message,
|
||||
final EventCallback callback) {
|
||||
if ("Accounts:CreateFirefoxAccountFromJSON".equals(event)) {
|
||||
AndroidFxAccount fxAccount = null;
|
||||
try {
|
||||
final NativeJSObject json = message.getObject("json");
|
||||
final String email = json.getString("email");
|
||||
final String uid = json.getString("uid");
|
||||
final boolean verified = json.optBoolean("verified", false);
|
||||
final byte[] unwrapkB = Utils.hex2Byte(json.getString("unwrapBKey"));
|
||||
final byte[] sessionToken = Utils.hex2Byte(json.getString("sessionToken"));
|
||||
final byte[] keyFetchToken = Utils.hex2Byte(json.getString("keyFetchToken"));
|
||||
final String authServerEndpoint =
|
||||
json.optString("authServerEndpoint", FxAccountConstants.DEFAULT_AUTH_SERVER_ENDPOINT);
|
||||
final String tokenServerEndpoint =
|
||||
json.optString("tokenServerEndpoint", FxAccountConstants.DEFAULT_TOKEN_SERVER_ENDPOINT);
|
||||
final String profileServerEndpoint =
|
||||
json.optString("profileServerEndpoint", FxAccountConstants.DEFAULT_PROFILE_SERVER_ENDPOINT);
|
||||
// TODO: handle choose what to Sync.
|
||||
State state = new Engaged(email, uid, verified, unwrapkB, sessionToken, keyFetchToken);
|
||||
fxAccount = AndroidFxAccount.addAndroidAccount(this,
|
||||
email,
|
||||
getProfile().getName(),
|
||||
authServerEndpoint,
|
||||
tokenServerEndpoint,
|
||||
profileServerEndpoint,
|
||||
state,
|
||||
AndroidFxAccount.DEFAULT_AUTHORITIES_TO_SYNC_AUTOMATICALLY_MAP);
|
||||
} catch (Exception e) {
|
||||
Log.w(LOGTAG, "Got exception creating Firefox Account from JSON; ignoring.", e);
|
||||
if (callback == null) {
|
||||
callback.sendError("Could not create Firefox Account from JSON: " + e.toString());
|
||||
}
|
||||
}
|
||||
if (callback != null) {
|
||||
callback.sendSuccess(fxAccount != null);
|
||||
}
|
||||
|
||||
} else if ("Accounts:Create".equals(event)) {
|
||||
// Do exactly the same thing as if you tapped 'Sync' in Settings.
|
||||
final Intent intent = new Intent(getContext(), FxAccountGetStartedActivity.class);
|
||||
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||
final NativeJSObject extras = message.optObject("extras", null);
|
||||
if (extras != null) {
|
||||
intent.putExtra("extras", extras.toString());
|
||||
}
|
||||
getContext().startActivity(intent);
|
||||
|
||||
} else if ("CharEncoding:Data".equals(event)) {
|
||||
if ("CharEncoding:Data".equals(event)) {
|
||||
final NativeJSObject[] charsets = message.getObjectArray("charsets");
|
||||
final int selected = message.getInt("selected");
|
||||
|
||||
@ -2033,24 +1982,6 @@ public class BrowserApp extends GeckoApp
|
||||
bringToFrontIntent.setClassName(AppConstants.ANDROID_PACKAGE_NAME, AppConstants.MOZ_ANDROID_BROWSER_INTENT_CLASS);
|
||||
bringToFrontIntent.setFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT);
|
||||
startActivity(bringToFrontIntent);
|
||||
} else if (event.equals("Accounts:Exist")) {
|
||||
final String kind = message.getString("kind");
|
||||
final JSONObject response = new JSONObject();
|
||||
|
||||
if ("any".equals(kind)) {
|
||||
response.put("exists", SyncAccounts.syncAccountsExist(getContext()) ||
|
||||
FirefoxAccounts.firefoxAccountsExist(getContext()));
|
||||
EventDispatcher.sendResponse(message, response);
|
||||
} else if ("fxa".equals(kind)) {
|
||||
response.put("exists", FirefoxAccounts.firefoxAccountsExist(getContext()));
|
||||
EventDispatcher.sendResponse(message, response);
|
||||
} else if ("sync11".equals(kind)) {
|
||||
response.put("exists", SyncAccounts.syncAccountsExist(getContext()));
|
||||
EventDispatcher.sendResponse(message, response);
|
||||
} else {
|
||||
response.put("error", "Unknown kind");
|
||||
EventDispatcher.sendError(message, response);
|
||||
}
|
||||
} else {
|
||||
super.handleMessage(event, message);
|
||||
}
|
||||
|
@ -32,7 +32,7 @@ public final class ThumbnailHelper {
|
||||
|
||||
public static final float TABS_PANEL_THUMBNAIL_ASPECT_RATIO = 0.8333333f;
|
||||
public static final float TOP_SITES_THUMBNAIL_ASPECT_RATIO = 0.571428571f; // this is a 4:7 ratio (as per UX decision)
|
||||
private static final float THUMBNAIL_ASPECT_RATIO;
|
||||
public static final float THUMBNAIL_ASPECT_RATIO;
|
||||
|
||||
static {
|
||||
// As we only want to generate one thumbnail for each tab, we calculate the
|
||||
|
@ -853,16 +853,21 @@ sync_java_files = [
|
||||
'fxa/activities/FxAccountAbstractSetupActivity.java',
|
||||
'fxa/activities/FxAccountAbstractUpdateCredentialsActivity.java',
|
||||
'fxa/activities/FxAccountConfirmAccountActivity.java',
|
||||
'fxa/activities/FxAccountConfirmAccountActivityWeb.java',
|
||||
'fxa/activities/FxAccountCreateAccountActivity.java',
|
||||
'fxa/activities/FxAccountCreateAccountNotAllowedActivity.java',
|
||||
'fxa/activities/FxAccountFinishMigratingActivity.java',
|
||||
'fxa/activities/FxAccountFinishMigratingActivityWeb.java',
|
||||
'fxa/activities/FxAccountGetStartedActivity.java',
|
||||
'fxa/activities/FxAccountGetStartedActivityWeb.java',
|
||||
'fxa/activities/FxAccountMigrationFinishedActivity.java',
|
||||
'fxa/activities/FxAccountSignInActivity.java',
|
||||
'fxa/activities/FxAccountStatusActivity.java',
|
||||
'fxa/activities/FxAccountStatusFragment.java',
|
||||
'fxa/activities/FxAccountUpdateCredentialsActivity.java',
|
||||
'fxa/activities/FxAccountUpdateCredentialsActivityWeb.java',
|
||||
'fxa/activities/FxAccountVerifiedAccountActivity.java',
|
||||
'fxa/activities/FxAccountWebFlowActivity.java',
|
||||
'fxa/activities/PicassoPreferenceIconTarget.java',
|
||||
'fxa/authenticator/AccountPickler.java',
|
||||
'fxa/authenticator/AndroidFxAccount.java',
|
||||
|
@ -13,7 +13,7 @@ import android.view.ViewGroup;
|
||||
import org.mozilla.gecko.R;
|
||||
import org.mozilla.gecko.Telemetry;
|
||||
import org.mozilla.gecko.TelemetryContract;
|
||||
import org.mozilla.gecko.fxa.activities.FxAccountGetStartedActivity;
|
||||
import org.mozilla.gecko.fxa.FxAccountConstants;
|
||||
|
||||
public class WelcomePanel extends FirstrunPanel {
|
||||
public static final int TITLE_RES = R.string.firstrun_panel_title_welcome;
|
||||
@ -26,8 +26,9 @@ public class WelcomePanel extends FirstrunPanel {
|
||||
public void onClick(View v) {
|
||||
Telemetry.sendUIEvent(TelemetryContract.Event.ACTION, TelemetryContract.Method.BUTTON, "firstrun-sync");
|
||||
|
||||
final Intent accountIntent = new Intent(getActivity(), FxAccountGetStartedActivity.class);
|
||||
startActivity(accountIntent);
|
||||
final Intent intent = new Intent(FxAccountConstants.ACTION_FXA_GET_STARTED);
|
||||
intent.setFlags(Intent.FLAG_ACTIVITY_NO_ANIMATION);
|
||||
startActivity(intent);
|
||||
|
||||
close();
|
||||
}
|
||||
|
@ -94,4 +94,10 @@ public class FxAccountConstants {
|
||||
* Account type.
|
||||
*/
|
||||
public static final String ACCOUNT_STATE_CHANGED_ACTION = AppConstants.MOZ_ANDROID_SHARED_FXACCOUNT_TYPE + ".accounts.ACCOUNT_STATE_CHANGED_ACTION";
|
||||
|
||||
public static final String ACTION_FXA_CONFIRM_ACCOUNT = AppConstants.ANDROID_PACKAGE_NAME + ".ACTION_FXA_CONFIRM_ACCOUNT";
|
||||
public static final String ACTION_FXA_FINISH_MIGRATING = AppConstants.ANDROID_PACKAGE_NAME + ".ACTION_FXA_FINISH_MIGRATING";
|
||||
public static final String ACTION_FXA_GET_STARTED = AppConstants.ANDROID_PACKAGE_NAME + ".ACTION_FXA_GET_STARTED";
|
||||
public static final String ACTION_FXA_STATUS = AppConstants.ANDROID_PACKAGE_NAME + ".ACTION_FXA_STATUS";
|
||||
public static final String ACTION_FXA_UPDATE_CREDENTIALS = AppConstants.ANDROID_PACKAGE_NAME + ".ACTION_FXA_UPDATE_CREDENTIALS";
|
||||
}
|
||||
|
@ -4,13 +4,6 @@
|
||||
|
||||
package org.mozilla.gecko.fxa.activities;
|
||||
|
||||
import org.mozilla.gecko.Locales.LocaleAwareActivity;
|
||||
import org.mozilla.gecko.background.common.log.Logger;
|
||||
import org.mozilla.gecko.background.fxa.FxAccountAgeLockoutHelper;
|
||||
import org.mozilla.gecko.fxa.FirefoxAccounts;
|
||||
import org.mozilla.gecko.fxa.authenticator.AndroidFxAccount;
|
||||
import org.mozilla.gecko.sync.setup.activities.ActivityUtils;
|
||||
|
||||
import android.accounts.Account;
|
||||
import android.app.Activity;
|
||||
import android.content.Intent;
|
||||
@ -18,6 +11,13 @@ import android.os.SystemClock;
|
||||
import android.view.View;
|
||||
import android.view.View.OnClickListener;
|
||||
import android.widget.TextView;
|
||||
import org.mozilla.gecko.Locales.LocaleAwareActivity;
|
||||
import org.mozilla.gecko.background.common.log.Logger;
|
||||
import org.mozilla.gecko.background.fxa.FxAccountAgeLockoutHelper;
|
||||
import org.mozilla.gecko.fxa.FirefoxAccounts;
|
||||
import org.mozilla.gecko.fxa.FxAccountConstants;
|
||||
import org.mozilla.gecko.fxa.authenticator.AndroidFxAccount;
|
||||
import org.mozilla.gecko.sync.setup.activities.ActivityUtils;
|
||||
|
||||
public abstract class FxAccountAbstractActivity extends LocaleAwareActivity {
|
||||
private static final String LOG_TAG = FxAccountAbstractActivity.class.getSimpleName();
|
||||
@ -43,26 +43,30 @@ public abstract class FxAccountAbstractActivity extends LocaleAwareActivity {
|
||||
* exists or if account creation is locked out due to an age verification
|
||||
* check failing (getting started, create account, sign in). This function
|
||||
* redirects as appropriate.
|
||||
*
|
||||
* @return true if redirected.
|
||||
*/
|
||||
protected void redirectIfAppropriate() {
|
||||
protected boolean redirectIfAppropriate() {
|
||||
if (cannotResumeWhenAccountsExist || cannotResumeWhenNoAccountsExist) {
|
||||
final Account account = FirefoxAccounts.getFirefoxAccount(this);
|
||||
if (cannotResumeWhenAccountsExist && account != null) {
|
||||
redirectToActivity(FxAccountStatusActivity.class);
|
||||
return;
|
||||
redirectToAction(FxAccountConstants.ACTION_FXA_STATUS);
|
||||
return true;
|
||||
}
|
||||
if (cannotResumeWhenNoAccountsExist && account == null) {
|
||||
redirectToActivity(FxAccountGetStartedActivity.class);
|
||||
return;
|
||||
redirectToAction(FxAccountConstants.ACTION_FXA_GET_STARTED);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
if (cannotResumeWhenLockedOut) {
|
||||
if (FxAccountAgeLockoutHelper.isLockedOut(SystemClock.elapsedRealtime())) {
|
||||
this.setResult(RESULT_CANCELED);
|
||||
redirectToActivity(FxAccountCreateAccountNotAllowedActivity.class);
|
||||
return;
|
||||
launchActivity(FxAccountCreateAccountNotAllowedActivity.class);
|
||||
finish();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -85,8 +89,12 @@ public abstract class FxAccountAbstractActivity extends LocaleAwareActivity {
|
||||
startActivity(intent);
|
||||
}
|
||||
|
||||
protected void redirectToActivity(Class<? extends Activity> activityClass) {
|
||||
launchActivity(activityClass);
|
||||
protected void redirectToAction(final String action) {
|
||||
final Intent intent = new Intent(action);
|
||||
// Per http://stackoverflow.com/a/8992365, this triggers a known bug with
|
||||
// the soft keyboard not being shown for the started activity. Why, Android, why?
|
||||
intent.setFlags(Intent.FLAG_ACTIVITY_NO_ANIMATION);
|
||||
startActivity(intent);
|
||||
finish();
|
||||
}
|
||||
|
||||
|
@ -4,9 +4,15 @@
|
||||
|
||||
package org.mozilla.gecko.fxa.activities;
|
||||
|
||||
import java.util.concurrent.Executor;
|
||||
import java.util.concurrent.Executors;
|
||||
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
import android.view.View;
|
||||
import android.view.View.OnClickListener;
|
||||
import android.widget.AutoCompleteTextView;
|
||||
import android.widget.Button;
|
||||
import android.widget.EditText;
|
||||
import android.widget.ProgressBar;
|
||||
import android.widget.TextView;
|
||||
import org.mozilla.gecko.R;
|
||||
import org.mozilla.gecko.background.common.log.Logger;
|
||||
import org.mozilla.gecko.background.common.telemetry.TelemetryWrapper;
|
||||
@ -18,6 +24,7 @@ import org.mozilla.gecko.background.fxa.FxAccountClientException.FxAccountClient
|
||||
import org.mozilla.gecko.background.fxa.FxAccountUtils;
|
||||
import org.mozilla.gecko.background.fxa.PasswordStretcher;
|
||||
import org.mozilla.gecko.fxa.FirefoxAccounts;
|
||||
import org.mozilla.gecko.fxa.FxAccountConstants;
|
||||
import org.mozilla.gecko.fxa.authenticator.AndroidFxAccount;
|
||||
import org.mozilla.gecko.fxa.login.Engaged;
|
||||
import org.mozilla.gecko.fxa.login.State;
|
||||
@ -25,15 +32,8 @@ import org.mozilla.gecko.fxa.tasks.FxAccountSignInTask;
|
||||
import org.mozilla.gecko.sync.setup.activities.ActivityUtils;
|
||||
import org.mozilla.gecko.sync.telemetry.TelemetryContract;
|
||||
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
import android.view.View;
|
||||
import android.view.View.OnClickListener;
|
||||
import android.widget.AutoCompleteTextView;
|
||||
import android.widget.Button;
|
||||
import android.widget.EditText;
|
||||
import android.widget.ProgressBar;
|
||||
import android.widget.TextView;
|
||||
import java.util.concurrent.Executor;
|
||||
import java.util.concurrent.Executors;
|
||||
|
||||
/**
|
||||
* Abstract activity which displays a screen for updating the local password.
|
||||
@ -109,7 +109,7 @@ public abstract class FxAccountAbstractUpdateCredentialsActivity extends FxAccou
|
||||
final State state = fxAccount.getState();
|
||||
fxAccount.setState(state.makeDoghouseState());
|
||||
// The status activity will say that the user needs to upgrade.
|
||||
redirectToActivity(FxAccountStatusActivity.class);
|
||||
redirectToAction(FxAccountConstants.ACTION_FXA_STATUS);
|
||||
return;
|
||||
}
|
||||
showRemoteError(e, R.string.fxaccount_update_credentials_unknown_error);
|
||||
|
@ -4,18 +4,6 @@
|
||||
|
||||
package org.mozilla.gecko.fxa.activities;
|
||||
|
||||
import org.mozilla.gecko.R;
|
||||
import org.mozilla.gecko.background.common.log.Logger;
|
||||
import org.mozilla.gecko.fxa.FirefoxAccounts;
|
||||
import org.mozilla.gecko.fxa.SyncStatusListener;
|
||||
import org.mozilla.gecko.fxa.authenticator.AndroidFxAccount;
|
||||
import org.mozilla.gecko.fxa.login.Engaged;
|
||||
import org.mozilla.gecko.fxa.login.State;
|
||||
import org.mozilla.gecko.fxa.login.State.Action;
|
||||
import org.mozilla.gecko.fxa.sync.FxAccountSyncStatusHelper;
|
||||
import org.mozilla.gecko.fxa.tasks.FxAccountCodeResender;
|
||||
import org.mozilla.gecko.sync.setup.activities.ActivityUtils;
|
||||
|
||||
import android.accounts.Account;
|
||||
import android.app.Activity;
|
||||
import android.content.Context;
|
||||
@ -24,6 +12,18 @@ import android.os.Bundle;
|
||||
import android.view.View;
|
||||
import android.view.View.OnClickListener;
|
||||
import android.widget.TextView;
|
||||
import org.mozilla.gecko.R;
|
||||
import org.mozilla.gecko.background.common.log.Logger;
|
||||
import org.mozilla.gecko.fxa.FirefoxAccounts;
|
||||
import org.mozilla.gecko.fxa.FxAccountConstants;
|
||||
import org.mozilla.gecko.fxa.SyncStatusListener;
|
||||
import org.mozilla.gecko.fxa.authenticator.AndroidFxAccount;
|
||||
import org.mozilla.gecko.fxa.login.Engaged;
|
||||
import org.mozilla.gecko.fxa.login.State;
|
||||
import org.mozilla.gecko.fxa.login.State.Action;
|
||||
import org.mozilla.gecko.fxa.sync.FxAccountSyncStatusHelper;
|
||||
import org.mozilla.gecko.fxa.tasks.FxAccountCodeResender;
|
||||
import org.mozilla.gecko.sync.setup.activities.ActivityUtils;
|
||||
|
||||
/**
|
||||
* Activity which displays account created successfully screen to the user, and
|
||||
@ -146,7 +146,7 @@ public class FxAccountConfirmAccountActivity extends FxAccountAbstractActivity i
|
||||
Logger.warn(LOG_TAG, "No need to verify Firefox Account that needs action " + neededAction.toString() +
|
||||
" (in state " + state.getStateLabel() + ").");
|
||||
setResult(RESULT_CANCELED);
|
||||
this.redirectToActivity(FxAccountStatusActivity.class);
|
||||
redirectToAction(FxAccountConstants.ACTION_FXA_STATUS);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -0,0 +1,11 @@
|
||||
/* 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/. */
|
||||
|
||||
package org.mozilla.gecko.fxa.activities;
|
||||
|
||||
public class FxAccountConfirmAccountActivityWeb extends FxAccountWebFlowActivity {
|
||||
public FxAccountConfirmAccountActivityWeb() {
|
||||
super(CANNOT_RESUME_WHEN_NO_ACCOUNTS_EXIST, "settings");
|
||||
}
|
||||
}
|
@ -429,7 +429,8 @@ public class FxAccountCreateAccountActivity extends FxAccountAbstractSetupActivi
|
||||
FxAccountUtils.pii(LOG_TAG, "Failed age check!");
|
||||
FxAccountAgeLockoutHelper.lockOut(SystemClock.elapsedRealtime());
|
||||
setResult(RESULT_CANCELED);
|
||||
redirectToActivity(FxAccountCreateAccountNotAllowedActivity.class);
|
||||
launchActivity(FxAccountCreateAccountNotAllowedActivity.class);
|
||||
finish();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
@ -0,0 +1,11 @@
|
||||
/* 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/. */
|
||||
|
||||
package org.mozilla.gecko.fxa.activities;
|
||||
|
||||
public class FxAccountFinishMigratingActivityWeb extends FxAccountWebFlowActivity {
|
||||
public FxAccountFinishMigratingActivityWeb() {
|
||||
super(CANNOT_RESUME_WHEN_NO_ACCOUNTS_EXIST, "signin", "migration=sync11");
|
||||
}
|
||||
}
|
@ -0,0 +1,11 @@
|
||||
/* 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/. */
|
||||
|
||||
package org.mozilla.gecko.fxa.activities;
|
||||
|
||||
public class FxAccountGetStartedActivityWeb extends FxAccountWebFlowActivity {
|
||||
public FxAccountGetStartedActivityWeb() {
|
||||
super(CANNOT_RESUME_WHEN_ACCOUNTS_EXIST, "signin");
|
||||
}
|
||||
}
|
@ -4,15 +4,6 @@
|
||||
|
||||
package org.mozilla.gecko.fxa.activities;
|
||||
|
||||
import org.mozilla.gecko.AppConstants;
|
||||
import org.mozilla.gecko.Locales.LocaleAwareFragmentActivity;
|
||||
import org.mozilla.gecko.R;
|
||||
import org.mozilla.gecko.background.common.log.Logger;
|
||||
import org.mozilla.gecko.background.fxa.FxAccountUtils;
|
||||
import org.mozilla.gecko.fxa.FirefoxAccounts;
|
||||
import org.mozilla.gecko.fxa.authenticator.AndroidFxAccount;
|
||||
import org.mozilla.gecko.sync.Utils;
|
||||
|
||||
import android.accounts.Account;
|
||||
import android.accounts.AccountManager;
|
||||
import android.accounts.AccountManagerCallback;
|
||||
@ -32,6 +23,15 @@ import android.view.Menu;
|
||||
import android.view.MenuInflater;
|
||||
import android.view.MenuItem;
|
||||
import android.widget.Toast;
|
||||
import org.mozilla.gecko.AppConstants;
|
||||
import org.mozilla.gecko.Locales.LocaleAwareFragmentActivity;
|
||||
import org.mozilla.gecko.R;
|
||||
import org.mozilla.gecko.background.common.log.Logger;
|
||||
import org.mozilla.gecko.background.fxa.FxAccountUtils;
|
||||
import org.mozilla.gecko.fxa.FirefoxAccounts;
|
||||
import org.mozilla.gecko.fxa.FxAccountConstants;
|
||||
import org.mozilla.gecko.fxa.authenticator.AndroidFxAccount;
|
||||
import org.mozilla.gecko.sync.Utils;
|
||||
|
||||
/**
|
||||
* Activity which displays account status.
|
||||
@ -85,7 +85,7 @@ public class FxAccountStatusActivity extends LocaleAwareFragmentActivity {
|
||||
Logger.warn(LOG_TAG, "Could not get Firefox Account.");
|
||||
|
||||
// Gracefully redirect to get started.
|
||||
Intent intent = new Intent(this, FxAccountGetStartedActivity.class);
|
||||
final Intent intent = new Intent(FxAccountConstants.ACTION_FXA_GET_STARTED);
|
||||
// Per http://stackoverflow.com/a/8992365, this triggers a known bug with
|
||||
// the soft keyboard not being shown for the started activity. Why, Android, why?
|
||||
intent.setFlags(Intent.FLAG_ACTIVITY_NO_ANIMATION);
|
||||
|
@ -4,32 +4,6 @@
|
||||
|
||||
package org.mozilla.gecko.fxa.activities;
|
||||
|
||||
import java.util.Calendar;
|
||||
import java.util.Date;
|
||||
import java.util.GregorianCalendar;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import org.mozilla.gecko.AppConstants;
|
||||
import org.mozilla.gecko.R;
|
||||
import org.mozilla.gecko.background.common.log.Logger;
|
||||
import org.mozilla.gecko.background.fxa.FxAccountUtils;
|
||||
import org.mozilla.gecko.background.preferences.PreferenceFragment;
|
||||
import org.mozilla.gecko.fxa.FirefoxAccounts;
|
||||
import org.mozilla.gecko.fxa.FxAccountConstants;
|
||||
import org.mozilla.gecko.fxa.SyncStatusListener;
|
||||
import org.mozilla.gecko.fxa.authenticator.AndroidFxAccount;
|
||||
import org.mozilla.gecko.fxa.login.Married;
|
||||
import org.mozilla.gecko.fxa.login.State;
|
||||
import org.mozilla.gecko.fxa.sync.FxAccountSyncStatusHelper;
|
||||
import org.mozilla.gecko.fxa.tasks.FxAccountCodeResender;
|
||||
import org.mozilla.gecko.sync.ExtendedJSONObject;
|
||||
import org.mozilla.gecko.sync.SharedPreferencesClientsDataDelegate;
|
||||
import org.mozilla.gecko.sync.SyncConfiguration;
|
||||
import org.mozilla.gecko.util.HardwareUtils;
|
||||
import org.mozilla.gecko.util.ThreadUtils;
|
||||
|
||||
import android.accounts.Account;
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.content.ContentResolver;
|
||||
@ -49,9 +23,33 @@ import android.preference.PreferenceScreen;
|
||||
import android.support.v4.content.LocalBroadcastManager;
|
||||
import android.text.TextUtils;
|
||||
import android.text.format.DateUtils;
|
||||
|
||||
import com.squareup.picasso.Picasso;
|
||||
import com.squareup.picasso.Target;
|
||||
import org.mozilla.gecko.AppConstants;
|
||||
import org.mozilla.gecko.R;
|
||||
import org.mozilla.gecko.background.common.log.Logger;
|
||||
import org.mozilla.gecko.background.fxa.FxAccountUtils;
|
||||
import org.mozilla.gecko.background.preferences.PreferenceFragment;
|
||||
import org.mozilla.gecko.fxa.FirefoxAccounts;
|
||||
import org.mozilla.gecko.fxa.FxAccountConstants;
|
||||
import org.mozilla.gecko.fxa.SyncStatusListener;
|
||||
import org.mozilla.gecko.fxa.authenticator.AndroidFxAccount;
|
||||
import org.mozilla.gecko.fxa.login.Married;
|
||||
import org.mozilla.gecko.fxa.login.State;
|
||||
import org.mozilla.gecko.fxa.sync.FxAccountSyncStatusHelper;
|
||||
import org.mozilla.gecko.fxa.tasks.FxAccountCodeResender;
|
||||
import org.mozilla.gecko.sync.ExtendedJSONObject;
|
||||
import org.mozilla.gecko.sync.SharedPreferencesClientsDataDelegate;
|
||||
import org.mozilla.gecko.sync.SyncConfiguration;
|
||||
import org.mozilla.gecko.util.HardwareUtils;
|
||||
import org.mozilla.gecko.util.ThreadUtils;
|
||||
|
||||
import java.util.Calendar;
|
||||
import java.util.Date;
|
||||
import java.util.GregorianCalendar;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* A fragment that displays the status of an AndroidFxAccount.
|
||||
@ -237,7 +235,7 @@ public class FxAccountStatusFragment
|
||||
@Override
|
||||
public boolean onPreferenceClick(Preference preference) {
|
||||
if (preference == needsPasswordPreference) {
|
||||
Intent intent = new Intent(getActivity(), FxAccountUpdateCredentialsActivity.class);
|
||||
final Intent intent = new Intent(FxAccountConstants.ACTION_FXA_UPDATE_CREDENTIALS);
|
||||
final Bundle extras = getExtrasForAccount();
|
||||
if (extras != null) {
|
||||
intent.putExtras(extras);
|
||||
@ -251,7 +249,7 @@ public class FxAccountStatusFragment
|
||||
}
|
||||
|
||||
if (preference == needsFinishMigratingPreference) {
|
||||
final Intent intent = new Intent(getActivity(), FxAccountFinishMigratingActivity.class);
|
||||
final Intent intent = new Intent(FxAccountConstants.ACTION_FXA_FINISH_MIGRATING);
|
||||
final Bundle extras = getExtrasForAccount();
|
||||
if (extras != null) {
|
||||
intent.putExtras(extras);
|
||||
@ -265,9 +263,11 @@ public class FxAccountStatusFragment
|
||||
}
|
||||
|
||||
if (preference == needsVerificationPreference) {
|
||||
FxAccountCodeResender.resendCode(getActivity().getApplicationContext(), fxAccount);
|
||||
if (AppConstants.MOZ_ANDROID_NATIVE_ACCOUNT_UI) {
|
||||
FxAccountCodeResender.resendCode(getActivity().getApplicationContext(), fxAccount);
|
||||
}
|
||||
|
||||
Intent intent = new Intent(getActivity(), FxAccountConfirmAccountActivity.class);
|
||||
final Intent intent = new Intent(FxAccountConstants.ACTION_FXA_CONFIRM_ACCOUNT);
|
||||
// Per http://stackoverflow.com/a/8992365, this triggers a known bug with
|
||||
// the soft keyboard not being shown for the started activity. Why, Android, why?
|
||||
intent.setFlags(Intent.FLAG_ACTIVITY_NO_ANIMATION);
|
||||
|
@ -0,0 +1,11 @@
|
||||
/* 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/. */
|
||||
|
||||
package org.mozilla.gecko.fxa.activities;
|
||||
|
||||
public class FxAccountUpdateCredentialsActivityWeb extends FxAccountWebFlowActivity {
|
||||
public FxAccountUpdateCredentialsActivityWeb() {
|
||||
super(CANNOT_RESUME_WHEN_NO_ACCOUNTS_EXIST, "force_auth");
|
||||
}
|
||||
}
|
@ -0,0 +1,64 @@
|
||||
/* 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/. */
|
||||
|
||||
package org.mozilla.gecko.fxa.activities;
|
||||
|
||||
import android.os.Bundle;
|
||||
import org.mozilla.gecko.Locales;
|
||||
import org.mozilla.gecko.background.common.log.Logger;
|
||||
import org.mozilla.gecko.fxa.FxAccountConstants;
|
||||
import org.mozilla.gecko.fxa.authenticator.AndroidFxAccount;
|
||||
import org.mozilla.gecko.sync.setup.activities.ActivityUtils;
|
||||
|
||||
/**
|
||||
* Activity which shows the status activity or passes through to web flow.
|
||||
*/
|
||||
public class FxAccountWebFlowActivity extends FxAccountAbstractActivity {
|
||||
protected static final String LOG_TAG = FxAccountWebFlowActivity.class.getSimpleName();
|
||||
|
||||
protected static final String ABOUT_ACCOUNTS = "about:accounts";
|
||||
private final String action;
|
||||
private final String extras;
|
||||
|
||||
public FxAccountWebFlowActivity(int resume, String action) {
|
||||
this(resume, action, null);
|
||||
}
|
||||
|
||||
public FxAccountWebFlowActivity(int resume, String action, String extras) {
|
||||
super(resume);
|
||||
this.action = action;
|
||||
this.extras = (extras != null) ? ("&" + extras) : "";
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public void onCreate(Bundle icicle) {
|
||||
Logger.setThreadLogTag(FxAccountConstants.GLOBAL_LOG_TAG);
|
||||
Logger.debug(LOG_TAG, "onCreate(" + icicle + ")");
|
||||
|
||||
Locales.initializeLocale(getApplicationContext());
|
||||
|
||||
super.onCreate(icicle);
|
||||
}
|
||||
|
||||
protected boolean redirectIfAppropriate() {
|
||||
final boolean redirected = super.redirectIfAppropriate();
|
||||
if (redirected) {
|
||||
return true;
|
||||
}
|
||||
ActivityUtils.openURLInFennec(getApplicationContext(),
|
||||
ABOUT_ACCOUNTS + "?action=" + action + extras);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onResume() {
|
||||
super.onResume();
|
||||
|
||||
// We are always redirected.
|
||||
this.finish();
|
||||
}
|
||||
}
|
@ -4,10 +4,14 @@
|
||||
|
||||
package org.mozilla.gecko.fxa.authenticator;
|
||||
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.util.concurrent.Executor;
|
||||
import java.util.concurrent.Executors;
|
||||
|
||||
import android.accounts.AbstractAccountAuthenticator;
|
||||
import android.accounts.Account;
|
||||
import android.accounts.AccountAuthenticatorResponse;
|
||||
import android.accounts.AccountManager;
|
||||
import android.accounts.NetworkErrorException;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
import org.mozilla.gecko.background.common.log.Logger;
|
||||
import org.mozilla.gecko.background.fxa.FxAccountClient;
|
||||
import org.mozilla.gecko.background.fxa.FxAccountClient20;
|
||||
@ -19,7 +23,6 @@ import org.mozilla.gecko.background.fxa.oauth.FxAccountOAuthClient10.Authorizati
|
||||
import org.mozilla.gecko.browserid.BrowserIDKeyPair;
|
||||
import org.mozilla.gecko.browserid.JSONWebTokenUtils;
|
||||
import org.mozilla.gecko.fxa.FxAccountConstants;
|
||||
import org.mozilla.gecko.fxa.activities.FxAccountGetStartedActivity;
|
||||
import org.mozilla.gecko.fxa.login.FxAccountLoginStateMachine;
|
||||
import org.mozilla.gecko.fxa.login.FxAccountLoginStateMachine.LoginStateMachineDelegate;
|
||||
import org.mozilla.gecko.fxa.login.FxAccountLoginTransition.Transition;
|
||||
@ -30,14 +33,9 @@ import org.mozilla.gecko.fxa.login.StateFactory;
|
||||
import org.mozilla.gecko.fxa.sync.FxAccountNotificationManager;
|
||||
import org.mozilla.gecko.fxa.sync.FxAccountSyncAdapter;
|
||||
|
||||
import android.accounts.AbstractAccountAuthenticator;
|
||||
import android.accounts.Account;
|
||||
import android.accounts.AccountAuthenticatorResponse;
|
||||
import android.accounts.AccountManager;
|
||||
import android.accounts.NetworkErrorException;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.util.concurrent.Executor;
|
||||
import java.util.concurrent.Executors;
|
||||
|
||||
public class FxAccountAuthenticator extends AbstractAccountAuthenticator {
|
||||
public static final String LOG_TAG = FxAccountAuthenticator.class.getSimpleName();
|
||||
@ -71,7 +69,7 @@ public class FxAccountAuthenticator extends AbstractAccountAuthenticator {
|
||||
return res;
|
||||
}
|
||||
|
||||
Intent intent = new Intent(context, FxAccountGetStartedActivity.class);
|
||||
final Intent intent = new Intent(FxAccountConstants.ACTION_FXA_GET_STARTED);
|
||||
res.putParcelable(AccountManager.KEY_INTENT, intent);
|
||||
return res;
|
||||
}
|
||||
|
@ -4,24 +4,22 @@
|
||||
|
||||
package org.mozilla.gecko.fxa.sync;
|
||||
|
||||
import org.mozilla.gecko.BrowserLocaleManager;
|
||||
import org.mozilla.gecko.R;
|
||||
import org.mozilla.gecko.background.common.log.Logger;
|
||||
import org.mozilla.gecko.background.common.telemetry.TelemetryWrapper;
|
||||
import org.mozilla.gecko.background.fxa.FxAccountUtils;
|
||||
import org.mozilla.gecko.fxa.activities.FxAccountFinishMigratingActivity;
|
||||
import org.mozilla.gecko.fxa.activities.FxAccountStatusActivity;
|
||||
import org.mozilla.gecko.fxa.authenticator.AndroidFxAccount;
|
||||
import org.mozilla.gecko.fxa.login.State;
|
||||
import org.mozilla.gecko.fxa.login.State.Action;
|
||||
import org.mozilla.gecko.sync.telemetry.TelemetryContract;
|
||||
|
||||
import android.app.NotificationManager;
|
||||
import android.app.PendingIntent;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.support.v4.app.NotificationCompat;
|
||||
import android.support.v4.app.NotificationCompat.Builder;
|
||||
import org.mozilla.gecko.BrowserLocaleManager;
|
||||
import org.mozilla.gecko.R;
|
||||
import org.mozilla.gecko.background.common.log.Logger;
|
||||
import org.mozilla.gecko.background.common.telemetry.TelemetryWrapper;
|
||||
import org.mozilla.gecko.background.fxa.FxAccountUtils;
|
||||
import org.mozilla.gecko.fxa.FxAccountConstants;
|
||||
import org.mozilla.gecko.fxa.authenticator.AndroidFxAccount;
|
||||
import org.mozilla.gecko.fxa.login.State;
|
||||
import org.mozilla.gecko.fxa.login.State.Action;
|
||||
import org.mozilla.gecko.sync.telemetry.TelemetryContract;
|
||||
|
||||
/**
|
||||
* Abstraction that manages notifications shown or hidden for a Firefox Account.
|
||||
@ -89,11 +87,11 @@ public class FxAccountNotificationManager {
|
||||
|
||||
title = context.getResources().getString(R.string.fxaccount_sync_finish_migrating_notification_title);
|
||||
text = context.getResources().getString(R.string.fxaccount_sync_finish_migrating_notification_text, state.email);
|
||||
notificationIntent = new Intent(context, FxAccountFinishMigratingActivity.class);
|
||||
notificationIntent = new Intent(FxAccountConstants.ACTION_FXA_FINISH_MIGRATING);
|
||||
} else {
|
||||
title = context.getResources().getString(R.string.fxaccount_sync_sign_in_error_notification_title);
|
||||
text = context.getResources().getString(R.string.fxaccount_sync_sign_in_error_notification_text, state.email);
|
||||
notificationIntent = new Intent(context, FxAccountStatusActivity.class);
|
||||
notificationIntent = new Intent(FxAccountConstants.ACTION_FXA_STATUS);
|
||||
}
|
||||
Logger.info(LOG_TAG, "State " + state.getStateLabel() + " needs action; offering notification with title: " + title);
|
||||
FxAccountUtils.pii(LOG_TAG, "And text: " + text);
|
||||
|
@ -4,22 +4,19 @@
|
||||
|
||||
package org.mozilla.gecko.home;
|
||||
|
||||
import java.util.EnumSet;
|
||||
import java.util.Locale;
|
||||
|
||||
import org.mozilla.gecko.R;
|
||||
import org.mozilla.gecko.fxa.FirefoxAccounts;
|
||||
import org.mozilla.gecko.fxa.activities.FxAccountCreateAccountActivity;
|
||||
import org.mozilla.gecko.fxa.activities.FxAccountFinishMigratingActivity;
|
||||
import org.mozilla.gecko.fxa.activities.FxAccountUpdateCredentialsActivity;
|
||||
import org.mozilla.gecko.home.HomePager.OnUrlOpenListener;
|
||||
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.View.OnClickListener;
|
||||
import android.view.ViewGroup;
|
||||
import org.mozilla.gecko.R;
|
||||
import org.mozilla.gecko.fxa.FirefoxAccounts;
|
||||
import org.mozilla.gecko.fxa.FxAccountConstants;
|
||||
import org.mozilla.gecko.home.HomePager.OnUrlOpenListener;
|
||||
|
||||
import java.util.EnumSet;
|
||||
import java.util.Locale;
|
||||
|
||||
/**
|
||||
* A <code>HomeFragment</code> which displays one of a small set of static views
|
||||
@ -102,8 +99,7 @@ public class RemoteTabsStaticFragment extends HomeFragment implements OnClickLis
|
||||
final int id = v.getId();
|
||||
if (id == R.id.remote_tabs_setup_get_started) {
|
||||
// This Activity will redirect to the correct Activity as needed.
|
||||
final Intent intent = new Intent(getActivity(), FxAccountCreateAccountActivity.class);
|
||||
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||
final Intent intent = new Intent(FxAccountConstants.ACTION_FXA_GET_STARTED);
|
||||
startActivity(intent);
|
||||
} else if (id == R.id.remote_tabs_setup_old_sync_link) {
|
||||
final String url = FirefoxAccounts.getOldSyncUpgradeURL(getResources(), Locale.getDefault());
|
||||
@ -118,11 +114,11 @@ public class RemoteTabsStaticFragment extends HomeFragment implements OnClickLis
|
||||
final EnumSet<OnUrlOpenListener.Flags> flags = EnumSet.noneOf(OnUrlOpenListener.Flags.class);
|
||||
mUrlOpenListener.onUrlOpen(CONFIRM_ACCOUNT_SUPPORT_URL, flags);
|
||||
} else if (id == R.id.remote_tabs_needs_password_sign_in) {
|
||||
final Intent intent = new Intent(getActivity(), FxAccountUpdateCredentialsActivity.class);
|
||||
final Intent intent = new Intent(FxAccountConstants.ACTION_FXA_UPDATE_CREDENTIALS);
|
||||
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||
startActivity(intent);
|
||||
} else if (id == R.id.remote_tabs_needs_finish_migrating_sign_in) {
|
||||
final Intent intent = new Intent(getActivity(), FxAccountFinishMigratingActivity.class);
|
||||
final Intent intent = new Intent(FxAccountConstants.ACTION_FXA_FINISH_MIGRATING);
|
||||
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||
startActivity(intent);
|
||||
}
|
||||
|
@ -145,6 +145,7 @@ if CONFIG['MOZ_WEBRTC']:
|
||||
gbjar = add_java_jar('gecko-browser')
|
||||
gbjar.sources += [
|
||||
'AboutPages.java',
|
||||
'AccountsHelper.java',
|
||||
'ActionModeCompat.java',
|
||||
'ActionModeCompatView.java',
|
||||
'ActivityHandlerHelper.java',
|
||||
|
@ -6,7 +6,6 @@ package org.mozilla.gecko.overlays.service.sharemethods;
|
||||
|
||||
import android.accounts.Account;
|
||||
import android.accounts.AccountManager;
|
||||
import android.app.Activity;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.SharedPreferences;
|
||||
@ -15,7 +14,6 @@ import android.os.Bundle;
|
||||
import android.os.Parcelable;
|
||||
import android.support.v4.content.LocalBroadcastManager;
|
||||
import android.util.Log;
|
||||
|
||||
import org.mozilla.gecko.GeckoProfile;
|
||||
import org.mozilla.gecko.R;
|
||||
import org.mozilla.gecko.db.BrowserDB;
|
||||
@ -23,8 +21,6 @@ import org.mozilla.gecko.db.RemoteClient;
|
||||
import org.mozilla.gecko.db.TabsAccessor;
|
||||
import org.mozilla.gecko.fxa.FirefoxAccounts;
|
||||
import org.mozilla.gecko.fxa.FxAccountConstants;
|
||||
import org.mozilla.gecko.fxa.activities.FxAccountGetStartedActivity;
|
||||
import org.mozilla.gecko.fxa.activities.FxAccountStatusActivity;
|
||||
import org.mozilla.gecko.fxa.authenticator.AndroidFxAccount;
|
||||
import org.mozilla.gecko.fxa.login.State;
|
||||
import org.mozilla.gecko.overlays.OverlayConstants;
|
||||
@ -159,7 +155,7 @@ public class SendTab extends ShareMethod {
|
||||
Log.w(LOGTAG, "Firefox Account named like " + fxAccount.getObfuscatedEmail() +
|
||||
" needs action before it can send a tab; redirecting to status activity.");
|
||||
|
||||
setOverrideIntent(FxAccountStatusActivity.class);
|
||||
setOverrideIntentAction(FxAccountConstants.ACTION_FXA_STATUS);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -184,7 +180,7 @@ public class SendTab extends ShareMethod {
|
||||
}
|
||||
|
||||
// Have registered UIs offer to set up a Firefox Account.
|
||||
setOverrideIntent(FxAccountGetStartedActivity.class);
|
||||
setOverrideIntentAction(FxAccountConstants.ACTION_FXA_GET_STARTED);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -206,7 +202,7 @@ public class SendTab extends ShareMethod {
|
||||
if (validGUIDs.isEmpty()) {
|
||||
// Guess we'd better override. We have no clients.
|
||||
// This does the broadcast for us.
|
||||
setOverrideIntent(FxAccountGetStartedActivity.class);
|
||||
setOverrideIntentAction(FxAccountConstants.ACTION_FXA_GET_STARTED);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -223,10 +219,10 @@ public class SendTab extends ShareMethod {
|
||||
* dispatch this intent instead of attempting to share with this ShareMethod whenever it is
|
||||
* non-null.
|
||||
*
|
||||
* @param activityClass The class of the activity we wish to launch instead of invoking a share.
|
||||
* @param action to launch instead of invoking a share.
|
||||
*/
|
||||
protected void setOverrideIntent(Class<? extends Activity> activityClass) {
|
||||
Intent intent = new Intent(context, activityClass);
|
||||
protected void setOverrideIntentAction(final String action) {
|
||||
Intent intent = new Intent(action);
|
||||
// Per http://stackoverflow.com/a/8992365, this triggers a known bug with
|
||||
// the soft keyboard not being shown for the started activity. Why, Android, why?
|
||||
intent.addFlags(Intent.FLAG_ACTIVITY_NO_ANIMATION);
|
||||
|
@ -5,18 +5,16 @@
|
||||
|
||||
package org.mozilla.gecko.preferences;
|
||||
|
||||
import org.mozilla.gecko.Telemetry;
|
||||
import org.mozilla.gecko.TelemetryContract;
|
||||
import org.mozilla.gecko.TelemetryContract.Method;
|
||||
import org.mozilla.gecko.fxa.activities.FxAccountGetStartedActivity;
|
||||
import org.mozilla.gecko.sync.setup.SyncAccounts;
|
||||
import org.mozilla.gecko.sync.setup.activities.SetupSyncActivity;
|
||||
import org.mozilla.gecko.util.HardwareUtils;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.preference.Preference;
|
||||
import android.util.AttributeSet;
|
||||
import org.mozilla.gecko.Telemetry;
|
||||
import org.mozilla.gecko.TelemetryContract;
|
||||
import org.mozilla.gecko.TelemetryContract.Method;
|
||||
import org.mozilla.gecko.fxa.FxAccountConstants;
|
||||
import org.mozilla.gecko.sync.setup.SyncAccounts;
|
||||
import org.mozilla.gecko.sync.setup.activities.SetupSyncActivity;
|
||||
|
||||
class SyncPreference extends Preference {
|
||||
private static final boolean DEFAULT_TO_FXA = true;
|
||||
@ -41,13 +39,9 @@ class SyncPreference extends Preference {
|
||||
}
|
||||
|
||||
private void launchFxASetup() {
|
||||
Intent intent = new Intent(mContext, FxAccountGetStartedActivity.class);
|
||||
final Intent intent = new Intent(FxAccountConstants.ACTION_FXA_GET_STARTED);
|
||||
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||
|
||||
if (HardwareUtils.IS_KINDLE_DEVICE) {
|
||||
intent.setFlags(Intent.FLAG_ACTIVITY_NO_ANIMATION);
|
||||
}
|
||||
|
||||
intent.setFlags(Intent.FLAG_ACTIVITY_NO_ANIMATION);
|
||||
mContext.startActivity(intent);
|
||||
}
|
||||
|
||||
|
@ -5,6 +5,7 @@
|
||||
|
||||
package org.mozilla.gecko.tabs;
|
||||
|
||||
import org.mozilla.gecko.AppConstants;
|
||||
import org.mozilla.gecko.R;
|
||||
import org.mozilla.gecko.ThumbnailHelper;
|
||||
import org.mozilla.gecko.widget.CropImageView;
|
||||
@ -34,7 +35,11 @@ public class TabsPanelThumbnailView extends CropImageView {
|
||||
|
||||
@Override
|
||||
protected float getAspectRatio() {
|
||||
return ThumbnailHelper.TABS_PANEL_THUMBNAIL_ASPECT_RATIO;
|
||||
if (AppConstants.NIGHTLY_BUILD) {
|
||||
return ThumbnailHelper.TABS_PANEL_THUMBNAIL_ASPECT_RATIO;
|
||||
} else {
|
||||
return ThumbnailHelper.TOP_SITES_THUMBNAIL_ASPECT_RATIO;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -546,6 +546,16 @@ var BrowserApp = {
|
||||
InitLater(() => AccessFu.attach(window), window, "AccessFu");
|
||||
}
|
||||
|
||||
if (!AppConstants.MOZ_ANDROID_NATIVE_ACCOUNT_UI) {
|
||||
// We can't delay registering WebChannel listeners: if the first page is
|
||||
// about:accounts, which can happen when starting the Firefox Account flow
|
||||
// from the first run experience, or via the Firefox Account Status
|
||||
// Activity, we can and do miss messages from the fxa-content-server.
|
||||
console.log("browser.js: loading Firefox Accounts WebChannel");
|
||||
Cu.import("resource://gre/modules/FxAccountsWebChannel.jsm");
|
||||
EnsureFxAccountsWebChannel();
|
||||
}
|
||||
|
||||
// Notify Java that Gecko has loaded.
|
||||
Messaging.sendRequest({ type: "Gecko:Ready" });
|
||||
|
||||
|
@ -117,3 +117,6 @@ MOZ_ADDON_SIGNING=1
|
||||
if test "$NIGHTLY_BUILD"; then
|
||||
MOZ_SWITCHBOARD=1
|
||||
fi
|
||||
|
||||
# Use native Firefox Accounts UI regardless of channel.
|
||||
MOZ_ANDROID_NATIVE_ACCOUNT_UI=1
|
||||
|
16
mobile/android/locales/en-US/chrome/aboutAccounts.properties
Normal file
16
mobile/android/locales/en-US/chrome/aboutAccounts.properties
Normal file
@ -0,0 +1,16 @@
|
||||
# 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/.
|
||||
|
||||
# LOCALIZATION NOTE (relinkDenied.message): Ideally, this string is short (it's
|
||||
# a toast message).
|
||||
relinkDenied.message = Already signed in to Sync!
|
||||
# LOCALIZATION NOTE (relinkDenied.openPrefs): Ideally, this string is short (it's a
|
||||
# button label) and upper-case, to match Google and Android's convention.
|
||||
relinkDenied.openPrefs = PREFS
|
||||
|
||||
relinkVerify.title = Are you sure you want to sign in to Sync?
|
||||
# LOCALIZATION NOTE (relinkVerify.message): Email address of a user previously signed in to Sync.
|
||||
relinkVerify.message = You were previously signed in to Sync with a different email address. Signing in will merge this browser’s bookmarks, passwords and other settings with %S
|
||||
relinkVerify.continue = Continue
|
||||
relinkVerify.cancel = Cancel
|
@ -7,6 +7,9 @@
|
||||
@AB_CD@.jar:
|
||||
% locale browser @AB_CD@ %locale/@AB_CD@/browser/
|
||||
locale/@AB_CD@/browser/about.dtd (%chrome/about.dtd)
|
||||
#ifndef MOZ_ANDROID_NATIVE_ACCOUNT_UI
|
||||
locale/@AB_CD@/browser/aboutAccounts.properties (%chrome/aboutAccounts.properties)
|
||||
#endif
|
||||
locale/@AB_CD@/browser/aboutAddons.dtd (%chrome/aboutAddons.dtd)
|
||||
locale/@AB_CD@/browser/aboutAddons.properties (%chrome/aboutAddons.properties)
|
||||
#ifdef MOZ_DEVICES
|
||||
|
@ -8,9 +8,9 @@ this.EXPORTED_SYMBOLS = ["Accounts"];
|
||||
|
||||
const { utils: Cu } = Components;
|
||||
|
||||
Cu.import("resource://gre/modules/Messaging.jsm");
|
||||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
Cu.import("resource://gre/modules/Promise.jsm");
|
||||
Cu.import("resource://gre/modules/Messaging.jsm"); /*global Messaging */
|
||||
Cu.import("resource://gre/modules/Promise.jsm"); /*global Promise */
|
||||
Cu.import("resource://gre/modules/Services.jsm"); /*global Services */
|
||||
|
||||
/**
|
||||
* A promise-based API for querying the existence of Sync accounts,
|
||||
@ -68,6 +68,19 @@ var Accounts = Object.freeze({
|
||||
});
|
||||
},
|
||||
|
||||
_addDefaultEndpoints: function (json) {
|
||||
let newData = Cu.cloneInto(json, {}, { cloneFunctions: false });
|
||||
let associations = {
|
||||
authServerEndpoint: 'identity.fxaccounts.auth.uri',
|
||||
profileServerEndpoint: 'identity.fxaccounts.remote.profile.uri',
|
||||
tokenServerEndpoint: 'identity.sync.tokenserver.uri'
|
||||
};
|
||||
for (let key in associations) {
|
||||
newData[key] = newData[key] || Services.urlFormatter.formatURLPref(associations[key]);
|
||||
}
|
||||
return newData;
|
||||
},
|
||||
|
||||
/**
|
||||
* Create a new Android Account corresponding to the given
|
||||
* fxa-content-server "login" JSON datum. The new account will be
|
||||
@ -78,9 +91,58 @@ var Accounts = Object.freeze({
|
||||
* Returns a Promise that resolves to a boolean indicating success.
|
||||
*/
|
||||
createFirefoxAccountFromJSON: function (json) {
|
||||
return Messaging.sendRequestForResponse({
|
||||
return Messaging.sendRequestForResult({
|
||||
type: "Accounts:CreateFirefoxAccountFromJSON",
|
||||
json: json
|
||||
json: this._addDefaultEndpoints(json)
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* Move an existing Android Account to the "Engaged" state with the given
|
||||
* fxa-content-server "login" JSON datum. The account will (re)start
|
||||
* syncing immediately, unless the user has manually configured the account
|
||||
* to not Sync.
|
||||
*
|
||||
* It is an error if no Android Account exists.
|
||||
*
|
||||
* Returns a Promise that resolves to a boolean indicating success.
|
||||
*/
|
||||
updateFirefoxAccountFromJSON: function (json) {
|
||||
return Messaging.sendRequestForResult({
|
||||
type: "Accounts:UpdateFirefoxAccountFromJSON",
|
||||
json: this._addDefaultEndpoints(json)
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* Fetch information about an existing Android Firefox Account.
|
||||
*
|
||||
* Returns a Promise that resolves to null if no Android Firefox Account
|
||||
* exists, or an object including at least a string-valued 'email' key.
|
||||
*/
|
||||
getFirefoxAccount: function () {
|
||||
return Messaging.sendRequestForResult({
|
||||
type: "Accounts:Exist",
|
||||
kind: "fxa",
|
||||
}).then(data => {
|
||||
if (!data || !data.exists) {
|
||||
return null;
|
||||
}
|
||||
delete data.exists;
|
||||
return data;
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* Delete an existing Android Firefox Account.
|
||||
*
|
||||
* It is an error if no Android Account exists.
|
||||
*
|
||||
* Returns a Promise that resolves to a boolean indicating success.
|
||||
*/
|
||||
deleteFirefoxAccount: function () {
|
||||
return Messaging.sendRequestForResult({
|
||||
type: "Accounts:DeleteFirefoxAccount",
|
||||
});
|
||||
}
|
||||
});
|
||||
|
368
mobile/android/modules/FxAccountsWebChannel.jsm
Normal file
368
mobile/android/modules/FxAccountsWebChannel.jsm
Normal file
@ -0,0 +1,368 @@
|
||||
// -*- Mode: js2; tab-width: 2; indent-tabs-mode: nil; js2-basic-offset: 2; js2-skip-preprocessor-directives: t; -*-
|
||||
/* 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/. */
|
||||
|
||||
/**
|
||||
* Firefox Accounts Web Channel.
|
||||
*
|
||||
* Use the WebChannel component to receive messages about account
|
||||
* state changes.
|
||||
*/
|
||||
this.EXPORTED_SYMBOLS = ["EnsureFxAccountsWebChannel"];
|
||||
|
||||
const {classes: Cc, interfaces: Ci, utils: Cu, results: Cr} = Components; /*global Components */
|
||||
|
||||
Cu.import("resource://gre/modules/Accounts.jsm"); /*global Accounts */
|
||||
Cu.import("resource://gre/modules/Notifications.jsm"); /*global Notifications */
|
||||
Cu.import("resource://gre/modules/Prompt.jsm"); /*global Prompt */
|
||||
Cu.import("resource://gre/modules/Services.jsm"); /*global Services */
|
||||
Cu.import("resource://gre/modules/WebChannel.jsm"); /*global WebChannel */
|
||||
Cu.import("resource://gre/modules/XPCOMUtils.jsm"); /*global XPCOMUtils */
|
||||
|
||||
const log = Cu.import("resource://gre/modules/AndroidLog.jsm", {}).AndroidLog.bind("FxAccounts");
|
||||
|
||||
const WEBCHANNEL_ID = "account_updates";
|
||||
|
||||
const COMMAND_LOADED = "fxaccounts:loaded";
|
||||
const COMMAND_CAN_LINK_ACCOUNT = "fxaccounts:can_link_account";
|
||||
const COMMAND_LOGIN = "fxaccounts:login";
|
||||
const COMMAND_CHANGE_PASSWORD = "fxaccounts:change_password";
|
||||
const COMMAND_DELETE_ACCOUNT = "fxaccounts:delete_account";
|
||||
|
||||
const PREF_LAST_FXA_USER = "identity.fxaccounts.lastSignedInUserHash";
|
||||
|
||||
XPCOMUtils.defineLazyGetter(this, "strings",
|
||||
() => Services.strings.createBundle("chrome://browser/locale/aboutAccounts.properties")); /*global strings */
|
||||
|
||||
Object.defineProperty(this, "NativeWindow",
|
||||
{ get: () => Services.wm.getMostRecentWindow("navigator:browser").NativeWindow }); /*global NativeWindow */
|
||||
|
||||
this.FxAccountsWebChannelHelpers = function() {
|
||||
};
|
||||
|
||||
this.FxAccountsWebChannelHelpers.prototype = {
|
||||
/**
|
||||
* Get the hash of account name of the previously signed in account.
|
||||
*/
|
||||
getPreviousAccountNameHashPref() {
|
||||
try {
|
||||
return Services.prefs.getComplexValue(PREF_LAST_FXA_USER, Ci.nsISupportsString).data;
|
||||
} catch (_) {
|
||||
return "";
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Given an account name, set the hash of the previously signed in account.
|
||||
*
|
||||
* @param acctName the account name of the user's account.
|
||||
*/
|
||||
setPreviousAccountNameHashPref(acctName) {
|
||||
let string = Cc["@mozilla.org/supports-string;1"]
|
||||
.createInstance(Ci.nsISupportsString);
|
||||
string.data = this.sha256(acctName);
|
||||
Services.prefs.setComplexValue(PREF_LAST_FXA_USER, Ci.nsISupportsString, string);
|
||||
},
|
||||
|
||||
/**
|
||||
* Given a string, returns the SHA265 hash in base64.
|
||||
*/
|
||||
sha256(str) {
|
||||
let converter = Cc["@mozilla.org/intl/scriptableunicodeconverter"]
|
||||
.createInstance(Ci.nsIScriptableUnicodeConverter);
|
||||
converter.charset = "UTF-8";
|
||||
// Data is an array of bytes.
|
||||
let data = converter.convertToByteArray(str, {});
|
||||
let hasher = Cc["@mozilla.org/security/hash;1"]
|
||||
.createInstance(Ci.nsICryptoHash);
|
||||
hasher.init(hasher.SHA256);
|
||||
hasher.update(data, data.length);
|
||||
|
||||
return hasher.finish(true);
|
||||
},
|
||||
};
|
||||
|
||||
/**
|
||||
* Create a new FxAccountsWebChannel to listen for account updates.
|
||||
*
|
||||
* @param {Object} options Options
|
||||
* @param {Object} options
|
||||
* @param {String} options.content_uri
|
||||
* The FxA Content server uri
|
||||
* @param {String} options.channel_id
|
||||
* The ID of the WebChannel
|
||||
* @param {String} options.helpers
|
||||
* Helpers functions. Should only be passed in for testing.
|
||||
* @constructor
|
||||
*/
|
||||
this.FxAccountsWebChannel = function(options) {
|
||||
if (!options) {
|
||||
throw new Error("Missing configuration options");
|
||||
}
|
||||
if (!options["content_uri"]) {
|
||||
throw new Error("Missing 'content_uri' option");
|
||||
}
|
||||
this._contentUri = options.content_uri;
|
||||
|
||||
if (!options["channel_id"]) {
|
||||
throw new Error("Missing 'channel_id' option");
|
||||
}
|
||||
this._webChannelId = options.channel_id;
|
||||
|
||||
// options.helpers is only specified by tests.
|
||||
this._helpers = options.helpers || new FxAccountsWebChannelHelpers(options);
|
||||
|
||||
this._setupChannel();
|
||||
};
|
||||
|
||||
this.FxAccountsWebChannel.prototype = {
|
||||
/**
|
||||
* WebChannel that is used to communicate with content page
|
||||
*/
|
||||
_channel: null,
|
||||
|
||||
/**
|
||||
* WebChannel ID.
|
||||
*/
|
||||
_webChannelId: null,
|
||||
/**
|
||||
* WebChannel origin, used to validate origin of messages
|
||||
*/
|
||||
_webChannelOrigin: null,
|
||||
|
||||
/**
|
||||
* Release all resources that are in use.
|
||||
*/
|
||||
tearDown() {
|
||||
this._channel.stopListening();
|
||||
this._channel = null;
|
||||
this._channelCallback = null;
|
||||
},
|
||||
|
||||
/**
|
||||
* Configures and registers a new WebChannel
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
_setupChannel() {
|
||||
// if this.contentUri is present but not a valid URI, then this will throw an error.
|
||||
try {
|
||||
this._webChannelOrigin = Services.io.newURI(this._contentUri, null, null);
|
||||
this._registerChannel();
|
||||
} catch (e) {
|
||||
log.e(e.toString());
|
||||
throw e;
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Create a new channel with the WebChannelBroker, setup a callback listener
|
||||
* @private
|
||||
*/
|
||||
_registerChannel() {
|
||||
/**
|
||||
* Processes messages that are called back from the FxAccountsChannel
|
||||
*
|
||||
* @param webChannelId {String}
|
||||
* Command webChannelId
|
||||
* @param message {Object}
|
||||
* Command message
|
||||
* @param sendingContext {Object}
|
||||
* Message sending context.
|
||||
* @param sendingContext.browser {browser}
|
||||
* The <browser> object that captured the
|
||||
* WebChannelMessageToChrome.
|
||||
* @param sendingContext.eventTarget {EventTarget}
|
||||
* The <EventTarget> where the message was sent.
|
||||
* @param sendingContext.principal {Principal}
|
||||
* The <Principal> of the EventTarget where the message was sent.
|
||||
* @private
|
||||
*
|
||||
*/
|
||||
let listener = (webChannelId, message, sendingContext) => {
|
||||
if (message) {
|
||||
let command = message.command;
|
||||
let data = message.data;
|
||||
log.d("FxAccountsWebChannel message received, command: " + command);
|
||||
|
||||
// Respond to the message with true or false.
|
||||
let respond = (data) => {
|
||||
let response = {
|
||||
command: command,
|
||||
messageId: message.messageId,
|
||||
data: data
|
||||
};
|
||||
log.d("Sending response to command: " + command);
|
||||
this._channel.send(response, sendingContext);
|
||||
};
|
||||
|
||||
switch (command) {
|
||||
case COMMAND_LOADED:
|
||||
let mm = sendingContext.browser.docShell
|
||||
.QueryInterface(Ci.nsIInterfaceRequestor)
|
||||
.getInterface(Ci.nsIContentFrameMessageManager);
|
||||
mm.sendAsyncMessage(COMMAND_LOADED);
|
||||
break;
|
||||
|
||||
case COMMAND_CAN_LINK_ACCOUNT:
|
||||
Accounts.getFirefoxAccount().then(account => {
|
||||
if (account) {
|
||||
// If we /have/ an Android Account, we never allow the user to
|
||||
// login to a different account. They need to manually delete
|
||||
// the first Android Account and then create a new one.
|
||||
if (account.email == data.email) {
|
||||
// In future, we should use a UID for this comparison.
|
||||
log.d("Relinking existing Android Account: email addresses agree.");
|
||||
respond({ok: true});
|
||||
} else {
|
||||
log.w("Not relinking existing Android Account: email addresses disagree!");
|
||||
let message = strings.GetStringFromName("relinkDenied.message");
|
||||
let buttonLabel = strings.GetStringFromName("relinkDenied.openPrefs");
|
||||
NativeWindow.toast.show(message, "long", {
|
||||
button: {
|
||||
icon: "drawable://switch_button_icon",
|
||||
label: buttonLabel,
|
||||
callback: () => {
|
||||
// We have an account, so this opens Sync native preferences.
|
||||
Accounts.launchSetup();
|
||||
},
|
||||
}
|
||||
});
|
||||
respond({ok: false});
|
||||
}
|
||||
} else {
|
||||
// If we /don't have/ an Android Account, we warn if we're
|
||||
// connecting to a new Account. This is to minimize surprise;
|
||||
// we never did this when changing accounts via the native UI.
|
||||
let prevAcctHash = this._helpers.getPreviousAccountNameHashPref();
|
||||
let shouldShowWarning = prevAcctHash && (prevAcctHash != this._helpers.sha256(data.email));
|
||||
|
||||
if (shouldShowWarning) {
|
||||
log.w("Warning about creating a new Android Account: previously linked to different email address!");
|
||||
let message = strings.formatStringFromName("relinkVerify.message", [data.email], 1);
|
||||
new Prompt({
|
||||
title: strings.GetStringFromName("relinkVerify.title"),
|
||||
message: message,
|
||||
buttons: [
|
||||
// This puts Cancel on the right.
|
||||
strings.GetStringFromName("relinkVerify.cancel"),
|
||||
strings.GetStringFromName("relinkVerify.continue"),
|
||||
],
|
||||
}).show(result => respond({ok: result && result.button == 1}));
|
||||
} else {
|
||||
log.d("Not warning about creating a new Android Account: no previously linked email address.");
|
||||
respond({ok: true});
|
||||
}
|
||||
}
|
||||
}).catch(e => {
|
||||
log.e(e.toString());
|
||||
respond({ok: false});
|
||||
});
|
||||
break;
|
||||
|
||||
case COMMAND_LOGIN:
|
||||
// Either create a new Android Account or re-connect an existing
|
||||
// Android Account here. There's not much to be done if we don't
|
||||
// succeed or get an error.
|
||||
Accounts.getFirefoxAccount().then(account => {
|
||||
if (!account) {
|
||||
return Accounts.createFirefoxAccountFromJSON(data).then(success => {
|
||||
if (!success) {
|
||||
throw new Error("Could not create Firefox Account!");
|
||||
}
|
||||
return success;
|
||||
});
|
||||
} else {
|
||||
return Accounts.updateFirefoxAccountFromJSON(data).then(success => {
|
||||
if (!success) {
|
||||
throw new Error("Could not update Firefox Account!");
|
||||
}
|
||||
return success;
|
||||
});
|
||||
}
|
||||
})
|
||||
.then(success => {
|
||||
if (!success) {
|
||||
throw new Error("Could not create or update Firefox Account!");
|
||||
}
|
||||
|
||||
// Remember who it is so we can show a relink warning when appropriate.
|
||||
this._helpers.setPreviousAccountNameHashPref(data.email);
|
||||
|
||||
log.i("Created or updated Firefox Account.");
|
||||
})
|
||||
.catch(e => {
|
||||
log.e(e.toString());
|
||||
});
|
||||
break;
|
||||
|
||||
case COMMAND_CHANGE_PASSWORD:
|
||||
// Only update an existing Android Account.
|
||||
Accounts.getFirefoxAccount().then(account => {
|
||||
if (!account) {
|
||||
throw new Error("Can't change password of non-existent Firefox Account!");
|
||||
}
|
||||
return Accounts.updateFirefoxAccountFromJSON(data);
|
||||
})
|
||||
.then(success => {
|
||||
if (!success) {
|
||||
throw new Error("Could not change Firefox Account password!");
|
||||
}
|
||||
log.i("Changed Firefox Account password.");
|
||||
})
|
||||
.catch(e => {
|
||||
log.e(e.toString());
|
||||
});
|
||||
break;
|
||||
|
||||
case COMMAND_DELETE_ACCOUNT:
|
||||
// The fxa-content-server has already confirmed the user's intent.
|
||||
// Bombs away. There's no recovery from failure, and not even a
|
||||
// real need to check an account exists (although we do, for error
|
||||
// messaging only).
|
||||
Accounts.getFirefoxAccount().then(account => {
|
||||
if (!account) {
|
||||
throw new Error("Can't delete non-existent Firefox Account!");
|
||||
}
|
||||
return Accounts.deleteFirefoxAccount().then(success => {
|
||||
if (!success) {
|
||||
throw new Error("Could not delete Firefox Account!");
|
||||
}
|
||||
log.i("Firefox Account deleted.");
|
||||
});
|
||||
}).catch(e => {
|
||||
log.e(e.toString());
|
||||
});
|
||||
break;
|
||||
|
||||
default:
|
||||
log.w("Ignoring unrecognized FxAccountsWebChannel command: " + JSON.stringify(command));
|
||||
break;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
this._channelCallback = listener;
|
||||
this._channel = new WebChannel(this._webChannelId, this._webChannelOrigin);
|
||||
this._channel.listen(listener);
|
||||
|
||||
log.d("FxAccountsWebChannel registered: " + this._webChannelId + " with origin " + this._webChannelOrigin.prePath);
|
||||
}
|
||||
};
|
||||
|
||||
let singleton;
|
||||
// The entry-point for this module, which ensures only one of our channels is
|
||||
// ever created - we require this because the WebChannel is global in scope and
|
||||
// allowing multiple channels would cause such notifications to be sent multiple
|
||||
// times.
|
||||
this.EnsureFxAccountsWebChannel = function() {
|
||||
if (!singleton) {
|
||||
let contentUri = Services.urlFormatter.formatURLPref("identity.fxaccounts.remote.webchannel.uri");
|
||||
// The FxAccountsWebChannel listens for events and updates the Java layer.
|
||||
singleton = new this.FxAccountsWebChannel({
|
||||
content_uri: contentUri,
|
||||
channel_id: WEBCHANNEL_ID,
|
||||
});
|
||||
}
|
||||
};
|
@ -11,6 +11,7 @@ EXTRA_JS_MODULES += [
|
||||
'dbg-browser-actors.js',
|
||||
'DelayedInit.jsm',
|
||||
'DownloadNotifications.jsm',
|
||||
'FxAccountsWebChannel.jsm',
|
||||
'HelperApps.jsm',
|
||||
'Home.jsm',
|
||||
'HomeProvider.jsm',
|
||||
|
@ -12,6 +12,10 @@
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
<!-- <category android:name="android.intent.category.LAUNCHER" /> -->
|
||||
</intent-filter>
|
||||
<intent-filter>
|
||||
<action android:name="@ANDROID_PACKAGE_NAME@.ACTION_FXA_STATUS"/>
|
||||
<category android:name="android.intent.category.DEFAULT"/>
|
||||
</intent-filter>
|
||||
</activity>
|
||||
|
||||
<activity
|
||||
@ -28,6 +32,12 @@
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
<!-- <category android:name="android.intent.category.LAUNCHER" /> -->
|
||||
</intent-filter>
|
||||
#ifdef MOZ_ANDROID_NATIVE_ACCOUNT_UI
|
||||
<intent-filter>
|
||||
<action android:name="@ANDROID_PACKAGE_NAME@.ACTION_FXA_GET_STARTED"/>
|
||||
<category android:name="android.intent.category.DEFAULT"/>
|
||||
</intent-filter>
|
||||
#endif
|
||||
</activity>
|
||||
|
||||
<activity
|
||||
@ -43,6 +53,12 @@
|
||||
android:configChanges="locale|layoutDirection"
|
||||
android:noHistory="true"
|
||||
android:windowSoftInputMode="adjustResize">
|
||||
#ifdef MOZ_ANDROID_NATIVE_ACCOUNT_UI
|
||||
<intent-filter>
|
||||
<action android:name="@ANDROID_PACKAGE_NAME@.ACTION_FXA_CONFIRM_ACCOUNT"/>
|
||||
<category android:name="android.intent.category.DEFAULT"/>
|
||||
</intent-filter>
|
||||
#endif
|
||||
</activity>
|
||||
|
||||
<activity
|
||||
@ -65,6 +81,12 @@
|
||||
android:name="org.mozilla.gecko.fxa.activities.FxAccountUpdateCredentialsActivity"
|
||||
android:configChanges="locale|layoutDirection"
|
||||
android:windowSoftInputMode="adjustResize">
|
||||
#ifdef MOZ_ANDROID_NATIVE_ACCOUNT_UI
|
||||
<intent-filter>
|
||||
<action android:name="@ANDROID_PACKAGE_NAME@.ACTION_FXA_UPDATE_CREDENTIALS"/>
|
||||
<category android:name="android.intent.category.DEFAULT"/>
|
||||
</intent-filter>
|
||||
#endif
|
||||
</activity>
|
||||
|
||||
<activity
|
||||
@ -72,6 +94,12 @@
|
||||
android:name="org.mozilla.gecko.fxa.activities.FxAccountFinishMigratingActivity"
|
||||
android:configChanges="locale|layoutDirection"
|
||||
android:windowSoftInputMode="adjustResize">
|
||||
#ifdef MOZ_ANDROID_NATIVE_ACCOUNT_UI
|
||||
<intent-filter>
|
||||
<action android:name="@ANDROID_PACKAGE_NAME@.ACTION_FXA_FINISH_MIGRATING"/>
|
||||
<category android:name="android.intent.category.DEFAULT"/>
|
||||
</intent-filter>
|
||||
#endif
|
||||
</activity>
|
||||
|
||||
<activity
|
||||
@ -105,3 +133,41 @@
|
||||
<data android:scheme="package"/>
|
||||
</intent-filter>
|
||||
</receiver>
|
||||
|
||||
#ifndef MOZ_ANDROID_NATIVE_ACCOUNT_UI
|
||||
<activity
|
||||
android:exported="false"
|
||||
android:name="org.mozilla.gecko.fxa.activities.FxAccountGetStartedActivityWeb">
|
||||
<intent-filter>
|
||||
<action android:name="@ANDROID_PACKAGE_NAME@.ACTION_FXA_GET_STARTED"/>
|
||||
<category android:name="android.intent.category.DEFAULT"/>
|
||||
</intent-filter>
|
||||
</activity>
|
||||
|
||||
<activity
|
||||
android:exported="false"
|
||||
android:name="org.mozilla.gecko.fxa.activities.FxAccountUpdateCredentialsActivityWeb">
|
||||
<intent-filter>
|
||||
<action android:name="@ANDROID_PACKAGE_NAME@.ACTION_FXA_UPDATE_CREDENTIALS"/>
|
||||
<category android:name="android.intent.category.DEFAULT"/>
|
||||
</intent-filter>
|
||||
</activity>
|
||||
|
||||
<activity
|
||||
android:exported="false"
|
||||
android:name="org.mozilla.gecko.fxa.activities.FxAccountFinishMigratingActivityWeb">
|
||||
<intent-filter>
|
||||
<action android:name="@ANDROID_PACKAGE_NAME@.ACTION_FXA_FINISH_MIGRATING"/>
|
||||
<category android:name="android.intent.category.DEFAULT"/>
|
||||
</intent-filter>
|
||||
</activity>
|
||||
|
||||
<activity
|
||||
android:exported="false"
|
||||
android:name="org.mozilla.gecko.fxa.activities.FxAccountConfirmAccountActivityWeb">
|
||||
<intent-filter>
|
||||
<action android:name="@ANDROID_PACKAGE_NAME@.ACTION_FXA_CONFIRM_ACCOUNT"/>
|
||||
<category android:name="android.intent.category.DEFAULT"/>
|
||||
</intent-filter>
|
||||
</activity>
|
||||
#endif
|
||||
|
@ -2074,57 +2074,54 @@ Engine.prototype = {
|
||||
case "https":
|
||||
case "ftp":
|
||||
// No use downloading the icon if the engine file is read-only
|
||||
if (!this._readOnly ||
|
||||
getBoolPref(BROWSER_SEARCH_PREF + "cache.enabled", true)) {
|
||||
LOG("_setIcon: Downloading icon: \"" + uri.spec +
|
||||
"\" for engine: \"" + this.name + "\"");
|
||||
var chan = NetUtil.ioService.newChannelFromURI2(uri,
|
||||
null, // aLoadingNode
|
||||
Services.scriptSecurityManager.getSystemPrincipal(),
|
||||
null, // aTriggeringPrincipal
|
||||
Ci.nsILoadInfo.SEC_NORMAL,
|
||||
Ci.nsIContentPolicy.TYPE_IMAGE);
|
||||
LOG("_setIcon: Downloading icon: \"" + uri.spec +
|
||||
"\" for engine: \"" + this.name + "\"");
|
||||
var chan = NetUtil.ioService.newChannelFromURI2(uri,
|
||||
null, // aLoadingNode
|
||||
Services.scriptSecurityManager.getSystemPrincipal(),
|
||||
null, // aTriggeringPrincipal
|
||||
Ci.nsILoadInfo.SEC_NORMAL,
|
||||
Ci.nsIContentPolicy.TYPE_IMAGE);
|
||||
|
||||
let iconLoadCallback = function (aByteArray, aEngine) {
|
||||
// This callback may run after we've already set a preferred icon,
|
||||
// so check again.
|
||||
if (aEngine._hasPreferredIcon && !aIsPreferred)
|
||||
return;
|
||||
let iconLoadCallback = function (aByteArray, aEngine) {
|
||||
// This callback may run after we've already set a preferred icon,
|
||||
// so check again.
|
||||
if (aEngine._hasPreferredIcon && !aIsPreferred)
|
||||
return;
|
||||
|
||||
if (!aByteArray || aByteArray.length > MAX_ICON_SIZE) {
|
||||
LOG("iconLoadCallback: load failed, or the icon was too large!");
|
||||
return;
|
||||
}
|
||||
|
||||
var str = btoa(String.fromCharCode.apply(null, aByteArray));
|
||||
let dataURL = ICON_DATAURL_PREFIX + str;
|
||||
aEngine._iconURI = makeURI(dataURL);
|
||||
|
||||
if (aWidth && aHeight) {
|
||||
aEngine._addIconToMap(aWidth, aHeight, dataURL)
|
||||
}
|
||||
|
||||
// The engine might not have a file yet, if it's being downloaded,
|
||||
// because the request for the engine file itself (_onLoad) may not
|
||||
// yet be complete. In that case, this change will be written to
|
||||
// file when _onLoad is called. For readonly engines, we'll store
|
||||
// the changes in the cache once notified below.
|
||||
if (aEngine._file && !aEngine._readOnly)
|
||||
aEngine._serializeToFile();
|
||||
|
||||
notifyAction(aEngine, SEARCH_ENGINE_CHANGED);
|
||||
aEngine._hasPreferredIcon = aIsPreferred;
|
||||
if (!aByteArray || aByteArray.length > MAX_ICON_SIZE) {
|
||||
LOG("iconLoadCallback: load failed, or the icon was too large!");
|
||||
return;
|
||||
}
|
||||
|
||||
// If we're currently acting as an "update engine", then the callback
|
||||
// should set the icon on the engine we're updating and not us, since
|
||||
// |this| might be gone by the time the callback runs.
|
||||
var engineToSet = this._engineToUpdate || this;
|
||||
var str = btoa(String.fromCharCode.apply(null, aByteArray));
|
||||
let dataURL = ICON_DATAURL_PREFIX + str;
|
||||
aEngine._iconURI = makeURI(dataURL);
|
||||
|
||||
var listener = new loadListener(chan, engineToSet, iconLoadCallback);
|
||||
chan.notificationCallbacks = listener;
|
||||
chan.asyncOpen(listener, null);
|
||||
if (aWidth && aHeight) {
|
||||
aEngine._addIconToMap(aWidth, aHeight, dataURL)
|
||||
}
|
||||
|
||||
// The engine might not have a file yet, if it's being downloaded,
|
||||
// because the request for the engine file itself (_onLoad) may not
|
||||
// yet be complete. In that case, this change will be written to
|
||||
// file when _onLoad is called. For readonly engines, we'll store
|
||||
// the changes in the cache once notified below.
|
||||
if (aEngine._file && !aEngine._readOnly)
|
||||
aEngine._serializeToFile();
|
||||
|
||||
notifyAction(aEngine, SEARCH_ENGINE_CHANGED);
|
||||
aEngine._hasPreferredIcon = aIsPreferred;
|
||||
}
|
||||
|
||||
// If we're currently acting as an "update engine", then the callback
|
||||
// should set the icon on the engine we're updating and not us, since
|
||||
// |this| might be gone by the time the callback runs.
|
||||
var engineToSet = this._engineToUpdate || this;
|
||||
|
||||
var listener = new loadListener(chan, engineToSet, iconLoadCallback);
|
||||
chan.notificationCallbacks = listener;
|
||||
chan.asyncOpen(listener, null);
|
||||
break;
|
||||
}
|
||||
},
|
||||
@ -3614,9 +3611,6 @@ SearchService.prototype = {
|
||||
},
|
||||
|
||||
_buildCache: function SRCH_SVC__buildCache() {
|
||||
if (!getBoolPref(BROWSER_SEARCH_PREF + "cache.enabled", true))
|
||||
return;
|
||||
|
||||
TelemetryStopwatch.start("SEARCH_SERVICE_BUILD_CACHE_MS");
|
||||
let cache = {};
|
||||
let locale = getLocale();
|
||||
@ -3697,13 +3691,10 @@ SearchService.prototype = {
|
||||
LOG("_syncLoadEngines: start");
|
||||
// See if we have a cache file so we don't have to parse a bunch of XML.
|
||||
let cache = {};
|
||||
let cacheEnabled = getBoolPref(BROWSER_SEARCH_PREF + "cache.enabled", true);
|
||||
if (cacheEnabled) {
|
||||
let cacheFile = getDir(NS_APP_USER_PROFILE_50_DIR);
|
||||
cacheFile.append("search.json");
|
||||
if (cacheFile.exists())
|
||||
cache = this._readCacheFile(cacheFile);
|
||||
}
|
||||
let cacheFile = getDir(NS_APP_USER_PROFILE_50_DIR);
|
||||
cacheFile.append("search.json");
|
||||
if (cacheFile.exists())
|
||||
cache = this._readCacheFile(cacheFile);
|
||||
|
||||
let [chromeFiles, chromeURIs] = this._findJAREngines();
|
||||
|
||||
@ -3756,7 +3747,7 @@ SearchService.prototype = {
|
||||
this._visibleDefaultEngines.some(notInCacheVisibleEngines) ||
|
||||
toLoad.some(modifiedDir);
|
||||
|
||||
if (!cacheEnabled || rebuildCache) {
|
||||
if (rebuildCache) {
|
||||
LOG("_loadEngines: Absent or outdated cache. Loading engines from disk.");
|
||||
distDirs.forEach(this._loadEnginesFromDir, this);
|
||||
|
||||
@ -3764,8 +3755,7 @@ SearchService.prototype = {
|
||||
|
||||
otherDirs.forEach(this._loadEnginesFromDir, this);
|
||||
|
||||
if (cacheEnabled)
|
||||
this._buildCache();
|
||||
this._buildCache();
|
||||
return;
|
||||
}
|
||||
|
||||
@ -3787,11 +3777,8 @@ SearchService.prototype = {
|
||||
LOG("_asyncLoadEngines: start");
|
||||
// See if we have a cache file so we don't have to parse a bunch of XML.
|
||||
let cache = {};
|
||||
let cacheEnabled = getBoolPref(BROWSER_SEARCH_PREF + "cache.enabled", true);
|
||||
if (cacheEnabled) {
|
||||
let cacheFilePath = OS.Path.join(OS.Constants.Path.profileDir, "search.json");
|
||||
cache = yield checkForSyncCompletion(this._asyncReadCacheFile(cacheFilePath));
|
||||
}
|
||||
let cacheFilePath = OS.Path.join(OS.Constants.Path.profileDir, "search.json");
|
||||
cache = yield checkForSyncCompletion(this._asyncReadCacheFile(cacheFilePath));
|
||||
|
||||
Services.obs.notifyObservers(null, SEARCH_SERVICE_TOPIC, "find-jar-engines");
|
||||
let [chromeFiles, chromeURIs] =
|
||||
@ -3882,7 +3869,7 @@ SearchService.prototype = {
|
||||
this._visibleDefaultEngines.some(notInCacheVisibleEngines) ||
|
||||
(yield checkForSyncCompletion(hasModifiedDir(toLoad)));
|
||||
|
||||
if (!cacheEnabled || rebuildCache) {
|
||||
if (rebuildCache) {
|
||||
LOG("_asyncLoadEngines: Absent or outdated cache. Loading engines from disk.");
|
||||
let engines = [];
|
||||
for (let loadDir of distDirs) {
|
||||
@ -3902,8 +3889,7 @@ SearchService.prototype = {
|
||||
for (let engine of engines) {
|
||||
this._addEngineToStore(engine);
|
||||
}
|
||||
if (cacheEnabled)
|
||||
this._buildCache();
|
||||
this._buildCache();
|
||||
return;
|
||||
}
|
||||
|
||||
@ -5545,12 +5531,6 @@ var engineUpdateService = {
|
||||
if (!getBoolPref(BROWSER_SEARCH_PREF + "update", true) || !engine._hasUpdates)
|
||||
return;
|
||||
|
||||
// We use the cache to store updated app engines, so refuse to update if the
|
||||
// cache is disabled.
|
||||
if (engine._readOnly &&
|
||||
!getBoolPref(BROWSER_SEARCH_PREF + "cache.enabled", true))
|
||||
return;
|
||||
|
||||
let testEngine = null;
|
||||
let updateURL = engine._getURLOfType(URLTYPE_OPENSEARCH);
|
||||
let updateURI = (updateURL && updateURL._hasRelation("self")) ?
|
||||
|
@ -7352,6 +7352,24 @@
|
||||
"n_buckets": 20,
|
||||
"description": "The amount of time spent in a specific performance tool view, keyed by view name (waterfall, js-calltree, js-flamegraph, etc)."
|
||||
},
|
||||
"VIEW_SOURCE_IN_BROWSER_OPENED_BOOLEAN": {
|
||||
"alert_emails": ["mozilla-dev-developer-tools@lists.mozilla.org", "jryans@mozilla.com"],
|
||||
"expires_in_version": "53",
|
||||
"kind": "boolean",
|
||||
"description": "How many times has view source in browser / tab been opened?"
|
||||
},
|
||||
"VIEW_SOURCE_IN_WINDOW_OPENED_BOOLEAN": {
|
||||
"alert_emails": ["mozilla-dev-developer-tools@lists.mozilla.org", "jryans@mozilla.com"],
|
||||
"expires_in_version": "53",
|
||||
"kind": "boolean",
|
||||
"description": "How many times has view source in a new window been opened?"
|
||||
},
|
||||
"VIEW_SOURCE_EXTERNAL_RESULT_BOOLEAN": {
|
||||
"alert_emails": ["mozilla-dev-developer-tools@lists.mozilla.org", "jryans@mozilla.com"],
|
||||
"expires_in_version": "53",
|
||||
"kind": "boolean",
|
||||
"description": "How many times has view source in an external editor been opened, and did it succeed?"
|
||||
},
|
||||
"BROWSER_IS_USER_DEFAULT": {
|
||||
"expires_in_version": "never",
|
||||
"kind": "boolean",
|
||||
@ -8755,21 +8773,21 @@
|
||||
"description": "Reports results from the graphics sanity test to track which drivers are having problems (0=TEST_PASSED, 1=TEST_FAILED_RENDER, 2=TEST_FAILED_VIDEO, 3=TEST_CRASHED)"
|
||||
},
|
||||
"READER_MODE_SERIALIZE_DOM_MS": {
|
||||
"expires_in_version": "42",
|
||||
"expires_in_version": "50",
|
||||
"kind": "exponential",
|
||||
"high": "5000",
|
||||
"n_buckets": 15,
|
||||
"description": "Time (ms) to serialize a DOM to send to the reader worker"
|
||||
},
|
||||
"READER_MODE_WORKER_PARSE_MS": {
|
||||
"expires_in_version": "42",
|
||||
"expires_in_version": "50",
|
||||
"kind": "exponential",
|
||||
"high": "10000",
|
||||
"n_buckets": 30,
|
||||
"description": "Time (ms) for the reader worker to parse a document"
|
||||
},
|
||||
"READER_MODE_DOWNLOAD_MS": {
|
||||
"expires_in_version": "42",
|
||||
"expires_in_version": "50",
|
||||
"kind": "exponential",
|
||||
"low": 50,
|
||||
"high": "40000",
|
||||
@ -8777,13 +8795,13 @@
|
||||
"description": "Time (ms) to download a document to show in reader mode"
|
||||
},
|
||||
"READER_MODE_PARSE_RESULT" : {
|
||||
"expires_in_version": "42",
|
||||
"expires_in_version": "50",
|
||||
"kind": "enumerated",
|
||||
"n_values": 5,
|
||||
"description": "The result of trying to parse a document to show in reader view (0=Success, 1=Error too many elements, 2=Error in worker, 3=Error no article)"
|
||||
},
|
||||
"READER_MODE_DOWNLOAD_RESULT" : {
|
||||
"expires_in_version": "42",
|
||||
"expires_in_version": "50",
|
||||
"kind": "enumerated",
|
||||
"n_values": 5,
|
||||
"description": "The result of trying to download a document to show in reader view (0=Success, 1=Error XHR, 2=Error no document)"
|
||||
|
@ -88,6 +88,9 @@ var gViewSourceUtils = {
|
||||
* The line number to focus on once the source is loaded.
|
||||
*/
|
||||
viewSourceInBrowser: function(aArgs) {
|
||||
Services.telemetry
|
||||
.getHistogramById("VIEW_SOURCE_IN_BROWSER_OPENED_BOOLEAN")
|
||||
.add(true);
|
||||
let viewSourceBrowser = new ViewSourceBrowser(aArgs.viewSourceBrowser);
|
||||
viewSourceBrowser.loadViewSource(aArgs);
|
||||
},
|
||||
@ -156,6 +159,9 @@ var gViewSourceUtils = {
|
||||
} catch (ex) {
|
||||
}
|
||||
}
|
||||
Services.telemetry
|
||||
.getHistogramById("VIEW_SOURCE_IN_WINDOW_OPENED_BOOLEAN")
|
||||
.add(true);
|
||||
openDialog("chrome://global/content/viewSource.xul",
|
||||
"_blank",
|
||||
"all,dialog=no",
|
||||
@ -340,7 +346,10 @@ var gViewSourceUtils = {
|
||||
// Calls the callback, keeping in mind undefined or null values.
|
||||
handleCallBack: function(aCallBack, result, data)
|
||||
{
|
||||
// ifcallback is undefined, default to the internal viewer
|
||||
Services.telemetry
|
||||
.getHistogramById("VIEW_SOURCE_EXTERNAL_RESULT_BOOLEAN")
|
||||
.add(result);
|
||||
// if callback is undefined, default to the internal viewer
|
||||
if (aCallBack === undefined) {
|
||||
this.internalViewerFallback(result, data);
|
||||
} else if (aCallBack) {
|
||||
|
@ -39,6 +39,8 @@ function* check_installed(inProfile, ...versions) {
|
||||
do_check_eq(addon.version, versions[i]);
|
||||
do_check_true(addon.isActive);
|
||||
do_check_false(addon.foreignInstall);
|
||||
do_check_false(hasFlag(addon.permissions, AddonManager.PERM_CAN_UPGRADE));
|
||||
do_check_false(hasFlag(addon.permissions, AddonManager.PERM_CAN_UNINSTALL));
|
||||
|
||||
// Verify the add-ons file is in the right place
|
||||
let file = expectedDir.clone();
|
||||
|
Loading…
Reference in New Issue
Block a user