mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-14 05:45:37 +00:00
Merge mozilla-central and b2g-inbound
This commit is contained in:
commit
b2932bde56
@ -992,8 +992,8 @@ pref("browser.autofocus", false);
|
||||
// Enable wakelock
|
||||
pref("dom.wakelock.enabled", true);
|
||||
|
||||
// Disable touch caret by default
|
||||
pref("touchcaret.enabled", false);
|
||||
// Enable touch caret by default
|
||||
pref("touchcaret.enabled", true);
|
||||
|
||||
// Disable selection caret by default
|
||||
pref("selectioncaret.enabled", false);
|
||||
|
251
b2g/chrome/content/devtools/adb.js
Normal file
251
b2g/chrome/content/devtools/adb.js
Normal file
@ -0,0 +1,251 @@
|
||||
/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- /
|
||||
/* vim: set shiftwidth=2 tabstop=2 autoindent cindent expandtab: */
|
||||
/* 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/. */
|
||||
|
||||
"use strict";
|
||||
|
||||
// This file is only loaded on Gonk to manage ADB state
|
||||
|
||||
let AdbController = {
|
||||
DEBUG: false,
|
||||
locked: undefined,
|
||||
remoteDebuggerEnabled: undefined,
|
||||
lockEnabled: undefined,
|
||||
disableAdbTimer: null,
|
||||
disableAdbTimeoutHours: 12,
|
||||
umsActive: false,
|
||||
|
||||
debug: function(str) {
|
||||
dump("AdbController: " + str + "\n");
|
||||
},
|
||||
|
||||
setLockscreenEnabled: function(value) {
|
||||
this.lockEnabled = value;
|
||||
if (this.DEBUG) {
|
||||
this.debug("setLockscreenEnabled = " + this.lockEnabled);
|
||||
}
|
||||
this.updateState();
|
||||
},
|
||||
|
||||
setLockscreenState: function(value) {
|
||||
this.locked = value;
|
||||
if (this.DEBUG) {
|
||||
this.debug("setLockscreenState = " + this.locked);
|
||||
}
|
||||
this.updateState();
|
||||
},
|
||||
|
||||
setRemoteDebuggerState: function(value) {
|
||||
this.remoteDebuggerEnabled = value;
|
||||
if (this.DEBUG) {
|
||||
this.debug("setRemoteDebuggerState = " + this.remoteDebuggerEnabled);
|
||||
}
|
||||
this.updateState();
|
||||
},
|
||||
|
||||
startDisableAdbTimer: function() {
|
||||
if (this.disableAdbTimer) {
|
||||
this.disableAdbTimer.cancel();
|
||||
} else {
|
||||
this.disableAdbTimer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer);
|
||||
try {
|
||||
this.disableAdbTimeoutHours =
|
||||
Services.prefs.getIntPref("b2g.adb.timeout-hours");
|
||||
} catch (e) {
|
||||
// This happens if the pref doesn't exist, in which case
|
||||
// disableAdbTimeoutHours will still be set to the default.
|
||||
}
|
||||
}
|
||||
if (this.disableAdbTimeoutHours <= 0) {
|
||||
if (this.DEBUG) {
|
||||
this.debug("Timer to disable ADB not started due to zero timeout");
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (this.DEBUG) {
|
||||
this.debug("Starting timer to disable ADB in " +
|
||||
this.disableAdbTimeoutHours + " hours");
|
||||
}
|
||||
let timeoutMilliseconds = this.disableAdbTimeoutHours * 60 * 60 * 1000;
|
||||
this.disableAdbTimer.initWithCallback(this, timeoutMilliseconds,
|
||||
Ci.nsITimer.TYPE_ONE_SHOT);
|
||||
},
|
||||
|
||||
stopDisableAdbTimer: function() {
|
||||
if (this.DEBUG) {
|
||||
this.debug("Stopping timer to disable ADB");
|
||||
}
|
||||
if (this.disableAdbTimer) {
|
||||
this.disableAdbTimer.cancel();
|
||||
this.disableAdbTimer = null;
|
||||
}
|
||||
},
|
||||
|
||||
notify: function(aTimer) {
|
||||
if (aTimer == this.disableAdbTimer) {
|
||||
this.disableAdbTimer = null;
|
||||
// The following dump will be the last thing that shows up in logcat,
|
||||
// and will at least give the user a clue about why logcat was
|
||||
// disconnected, if the user happens to be using logcat.
|
||||
dump("AdbController: ADB timer expired - disabling ADB\n");
|
||||
navigator.mozSettings.createLock().set(
|
||||
{'debugger.remote-mode': 'disabled'});
|
||||
}
|
||||
},
|
||||
|
||||
updateState: function() {
|
||||
this.umsActive = false;
|
||||
this.storages = navigator.getDeviceStorages('sdcard');
|
||||
this.updateStorageState(0);
|
||||
},
|
||||
|
||||
updateStorageState: function(storageIndex) {
|
||||
if (storageIndex >= this.storages.length) {
|
||||
// We've iterated through all of the storage objects, now we can
|
||||
// really do updateStateInternal.
|
||||
this.updateStateInternal();
|
||||
return;
|
||||
}
|
||||
let storage = this.storages[storageIndex];
|
||||
if (this.DEBUG) {
|
||||
this.debug("Checking availability of storage: '" +
|
||||
storage.storageName);
|
||||
}
|
||||
|
||||
let req = storage.available();
|
||||
req.onsuccess = function(e) {
|
||||
if (this.DEBUG) {
|
||||
this.debug("Storage: '" + storage.storageName + "' is '" +
|
||||
e.target.result);
|
||||
}
|
||||
if (e.target.result == 'shared') {
|
||||
// We've found a storage area that's being shared with the PC.
|
||||
// We can stop looking now.
|
||||
this.umsActive = true;
|
||||
this.updateStateInternal();
|
||||
return;
|
||||
}
|
||||
this.updateStorageState(storageIndex + 1);
|
||||
}.bind(this);
|
||||
req.onerror = function(e) {
|
||||
dump("AdbController: error querying storage availability for '" +
|
||||
this.storages[storageIndex].storageName + "' (ignoring)\n");
|
||||
this.updateStorageState(storageIndex + 1);
|
||||
}.bind(this);
|
||||
},
|
||||
|
||||
updateStateInternal: function() {
|
||||
if (this.DEBUG) {
|
||||
this.debug("updateStateInternal: called");
|
||||
}
|
||||
|
||||
if (this.remoteDebuggerEnabled === undefined ||
|
||||
this.lockEnabled === undefined ||
|
||||
this.locked === undefined) {
|
||||
// Part of initializing the settings database will cause the observers
|
||||
// to trigger. We want to wait until both have been initialized before
|
||||
// we start changing ther adb state. Without this then we can wind up
|
||||
// toggling adb off and back on again (or on and back off again).
|
||||
//
|
||||
// For completeness, one scenario which toggles adb is using the unagi.
|
||||
// The unagi has adb enabled by default (prior to b2g starting). If you
|
||||
// have the phone lock disabled and remote debugging enabled, then we'll
|
||||
// receive an unlock event and an rde event. However at the time we
|
||||
// receive the unlock event we haven't yet received the rde event, so
|
||||
// we turn adb off momentarily, which disconnects a logcat that might
|
||||
// be running. Changing the defaults (in AdbController) just moves the
|
||||
// problem to a different phone, which has adb disabled by default and
|
||||
// we wind up turning on adb for a short period when we shouldn't.
|
||||
//
|
||||
// By waiting until both values are properly initialized, we avoid
|
||||
// turning adb on or off accidentally.
|
||||
if (this.DEBUG) {
|
||||
this.debug("updateState: Waiting for all vars to be initialized");
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// Check if we have a remote debugging session going on. If so, we won't
|
||||
// disable adb even if the screen is locked.
|
||||
let isDebugging = USBRemoteDebugger.isDebugging;
|
||||
if (this.DEBUG) {
|
||||
this.debug("isDebugging=" + isDebugging);
|
||||
}
|
||||
|
||||
// If USB Mass Storage, USB tethering, or a debug session is active,
|
||||
// then we don't want to disable adb in an automatic fashion (i.e.
|
||||
// when the screen locks or due to timeout).
|
||||
let sysUsbConfig = libcutils.property_get("sys.usb.config");
|
||||
let rndisActive = (sysUsbConfig.split(",").indexOf("rndis") >= 0);
|
||||
let usbFuncActive = rndisActive || this.umsActive || isDebugging;
|
||||
|
||||
let enableAdb = this.remoteDebuggerEnabled &&
|
||||
(!(this.lockEnabled && this.locked) || usbFuncActive);
|
||||
|
||||
let useDisableAdbTimer = true;
|
||||
try {
|
||||
if (Services.prefs.getBoolPref("marionette.defaultPrefs.enabled")) {
|
||||
// Marionette is enabled. Marionette requires that adb be on (and also
|
||||
// requires that remote debugging be off). The fact that marionette
|
||||
// is enabled also implies that we're doing a non-production build, so
|
||||
// we want adb enabled all of the time.
|
||||
enableAdb = true;
|
||||
useDisableAdbTimer = false;
|
||||
}
|
||||
} catch (e) {
|
||||
// This means that the pref doesn't exist. Which is fine. We just leave
|
||||
// enableAdb alone.
|
||||
}
|
||||
if (this.DEBUG) {
|
||||
this.debug("updateState: enableAdb = " + enableAdb +
|
||||
" remoteDebuggerEnabled = " + this.remoteDebuggerEnabled +
|
||||
" lockEnabled = " + this.lockEnabled +
|
||||
" locked = " + this.locked +
|
||||
" usbFuncActive = " + usbFuncActive);
|
||||
}
|
||||
|
||||
// Configure adb.
|
||||
let currentConfig = libcutils.property_get("persist.sys.usb.config");
|
||||
let configFuncs = currentConfig.split(",");
|
||||
let adbIndex = configFuncs.indexOf("adb");
|
||||
|
||||
if (enableAdb) {
|
||||
// Add adb to the list of functions, if not already present
|
||||
if (adbIndex < 0) {
|
||||
configFuncs.push("adb");
|
||||
}
|
||||
} else {
|
||||
// Remove adb from the list of functions, if present
|
||||
if (adbIndex >= 0) {
|
||||
configFuncs.splice(adbIndex, 1);
|
||||
}
|
||||
}
|
||||
let newConfig = configFuncs.join(",");
|
||||
if (newConfig != currentConfig) {
|
||||
if (this.DEBUG) {
|
||||
this.debug("updateState: currentConfig = " + currentConfig);
|
||||
this.debug("updateState: newConfig = " + newConfig);
|
||||
}
|
||||
try {
|
||||
libcutils.property_set("persist.sys.usb.config", newConfig);
|
||||
} catch(e) {
|
||||
dump("Error configuring adb: " + e);
|
||||
}
|
||||
}
|
||||
if (useDisableAdbTimer) {
|
||||
if (enableAdb && !usbFuncActive) {
|
||||
this.startDisableAdbTimer();
|
||||
} else {
|
||||
this.stopDisableAdbTimer();
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
SettingsListener.observe("lockscreen.locked", false,
|
||||
AdbController.setLockscreenState.bind(AdbController));
|
||||
SettingsListener.observe("lockscreen.enabled", false,
|
||||
AdbController.setLockscreenEnabled.bind(AdbController));
|
275
b2g/chrome/content/devtools/debugger.js
Normal file
275
b2g/chrome/content/devtools/debugger.js
Normal file
@ -0,0 +1,275 @@
|
||||
/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- /
|
||||
/* vim: set shiftwidth=2 tabstop=2 autoindent cindent expandtab: */
|
||||
/* 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/. */
|
||||
|
||||
"use strict";
|
||||
|
||||
XPCOMUtils.defineLazyGetter(this, "DebuggerServer", function() {
|
||||
Cu.import("resource://gre/modules/devtools/dbg-server.jsm");
|
||||
return DebuggerServer;
|
||||
});
|
||||
|
||||
XPCOMUtils.defineLazyGetter(this, "devtools", function() {
|
||||
const { devtools } =
|
||||
Cu.import("resource://gre/modules/devtools/Loader.jsm", {});
|
||||
return devtools;
|
||||
});
|
||||
|
||||
XPCOMUtils.defineLazyGetter(this, "discovery", function() {
|
||||
return devtools.require("devtools/toolkit/discovery/discovery");
|
||||
});
|
||||
|
||||
let RemoteDebugger = {
|
||||
_promptDone: false,
|
||||
_promptAnswer: false,
|
||||
_listening: false,
|
||||
|
||||
prompt: function() {
|
||||
this._listen();
|
||||
|
||||
this._promptDone = false;
|
||||
|
||||
shell.sendChromeEvent({
|
||||
"type": "remote-debugger-prompt"
|
||||
});
|
||||
|
||||
while(!this._promptDone) {
|
||||
Services.tm.currentThread.processNextEvent(true);
|
||||
}
|
||||
|
||||
return this._promptAnswer;
|
||||
},
|
||||
|
||||
_listen: function() {
|
||||
if (this._listening) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.handleEvent = this.handleEvent.bind(this);
|
||||
let content = shell.contentBrowser.contentWindow;
|
||||
content.addEventListener("mozContentEvent", this, false, true);
|
||||
this._listening = true;
|
||||
},
|
||||
|
||||
handleEvent: function(event) {
|
||||
let detail = event.detail;
|
||||
if (detail.type !== "remote-debugger-prompt") {
|
||||
return;
|
||||
}
|
||||
this._promptAnswer = detail.value;
|
||||
this._promptDone = true;
|
||||
},
|
||||
|
||||
initServer: function() {
|
||||
if (DebuggerServer.initialized) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Ask for remote connections.
|
||||
DebuggerServer.init(this.prompt.bind(this));
|
||||
|
||||
// /!\ Be careful when adding a new actor, especially global actors.
|
||||
// Any new global actor will be exposed and returned by the root actor.
|
||||
|
||||
// Add Firefox-specific actors, but prevent tab actors to be loaded in
|
||||
// the parent process, unless we enable certified apps debugging.
|
||||
let restrictPrivileges = Services.prefs.getBoolPref("devtools.debugger.forbid-certified-apps");
|
||||
DebuggerServer.addBrowserActors("navigator:browser", restrictPrivileges);
|
||||
|
||||
/**
|
||||
* Construct a root actor appropriate for use in a server running in B2G.
|
||||
* The returned root actor respects the factories registered with
|
||||
* DebuggerServer.addGlobalActor only if certified apps debugging is on,
|
||||
* otherwise we used an explicit limited list of global actors
|
||||
*
|
||||
* * @param connection DebuggerServerConnection
|
||||
* The conection to the client.
|
||||
*/
|
||||
DebuggerServer.createRootActor = function createRootActor(connection)
|
||||
{
|
||||
let { Promise: promise } = Cu.import("resource://gre/modules/Promise.jsm", {});
|
||||
let parameters = {
|
||||
// We do not expose browser tab actors yet,
|
||||
// but we still have to define tabList.getList(),
|
||||
// otherwise, client won't be able to fetch global actors
|
||||
// from listTabs request!
|
||||
tabList: {
|
||||
getList: function() {
|
||||
return promise.resolve([]);
|
||||
}
|
||||
},
|
||||
// Use an explicit global actor list to prevent exposing
|
||||
// unexpected actors
|
||||
globalActorFactories: restrictPrivileges ? {
|
||||
webappsActor: DebuggerServer.globalActorFactories.webappsActor,
|
||||
deviceActor: DebuggerServer.globalActorFactories.deviceActor,
|
||||
} : DebuggerServer.globalActorFactories
|
||||
};
|
||||
let { RootActor } = devtools.require("devtools/server/actors/root");
|
||||
let root = new RootActor(connection, parameters);
|
||||
root.applicationType = "operating-system";
|
||||
return root;
|
||||
};
|
||||
|
||||
#ifdef MOZ_WIDGET_GONK
|
||||
DebuggerServer.on("connectionchange", function() {
|
||||
AdbController.updateState();
|
||||
});
|
||||
#endif
|
||||
}
|
||||
};
|
||||
|
||||
let USBRemoteDebugger = {
|
||||
|
||||
get isDebugging() {
|
||||
if (!this._listener) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return DebuggerServer._connections &&
|
||||
Object.keys(DebuggerServer._connections).length > 0;
|
||||
},
|
||||
|
||||
start: function() {
|
||||
if (this._listener) {
|
||||
return;
|
||||
}
|
||||
|
||||
RemoteDebugger.initServer();
|
||||
|
||||
let portOrPath =
|
||||
Services.prefs.getCharPref("devtools.debugger.unix-domain-socket") ||
|
||||
"/data/local/debugger-socket";
|
||||
|
||||
try {
|
||||
debug("Starting USB debugger on " + portOrPath);
|
||||
this._listener = DebuggerServer.openListener(portOrPath);
|
||||
// Temporary event, until bug 942756 lands and offers a way to know
|
||||
// when the server is up and running.
|
||||
Services.obs.notifyObservers(null, "debugger-server-started", null);
|
||||
} catch (e) {
|
||||
debug("Unable to start USB debugger server: " + e);
|
||||
}
|
||||
},
|
||||
|
||||
stop: function() {
|
||||
if (!this._listener) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
this._listener.close();
|
||||
this._listener = null;
|
||||
} catch (e) {
|
||||
debug("Unable to stop USB debugger server: " + e);
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
let WiFiRemoteDebugger = {
|
||||
|
||||
start: function() {
|
||||
if (this._listener) {
|
||||
return;
|
||||
}
|
||||
|
||||
RemoteDebugger.initServer();
|
||||
|
||||
try {
|
||||
debug("Starting WiFi debugger");
|
||||
this._listener = DebuggerServer.openListener(-1);
|
||||
let port = this._listener.port;
|
||||
debug("Started WiFi debugger on " + port);
|
||||
discovery.addService("devtools", { port: port });
|
||||
} catch (e) {
|
||||
debug("Unable to start WiFi debugger server: " + e);
|
||||
}
|
||||
},
|
||||
|
||||
stop: function() {
|
||||
if (!this._listener) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
discovery.removeService("devtools");
|
||||
this._listener.close();
|
||||
this._listener = null;
|
||||
} catch (e) {
|
||||
debug("Unable to stop WiFi debugger server: " + e);
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
(function() {
|
||||
// Track these separately here so we can determine the correct value for the
|
||||
// pref "devtools.debugger.remote-enabled", which is true when either mode of
|
||||
// using DevTools is enabled.
|
||||
let devtoolsUSB = false;
|
||||
let devtoolsWiFi = false;
|
||||
|
||||
// Keep the old setting to not break people that won't have updated
|
||||
// gaia and gecko.
|
||||
SettingsListener.observe("devtools.debugger.remote-enabled", false,
|
||||
function(value) {
|
||||
devtoolsUSB = value;
|
||||
Services.prefs.setBoolPref("devtools.debugger.remote-enabled",
|
||||
devtoolsUSB || devtoolsWiFi);
|
||||
// This preference is consulted during startup
|
||||
Services.prefs.savePrefFile(null);
|
||||
try {
|
||||
value ? USBRemoteDebugger.start() : USBRemoteDebugger.stop();
|
||||
} catch(e) {
|
||||
dump("Error while initializing USB devtools: " +
|
||||
e + "\n" + e.stack + "\n");
|
||||
}
|
||||
});
|
||||
|
||||
SettingsListener.observe("debugger.remote-mode", "disabled", function(value) {
|
||||
if (["disabled", "adb-only", "adb-devtools"].indexOf(value) == -1) {
|
||||
dump("Illegal value for debugger.remote-mode: " + value + "\n");
|
||||
return;
|
||||
}
|
||||
|
||||
devtoolsUSB = value == "adb-devtools";
|
||||
Services.prefs.setBoolPref("devtools.debugger.remote-enabled",
|
||||
devtoolsUSB || devtoolsWiFi);
|
||||
// This preference is consulted during startup
|
||||
Services.prefs.savePrefFile(null);
|
||||
|
||||
try {
|
||||
(value == "adb-devtools") ? USBRemoteDebugger.start()
|
||||
: USBRemoteDebugger.stop();
|
||||
} catch(e) {
|
||||
dump("Error while initializing USB devtools: " +
|
||||
e + "\n" + e.stack + "\n");
|
||||
}
|
||||
|
||||
#ifdef MOZ_WIDGET_GONK
|
||||
AdbController.setRemoteDebuggerState(value != "disabled");
|
||||
#endif
|
||||
});
|
||||
|
||||
SettingsListener.observe("devtools.remote.wifi.enabled", false,
|
||||
function(value) {
|
||||
devtoolsWiFi = value;
|
||||
Services.prefs.setBoolPref("devtools.debugger.remote-enabled",
|
||||
devtoolsUSB || devtoolsWiFi);
|
||||
// Allow remote debugging on non-local interfaces when WiFi debug is enabled
|
||||
// TODO: Bug 1034411: Lock down to WiFi interface, instead of all interfaces
|
||||
Services.prefs.setBoolPref("devtools.debugger.force-local", !value);
|
||||
// This preference is consulted during startup
|
||||
Services.prefs.savePrefFile(null);
|
||||
|
||||
try {
|
||||
value ? WiFiRemoteDebugger.start() : WiFiRemoteDebugger.stop();
|
||||
} catch(e) {
|
||||
dump("Error while initializing WiFi devtools: " +
|
||||
e + "\n" + e.stack + "\n");
|
||||
}
|
||||
});
|
||||
})();
|
@ -4,6 +4,8 @@
|
||||
|
||||
'use strict';
|
||||
|
||||
// settings.js loads this file when the HUD setting is enabled.
|
||||
|
||||
const DEVELOPER_HUD_LOG_PREFIX = 'DeveloperHUD';
|
||||
|
||||
XPCOMUtils.defineLazyGetter(this, 'devtools', function() {
|
@ -4,7 +4,7 @@
|
||||
* 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/. */
|
||||
|
||||
"use strict;"
|
||||
"use strict";
|
||||
|
||||
const Cc = Components.classes;
|
||||
const Ci = Components.interfaces;
|
||||
@ -176,14 +176,14 @@ Components.utils.import('resource://gre/modules/ctypes.jsm');
|
||||
}
|
||||
})();
|
||||
|
||||
// =================== DevTools ====================
|
||||
// =================== DevTools HUD ====================
|
||||
|
||||
let developerHUD;
|
||||
SettingsListener.observe('devtools.overlay', false, (value) => {
|
||||
if (value) {
|
||||
if (!developerHUD) {
|
||||
let scope = {};
|
||||
Services.scriptloader.loadSubScript('chrome://b2g/content/devtools.js', scope);
|
||||
Services.scriptloader.loadSubScript('chrome://b2g/content/devtools/hud.js', scope);
|
||||
developerHUD = scope.developerHUD;
|
||||
}
|
||||
developerHUD.init();
|
||||
@ -194,321 +194,6 @@ SettingsListener.observe('devtools.overlay', false, (value) => {
|
||||
}
|
||||
});
|
||||
|
||||
// =================== Debugger / ADB ====================
|
||||
|
||||
#ifdef MOZ_WIDGET_GONK
|
||||
let AdbController = {
|
||||
DEBUG: false,
|
||||
locked: undefined,
|
||||
remoteDebuggerEnabled: undefined,
|
||||
lockEnabled: undefined,
|
||||
disableAdbTimer: null,
|
||||
disableAdbTimeoutHours: 12,
|
||||
umsActive: false,
|
||||
|
||||
debug: function(str) {
|
||||
dump("AdbController: " + str + "\n");
|
||||
},
|
||||
|
||||
setLockscreenEnabled: function(value) {
|
||||
this.lockEnabled = value;
|
||||
if (this.DEBUG) {
|
||||
this.debug("setLockscreenEnabled = " + this.lockEnabled);
|
||||
}
|
||||
this.updateState();
|
||||
},
|
||||
|
||||
setLockscreenState: function(value) {
|
||||
this.locked = value;
|
||||
if (this.DEBUG) {
|
||||
this.debug("setLockscreenState = " + this.locked);
|
||||
}
|
||||
this.updateState();
|
||||
},
|
||||
|
||||
setRemoteDebuggerState: function(value) {
|
||||
this.remoteDebuggerEnabled = value;
|
||||
if (this.DEBUG) {
|
||||
this.debug("setRemoteDebuggerState = " + this.remoteDebuggerEnabled);
|
||||
}
|
||||
this.updateState();
|
||||
},
|
||||
|
||||
startDisableAdbTimer: function() {
|
||||
if (this.disableAdbTimer) {
|
||||
this.disableAdbTimer.cancel();
|
||||
} else {
|
||||
this.disableAdbTimer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer);
|
||||
try {
|
||||
this.disableAdbTimeoutHours =
|
||||
Services.prefs.getIntPref("b2g.adb.timeout-hours");
|
||||
} catch (e) {
|
||||
// This happens if the pref doesn't exist, in which case
|
||||
// disableAdbTimeoutHours will still be set to the default.
|
||||
}
|
||||
}
|
||||
if (this.disableAdbTimeoutHours <= 0) {
|
||||
if (this.DEBUG) {
|
||||
this.debug("Timer to disable ADB not started due to zero timeout");
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (this.DEBUG) {
|
||||
this.debug("Starting timer to disable ADB in " +
|
||||
this.disableAdbTimeoutHours + " hours");
|
||||
}
|
||||
let timeoutMilliseconds = this.disableAdbTimeoutHours * 60 * 60 * 1000;
|
||||
this.disableAdbTimer.initWithCallback(this, timeoutMilliseconds,
|
||||
Ci.nsITimer.TYPE_ONE_SHOT);
|
||||
},
|
||||
|
||||
stopDisableAdbTimer: function() {
|
||||
if (this.DEBUG) {
|
||||
this.debug("Stopping timer to disable ADB");
|
||||
}
|
||||
if (this.disableAdbTimer) {
|
||||
this.disableAdbTimer.cancel();
|
||||
this.disableAdbTimer = null;
|
||||
}
|
||||
},
|
||||
|
||||
notify: function(aTimer) {
|
||||
if (aTimer == this.disableAdbTimer) {
|
||||
this.disableAdbTimer = null;
|
||||
// The following dump will be the last thing that shows up in logcat,
|
||||
// and will at least give the user a clue about why logcat was
|
||||
// disconnected, if the user happens to be using logcat.
|
||||
dump("AdbController: ADB timer expired - disabling ADB\n");
|
||||
navigator.mozSettings.createLock().set(
|
||||
{'debugger.remote-mode': 'disabled'});
|
||||
}
|
||||
},
|
||||
|
||||
updateState: function() {
|
||||
this.umsActive = false;
|
||||
this.storages = navigator.getDeviceStorages('sdcard');
|
||||
this.updateStorageState(0);
|
||||
},
|
||||
|
||||
updateStorageState: function(storageIndex) {
|
||||
if (storageIndex >= this.storages.length) {
|
||||
// We've iterated through all of the storage objects, now we can
|
||||
// really do updateStateInternal.
|
||||
this.updateStateInternal();
|
||||
return;
|
||||
}
|
||||
let storage = this.storages[storageIndex];
|
||||
if (this.DEBUG) {
|
||||
this.debug("Checking availability of storage: '" +
|
||||
storage.storageName);
|
||||
}
|
||||
|
||||
let req = storage.available();
|
||||
req.onsuccess = function(e) {
|
||||
if (this.DEBUG) {
|
||||
this.debug("Storage: '" + storage.storageName + "' is '" +
|
||||
e.target.result);
|
||||
}
|
||||
if (e.target.result == 'shared') {
|
||||
// We've found a storage area that's being shared with the PC.
|
||||
// We can stop looking now.
|
||||
this.umsActive = true;
|
||||
this.updateStateInternal();
|
||||
return;
|
||||
}
|
||||
this.updateStorageState(storageIndex + 1);
|
||||
}.bind(this);
|
||||
req.onerror = function(e) {
|
||||
dump("AdbController: error querying storage availability for '" +
|
||||
this.storages[storageIndex].storageName + "' (ignoring)\n");
|
||||
this.updateStorageState(storageIndex + 1);
|
||||
}.bind(this);
|
||||
},
|
||||
|
||||
updateStateInternal: function() {
|
||||
if (this.DEBUG) {
|
||||
this.debug("updateStateInternal: called");
|
||||
}
|
||||
|
||||
if (this.remoteDebuggerEnabled === undefined ||
|
||||
this.lockEnabled === undefined ||
|
||||
this.locked === undefined) {
|
||||
// Part of initializing the settings database will cause the observers
|
||||
// to trigger. We want to wait until both have been initialized before
|
||||
// we start changing ther adb state. Without this then we can wind up
|
||||
// toggling adb off and back on again (or on and back off again).
|
||||
//
|
||||
// For completeness, one scenario which toggles adb is using the unagi.
|
||||
// The unagi has adb enabled by default (prior to b2g starting). If you
|
||||
// have the phone lock disabled and remote debugging enabled, then we'll
|
||||
// receive an unlock event and an rde event. However at the time we
|
||||
// receive the unlock event we haven't yet received the rde event, so
|
||||
// we turn adb off momentarily, which disconnects a logcat that might
|
||||
// be running. Changing the defaults (in AdbController) just moves the
|
||||
// problem to a different phone, which has adb disabled by default and
|
||||
// we wind up turning on adb for a short period when we shouldn't.
|
||||
//
|
||||
// By waiting until both values are properly initialized, we avoid
|
||||
// turning adb on or off accidentally.
|
||||
if (this.DEBUG) {
|
||||
this.debug("updateState: Waiting for all vars to be initialized");
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// Check if we have a remote debugging session going on. If so, we won't
|
||||
// disable adb even if the screen is locked.
|
||||
let isDebugging = USBRemoteDebugger.isDebugging;
|
||||
if (this.DEBUG) {
|
||||
this.debug("isDebugging=" + isDebugging);
|
||||
}
|
||||
|
||||
// If USB Mass Storage, USB tethering, or a debug session is active,
|
||||
// then we don't want to disable adb in an automatic fashion (i.e.
|
||||
// when the screen locks or due to timeout).
|
||||
let sysUsbConfig = libcutils.property_get("sys.usb.config");
|
||||
let rndisActive = (sysUsbConfig.split(",").indexOf("rndis") >= 0);
|
||||
let usbFuncActive = rndisActive || this.umsActive || isDebugging;
|
||||
|
||||
let enableAdb = this.remoteDebuggerEnabled &&
|
||||
(!(this.lockEnabled && this.locked) || usbFuncActive);
|
||||
|
||||
let useDisableAdbTimer = true;
|
||||
try {
|
||||
if (Services.prefs.getBoolPref("marionette.defaultPrefs.enabled")) {
|
||||
// Marionette is enabled. Marionette requires that adb be on (and also
|
||||
// requires that remote debugging be off). The fact that marionette
|
||||
// is enabled also implies that we're doing a non-production build, so
|
||||
// we want adb enabled all of the time.
|
||||
enableAdb = true;
|
||||
useDisableAdbTimer = false;
|
||||
}
|
||||
} catch (e) {
|
||||
// This means that the pref doesn't exist. Which is fine. We just leave
|
||||
// enableAdb alone.
|
||||
}
|
||||
if (this.DEBUG) {
|
||||
this.debug("updateState: enableAdb = " + enableAdb +
|
||||
" remoteDebuggerEnabled = " + this.remoteDebuggerEnabled +
|
||||
" lockEnabled = " + this.lockEnabled +
|
||||
" locked = " + this.locked +
|
||||
" usbFuncActive = " + usbFuncActive);
|
||||
}
|
||||
|
||||
// Configure adb.
|
||||
let currentConfig = libcutils.property_get("persist.sys.usb.config");
|
||||
let configFuncs = currentConfig.split(",");
|
||||
let adbIndex = configFuncs.indexOf("adb");
|
||||
|
||||
if (enableAdb) {
|
||||
// Add adb to the list of functions, if not already present
|
||||
if (adbIndex < 0) {
|
||||
configFuncs.push("adb");
|
||||
}
|
||||
} else {
|
||||
// Remove adb from the list of functions, if present
|
||||
if (adbIndex >= 0) {
|
||||
configFuncs.splice(adbIndex, 1);
|
||||
}
|
||||
}
|
||||
let newConfig = configFuncs.join(",");
|
||||
if (newConfig != currentConfig) {
|
||||
if (this.DEBUG) {
|
||||
this.debug("updateState: currentConfig = " + currentConfig);
|
||||
this.debug("updateState: newConfig = " + newConfig);
|
||||
}
|
||||
try {
|
||||
libcutils.property_set("persist.sys.usb.config", newConfig);
|
||||
} catch(e) {
|
||||
dump("Error configuring adb: " + e);
|
||||
}
|
||||
}
|
||||
if (useDisableAdbTimer) {
|
||||
if (enableAdb && !usbFuncActive) {
|
||||
this.startDisableAdbTimer();
|
||||
} else {
|
||||
this.stopDisableAdbTimer();
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
SettingsListener.observe("lockscreen.locked", false,
|
||||
AdbController.setLockscreenState.bind(AdbController));
|
||||
SettingsListener.observe("lockscreen.enabled", false,
|
||||
AdbController.setLockscreenEnabled.bind(AdbController));
|
||||
#endif
|
||||
|
||||
(function() {
|
||||
// Track these separately here so we can determine the correct value for the
|
||||
// pref "devtools.debugger.remote-enabled", which is true when either mode of
|
||||
// using DevTools is enabled.
|
||||
let devtoolsUSB = false;
|
||||
let devtoolsWiFi = false;
|
||||
|
||||
// Keep the old setting to not break people that won't have updated
|
||||
// gaia and gecko.
|
||||
SettingsListener.observe('devtools.debugger.remote-enabled', false,
|
||||
function(value) {
|
||||
devtoolsUSB = value;
|
||||
Services.prefs.setBoolPref('devtools.debugger.remote-enabled',
|
||||
devtoolsUSB || devtoolsWiFi);
|
||||
// This preference is consulted during startup
|
||||
Services.prefs.savePrefFile(null);
|
||||
try {
|
||||
value ? USBRemoteDebugger.start() : USBRemoteDebugger.stop();
|
||||
} catch(e) {
|
||||
dump("Error while initializing USB devtools: "
|
||||
+ e + "\n" + e.stack + "\n");
|
||||
}
|
||||
});
|
||||
|
||||
SettingsListener.observe('debugger.remote-mode', 'disabled', function(value) {
|
||||
if (['disabled', 'adb-only', 'adb-devtools'].indexOf(value) == -1) {
|
||||
dump('Illegal value for debugger.remote-mode: ' + value + '\n');
|
||||
return;
|
||||
}
|
||||
|
||||
devtoolsUSB = value == 'adb-devtools';
|
||||
Services.prefs.setBoolPref('devtools.debugger.remote-enabled',
|
||||
devtoolsUSB || devtoolsWiFi);
|
||||
// This preference is consulted during startup
|
||||
Services.prefs.savePrefFile(null);
|
||||
|
||||
try {
|
||||
(value == 'adb-devtools') ? USBRemoteDebugger.start()
|
||||
: USBRemoteDebugger.stop();
|
||||
} catch(e) {
|
||||
dump("Error while initializing USB devtools: "
|
||||
+ e + "\n" + e.stack + "\n");
|
||||
}
|
||||
|
||||
#ifdef MOZ_WIDGET_GONK
|
||||
AdbController.setRemoteDebuggerState(value != 'disabled');
|
||||
#endif
|
||||
});
|
||||
|
||||
SettingsListener.observe('devtools.remote.wifi.enabled', false,
|
||||
function(value) {
|
||||
devtoolsWiFi = value;
|
||||
Services.prefs.setBoolPref('devtools.debugger.remote-enabled',
|
||||
devtoolsUSB || devtoolsWiFi);
|
||||
// Allow remote debugging on non-local interfaces when WiFi debug is enabled
|
||||
// TODO: Bug 1034411: Lock down to WiFi interface, instead of all interfaces
|
||||
Services.prefs.setBoolPref('devtools.debugger.force-local', !value);
|
||||
// This preference is consulted during startup
|
||||
Services.prefs.savePrefFile(null);
|
||||
|
||||
try {
|
||||
value ? WiFiRemoteDebugger.start() : WiFiRemoteDebugger.stop();
|
||||
} catch(e) {
|
||||
dump("Error while initializing WiFi devtools: "
|
||||
+ e + "\n" + e.stack + "\n");
|
||||
}
|
||||
});
|
||||
})();
|
||||
|
||||
// =================== Device Storage ====================
|
||||
SettingsListener.observe('device.storage.writable.name', 'sdcard', function(value) {
|
||||
if (Services.prefs.getPrefType('device.storage.writable.name') != Ci.nsIPrefBranch.PREF_STRING) {
|
||||
|
@ -32,7 +32,14 @@
|
||||
<!-- this script handles the "runapp" argument for desktop builds -->
|
||||
<script type="application/javascript;version=1.8"
|
||||
src="chrome://b2g/content/runapp.js"> </script>
|
||||
#else
|
||||
<!-- this file is only loaded on Gonk to manage ADB state -->
|
||||
<script type="application/javascript;version=1.8"
|
||||
src="chrome://b2g/content/devtools/adb.js"> </script>
|
||||
#endif
|
||||
<!-- manages DevTools server state -->
|
||||
<script type="application/javascript;version=1.8"
|
||||
src="chrome://b2g/content/devtools/debugger.js"> </script>
|
||||
</head>
|
||||
<body id="container">
|
||||
#ifdef FXOS_SIMULATOR
|
||||
|
@ -51,21 +51,6 @@ XPCOMUtils.defineLazyServiceGetter(Services, 'fm',
|
||||
'@mozilla.org/focus-manager;1',
|
||||
'nsIFocusManager');
|
||||
|
||||
XPCOMUtils.defineLazyGetter(this, 'DebuggerServer', function() {
|
||||
Cu.import('resource://gre/modules/devtools/dbg-server.jsm');
|
||||
return DebuggerServer;
|
||||
});
|
||||
|
||||
XPCOMUtils.defineLazyGetter(this, 'devtools', function() {
|
||||
const { devtools } =
|
||||
Cu.import('resource://gre/modules/devtools/Loader.jsm', {});
|
||||
return devtools;
|
||||
});
|
||||
|
||||
XPCOMUtils.defineLazyGetter(this, 'discovery', function() {
|
||||
return devtools.require('devtools/toolkit/discovery/discovery');
|
||||
});
|
||||
|
||||
XPCOMUtils.defineLazyGetter(this, "ppmm", function() {
|
||||
return Cc["@mozilla.org/parentprocessmessagemanager;1"]
|
||||
.getService(Ci.nsIMessageListenerManager);
|
||||
@ -730,9 +715,6 @@ var CustomEventManager = {
|
||||
case 'system-message-listener-ready':
|
||||
Services.obs.notifyObservers(null, 'system-message-listener-ready', null);
|
||||
break;
|
||||
case 'remote-debugger-prompt':
|
||||
RemoteDebugger.handleEvent(detail);
|
||||
break;
|
||||
case 'captive-portal-login-cancel':
|
||||
CaptivePortalLoginHelper.handleEvent(detail);
|
||||
break;
|
||||
@ -860,172 +842,6 @@ let IndexedDBPromptHelper = {
|
||||
}
|
||||
}
|
||||
|
||||
let RemoteDebugger = {
|
||||
_promptDone: false,
|
||||
_promptAnswer: false,
|
||||
|
||||
prompt: function debugger_prompt() {
|
||||
this._promptDone = false;
|
||||
|
||||
shell.sendChromeEvent({
|
||||
"type": "remote-debugger-prompt"
|
||||
});
|
||||
|
||||
while(!this._promptDone) {
|
||||
Services.tm.currentThread.processNextEvent(true);
|
||||
}
|
||||
|
||||
return this._promptAnswer;
|
||||
},
|
||||
|
||||
handleEvent: function debugger_handleEvent(detail) {
|
||||
this._promptAnswer = detail.value;
|
||||
this._promptDone = true;
|
||||
},
|
||||
|
||||
initServer: function() {
|
||||
if (DebuggerServer.initialized) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Ask for remote connections.
|
||||
DebuggerServer.init(this.prompt.bind(this));
|
||||
|
||||
// /!\ Be careful when adding a new actor, especially global actors.
|
||||
// Any new global actor will be exposed and returned by the root actor.
|
||||
|
||||
// Add Firefox-specific actors, but prevent tab actors to be loaded in
|
||||
// the parent process, unless we enable certified apps debugging.
|
||||
let restrictPrivileges = Services.prefs.getBoolPref("devtools.debugger.forbid-certified-apps");
|
||||
DebuggerServer.addBrowserActors("navigator:browser", restrictPrivileges);
|
||||
|
||||
/**
|
||||
* Construct a root actor appropriate for use in a server running in B2G.
|
||||
* The returned root actor respects the factories registered with
|
||||
* DebuggerServer.addGlobalActor only if certified apps debugging is on,
|
||||
* otherwise we used an explicit limited list of global actors
|
||||
*
|
||||
* * @param connection DebuggerServerConnection
|
||||
* The conection to the client.
|
||||
*/
|
||||
DebuggerServer.createRootActor = function createRootActor(connection)
|
||||
{
|
||||
let { Promise: promise } = Cu.import("resource://gre/modules/Promise.jsm", {});
|
||||
let parameters = {
|
||||
// We do not expose browser tab actors yet,
|
||||
// but we still have to define tabList.getList(),
|
||||
// otherwise, client won't be able to fetch global actors
|
||||
// from listTabs request!
|
||||
tabList: {
|
||||
getList: function() {
|
||||
return promise.resolve([]);
|
||||
}
|
||||
},
|
||||
// Use an explicit global actor list to prevent exposing
|
||||
// unexpected actors
|
||||
globalActorFactories: restrictPrivileges ? {
|
||||
webappsActor: DebuggerServer.globalActorFactories.webappsActor,
|
||||
deviceActor: DebuggerServer.globalActorFactories.deviceActor,
|
||||
} : DebuggerServer.globalActorFactories
|
||||
};
|
||||
let { RootActor } = devtools.require("devtools/server/actors/root");
|
||||
let root = new RootActor(connection, parameters);
|
||||
root.applicationType = "operating-system";
|
||||
return root;
|
||||
};
|
||||
|
||||
#ifdef MOZ_WIDGET_GONK
|
||||
DebuggerServer.on("connectionchange", function() {
|
||||
AdbController.updateState();
|
||||
});
|
||||
#endif
|
||||
}
|
||||
};
|
||||
|
||||
let USBRemoteDebugger = {
|
||||
|
||||
get isDebugging() {
|
||||
if (!this._listener) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return DebuggerServer._connections &&
|
||||
Object.keys(DebuggerServer._connections).length > 0;
|
||||
},
|
||||
|
||||
start: function() {
|
||||
if (this._listener) {
|
||||
return;
|
||||
}
|
||||
|
||||
RemoteDebugger.initServer();
|
||||
|
||||
let portOrPath =
|
||||
Services.prefs.getCharPref("devtools.debugger.unix-domain-socket") ||
|
||||
"/data/local/debugger-socket";
|
||||
|
||||
try {
|
||||
debug("Starting USB debugger on " + portOrPath);
|
||||
this._listener = DebuggerServer.openListener(portOrPath);
|
||||
// Temporary event, until bug 942756 lands and offers a way to know
|
||||
// when the server is up and running.
|
||||
Services.obs.notifyObservers(null, 'debugger-server-started', null);
|
||||
} catch (e) {
|
||||
debug('Unable to start USB debugger server: ' + e);
|
||||
}
|
||||
},
|
||||
|
||||
stop: function() {
|
||||
if (!this._listener) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
this._listener.close();
|
||||
this._listener = null;
|
||||
} catch (e) {
|
||||
debug('Unable to stop USB debugger server: ' + e);
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
let WiFiRemoteDebugger = {
|
||||
|
||||
start: function() {
|
||||
if (this._listener) {
|
||||
return;
|
||||
}
|
||||
|
||||
RemoteDebugger.initServer();
|
||||
|
||||
try {
|
||||
debug("Starting WiFi debugger");
|
||||
this._listener = DebuggerServer.openListener(-1);
|
||||
let port = this._listener.port;
|
||||
debug("Started WiFi debugger on " + port);
|
||||
discovery.addService("devtools", { port: port });
|
||||
} catch (e) {
|
||||
debug('Unable to start WiFi debugger server: ' + e);
|
||||
}
|
||||
},
|
||||
|
||||
stop: function() {
|
||||
if (!this._listener) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
discovery.removeService("devtools");
|
||||
this._listener.close();
|
||||
this._listener = null;
|
||||
} catch (e) {
|
||||
debug('Unable to stop WiFi debugger server: ' + e);
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
let KeyboardHelper = {
|
||||
handleEvent: function keyboard_handleEvent(detail) {
|
||||
Keyboard.setLayouts(detail.layouts);
|
||||
|
@ -13,7 +13,11 @@ chrome.jar:
|
||||
* content/shell.html (content/shell.html)
|
||||
* content/shell.js (content/shell.js)
|
||||
content/shell.css (content/shell.css)
|
||||
content/devtools.js (content/devtools.js)
|
||||
#ifdef MOZ_WIDGET_GONK
|
||||
content/devtools/adb.js (content/devtools/adb.js)
|
||||
#endif
|
||||
* content/devtools/debugger.js (content/devtools/debugger.js)
|
||||
content/devtools/hud.js (content/devtools/hud.js)
|
||||
#ifdef FXOS_SIMULATOR
|
||||
content/desktop.css (content/desktop.css)
|
||||
content/images/desktop/home-black.png (content/images/desktop/home-black.png)
|
||||
|
@ -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="00aa329503d73435c9821d4a50c2797a0374eac6"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="acead54e798dcc436433fc359dda3a1409c5a44a"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="3bb61a27cd2941b2ba9b616a11aaa44269210396"/>
|
||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
|
||||
<project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="cd88d860656c31c7da7bb310d6a160d0011b0961"/>
|
||||
|
@ -12,12 +12,12 @@
|
||||
<!--original fetch url was https://git.mozilla.org/releases-->
|
||||
<remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
|
||||
<!-- B2G specific things. -->
|
||||
<project name="platform_build" path="build" remote="b2g" revision="3aa6abd313f965a84aa86c6b213dc154e4875139">
|
||||
<project name="platform_build" path="build" remote="b2g" revision="7eef86294cd794ab9e6a53d218c238bfc63c3a6d">
|
||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
|
||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="00aa329503d73435c9821d4a50c2797a0374eac6"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="acead54e798dcc436433fc359dda3a1409c5a44a"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="3bb61a27cd2941b2ba9b616a11aaa44269210396"/>
|
||||
<project name="moztt" path="external/moztt" remote="b2g" revision="562d357b72279a9e35d4af5aeecc8e1ffa2f44f1"/>
|
||||
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="dbc46f0bc269791c52becbef22f84c63469ee8be"/>
|
||||
|
@ -12,10 +12,10 @@
|
||||
<!--original fetch url was https://git.mozilla.org/releases-->
|
||||
<remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
|
||||
<!-- B2G specific things. -->
|
||||
<project name="platform_build" path="build" remote="b2g" revision="7945ca73e687be5edbc7b928dc7fe3a208242144">
|
||||
<project name="platform_build" path="build" remote="b2g" revision="1865c6639c51f0290d5778adef146147d5d6a5f0">
|
||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="00aa329503d73435c9821d4a50c2797a0374eac6"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="acead54e798dcc436433fc359dda3a1409c5a44a"/>
|
||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="3bb61a27cd2941b2ba9b616a11aaa44269210396"/>
|
||||
<project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>
|
||||
|
@ -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="00aa329503d73435c9821d4a50c2797a0374eac6"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="acead54e798dcc436433fc359dda3a1409c5a44a"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="3bb61a27cd2941b2ba9b616a11aaa44269210396"/>
|
||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
|
||||
<project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="cd88d860656c31c7da7bb310d6a160d0011b0961"/>
|
||||
|
@ -12,12 +12,12 @@
|
||||
<!--original fetch url was https://git.mozilla.org/releases-->
|
||||
<remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
|
||||
<!-- B2G specific things. -->
|
||||
<project name="platform_build" path="build" remote="b2g" revision="3aa6abd313f965a84aa86c6b213dc154e4875139">
|
||||
<project name="platform_build" path="build" remote="b2g" revision="7eef86294cd794ab9e6a53d218c238bfc63c3a6d">
|
||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>
|
||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="00aa329503d73435c9821d4a50c2797a0374eac6"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="acead54e798dcc436433fc359dda3a1409c5a44a"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="3bb61a27cd2941b2ba9b616a11aaa44269210396"/>
|
||||
<project name="moztt" path="external/moztt" remote="b2g" revision="562d357b72279a9e35d4af5aeecc8e1ffa2f44f1"/>
|
||||
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="dbc46f0bc269791c52becbef22f84c63469ee8be"/>
|
||||
|
@ -4,6 +4,6 @@
|
||||
"remote": "",
|
||||
"branch": ""
|
||||
},
|
||||
"revision": "16e1bcb1ef744dbffbc9330ac395fa275d178fd0",
|
||||
"revision": "ffbb39b4a20479d949ef88c688bf0534677d845a",
|
||||
"repo_path": "/integration/gaia-central"
|
||||
}
|
||||
|
@ -17,7 +17,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="00aa329503d73435c9821d4a50c2797a0374eac6"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="acead54e798dcc436433fc359dda3a1409c5a44a"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="3bb61a27cd2941b2ba9b616a11aaa44269210396"/>
|
||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
|
||||
<project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>
|
||||
|
@ -15,7 +15,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="00aa329503d73435c9821d4a50c2797a0374eac6"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="acead54e798dcc436433fc359dda3a1409c5a44a"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="3bb61a27cd2941b2ba9b616a11aaa44269210396"/>
|
||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
|
||||
<project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>
|
||||
|
@ -12,12 +12,12 @@
|
||||
<!--original fetch url was https://git.mozilla.org/releases-->
|
||||
<remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
|
||||
<!-- B2G specific things. -->
|
||||
<project name="platform_build" path="build" remote="b2g" revision="3aa6abd313f965a84aa86c6b213dc154e4875139">
|
||||
<project name="platform_build" path="build" remote="b2g" revision="7eef86294cd794ab9e6a53d218c238bfc63c3a6d">
|
||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
|
||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="00aa329503d73435c9821d4a50c2797a0374eac6"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="acead54e798dcc436433fc359dda3a1409c5a44a"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="3bb61a27cd2941b2ba9b616a11aaa44269210396"/>
|
||||
<project name="moztt" path="external/moztt" remote="b2g" revision="562d357b72279a9e35d4af5aeecc8e1ffa2f44f1"/>
|
||||
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="dbc46f0bc269791c52becbef22f84c63469ee8be"/>
|
||||
|
@ -17,7 +17,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="00aa329503d73435c9821d4a50c2797a0374eac6"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="acead54e798dcc436433fc359dda3a1409c5a44a"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="3bb61a27cd2941b2ba9b616a11aaa44269210396"/>
|
||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
|
||||
<project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>
|
||||
|
@ -422,6 +422,7 @@ Convert(bt_device_type_t aIn, BluetoothDeviceType& aOut)
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
#if ANDROID_VERSION >= 18
|
||||
static nsresult
|
||||
Convert(const bt_remote_version_t& aIn, BluetoothRemoteInfo& aOut)
|
||||
{
|
||||
@ -431,6 +432,7 @@ Convert(const bt_remote_version_t& aIn, BluetoothRemoteInfo& aOut)
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
#endif
|
||||
|
||||
static nsresult
|
||||
Convert(const bt_service_record_t& aIn, BluetoothServiceRecord& aOut)
|
||||
@ -840,10 +842,12 @@ Convert(const bt_property_t& aIn, BluetoothProperty& aOut)
|
||||
case PROPERTY_REMOTE_RSSI:
|
||||
aOut.mInt32 = *static_cast<int32_t*>(aIn.val);
|
||||
break;
|
||||
#if ANDROID_VERSION >= 18
|
||||
case PROPERTY_REMOTE_VERSION_INFO:
|
||||
rv = Convert(*static_cast<bt_remote_version_t*>(aIn.val),
|
||||
aOut.mRemoteInfo);
|
||||
break;
|
||||
#endif
|
||||
case PROPERTY_REMOTE_DEVICE_TIMESTAMP:
|
||||
/* nothing to do */
|
||||
break;
|
||||
@ -3036,18 +3040,20 @@ BluetoothInterface::Init(BluetoothNotificationHandler* aNotificationHandler,
|
||||
{
|
||||
static bt_callbacks_t sBluetoothCallbacks = {
|
||||
sizeof(sBluetoothCallbacks),
|
||||
.adapter_state_changed_cb = BluetoothCallback::AdapterStateChanged,
|
||||
.adapter_properties_cb = BluetoothCallback::AdapterProperties,
|
||||
.remote_device_properties_cb = BluetoothCallback::RemoteDeviceProperties,
|
||||
.device_found_cb = BluetoothCallback::DeviceFound,
|
||||
.discovery_state_changed_cb= BluetoothCallback::DiscoveryStateChanged,
|
||||
.pin_request_cb = BluetoothCallback::PinRequest,
|
||||
.ssp_request_cb = BluetoothCallback::SspRequest,
|
||||
.bond_state_changed_cb = BluetoothCallback::BondStateChanged,
|
||||
.acl_state_changed_cb = BluetoothCallback::AclStateChanged,
|
||||
.thread_evt_cb = BluetoothCallback::ThreadEvt,
|
||||
.dut_mode_recv_cb = BluetoothCallback::DutModeRecv,
|
||||
.le_test_mode_cb = BluetoothCallback::LeTestMode
|
||||
BluetoothCallback::AdapterStateChanged,
|
||||
BluetoothCallback::AdapterProperties,
|
||||
BluetoothCallback::RemoteDeviceProperties,
|
||||
BluetoothCallback::DeviceFound,
|
||||
BluetoothCallback::DiscoveryStateChanged,
|
||||
BluetoothCallback::PinRequest,
|
||||
BluetoothCallback::SspRequest,
|
||||
BluetoothCallback::BondStateChanged,
|
||||
BluetoothCallback::AclStateChanged,
|
||||
BluetoothCallback::ThreadEvt,
|
||||
BluetoothCallback::DutModeRecv,
|
||||
#if ANDROID_VERSION >= 18
|
||||
BluetoothCallback::LeTestMode
|
||||
#endif
|
||||
};
|
||||
|
||||
sNotificationHandler = aNotificationHandler;
|
||||
|
@ -59,13 +59,13 @@ const ICC_MAX_LINEAR_FIXED_RECORDS = 0xfe;
|
||||
|
||||
// MMI match groups
|
||||
const MMI_MATCH_GROUP_FULL_MMI = 1;
|
||||
const MMI_MATCH_GROUP_MMI_PROCEDURE = 2;
|
||||
const MMI_MATCH_GROUP_PROCEDURE = 2;
|
||||
const MMI_MATCH_GROUP_SERVICE_CODE = 3;
|
||||
const MMI_MATCH_GROUP_SIA = 5;
|
||||
const MMI_MATCH_GROUP_SIB = 7;
|
||||
const MMI_MATCH_GROUP_SIC = 9;
|
||||
const MMI_MATCH_GROUP_PWD_CONFIRM = 11;
|
||||
const MMI_MATCH_GROUP_DIALING_NUMBER = 12;
|
||||
const MMI_MATCH_GROUP_SIA = 4;
|
||||
const MMI_MATCH_GROUP_SIB = 5;
|
||||
const MMI_MATCH_GROUP_SIC = 6;
|
||||
const MMI_MATCH_GROUP_PWD_CONFIRM = 7;
|
||||
const MMI_MATCH_GROUP_DIALING_NUMBER = 8;
|
||||
|
||||
const MMI_MAX_LENGTH_SHORT_CODE = 2;
|
||||
|
||||
@ -1679,20 +1679,6 @@ RilObject.prototype = {
|
||||
this.exitEmergencyCbMode();
|
||||
}
|
||||
|
||||
if (!this._isCdma) {
|
||||
// TODO: Both dial() and sendMMI() functions should be unified at some
|
||||
// point in the future. In the mean time we handle temporary CLIR MMI
|
||||
// commands through the dial() function. Please see bug 889737.
|
||||
let mmi = this._parseMMI(options.number);
|
||||
if (mmi && this._isTemporaryModeCLIR(mmi)) {
|
||||
options.number = mmi.dialNumber;
|
||||
// In temporary mode, MMI_PROCEDURE_ACTIVATION means allowing CLI
|
||||
// presentation, i.e. CLIR_SUPPRESSION. See TS 22.030, Annex B.
|
||||
options.clirMode = mmi.procedure == MMI_PROCEDURE_ACTIVATION ?
|
||||
CLIR_SUPPRESSION : CLIR_INVOCATION;
|
||||
}
|
||||
}
|
||||
|
||||
options.request = REQUEST_DIAL;
|
||||
this.sendDialRequest(options);
|
||||
},
|
||||
@ -1907,7 +1893,7 @@ RilObject.prototype = {
|
||||
} else if (call.state == CALL_STATE_ACTIVE) {
|
||||
this.sendSwitchWaitingRequest();
|
||||
}
|
||||
},
|
||||
},
|
||||
|
||||
resumeCall: function(options) {
|
||||
let call = this.currentCalls[options.callIndex];
|
||||
@ -2390,6 +2376,20 @@ RilObject.prototype = {
|
||||
{callback: callback});
|
||||
},
|
||||
|
||||
/**
|
||||
* Parse the dial number to extract its mmi code part.
|
||||
*
|
||||
* @param number
|
||||
* Phone number to be parsed
|
||||
*/
|
||||
parseMMIFromDialNumber: function(options) {
|
||||
// We don't have to parse mmi in cdma.
|
||||
if (!this._isCdma) {
|
||||
options.mmi = this._parseMMI(options.number);
|
||||
}
|
||||
this.sendChromeMessage(options);
|
||||
},
|
||||
|
||||
/**
|
||||
* Helper to parse MMI/USSD string. TS.22.030 Figure 3.5.3.2.
|
||||
*/
|
||||
@ -2398,21 +2398,11 @@ RilObject.prototype = {
|
||||
return null;
|
||||
}
|
||||
|
||||
let matches = this._matchMMIRegexp(mmiString);
|
||||
let matches = this._getMMIRegExp().exec(mmiString);
|
||||
if (matches) {
|
||||
// After successfully executing the regular expresion over the MMI string,
|
||||
// the following match groups should contain:
|
||||
// 1 = full MMI string that might be used as a USSD request.
|
||||
// 2 = MMI procedure.
|
||||
// 3 = Service code.
|
||||
// 5 = SIA.
|
||||
// 7 = SIB.
|
||||
// 9 = SIC.
|
||||
// 11 = Password registration.
|
||||
// 12 = Dialing number.
|
||||
return {
|
||||
fullMMI: matches[MMI_MATCH_GROUP_FULL_MMI],
|
||||
procedure: matches[MMI_MATCH_GROUP_MMI_PROCEDURE],
|
||||
procedure: matches[MMI_MATCH_GROUP_PROCEDURE],
|
||||
serviceCode: matches[MMI_MATCH_GROUP_SERVICE_CODE],
|
||||
sia: matches[MMI_MATCH_GROUP_SIA],
|
||||
sib: matches[MMI_MATCH_GROUP_SIB],
|
||||
@ -2422,8 +2412,7 @@ RilObject.prototype = {
|
||||
};
|
||||
}
|
||||
|
||||
if (this._isPoundString(mmiString) ||
|
||||
this._isMMIShortString(mmiString)) {
|
||||
if (this._isPoundString(mmiString) || this._isMMIShortString(mmiString)) {
|
||||
return {
|
||||
fullMMI: mmiString
|
||||
};
|
||||
@ -2433,56 +2422,80 @@ RilObject.prototype = {
|
||||
},
|
||||
|
||||
/**
|
||||
* Helper to parse MMI string via regular expression. TS.22.030 Figure
|
||||
* 3.5.3.2.
|
||||
* Build the regex to parse MMI string.
|
||||
*
|
||||
* The resulting groups after matching will be:
|
||||
* 1 = full MMI string that might be used as a USSD request.
|
||||
* 2 = MMI procedure.
|
||||
* 3 = Service code.
|
||||
* 4 = SIA.
|
||||
* 5 = SIB.
|
||||
* 6 = SIC.
|
||||
* 7 = Password registration.
|
||||
* 8 = Dialing number.
|
||||
*
|
||||
* @see TS.22.030 Figure 3.5.3.2.
|
||||
*/
|
||||
_matchMMIRegexp: function(mmiString) {
|
||||
// Regexp to parse and process the MMI code.
|
||||
if (this._mmiRegExp == null) {
|
||||
// The first group of the regexp takes the whole MMI string.
|
||||
// The second group takes the MMI procedure that can be:
|
||||
// - Activation (*SC*SI#).
|
||||
// - Deactivation (#SC*SI#).
|
||||
// - Interrogation (*#SC*SI#).
|
||||
// - Registration (**SC*SI#).
|
||||
// - Erasure (##SC*SI#).
|
||||
// where SC = Service Code (2 or 3 digits) and SI = Supplementary Info
|
||||
// (variable length).
|
||||
let pattern = "((\\*[*#]?|##?)";
|
||||
_buildMMIRegExp: function() {
|
||||
// The general structure of the codes is as follows:
|
||||
// - Activation (*SC*SI#).
|
||||
// - Deactivation (#SC*SI#).
|
||||
// - Interrogation (*#SC*SI#).
|
||||
// - Registration (**SC*SI#).
|
||||
// - Erasure (##SC*SI#).
|
||||
//
|
||||
// where SC = Service Code (2 or 3 digits) and SI = Supplementary Info
|
||||
// (variable length).
|
||||
|
||||
// Third group of the regexp looks for the MMI Service code, which is a
|
||||
// 2 or 3 digits that uniquely specifies the Supplementary Service
|
||||
// associated with the MMI code.
|
||||
pattern += "(\\d{2,3})";
|
||||
// MMI procedure, which could be *, #, *#, **, ##
|
||||
let procedure = "(\\*[*#]?|##?)";
|
||||
|
||||
// Groups from 4 to 9 looks for the MMI Supplementary Information SIA,
|
||||
// SIB and SIC. SIA may comprise e.g. a PIN code or Directory Number,
|
||||
// SIB may be used to specify the tele or bearer service and SIC to
|
||||
// specify the value of the "No Reply Condition Timer". Where a particular
|
||||
// service request does not require any SI, "*SI" is not entered. The use
|
||||
// of SIA, SIB and SIC is optional and shall be entered in any of the
|
||||
// following formats:
|
||||
// - *SIA*SIB*SIC#
|
||||
// - *SIA*SIB#
|
||||
// - *SIA**SIC#
|
||||
// - *SIA#
|
||||
// - **SIB*SIC#
|
||||
// - ***SISC#
|
||||
pattern += "(\\*([^*#]*)(\\*([^*#]*)(\\*([^*#]*)";
|
||||
// MMI Service code, which is a 2 or 3 digits that uniquely specifies the
|
||||
// Supplementary Service associated with the MMI code.
|
||||
let serviceCode = "(\\d{2,3})";
|
||||
|
||||
// The eleventh group takes the password for the case of a password
|
||||
// registration procedure.
|
||||
pattern += "(\\*([^*#]*))?)?)?)?#)";
|
||||
|
||||
// The last group takes the dial string after the #.
|
||||
pattern += "([^#]*)";
|
||||
|
||||
this._mmiRegExp = new RegExp(pattern);
|
||||
// MMI Supplementary Information SIA, SIB and SIC. SIA may comprise e.g. a
|
||||
// PIN code or Directory Number, SIB may be used to specify the tele or
|
||||
// bearer service and SIC to specify the value of the "No Reply Condition
|
||||
// Timer". Where a particular service request does not require any SI,
|
||||
// "*SI" is not entered. The use of SIA, SIB and SIC is optional and shall
|
||||
// be entered in any of the following formats:
|
||||
// - *SIA*SIB*SIC#
|
||||
// - *SIA*SIB#
|
||||
// - *SIA**SIC#
|
||||
// - *SIA#
|
||||
// - **SIB*SIC#
|
||||
// - ***SIC#
|
||||
//
|
||||
// Also catch the additional NEW_PASSWORD for the case of a password
|
||||
// registration procedure. Ex:
|
||||
// - * 03 * ZZ * OLD_PASSWORD * NEW_PASSWORD * NEW_PASSWORD #
|
||||
// - ** 03 * ZZ * OLD_PASSWORD * NEW_PASSWORD * NEW_PASSWORD #
|
||||
// - * 03 ** OLD_PASSWORD * NEW_PASSWORD * NEW_PASSWORD #
|
||||
// - ** 03 ** OLD_PASSWORD * NEW_PASSWORD * NEW_PASSWORD #
|
||||
let si = "\\*([^*#]*)";
|
||||
let allSi = "";
|
||||
for (let i = 0; i < 4; ++i) {
|
||||
allSi = "(?:" + si + allSi + ")?";
|
||||
}
|
||||
|
||||
// Regex only applys for those well-defined MMI strings (refer to TS.22.030
|
||||
// Annex B), otherwise, null should be the expected return value.
|
||||
return this._mmiRegExp.exec(mmiString);
|
||||
let fullmmi = "(" + procedure + serviceCode + allSi + "#)";
|
||||
|
||||
// dial string after the #.
|
||||
let dialString = "([^#]*)";
|
||||
|
||||
return new RegExp(fullmmi + dialString);
|
||||
},
|
||||
|
||||
/**
|
||||
* Provide the regex to parse MMI string.
|
||||
*/
|
||||
_getMMIRegExp: function() {
|
||||
if (!this._mmiRegExp) {
|
||||
this._mmiRegExp = this._buildMMIRegExp();
|
||||
}
|
||||
|
||||
return this._mmiRegExp;
|
||||
},
|
||||
|
||||
/**
|
||||
@ -2508,11 +2521,12 @@ RilObject.prototype = {
|
||||
return true;
|
||||
}
|
||||
|
||||
if ((mmiString.length != 2) || (mmiString.charAt(0) !== '1')) {
|
||||
return true;
|
||||
// Input string is 2 digits starting with a "1"
|
||||
if ((mmiString.length == 2) && (mmiString.charAt(0) === '1')) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return false;
|
||||
return true;
|
||||
},
|
||||
|
||||
sendMMI: function(options) {
|
||||
@ -3390,20 +3404,6 @@ RilObject.prototype = {
|
||||
Buf.sendParcel();
|
||||
},
|
||||
|
||||
/**
|
||||
* Checks whether to temporarily suppress caller id for the call.
|
||||
*
|
||||
* @param mmi
|
||||
* MMI full object.
|
||||
*/
|
||||
_isTemporaryModeCLIR: function(mmi) {
|
||||
return (mmi &&
|
||||
mmi.serviceCode == MMI_SC_CLIR &&
|
||||
mmi.dialNumber &&
|
||||
(mmi.procedure == MMI_PROCEDURE_ACTIVATION ||
|
||||
mmi.procedure == MMI_PROCEDURE_DEACTIVATION));
|
||||
},
|
||||
|
||||
/**
|
||||
* Report STK Service is running.
|
||||
*/
|
||||
|
@ -64,8 +64,7 @@ class Telephony::Callback : public nsITelephonyCallback
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
|
||||
Callback(Telephony* aTelephony, Promise* aPromise, uint32_t aServiceId,
|
||||
const nsAString& aNumber)
|
||||
Callback(Telephony* aTelephony, Promise* aPromise, uint32_t aServiceId)
|
||||
: mTelephony(aTelephony), mPromise(aPromise), mServiceId(aServiceId)
|
||||
{
|
||||
MOZ_ASSERT(mTelephony);
|
||||
@ -264,7 +263,7 @@ Telephony::DialInternal(uint32_t aServiceId, const nsAString& aNumber,
|
||||
}
|
||||
|
||||
nsCOMPtr<nsITelephonyCallback> callback =
|
||||
new Callback(this, promise, aServiceId, aNumber);
|
||||
new Callback(this, promise, aServiceId);
|
||||
nsresult rv = mService->Dial(aServiceId, aNumber, aEmergency, callback);
|
||||
if (NS_FAILED(rv)) {
|
||||
promise->MaybeReject(NS_ERROR_DOM_INVALID_STATE_ERR);
|
||||
|
@ -178,6 +178,10 @@ TelephonyService.prototype = {
|
||||
return gRadioInterfaceLayer.getRadioInterface(aClientId);
|
||||
},
|
||||
|
||||
_sendToRilWorker: function(aClientId, aType, aMessage, aCallback) {
|
||||
this._getClient(aClientId).sendWorkerMessage(aType, aMessage, aCallback);
|
||||
},
|
||||
|
||||
// An array of nsITelephonyListener instances.
|
||||
_listeners: null,
|
||||
_notifyAllListeners: function(aMethodName, aArgs) {
|
||||
@ -318,8 +322,7 @@ TelephonyService.prototype = {
|
||||
_enumerateCallsForClient: function(aClientId) {
|
||||
if (DEBUG) debug("Enumeration of calls for client " + aClientId);
|
||||
|
||||
this._getClient(aClientId).sendWorkerMessage("enumerateCalls", null,
|
||||
(function(response) {
|
||||
this._sendToRilWorker(aClientId, "enumerateCalls", null, response => {
|
||||
if (!this._currentCalls[aClientId]) {
|
||||
this._currentCalls[aClientId] = {};
|
||||
}
|
||||
@ -331,9 +334,7 @@ TelephonyService.prototype = {
|
||||
|
||||
this._currentCalls[aClientId][call.callIndex] = call;
|
||||
}
|
||||
|
||||
return false;
|
||||
}).bind(this));
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
@ -356,6 +357,35 @@ TelephonyService.prototype = {
|
||||
return numbers.indexOf(aNumber) != -1;
|
||||
},
|
||||
|
||||
/**
|
||||
* Checks whether to temporarily suppress caller id for the call.
|
||||
*
|
||||
* @param aMmi
|
||||
* MMI full object.
|
||||
*/
|
||||
_isTemporaryCLIR: function(aMmi) {
|
||||
return (aMmi && aMmi.serviceCode === RIL.MMI_SC_CLIR) && aMmi.dialNumber;
|
||||
},
|
||||
|
||||
/**
|
||||
* Map MMI procedure to CLIR MODE.
|
||||
*
|
||||
* @param aProcedure
|
||||
* MMI procedure
|
||||
*/
|
||||
_getTemporaryCLIRMode: function(aProcedure) {
|
||||
// In temporary mode, MMI_PROCEDURE_ACTIVATION means allowing CLI
|
||||
// presentation, i.e. CLIR_SUPPRESSION. See TS 22.030, Annex B.
|
||||
switch (aProcedure) {
|
||||
case RIL.MMI_PROCEDURE_ACTIVATION:
|
||||
return RIL.CLIR_SUPPRESSION;
|
||||
case RIL.MMI_PROCEDURE_DEACTIVATION:
|
||||
return RIL.CLIR_INVOCATION;
|
||||
default:
|
||||
return RIL.CLIR_DEFAULT;
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* nsITelephonyService interface.
|
||||
*/
|
||||
@ -456,7 +486,31 @@ TelephonyService.prototype = {
|
||||
this.notifyCallStateChanged(aClientId, parentCall);
|
||||
},
|
||||
|
||||
_composeDialRequest: function(aClientId, aNumber) {
|
||||
return new Promise((resolve, reject) => {
|
||||
this._sendToRilWorker(aClientId, "parseMMIFromDialNumber",
|
||||
{number: aNumber}, response => {
|
||||
let options = {};
|
||||
let mmi = response.mmi;
|
||||
|
||||
if (!mmi) {
|
||||
resolve({
|
||||
number: aNumber
|
||||
});
|
||||
} else if (this._isTemporaryCLIR(mmi)) {
|
||||
resolve({
|
||||
number: mmi.dialNumber,
|
||||
clirMode: this._getTemporaryCLIRMode(mmi.procedure)
|
||||
});
|
||||
} else {
|
||||
reject(DIAL_ERROR_BAD_NUMBER);
|
||||
}
|
||||
});
|
||||
});
|
||||
},
|
||||
|
||||
isDialing: false,
|
||||
|
||||
dial: function(aClientId, aNumber, aIsDialEmergency, aCallback) {
|
||||
if (DEBUG) debug("Dialing " + (aIsDialEmergency ? "emergency " : "") + aNumber);
|
||||
|
||||
@ -495,49 +549,48 @@ TelephonyService.prototype = {
|
||||
return;
|
||||
}
|
||||
|
||||
let isEmergencyNumber = this._isEmergencyNumber(aNumber);
|
||||
this._composeDialRequest(aClientId, aNumber).then(options => {
|
||||
options.isEmergency = this._isEmergencyNumber(options.number);
|
||||
options.isDialEmergency = aIsDialEmergency;
|
||||
|
||||
if (isEmergencyNumber) {
|
||||
// Automatically select a proper clientId for emergency call.
|
||||
aClientId = gRadioInterfaceLayer.getClientIdForEmergencyCall() ;
|
||||
if (aClientId === -1) {
|
||||
if (DEBUG) debug("Error: No client is avaialble for emergency call.");
|
||||
aCallback.notifyDialError(DIAL_ERROR_INVALID_STATE_ERROR);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
this.isDialing = true;
|
||||
|
||||
let options = {
|
||||
isDialEmergency: aIsDialEmergency,
|
||||
isEmergency: isEmergencyNumber,
|
||||
number: aNumber
|
||||
};
|
||||
|
||||
this._getClient(aClientId).sendWorkerMessage("dial", options,
|
||||
(function(response) {
|
||||
this.isDialing = false;
|
||||
if (!response.success) {
|
||||
aCallback.notifyDialError(response.errorMsg);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!response.isCdma) {
|
||||
aCallback.notifyDialSuccess(response.callIndex, response.number);
|
||||
} else {
|
||||
let currentCallId = Object.keys(this._currentCalls[aClientId])[0];
|
||||
if (currentCallId === undefined) {
|
||||
aCallback.notifyDialSuccess(response.callIndex, response.number);
|
||||
} else {
|
||||
// RIL doesn't hold the 2nd call. We create one by ourselves.
|
||||
aCallback.notifyDialSuccess(CDMA_SECOND_CALL_INDEX, response.number);
|
||||
this._addCdmaChildCall(aClientId, aNumber, currentCallId);
|
||||
if (options.isEmergency) {
|
||||
// Automatically select a proper clientId for emergency call.
|
||||
aClientId = gRadioInterfaceLayer.getClientIdForEmergencyCall() ;
|
||||
if (aClientId === -1) {
|
||||
if (DEBUG) debug("Error: No client is avaialble for emergency call.");
|
||||
aCallback.notifyDialError(DIAL_ERROR_INVALID_STATE_ERROR);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}).bind(this));
|
||||
this._dialInternal(aClientId, options, aCallback);
|
||||
}, cause => {
|
||||
aCallback.notifyDialError(DIAL_ERROR_BAD_NUMBER);
|
||||
});
|
||||
},
|
||||
|
||||
_dialInternal: function(aClientId, aOptions, aCallback) {
|
||||
this.isDialing = true;
|
||||
|
||||
this._sendToRilWorker(aClientId, "dial", aOptions, response => {
|
||||
this.isDialing = false;
|
||||
|
||||
if (!response.success) {
|
||||
aCallback.notifyDialError(response.errorMsg);
|
||||
return;
|
||||
}
|
||||
|
||||
let currentCdmaCallIndex = !response.isCdma ? null :
|
||||
Object.keys(this._currentCalls[aClientId])[0];
|
||||
|
||||
if (currentCdmaCallIndex == null) {
|
||||
aCallback.notifyDialSuccess(response.callIndex, response.number);
|
||||
} else {
|
||||
// RIL doesn't hold the 2nd call. We create one by ourselves.
|
||||
aCallback.notifyDialSuccess(CDMA_SECOND_CALL_INDEX, response.number);
|
||||
this._addCdmaChildCall(aClientId, aNumber, currentCdmaCallIndex);
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
hangUp: function(aClientId, aCallIndex) {
|
||||
@ -547,24 +600,24 @@ TelephonyService.prototype = {
|
||||
// the parent call, we send 'parentId' to RIL.
|
||||
this.hangUp(aClientId, parentId);
|
||||
} else {
|
||||
this._getClient(aClientId).sendWorkerMessage("hangUp", { callIndex: aCallIndex });
|
||||
this._sendToRilWorker(aClientId, "hangUp", { callIndex: aCallIndex });
|
||||
}
|
||||
},
|
||||
|
||||
startTone: function(aClientId, aDtmfChar) {
|
||||
this._getClient(aClientId).sendWorkerMessage("startTone", { dtmfChar: aDtmfChar });
|
||||
this._sendToRilWorker(aClientId, "startTone", { dtmfChar: aDtmfChar });
|
||||
},
|
||||
|
||||
stopTone: function(aClientId) {
|
||||
this._getClient(aClientId).sendWorkerMessage("stopTone");
|
||||
this._sendToRilWorker(aClientId, "stopTone");
|
||||
},
|
||||
|
||||
answerCall: function(aClientId, aCallIndex) {
|
||||
this._getClient(aClientId).sendWorkerMessage("answerCall", { callIndex: aCallIndex });
|
||||
this._sendToRilWorker(aClientId, "answerCall", { callIndex: aCallIndex });
|
||||
},
|
||||
|
||||
rejectCall: function(aClientId, aCallIndex) {
|
||||
this._getClient(aClientId).sendWorkerMessage("rejectCall", { callIndex: aCallIndex });
|
||||
this._sendToRilWorker(aClientId, "rejectCall", { callIndex: aCallIndex });
|
||||
},
|
||||
|
||||
holdCall: function(aClientId, aCallIndex) {
|
||||
@ -575,7 +628,7 @@ TelephonyService.prototype = {
|
||||
return;
|
||||
}
|
||||
|
||||
this._getClient(aClientId).sendWorkerMessage("holdCall", { callIndex: aCallIndex });
|
||||
this._sendToRilWorker(aClientId, "holdCall", { callIndex: aCallIndex });
|
||||
},
|
||||
|
||||
resumeCall: function(aClientId, aCallIndex) {
|
||||
@ -586,7 +639,7 @@ TelephonyService.prototype = {
|
||||
return;
|
||||
}
|
||||
|
||||
this._getClient(aClientId).sendWorkerMessage("resumeCall", { callIndex: aCallIndex });
|
||||
this._sendToRilWorker(aClientId, "resumeCall", { callIndex: aCallIndex });
|
||||
},
|
||||
|
||||
conferenceCall: function(aClientId) {
|
||||
@ -619,19 +672,17 @@ TelephonyService.prototype = {
|
||||
this.notifyConferenceCallStateChanged(RIL.CALL_STATE_ACTIVE);
|
||||
}
|
||||
|
||||
this._getClient(aClientId).sendWorkerMessage("conferenceCall", null,
|
||||
(function(response) {
|
||||
this._sendToRilWorker(aClientId, "conferenceCall", null, response => {
|
||||
if (!response.success) {
|
||||
this._notifyAllListeners("notifyConferenceError", [response.errorName,
|
||||
response.errorMsg]);
|
||||
return false;
|
||||
return;
|
||||
}
|
||||
|
||||
if (response.isCdma) {
|
||||
onCdmaConferenceCallSuccess.call(this);
|
||||
}
|
||||
return false;
|
||||
}).bind(this));
|
||||
});
|
||||
},
|
||||
|
||||
separateCall: function(aClientId, aCallIndex) {
|
||||
@ -664,28 +715,26 @@ TelephonyService.prototype = {
|
||||
this.notifyCallDisconnected(aClientId, childCall);
|
||||
}
|
||||
|
||||
this._getClient(aClientId).sendWorkerMessage("separateCall", {
|
||||
callIndex: aCallIndex
|
||||
}, (function(response) {
|
||||
this._sendToRilWorker(aClientId, "separateCall", { callIndex: aCallIndex },
|
||||
response => {
|
||||
if (!response.success) {
|
||||
this._notifyAllListeners("notifyConferenceError", [response.errorName,
|
||||
response.errorMsg]);
|
||||
return false;
|
||||
return;
|
||||
}
|
||||
|
||||
if (response.isCdma) {
|
||||
onCdmaSeparateCallSuccess.call(this);
|
||||
}
|
||||
return false;
|
||||
}).bind(this));
|
||||
});
|
||||
},
|
||||
|
||||
holdConference: function(aClientId) {
|
||||
this._getClient(aClientId).sendWorkerMessage("holdConference");
|
||||
this._sendToRilWorker(aClientId, "holdConference");
|
||||
},
|
||||
|
||||
resumeConference: function(aClientId) {
|
||||
this._getClient(aClientId).sendWorkerMessage("resumeConference");
|
||||
this._sendToRilWorker(aClientId, "resumeConference");
|
||||
},
|
||||
|
||||
get microphoneMuted() {
|
||||
|
@ -63,3 +63,4 @@ disabled = Bug 821958
|
||||
[test_incomingcall_phonestate_speaker.js]
|
||||
[test_temporary_clir.js]
|
||||
[test_outgoing_error_state.js]
|
||||
[test_mmi_code.js]
|
||||
|
23
dom/telephony/test/marionette/test_mmi_code.js
Normal file
23
dom/telephony/test/marionette/test_mmi_code.js
Normal file
@ -0,0 +1,23 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
MARIONETTE_TIMEOUT = 60000;
|
||||
MARIONETTE_HEAD_JS = 'head.js';
|
||||
|
||||
let number = "";
|
||||
|
||||
function dialMMI() {
|
||||
telephony.dial("*#06#").then(null, cause => {
|
||||
log("Received promise 'reject'");
|
||||
|
||||
is(telephony.active, null);
|
||||
is(telephony.calls.length, 0);
|
||||
is(cause, "BadNumberError");
|
||||
|
||||
finish();
|
||||
});
|
||||
}
|
||||
|
||||
startTest(function() {
|
||||
dialMMI();
|
||||
});
|
@ -169,6 +169,13 @@ void LossyConvertUTF8toUTF16(const char* aInput, uint32_t aLength, nsAString& aO
|
||||
uint32_t j = 0;
|
||||
for (uint32_t i = 0; i < srclen; i++, j++) {
|
||||
uint32_t v = uint32_t(src[i]);
|
||||
if (v == uint32_t('\0') && i < srclen - 1) {
|
||||
// If the leading byte is '\0' and it's not the last byte,
|
||||
// just ignore it to prevent from being truncated. This could
|
||||
// be caused by |convertToBytes| (e.g. \x00 would be converted to '\0')
|
||||
j--;
|
||||
continue;
|
||||
}
|
||||
if (!(v & 0x80)) {
|
||||
// ASCII code unit. Simple copy.
|
||||
dst[j] = char16_t(v);
|
||||
|
@ -2898,24 +2898,28 @@ WifiWorker.prototype = {
|
||||
// No change.
|
||||
if (enabled === WifiManager.enabled) {
|
||||
this._sendMessage(message, true, true, msg);
|
||||
return;
|
||||
}
|
||||
|
||||
// Can't enable wifi while hotspot mode is enabled.
|
||||
if (enabled && (this.tetheringSettings[SETTINGS_WIFI_TETHERING_ENABLED] ||
|
||||
WifiManager.isWifiTetheringEnabled(WifiManager.tetheringState))) {
|
||||
self._sendMessage(message, false, "Can't enable Wifi while hotspot mode is enabled", msg);
|
||||
}
|
||||
|
||||
// Reply error to pending requests.
|
||||
if (!enabled) {
|
||||
this._clearPendingRequest();
|
||||
return;
|
||||
}
|
||||
|
||||
WifiManager.setWifiEnabled(enabled, function(ok) {
|
||||
if (ok === 0 || ok === "no change") {
|
||||
self._sendMessage(message, true, true, msg);
|
||||
|
||||
// Reply error to pending requests.
|
||||
if (!enabled) {
|
||||
self._clearPendingRequest();
|
||||
} else {
|
||||
WifiManager.start();
|
||||
}
|
||||
} else {
|
||||
self._sendMessage(message, false, "Set power saving mode failed", msg);
|
||||
self._sendMessage(message, false, "Set wifi enabled failed", msg);
|
||||
}
|
||||
});
|
||||
},
|
||||
|
@ -258,29 +258,39 @@ let gTestSuite = (function() {
|
||||
*
|
||||
* @return a resolved promise or deferred promise.
|
||||
*/
|
||||
function ensureWifiEnabled(aEnabled) {
|
||||
function ensureWifiEnabled(aEnabled, useAPI) {
|
||||
if (wifiManager.enabled === aEnabled) {
|
||||
log('Already ' + (aEnabled ? 'enabled' : 'disabled'));
|
||||
return Promise.resolve();
|
||||
}
|
||||
return requestWifiEnabled(aEnabled);
|
||||
return requestWifiEnabled(aEnabled, useAPI);
|
||||
}
|
||||
|
||||
/**
|
||||
* Issue a request to enable/disable wifi.
|
||||
*
|
||||
* For current design, this function will attempt to enable/disable wifi by
|
||||
* writing 'wifi.enabled' regardless of the wifi state.
|
||||
* This function will attempt to enable/disable wifi, by calling API or by
|
||||
* writing settings 'wifi.enabled' regardless of the wifi state, based on the
|
||||
* value of |userAPI| parameter.
|
||||
* Default is using settings.
|
||||
*
|
||||
* Note there's a limitation of co-existance of both method, per bug 930355,
|
||||
* that once enable/disable wifi by API, the settings method won't work until
|
||||
* reboot. So the test of wifi enable API should be executed last.
|
||||
* TODO: Remove settings method after enable/disable wifi by settings is
|
||||
* removed after bug 1050147.
|
||||
*
|
||||
* Fulfill params: (none)
|
||||
* Reject params: (none)
|
||||
*
|
||||
* @return A deferred promise.
|
||||
*/
|
||||
function requestWifiEnabled(aEnabled) {
|
||||
function requestWifiEnabled(aEnabled, useAPI) {
|
||||
return Promise.all([
|
||||
waitForWifiManagerEventOnce(aEnabled ? 'enabled' : 'disabled'),
|
||||
setSettings({ 'wifi.enabled': aEnabled }),
|
||||
useAPI ?
|
||||
wrapDomRequestAsPromise(wifiManager.setWifiEnabled(aEnabled)) :
|
||||
setSettings({ 'wifi.enabled': aEnabled }),
|
||||
]);
|
||||
}
|
||||
|
||||
|
@ -11,3 +11,4 @@ qemu = true
|
||||
[test_wifi_tethering_wifi_disabled.js]
|
||||
[test_wifi_tethering_wifi_inactive.js]
|
||||
[test_wifi_tethering_wifi_active.js]
|
||||
[test_wifi_enable_api.js]
|
||||
|
13
dom/wifi/test/marionette/test_wifi_enable_api.js
Normal file
13
dom/wifi/test/marionette/test_wifi_enable_api.js
Normal file
@ -0,0 +1,13 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
MARIONETTE_TIMEOUT = 60000;
|
||||
MARIONETTE_HEAD_JS = 'head.js';
|
||||
|
||||
gTestSuite.doTest(function() {
|
||||
return Promise.resolve()
|
||||
.then(() => gTestSuite.ensureWifiEnabled(false, true))
|
||||
.then(() => gTestSuite.requestWifiEnabled(true, true))
|
||||
.then(() => gTestSuite.requestWifiEnabled(false, true))
|
||||
.then(() => gTestSuite.ensureWifiEnabled(true, true));
|
||||
});
|
@ -148,8 +148,10 @@ var tests = [
|
||||
|
||||
if (navigator.appVersion.indexOf("Android") == -1 &&
|
||||
SpecialPowers.Services.appinfo.name != "B2G") {
|
||||
tests.push(function() {SpecialPowers.setBoolPref("touchcaret.enabled", false);});
|
||||
tests.push([ 'bug512295-1.html' , 'bug512295-1-ref.html' ]);
|
||||
tests.push([ 'bug512295-2.html' , 'bug512295-2-ref.html' ]);
|
||||
tests.push(function() {SpecialPowers.clearUserPref("touchcaret.enabled");});
|
||||
tests.push(function() {SpecialPowers.setBoolPref("layout.css.overflow-clip-box.enabled", true);});
|
||||
tests.push([ 'bug966992-1.html' , 'bug966992-1-ref.html' ]);
|
||||
tests.push([ 'bug966992-2.html' , 'bug966992-2-ref.html' ]);
|
||||
|
Loading…
Reference in New Issue
Block a user