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
04c90e50f6
@ -707,6 +707,8 @@ var CustomEventManager = {
|
||||
switch(detail.type) {
|
||||
case 'webapps-install-granted':
|
||||
case 'webapps-install-denied':
|
||||
case 'webapps-uninstall-granted':
|
||||
case 'webapps-uninstall-denied':
|
||||
WebappsHelper.handleEvent(detail);
|
||||
break;
|
||||
case 'select-choicechange':
|
||||
@ -749,6 +751,7 @@ var WebappsHelper = {
|
||||
init: function webapps_init() {
|
||||
Services.obs.addObserver(this, "webapps-launch", false);
|
||||
Services.obs.addObserver(this, "webapps-ask-install", false);
|
||||
Services.obs.addObserver(this, "webapps-ask-uninstall", false);
|
||||
Services.obs.addObserver(this, "webapps-close", false);
|
||||
},
|
||||
|
||||
@ -771,6 +774,12 @@ var WebappsHelper = {
|
||||
case "webapps-install-denied":
|
||||
DOMApplicationRegistry.denyInstall(installer);
|
||||
break;
|
||||
case "webapps-uninstall-granted":
|
||||
DOMApplicationRegistry.confirmUninstall(installer);
|
||||
break;
|
||||
case "webapps-uninstall-denied":
|
||||
DOMApplicationRegistry.denyUninstall(installer);
|
||||
break;
|
||||
}
|
||||
},
|
||||
|
||||
@ -778,6 +787,8 @@ var WebappsHelper = {
|
||||
let json = JSON.parse(data);
|
||||
json.mm = subject;
|
||||
|
||||
let id;
|
||||
|
||||
switch(topic) {
|
||||
case "webapps-launch":
|
||||
DOMApplicationRegistry.getManifestFor(json.manifestURL).then((aManifest) => {
|
||||
@ -795,13 +806,21 @@ var WebappsHelper = {
|
||||
});
|
||||
break;
|
||||
case "webapps-ask-install":
|
||||
let id = this.registerInstaller(json);
|
||||
id = this.registerInstaller(json);
|
||||
shell.sendChromeEvent({
|
||||
type: "webapps-ask-install",
|
||||
id: id,
|
||||
app: json.app
|
||||
});
|
||||
break;
|
||||
case "webapps-ask-uninstall":
|
||||
id = this.registerInstaller(json);
|
||||
shell.sendChromeEvent({
|
||||
type: "webapps-ask-uninstall",
|
||||
id: id,
|
||||
app: json.app
|
||||
});
|
||||
break;
|
||||
case "webapps-close":
|
||||
shell.sendCustomEvent("webapps-close", {
|
||||
"manifestURL": json.manifestURL
|
||||
|
@ -15,7 +15,7 @@
|
||||
<project name="platform_build" path="build" remote="b2g" revision="53a59364ce4f14068034c8d6fe01f4f6b9f78f23">
|
||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="a25ae14dbd2fe3e25144a7064efc0cc4e31042b8"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="1934a2297ffc0d90424cd9cd3294c4a8c74a7333"/>
|
||||
<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"/>
|
||||
@ -133,9 +133,9 @@
|
||||
<project name="platform/hardware/akm" path="hardware/akm" revision="6d3be412647b0eab0adff8a2768736cf4eb68039"/>
|
||||
<project groups="invensense" name="platform/hardware/invensense" path="hardware/invensense" revision="e6d9ab28b4f4e7684f6c07874ee819c9ea0002a2"/>
|
||||
<project name="platform/hardware/ril" path="hardware/ril" revision="865ce3b4a2ba0b3a31421ca671f4d6c5595f8690"/>
|
||||
<project name="kernel/common" path="kernel" revision="388015e5f2f34a8156500226bf37be76a68154ce"/>
|
||||
<project name="kernel/common" path="kernel" revision="f3a717dd8dbb08e558c807c5ede071d83d454207"/>
|
||||
<project name="platform/system/core" path="system/core" revision="b5de04ae22343b6bdaa3455aee291bdf9a872738"/>
|
||||
<project name="u-boot" path="u-boot" revision="3ab28edd4be2673ac979a2338be8d9f0f25b8314"/>
|
||||
<project name="u-boot" path="u-boot" revision="d18f67c122a69f5ff7596a604cf484de5e824f9b"/>
|
||||
<project name="vendor/sprd/gps" path="vendor/sprd/gps" revision="7feb3df0e150053e0143ef525f6e082bda320aea"/>
|
||||
<project name="vendor/sprd/open-source" path="vendor/sprd/open-source" revision="8010ea42ca4963d610c88279dbe35dbaa2f6daf6"/>
|
||||
<project name="vendor/sprd/partner" path="vendor/sprd/partner" revision="8649c7145972251af11b0639997edfecabfc7c2e"/>
|
||||
|
@ -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="a25ae14dbd2fe3e25144a7064efc0cc4e31042b8"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="1934a2297ffc0d90424cd9cd3294c4a8c74a7333"/>
|
||||
<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"/>
|
||||
|
@ -17,7 +17,7 @@
|
||||
</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="a25ae14dbd2fe3e25144a7064efc0cc4e31042b8"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="1934a2297ffc0d90424cd9cd3294c4a8c74a7333"/>
|
||||
<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="d59843c1d66bd8d93c6012efda47fa447b99813c"/>
|
||||
|
@ -15,7 +15,7 @@
|
||||
<project name="platform_build" path="build" remote="b2g" revision="53a59364ce4f14068034c8d6fe01f4f6b9f78f23">
|
||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="a25ae14dbd2fe3e25144a7064efc0cc4e31042b8"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="1934a2297ffc0d90424cd9cd3294c4a8c74a7333"/>
|
||||
<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="a25ae14dbd2fe3e25144a7064efc0cc4e31042b8"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="1934a2297ffc0d90424cd9cd3294c4a8c74a7333"/>
|
||||
<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"/>
|
||||
|
@ -17,7 +17,7 @@
|
||||
</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="a25ae14dbd2fe3e25144a7064efc0cc4e31042b8"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="1934a2297ffc0d90424cd9cd3294c4a8c74a7333"/>
|
||||
<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="d59843c1d66bd8d93c6012efda47fa447b99813c"/>
|
||||
|
@ -4,6 +4,6 @@
|
||||
"remote": "",
|
||||
"branch": ""
|
||||
},
|
||||
"revision": "75d8e419442b5810145a888944ab0ab4f75bbcc9",
|
||||
"revision": "5efa211f0198ab15798b456445f163d57e735cdb",
|
||||
"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="a25ae14dbd2fe3e25144a7064efc0cc4e31042b8"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="1934a2297ffc0d90424cd9cd3294c4a8c74a7333"/>
|
||||
<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="a25ae14dbd2fe3e25144a7064efc0cc4e31042b8"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="1934a2297ffc0d90424cd9cd3294c4a8c74a7333"/>
|
||||
<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"/>
|
||||
|
@ -17,7 +17,7 @@
|
||||
</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="a25ae14dbd2fe3e25144a7064efc0cc4e31042b8"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="1934a2297ffc0d90424cd9cd3294c4a8c74a7333"/>
|
||||
<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="d59843c1d66bd8d93c6012efda47fa447b99813c"/>
|
||||
|
@ -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="a25ae14dbd2fe3e25144a7064efc0cc4e31042b8"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="1934a2297ffc0d90424cd9cd3294c4a8c74a7333"/>
|
||||
<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"/>
|
||||
|
@ -233,8 +233,10 @@ Tools.canvasDebugger = {
|
||||
label: l10n("ToolboxCanvasDebugger.label", canvasDebuggerStrings),
|
||||
panelLabel: l10n("ToolboxCanvasDebugger.panelLabel", canvasDebuggerStrings),
|
||||
tooltip: l10n("ToolboxCanvasDebugger.tooltip", canvasDebuggerStrings),
|
||||
// Hide the Canvas Debugger in the Add-on Debugger and Browser Toolbox
|
||||
// (bug 1047520).
|
||||
isTargetSupported: function(target) {
|
||||
return !target.isAddon;
|
||||
return !target.isAddon && !target.chrome;
|
||||
},
|
||||
build: function (iframeWindow, toolbox) {
|
||||
let panel = new CanvasDebuggerPanel(iframeWindow, toolbox);
|
||||
|
@ -500,8 +500,7 @@ StyleEditorUI.prototype = {
|
||||
this._selectEditor(editor);
|
||||
}
|
||||
|
||||
if (this._styleSheetToSelect
|
||||
&& this._styleSheetToSelect.stylesheet == editor.styleSheet.href) {
|
||||
if (this._isEditorToSelect(editor)) {
|
||||
this.switchToSelectedSheet();
|
||||
}
|
||||
|
||||
@ -566,25 +565,42 @@ StyleEditorUI.prototype = {
|
||||
* Promise that will resolve when the editor is selected.
|
||||
*/
|
||||
switchToSelectedSheet: function() {
|
||||
let sheet = this._styleSheetToSelect;
|
||||
let isHref = sheet.stylesheet === null || typeof sheet.stylesheet == "string";
|
||||
let toSelect = this._styleSheetToSelect;
|
||||
|
||||
for (let editor of this.editors) {
|
||||
if ((isHref && editor.styleSheet.href == sheet.stylesheet) ||
|
||||
sheet.stylesheet == editor.styleSheet) {
|
||||
if (this._isEditorToSelect(editor)) {
|
||||
// The _styleSheetBoundToSelect will always hold the latest pending
|
||||
// requested style sheet (with line and column) which is not yet
|
||||
// selected by the source editor. Only after we select that particular
|
||||
// editor and go the required line and column, it will become null.
|
||||
this._styleSheetBoundToSelect = this._styleSheetToSelect;
|
||||
this._styleSheetToSelect = null;
|
||||
return this._selectEditor(editor, sheet.line, sheet.col);
|
||||
return this._selectEditor(editor, toSelect.line, toSelect.col);
|
||||
}
|
||||
}
|
||||
|
||||
return promise.resolve();
|
||||
},
|
||||
|
||||
/**
|
||||
* Returns whether a given editor is the current editor to be selected. Tests
|
||||
* based on href or underlying stylesheet.
|
||||
*
|
||||
* @param {StyleSheetEditor} editor
|
||||
* The editor to test.
|
||||
*/
|
||||
_isEditorToSelect: function(editor) {
|
||||
let toSelect = this._styleSheetToSelect;
|
||||
if (!toSelect) {
|
||||
return false;
|
||||
}
|
||||
let isHref = toSelect.stylesheet === null ||
|
||||
typeof toSelect.stylesheet == "string";
|
||||
|
||||
return (isHref && editor.styleSheet.href == toSelect.stylesheet) ||
|
||||
(toSelect.stylesheet == editor.styleSheet);
|
||||
},
|
||||
|
||||
/**
|
||||
* Select an editor in the UI.
|
||||
*
|
||||
|
@ -42,6 +42,7 @@ function test() {
|
||||
|
||||
function checkCache() {
|
||||
checkDiskCacheFor(TEST_HOST, function() {
|
||||
gUI.off("editor-added", onEditorAdded);
|
||||
win.close();
|
||||
win = null;
|
||||
gUI = null;
|
||||
|
@ -1424,19 +1424,16 @@ SelectorView.prototype = {
|
||||
return;
|
||||
}
|
||||
|
||||
let location = promise.resolve({
|
||||
href: rule.href,
|
||||
line: rule.line
|
||||
});
|
||||
if (rule.href && Services.prefs.getBoolPref(PREF_ORIG_SOURCES)) {
|
||||
let location = promise.resolve(rule.location);
|
||||
if (Services.prefs.getBoolPref(PREF_ORIG_SOURCES)) {
|
||||
location = rule.getOriginalLocation();
|
||||
}
|
||||
|
||||
location.then(({href, line}) => {
|
||||
location.then(({source, href, line, column}) => {
|
||||
let target = inspector.target;
|
||||
if (ToolDefinitions.styleEditor.isTargetSupported(target)) {
|
||||
gDevTools.showToolbox(target, "styleeditor").then(function(toolbox) {
|
||||
toolbox.getCurrentPanel().selectStyleSheet(href, line);
|
||||
let sheet = source || href;
|
||||
toolbox.getCurrentPanel().selectStyleSheet(sheet, line, column);
|
||||
});
|
||||
}
|
||||
});
|
||||
|
@ -61,11 +61,12 @@ function RuleViewTool(aInspector, aWindow, aIFrame)
|
||||
if (Services.prefs.getBoolPref(PREF_ORIG_SOURCES)) {
|
||||
location = rule.getOriginalLocation();
|
||||
}
|
||||
location.then(({ href, line, column }) => {
|
||||
location.then(({ source, href, line, column }) => {
|
||||
let target = this.inspector.target;
|
||||
if (ToolDefinitions.styleEditor.isTargetSupported(target)) {
|
||||
gDevTools.showToolbox(target, "styleeditor").then(function(toolbox) {
|
||||
toolbox.getCurrentPanel().selectStyleSheet(href, line, column);
|
||||
let sheet = source || href;
|
||||
toolbox.getCurrentPanel().selectStyleSheet(sheet, line, column);
|
||||
});
|
||||
}
|
||||
return;
|
||||
|
@ -21,6 +21,9 @@ const DOCUMENT_URL = "data:text/html;charset=utf-8,"+encodeURIComponent(
|
||||
'.nomatches {color: #ff0000;}</style> <div id="first" style="margin: 10em; ',
|
||||
'font-size: 14pt; font-family: helvetica, sans-serif; color: #AAA">',
|
||||
'</style>',
|
||||
'<style>',
|
||||
'div { color: #f06; }',
|
||||
'</style>',
|
||||
'<link rel="stylesheet" type="text/css" href="'+STYLESHEET_URL+'">',
|
||||
'</head>',
|
||||
'<body>',
|
||||
@ -50,7 +53,8 @@ let test = asyncTest(function*() {
|
||||
yield selectNode("span", inspector);
|
||||
|
||||
yield testInlineStyle(view, inspector);
|
||||
yield testInlineStyleSheet(view, toolbox);
|
||||
yield testFirstInlineStyleSheet(view, toolbox);
|
||||
yield testSecondInlineStyleSheet(view, toolbox);
|
||||
yield testExternalStyleSheet(view, toolbox);
|
||||
});
|
||||
|
||||
@ -61,8 +65,7 @@ function* testInlineStyle(view, inspector) {
|
||||
|
||||
let onWindow = waitForWindow();
|
||||
info("Clicking on the first rule-link in the computed-view");
|
||||
let link = getComputedViewLinkByIndex(view, 0);
|
||||
link.click();
|
||||
clickLinkByIndex(view, 0);
|
||||
|
||||
let win = yield onWindow;
|
||||
|
||||
@ -72,15 +75,14 @@ function* testInlineStyle(view, inspector) {
|
||||
win.close();
|
||||
}
|
||||
|
||||
function* testInlineStyleSheet(view, toolbox) {
|
||||
function* testFirstInlineStyleSheet(view, toolbox) {
|
||||
info("Testing inline stylesheet");
|
||||
|
||||
info("Listening for toolbox switch to the styleeditor");
|
||||
let onSwitch = waitForStyleEditor(toolbox);
|
||||
|
||||
info("Clicking an inline stylesheet");
|
||||
let link = getComputedViewLinkByIndex(view, 2);
|
||||
link.click();
|
||||
clickLinkByIndex(view, 2);
|
||||
let editor = yield onSwitch;
|
||||
|
||||
ok(true, "Switched to the style-editor panel in the toolbox");
|
||||
@ -88,6 +90,24 @@ function* testInlineStyleSheet(view, toolbox) {
|
||||
validateStyleEditorSheet(editor, 0);
|
||||
}
|
||||
|
||||
function* testSecondInlineStyleSheet(view, toolbox) {
|
||||
info("Testing second inline stylesheet");
|
||||
|
||||
info("Waiting for the stylesheet editor to be selected");
|
||||
let panel = toolbox.getCurrentPanel();
|
||||
let onSelected = panel.UI.once("editor-selected");
|
||||
|
||||
info("Switching back to the inspector panel in the toolbox");
|
||||
yield toolbox.selectTool("inspector");
|
||||
|
||||
info("Clicking on second inline stylesheet link");
|
||||
clickLinkByIndex(view, 4);
|
||||
let editor = yield onSelected;
|
||||
|
||||
is(toolbox.currentToolId, "styleeditor", "The style editor is selected again");
|
||||
validateStyleEditorSheet(editor, 1);
|
||||
}
|
||||
|
||||
function* testExternalStyleSheet(view, toolbox) {
|
||||
info("Testing external stylesheet");
|
||||
|
||||
@ -99,12 +119,11 @@ function* testExternalStyleSheet(view, toolbox) {
|
||||
yield toolbox.selectTool("inspector");
|
||||
|
||||
info("Clicking on an external stylesheet link");
|
||||
let link = getComputedViewLinkByIndex(view, 1);
|
||||
link.click();
|
||||
clickLinkByIndex(view, 1);
|
||||
let editor = yield onSelected;
|
||||
|
||||
is(toolbox.currentToolId, "styleeditor", "The style editor is selected again");
|
||||
validateStyleEditorSheet(editor, 1);
|
||||
validateStyleEditorSheet(editor, 2);
|
||||
}
|
||||
|
||||
function validateStyleEditorSheet(editor, expectedSheetIndex) {
|
||||
@ -112,3 +131,9 @@ function validateStyleEditorSheet(editor, expectedSheetIndex) {
|
||||
let sheet = content.document.styleSheets[expectedSheetIndex];
|
||||
is(editor.styleSheet.href, sheet.href, "loaded stylesheet matches document stylesheet");
|
||||
}
|
||||
|
||||
function clickLinkByIndex(view, index) {
|
||||
let link = getComputedViewLinkByIndex(view, index);
|
||||
link.scrollIntoView();
|
||||
link.click();
|
||||
}
|
||||
|
@ -24,6 +24,9 @@ const DOCUMENT_URL = "data:text/html;charset=utf-8,"+encodeURIComponent(
|
||||
'.nomatches {color: #ff0000;}</style> <div id="first" style="margin: 10em; ',
|
||||
'font-size: 14pt; font-family: helvetica, sans-serif; color: #AAA">',
|
||||
'</style>',
|
||||
'<style>',
|
||||
'div { font-weight: bold; }',
|
||||
'</style>',
|
||||
'<link rel="stylesheet" type="text/css" href="'+STYLESHEET_URL+'">',
|
||||
'<link rel="stylesheet" type="text/css" href="'+EXTERNAL_STYLESHEET_URL+'">',
|
||||
'</head>',
|
||||
@ -52,7 +55,8 @@ let test = asyncTest(function*() {
|
||||
yield selectNode("div", inspector);
|
||||
|
||||
yield testInlineStyle(view, inspector);
|
||||
yield testInlineStyleSheet(view, toolbox);
|
||||
yield testFirstInlineStyleSheet(view, toolbox);
|
||||
yield testSecondInlineStyleSheet(view, toolbox);
|
||||
yield testExternalStyleSheet(view, toolbox);
|
||||
});
|
||||
|
||||
@ -61,9 +65,7 @@ function* testInlineStyle(view, inspector) {
|
||||
|
||||
let onWindow = waitForWindow();
|
||||
info("Clicking on the first link in the rule-view");
|
||||
let link = getRuleViewLinkByIndex(view, 0);
|
||||
link.scrollIntoView();
|
||||
link.click();
|
||||
clickLinkByIndex(view, 0);
|
||||
|
||||
let win = yield onWindow;
|
||||
|
||||
@ -73,16 +75,14 @@ function* testInlineStyle(view, inspector) {
|
||||
win.close();
|
||||
}
|
||||
|
||||
function* testInlineStyleSheet(view, toolbox) {
|
||||
function* testFirstInlineStyleSheet(view, toolbox) {
|
||||
info("Testing inline stylesheet");
|
||||
|
||||
info("Listening for toolbox switch to the styleeditor");
|
||||
let onSwitch = waitForStyleEditor(toolbox);
|
||||
|
||||
info("Clicking an inline stylesheet");
|
||||
let link = getRuleViewLinkByIndex(view, 4);
|
||||
link.scrollIntoView();
|
||||
link.click();
|
||||
clickLinkByIndex(view, 4);
|
||||
let editor = yield onSwitch;
|
||||
|
||||
ok(true, "Switched to the style-editor panel in the toolbox");
|
||||
@ -90,6 +90,25 @@ function* testInlineStyleSheet(view, toolbox) {
|
||||
validateStyleEditorSheet(editor, 0);
|
||||
}
|
||||
|
||||
function* testSecondInlineStyleSheet(view, toolbox) {
|
||||
info("Testing second inline stylesheet");
|
||||
|
||||
info("Waiting for the stylesheet editor to be selected");
|
||||
let panel = toolbox.getCurrentPanel();
|
||||
let onSelected = panel.UI.once("editor-selected");
|
||||
|
||||
info("Switching back to the inspector panel in the toolbox");
|
||||
yield toolbox.selectTool("inspector");
|
||||
|
||||
info("Clicking on second inline stylesheet link");
|
||||
testRuleViewLinkLabel(view);
|
||||
clickLinkByIndex(view, 3);
|
||||
let editor = yield onSelected;
|
||||
|
||||
is(toolbox.currentToolId, "styleeditor", "The style editor is selected again");
|
||||
validateStyleEditorSheet(editor, 1);
|
||||
}
|
||||
|
||||
function* testExternalStyleSheet(view, toolbox) {
|
||||
info("Testing external stylesheet");
|
||||
|
||||
@ -102,19 +121,20 @@ function* testExternalStyleSheet(view, toolbox) {
|
||||
|
||||
info("Clicking on an external stylesheet link");
|
||||
testRuleViewLinkLabel(view);
|
||||
let link = getRuleViewLinkByIndex(view, 1);
|
||||
link.scrollIntoView();
|
||||
link.click();
|
||||
clickLinkByIndex(view, 1);
|
||||
let editor = yield onSelected;
|
||||
|
||||
is(toolbox.currentToolId, "styleeditor", "The style editor is selected again");
|
||||
validateStyleEditorSheet(editor, 1);
|
||||
validateStyleEditorSheet(editor, 2);
|
||||
}
|
||||
|
||||
function validateStyleEditorSheet(editor, expectedSheetIndex) {
|
||||
info("validating style editor stylesheet");
|
||||
is(editor.styleSheet.styleSheetIndex, expectedSheetIndex,
|
||||
"loaded stylesheet index matches document stylesheet");
|
||||
|
||||
let sheet = content.document.styleSheets[expectedSheetIndex];
|
||||
is(editor.styleSheet.href, sheet.href, "loaded stylesheet matches document stylesheet");
|
||||
is(editor.styleSheet.href, sheet.href, "loaded stylesheet href matches document stylesheet");
|
||||
}
|
||||
|
||||
function testRuleViewLinkLabel(view) {
|
||||
@ -128,3 +148,9 @@ function testRuleViewLinkLabel(view) {
|
||||
is(tooltipText, EXTERNAL_STYLESHEET_URL,
|
||||
"rule view stylesheet tooltip text matches the full URI path");
|
||||
}
|
||||
|
||||
function clickLinkByIndex(view, index) {
|
||||
let link = getRuleViewLinkByIndex(view, index);
|
||||
link.scrollIntoView();
|
||||
link.click();
|
||||
}
|
||||
|
@ -449,6 +449,12 @@ webapps.install.accesskey = I
|
||||
webapps.requestInstall = Do you want to install "%1$S" from this site (%2$S)?
|
||||
webapps.install.success = Application Installed
|
||||
webapps.install.inprogress = Installation in progress
|
||||
webapps.uninstall = Uninstall
|
||||
webapps.uninstall.accesskey = U
|
||||
webapps.doNotUninstall = Don't Uninstall
|
||||
webapps.doNotUninstall.accesskey = D
|
||||
#LOCALIZATION NOTE (webapps.requestUninstall) %1$S is the web app name
|
||||
webapps.requestUninstall = Do you want to uninstall "%1$S"?
|
||||
|
||||
# LOCALIZATION NOTE (fullscreen.entered): displayed when we enter HTML5 fullscreen mode, %S is the domain name of the focused website (e.g. mozilla.com).
|
||||
fullscreen.entered=%S is now fullscreen.
|
||||
|
@ -31,6 +31,7 @@ this.WebappManager = {
|
||||
|
||||
init: function() {
|
||||
Services.obs.addObserver(this, "webapps-ask-install", false);
|
||||
Services.obs.addObserver(this, "webapps-ask-uninstall", false);
|
||||
Services.obs.addObserver(this, "webapps-launch", false);
|
||||
Services.obs.addObserver(this, "webapps-uninstall", false);
|
||||
cpmm.addMessageListener("Webapps:Install:Return:OK", this);
|
||||
@ -40,6 +41,7 @@ this.WebappManager = {
|
||||
|
||||
uninit: function() {
|
||||
Services.obs.removeObserver(this, "webapps-ask-install");
|
||||
Services.obs.removeObserver(this, "webapps-ask-uninstall");
|
||||
Services.obs.removeObserver(this, "webapps-launch");
|
||||
Services.obs.removeObserver(this, "webapps-uninstall");
|
||||
cpmm.removeMessageListener("Webapps:Install:Return:OK", this);
|
||||
@ -81,13 +83,20 @@ this.WebappManager = {
|
||||
let data = JSON.parse(aData);
|
||||
data.mm = aSubject;
|
||||
|
||||
let win;
|
||||
switch(aTopic) {
|
||||
case "webapps-ask-install":
|
||||
let win = this._getWindowForId(data.oid);
|
||||
win = this._getWindowForId(data.oid);
|
||||
if (win && win.location.href == data.from) {
|
||||
this.doInstall(data, win);
|
||||
}
|
||||
break;
|
||||
case "webapps-ask-uninstall":
|
||||
win = this._getWindowForId(data.windowId);
|
||||
if (win && win.location.href == data.from) {
|
||||
this.doUninstall(data, win);
|
||||
}
|
||||
break;
|
||||
case "webapps-launch":
|
||||
WebappOSUtils.launch(data);
|
||||
break;
|
||||
@ -193,6 +202,49 @@ this.WebappManager = {
|
||||
"webapps-notification-icon",
|
||||
mainAction);
|
||||
|
||||
},
|
||||
|
||||
doUninstall: function(aData, aWindow) {
|
||||
let browser = aWindow.QueryInterface(Ci.nsIInterfaceRequestor)
|
||||
.getInterface(Ci.nsIWebNavigation)
|
||||
.QueryInterface(Ci.nsIDocShell)
|
||||
.chromeEventHandler;
|
||||
let chromeDoc = browser.ownerDocument;
|
||||
let chromeWin = chromeDoc.defaultView;
|
||||
|
||||
let bundle = chromeWin.gNavigatorBundle;
|
||||
let jsonManifest = aData.app.manifest;
|
||||
|
||||
let notification;
|
||||
|
||||
let mainAction = {
|
||||
label: bundle.getString("webapps.uninstall"),
|
||||
accessKey: bundle.getString("webapps.uninstall.accesskey"),
|
||||
callback: () => {
|
||||
notification.remove();
|
||||
DOMApplicationRegistry.confirmUninstall(aData);
|
||||
}
|
||||
};
|
||||
|
||||
let secondaryAction = {
|
||||
label: bundle.getString("webapps.doNotUninstall"),
|
||||
accessKey: bundle.getString("webapps.doNotUninstall.accesskey"),
|
||||
callback: () => {
|
||||
notification.remove();
|
||||
DOMApplicationRegistry.denyUninstall(aData, "USER_DECLINED");
|
||||
}
|
||||
};
|
||||
|
||||
let manifest = new ManifestHelper(jsonManifest, aData.app.origin,
|
||||
aData.app.manifestURL);
|
||||
|
||||
let message = bundle.getFormattedString("webapps.requestUninstall",
|
||||
[manifest.name]);
|
||||
|
||||
notification = chromeWin.PopupNotifications.show(
|
||||
browser, "webapps-uninstall", message,
|
||||
"webapps-notification-icon",
|
||||
mainAction, [secondaryAction]);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -405,9 +405,10 @@ interface nsIFrameScriptLoader : nsISupports
|
||||
jsval getDelayedFrameScripts();
|
||||
};
|
||||
|
||||
[scriptable, builtinclass, uuid(ad57800b-ff21-4e2f-91d3-e68615ae8afe)]
|
||||
[scriptable, builtinclass, uuid(637e8538-4f8f-4a3d-8510-e74386233e19)]
|
||||
interface nsIProcessChecker : nsISupports
|
||||
{
|
||||
bool killChild();
|
||||
|
||||
/**
|
||||
* Return true if the "remote" process has |aPermission|. This is
|
||||
|
@ -803,6 +803,18 @@ nsFrameMessageManager::Atob(const nsAString& aAsciiString,
|
||||
|
||||
// nsIProcessChecker
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsFrameMessageManager::KillChild(bool *aValid)
|
||||
{
|
||||
if (!mCallback) {
|
||||
*aValid = false;
|
||||
return NS_ERROR_NOT_AVAILABLE;
|
||||
}
|
||||
|
||||
*aValid = mCallback->KillChild();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsFrameMessageManager::AssertProcessInternal(ProcessCheckerType aType,
|
||||
const nsAString& aCapability,
|
||||
|
@ -98,6 +98,12 @@ public:
|
||||
return false;
|
||||
}
|
||||
|
||||
virtual bool KillChild()
|
||||
{
|
||||
// By default, does nothing.
|
||||
return false;
|
||||
}
|
||||
|
||||
protected:
|
||||
bool BuildClonedMessageDataForParent(nsIContentParent* aParent,
|
||||
const StructuredCloneData& aData,
|
||||
|
@ -54,10 +54,12 @@
|
||||
}
|
||||
|
||||
function cleanup() {
|
||||
let req = navigator.mozApps.mgmt.uninstall(app);
|
||||
req.onsuccess = function () {
|
||||
SimpleTest.finish();
|
||||
};
|
||||
SpecialPowers.autoConfirmAppUninstall(function () {
|
||||
let req = navigator.mozApps.mgmt.uninstall(app);
|
||||
req.onsuccess = function () {
|
||||
SimpleTest.finish();
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
setupTest();
|
||||
|
@ -69,11 +69,19 @@ GetPluginFile(const std::string& aPluginPath,
|
||||
}
|
||||
#endif
|
||||
|
||||
nsAutoString leafName;
|
||||
if (NS_FAILED(aLibFile->GetLeafName(leafName))) {
|
||||
nsCOMPtr<nsIFile> parent;
|
||||
rv = aLibFile->GetParent(getter_AddRefs(parent));
|
||||
if (NS_FAILED(rv)) {
|
||||
return false;
|
||||
}
|
||||
nsAutoString baseName(Substring(leafName, 4, leafName.Length() - 1));
|
||||
|
||||
nsAutoString parentLeafName;
|
||||
rv = parent->GetLeafName(parentLeafName);
|
||||
if (NS_FAILED(rv)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
nsAutoString baseName(Substring(parentLeafName, 4, parentLeafName.Length() - 1));
|
||||
|
||||
#if defined(XP_MACOSX)
|
||||
nsAutoString binaryName = NS_LITERAL_STRING("lib") + baseName + NS_LITERAL_STRING(".dylib");
|
||||
|
@ -90,16 +90,23 @@ GMPParent::Init(GeckoMediaPluginService *aService, nsIFile* aPluginDir)
|
||||
mService = aService;
|
||||
mDirectory = aPluginDir;
|
||||
|
||||
nsAutoString leafname;
|
||||
nsresult rv = aPluginDir->GetLeafName(leafname);
|
||||
// aPluginDir is <profile-dir>/<gmp-plugin-id>/<version>
|
||||
// where <gmp-plugin-id> should be gmp-gmpopenh264
|
||||
nsCOMPtr<nsIFile> parent;
|
||||
nsresult rv = aPluginDir->GetParent(getter_AddRefs(parent));
|
||||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
}
|
||||
nsAutoString parentLeafName;
|
||||
rv = parent->GetLeafName(parentLeafName);
|
||||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
}
|
||||
LOGD(("%s::%s: %p for %s", __CLASS__, __FUNCTION__, this,
|
||||
NS_LossyConvertUTF16toASCII(leafname).get()));
|
||||
NS_LossyConvertUTF16toASCII(parentLeafName).get()));
|
||||
|
||||
MOZ_ASSERT(leafname.Length() > 4);
|
||||
mName = Substring(leafname, 4);
|
||||
MOZ_ASSERT(parentLeafName.Length() > 4);
|
||||
mName = Substring(parentLeafName, 4);
|
||||
|
||||
return ReadGMPMetaData();
|
||||
}
|
||||
|
@ -215,6 +215,7 @@ WebappsRegistry.prototype = {
|
||||
let mgmt = Cc["@mozilla.org/webapps/manager;1"]
|
||||
.createInstance(Ci.nsISupports);
|
||||
mgmt.wrappedJSObject.init(this._window);
|
||||
mgmt.wrappedJSObject._windowId = this._id;
|
||||
this._mgmt = mgmt.__DOM_IMPL__
|
||||
? mgmt.__DOM_IMPL__
|
||||
: this._window.DOMApplicationsManager._create(this._window, mgmt.wrappedJSObject);
|
||||
@ -721,10 +722,15 @@ WebappsApplicationMgmt.prototype = {
|
||||
|
||||
uninstall: function(aApp) {
|
||||
let request = this.createRequest();
|
||||
cpmm.sendAsyncMessage("Webapps:Uninstall", { origin: aApp.origin,
|
||||
manifestURL: aApp.manifestURL,
|
||||
oid: this._id,
|
||||
requestID: this.getRequestId(request) });
|
||||
|
||||
cpmm.sendAsyncMessage("Webapps:Uninstall", {
|
||||
origin: aApp.origin,
|
||||
manifestURL: aApp.manifestURL,
|
||||
oid: this._id,
|
||||
from: this._window.location.href,
|
||||
windowId: this._windowId,
|
||||
requestID: this.getRequestId(request)
|
||||
});
|
||||
return request;
|
||||
},
|
||||
|
||||
|
@ -162,6 +162,7 @@ this.DOMApplicationRegistry = {
|
||||
children: [ ],
|
||||
allAppsLaunchable: false,
|
||||
_updateHandlers: [ ],
|
||||
_pendingUninstalls: {},
|
||||
|
||||
init: function() {
|
||||
this.messages = ["Webapps:Install", "Webapps:Uninstall",
|
||||
@ -547,7 +548,7 @@ this.DOMApplicationRegistry = {
|
||||
if (this.webapps[id].manifestURL === httpsManifestURL) {
|
||||
debug("Found a http/https match: " + app.manifestURL + " / " +
|
||||
this.webapps[id].manifestURL);
|
||||
this.uninstall(app.manifestURL, function() {}, function() {});
|
||||
this.uninstall(app.manifestURL);
|
||||
return;
|
||||
}
|
||||
}
|
||||
@ -2638,7 +2639,7 @@ this.DOMApplicationRegistry = {
|
||||
manifest: jsonManifest
|
||||
},
|
||||
isReinstall,
|
||||
this.uninstall.bind(this, aData, aData.mm)
|
||||
this.doUninstall.bind(this, aData, aData.mm)
|
||||
);
|
||||
}
|
||||
|
||||
@ -3675,39 +3676,50 @@ this.DOMApplicationRegistry = {
|
||||
AppDownloadManager.remove(aNewApp.manifestURL);
|
||||
},
|
||||
|
||||
doUninstall: function(aData, aMm) {
|
||||
this.uninstall(aData.manifestURL,
|
||||
function onsuccess() {
|
||||
aMm.sendAsyncMessage("Webapps:Uninstall:Return:OK", aData);
|
||||
},
|
||||
function onfailure() {
|
||||
// Fall-through, fails to uninstall the desired app because:
|
||||
// - we cannot find the app to be uninstalled.
|
||||
// - the app to be uninstalled is not removable.
|
||||
aMm.sendAsyncMessage("Webapps:Uninstall:Return:KO", aData);
|
||||
doUninstall: Task.async(function*(aData, aMm) {
|
||||
// The yields here could get stuck forever, so we only hold
|
||||
// a weak reference to the message manager while yielding, to avoid
|
||||
// leaking the whole page associationed with the message manager.
|
||||
aMm = Cu.getWeakReference(aMm);
|
||||
|
||||
let response = "Webapps:Uninstall:Return:OK";
|
||||
|
||||
try {
|
||||
aData.app = yield this._getAppWithManifest(aData.manifestURL);
|
||||
|
||||
let prefName = "dom.mozApps.auto_confirm_uninstall";
|
||||
if (Services.prefs.prefHasUserValue(prefName) &&
|
||||
Services.prefs.getBoolPref(prefName)) {
|
||||
yield this._uninstallApp(aData.app);
|
||||
} else {
|
||||
yield this._promptForUninstall(aData);
|
||||
}
|
||||
);
|
||||
} catch (error) {
|
||||
aData.error = error;
|
||||
response = "Webapps:Uninstall:Return:KO";
|
||||
}
|
||||
|
||||
if (aMm = aMm.get()) {
|
||||
aMm.sendAsyncMessage(response, aData);
|
||||
}
|
||||
}),
|
||||
|
||||
uninstall: function(aManifestURL) {
|
||||
return this._getAppWithManifest(aManifestURL)
|
||||
.then(this._uninstallApp.bind(this));
|
||||
},
|
||||
|
||||
uninstall: function(aManifestURL, aOnSuccess, aOnFailure) {
|
||||
debug("uninstall " + aManifestURL);
|
||||
|
||||
let app = this.getAppByManifestURL(aManifestURL);
|
||||
if (!app) {
|
||||
aOnFailure("NO_SUCH_APP");
|
||||
return;
|
||||
}
|
||||
let id = app.id;
|
||||
|
||||
if (!app.removable) {
|
||||
_uninstallApp: Task.async(function*(aApp) {
|
||||
if (!aApp.removable) {
|
||||
debug("Error: cannot uninstall a non-removable app.");
|
||||
aOnFailure("NON_REMOVABLE_APP");
|
||||
return;
|
||||
throw new Error("NON_REMOVABLE_APP");
|
||||
}
|
||||
|
||||
let id = aApp.id;
|
||||
|
||||
// Check if we are downloading something for this app, and cancel the
|
||||
// download if needed.
|
||||
this.cancelDownload(app.manifestURL);
|
||||
this.cancelDownload(aApp.manifestURL);
|
||||
|
||||
// Clean up the deprecated manifest cache if needed.
|
||||
if (id in this._manifestCache) {
|
||||
@ -3715,18 +3727,13 @@ this.DOMApplicationRegistry = {
|
||||
}
|
||||
|
||||
// Clear private data first.
|
||||
this._clearPrivateData(app.localId, false);
|
||||
this._clearPrivateData(aApp.localId, false);
|
||||
|
||||
// Then notify observers.
|
||||
// We have to clone the app object as nsIDOMApplication objects are
|
||||
// stringified as an empty object. (see bug 830376)
|
||||
let appClone = AppsUtils.cloneAppObject(app);
|
||||
Services.obs.notifyObservers(null, "webapps-uninstall", JSON.stringify(appClone));
|
||||
Services.obs.notifyObservers(null, "webapps-uninstall", JSON.stringify(aApp));
|
||||
|
||||
if (supportSystemMessages()) {
|
||||
this._readManifests([{ id: id }]).then((aResult) => {
|
||||
this._unregisterActivities(aResult[0].manifest, app);
|
||||
});
|
||||
this._unregisterActivities(aApp.manifest, aApp);
|
||||
}
|
||||
|
||||
let dir = this._getAppDir(id);
|
||||
@ -3736,18 +3743,47 @@ this.DOMApplicationRegistry = {
|
||||
|
||||
delete this.webapps[id];
|
||||
|
||||
this._saveApps().then(() => {
|
||||
this.broadcastMessage("Webapps:Uninstall:Broadcast:Return:OK", appClone);
|
||||
this.broadcastMessage("Webapps:RemoveApp", { id: id });
|
||||
try {
|
||||
if (aOnSuccess) {
|
||||
aOnSuccess();
|
||||
}
|
||||
} catch(ex) {
|
||||
Cu.reportError("DOMApplicationRegistry: Exception on app uninstall: " +
|
||||
ex + "\n" + ex.stack);
|
||||
}
|
||||
});
|
||||
yield this._saveApps();
|
||||
|
||||
this.broadcastMessage("Webapps:Uninstall:Broadcast:Return:OK", aApp);
|
||||
this.broadcastMessage("Webapps:RemoveApp", { id: id });
|
||||
|
||||
return aApp;
|
||||
}),
|
||||
|
||||
_promptForUninstall: function(aData) {
|
||||
let deferred = Promise.defer();
|
||||
this._pendingUninstalls[aData.requestID] = deferred;
|
||||
Services.obs.notifyObservers(null, "webapps-ask-uninstall",
|
||||
JSON.stringify(aData));
|
||||
return deferred.promise;
|
||||
},
|
||||
|
||||
confirmUninstall: function(aData) {
|
||||
let pending = this._pendingUninstalls[aData.requestID];
|
||||
if (pending) {
|
||||
delete this._pendingUninstalls[aData.requestID];
|
||||
return this._uninstallApp(aData.app).then(() => {
|
||||
pending.resolve();
|
||||
return aData.app;
|
||||
});
|
||||
}
|
||||
return Promise.reject(new Error("PENDING_UNINSTALL_NOT_FOUND"));
|
||||
},
|
||||
|
||||
denyUninstall: function(aData, aReason = "ERROR_UNKNOWN_FAILURE") {
|
||||
// Fails to uninstall the desired app because:
|
||||
// - we cannot find the app to be uninstalled.
|
||||
// - the app to be uninstalled is not removable.
|
||||
// - the user declined the confirmation
|
||||
debug("Failed to uninstall app: " + aReason);
|
||||
let pending = this._pendingUninstalls[aData.requestID];
|
||||
if (pending) {
|
||||
delete this._pendingUninstalls[aData.requestID];
|
||||
pending.reject(new Error(aReason));
|
||||
return Promise.resolve();
|
||||
}
|
||||
return Promise.reject(new Error("PENDING_UNINSTALL_NOT_FOUND"));
|
||||
},
|
||||
|
||||
getSelf: function(aData, aMm) {
|
||||
@ -4067,6 +4103,17 @@ this.DOMApplicationRegistry = {
|
||||
return AppsUtils.getAppByManifestURL(this.webapps, aManifestURL);
|
||||
},
|
||||
|
||||
_getAppWithManifest: Task.async(function*(aManifestURL) {
|
||||
let app = this.getAppByManifestURL(aManifestURL);
|
||||
if (!app) {
|
||||
throw new Error("NO_SUCH_APP");
|
||||
}
|
||||
|
||||
app.manifest = ( yield this._readManifests([{ id: app.id }]) )[0].manifest;
|
||||
|
||||
return app;
|
||||
}),
|
||||
|
||||
getCSPByLocalId: function(aLocalId) {
|
||||
debug("getCSPByLocalId:" + aLocalId);
|
||||
return AppsUtils.getCSPByLocalId(this.webapps, aLocalId);
|
||||
|
@ -72,6 +72,8 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=826058
|
||||
yield undefined;
|
||||
SpecialPowers.autoConfirmAppInstall(continueTest);
|
||||
yield undefined;
|
||||
SpecialPowers.autoConfirmAppUninstall(continueTest);
|
||||
yield undefined;
|
||||
|
||||
// Load the app, uninstalled.
|
||||
checkAppState(null, false, 1, continueTest);
|
||||
|
@ -44,6 +44,9 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=795164
|
||||
SpecialPowers.autoConfirmAppInstall(continueTest);
|
||||
yield undefined;
|
||||
|
||||
SpecialPowers.autoConfirmAppUninstall(continueTest);
|
||||
yield undefined;
|
||||
|
||||
// Keeping track of the number of times `mozApps.mgmt.onuninstall` gets triggered
|
||||
let uninstallCount = 0;
|
||||
|
||||
|
@ -71,6 +71,9 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=945152
|
||||
SpecialPowers.autoConfirmAppInstall(continueTest);
|
||||
yield undefined;
|
||||
|
||||
SpecialPowers.autoConfirmAppUninstall(continueTest);
|
||||
yield undefined;
|
||||
|
||||
// Create app on server side.
|
||||
createApp(continueTest);
|
||||
yield undefined;
|
||||
|
@ -60,6 +60,9 @@ function runTest() {
|
||||
SpecialPowers.autoConfirmAppInstall(continueTest);
|
||||
yield undefined;
|
||||
|
||||
SpecialPowers.autoConfirmAppUninstall(continueTest);
|
||||
yield undefined;
|
||||
|
||||
request = navigator.mozApps.mgmt.getAll();
|
||||
request.onerror = cbError;
|
||||
request.onsuccess = continueTest;
|
||||
|
@ -57,6 +57,9 @@ function runTest() {
|
||||
SpecialPowers.autoConfirmAppInstall(continueTest);
|
||||
yield undefined;
|
||||
|
||||
SpecialPowers.autoConfirmAppUninstall(continueTest);
|
||||
yield undefined;
|
||||
|
||||
// Test install with three valid receipts
|
||||
let valid_receipt1 = 'eyJhbGciOiAiSFMyNTYiLCAidHlwIjogIkpXVCJ9.eyJwcm9kdWN0IjogeyJ1cmwiOiAiaHR0cHM6Ly93d3cubW96aWxsYS5vcmciLCAic3RvcmVkYXRhIjogIjUxNjkzMTQzNTYifSwgInJlaXNzdWUiOiAiaHR0cDovL21vY2hpLnRlc3Q6ODg4OC9yZWlzc3VlLzUxNjkzMTQzNTYiLCAidXNlciI6IHsidHlwZSI6ICJkaXJlY3RlZC1pZGVudGlmaWVyIiwgInZhbHVlIjogIjRmYjM1MTUxLTJiOWItNGJhMi04MjgzLWM0OWQzODE2NDBiZCJ9LCAidmVyaWZ5IjogImh0dHA6Ly9tb2NoaS50ZXN0Ojg4ODgvdmVyaWZ5LzUxNjkzMTQzNTYiLCAiaXNzIjogImh0dHA6Ly9tb2NoaS50ZXN0Ojg4ODgiLCAiaWF0IjogMTMxMzYwMTg4LCAidHlwIjogInB1cmNoYXNlLXJlY2VpcHQiLCAibmJmIjogMTMxMzYwMTg1LCAiZGV0YWlsIjogImh0dHA6Ly9tb2NoaS50ZXN0Ojg4ODgvcmVjZWlwdC81MTY5MzE0MzU2In0.eZpTEnCLUR3iP3rm9WyJOqx1k66mQaAxqcrvX11r5E0';
|
||||
|
||||
|
@ -131,8 +131,10 @@ PackagedTestHelper.setSteps([
|
||||
SpecialPowers.addPermission("webapps-manage", true, document);
|
||||
SpecialPowers.addPermission("browser", true, document);
|
||||
SpecialPowers.autoConfirmAppInstall(() =>
|
||||
SpecialPowers.pushPrefEnv({set: [["dom.mozBrowserFramesEnabled", true]]},
|
||||
PackagedTestHelper.next));
|
||||
SpecialPowers.autoConfirmAppUninstall(() =>
|
||||
SpecialPowers.pushPrefEnv({set: [["dom.mozBrowserFramesEnabled",
|
||||
true]]},
|
||||
PackagedTestHelper.next)));
|
||||
},
|
||||
function() {
|
||||
info("== TEST == Marketplace packaged app from https://marketplace.firefox.com/");
|
||||
|
@ -140,6 +140,9 @@ function runTest() {
|
||||
SpecialPowers.autoConfirmAppInstall(continueTest);
|
||||
yield undefined;
|
||||
|
||||
SpecialPowers.autoConfirmAppUninstall(continueTest);
|
||||
yield undefined;
|
||||
|
||||
setState("setVersion", 1, continueTest);
|
||||
yield undefined;
|
||||
|
||||
|
@ -90,6 +90,10 @@ var steps = [
|
||||
info("autoConfirmAppInstall");
|
||||
SpecialPowers.autoConfirmAppInstall(PackagedTestHelper.next);
|
||||
},
|
||||
function() {
|
||||
ok(true, "autoConfirmAppUninstall");
|
||||
SpecialPowers.autoConfirmAppUninstall(PackagedTestHelper.next);
|
||||
},
|
||||
function() {
|
||||
PackagedTestHelper.setAppVersion(0, PackagedTestHelper.next);
|
||||
},
|
||||
|
@ -57,6 +57,9 @@ function runTest() {
|
||||
SpecialPowers.autoConfirmAppInstall(continueTest);
|
||||
yield undefined;
|
||||
|
||||
SpecialPowers.autoConfirmAppUninstall(continueTest);
|
||||
yield undefined;
|
||||
|
||||
var request = navigator.mozApps.install(gManifestURL);
|
||||
request.onerror = cbError;
|
||||
request.onsuccess = continueTest;
|
||||
|
@ -106,6 +106,10 @@ var steps = [
|
||||
info("autoConfirmAppInstall");
|
||||
SpecialPowers.autoConfirmAppInstall(PackagedTestHelper.next);
|
||||
},
|
||||
function() {
|
||||
info("autoConfirmAppUninstall");
|
||||
SpecialPowers.autoConfirmAppUninstall(PackagedTestHelper.next);
|
||||
},
|
||||
function() {
|
||||
info("== TEST == Install packaged app");
|
||||
var miniManifestURL = gSJS + "?" + "app=valid&" + "version=1";
|
||||
|
@ -44,6 +44,9 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=830258
|
||||
SpecialPowers.autoConfirmAppInstall(continueTest);
|
||||
yield undefined;
|
||||
|
||||
SpecialPowers.autoConfirmAppUninstall(continueTest);
|
||||
yield undefined;
|
||||
|
||||
let request = navigator.mozApps.install(url1);
|
||||
request.onerror = mozAppsError;
|
||||
request.onsuccess = continueTest;
|
||||
|
@ -190,7 +190,9 @@
|
||||
|
||||
// No confirmation needed when an app is installed
|
||||
function() {
|
||||
SpecialPowers.autoConfirmAppInstall(runTest);
|
||||
SpecialPowers.autoConfirmAppInstall(() => {
|
||||
SpecialPowers.autoConfirmAppUninstall(runTest);
|
||||
});
|
||||
},
|
||||
|
||||
// Installing the app
|
||||
|
@ -2328,23 +2328,23 @@ BluetoothHandsfreeInterface::Init(
|
||||
BluetoothHandsfreeResultHandler* aRes)
|
||||
{
|
||||
static bthf_callbacks_t sCallbacks = {
|
||||
.size = sizeof(sCallbacks),
|
||||
.connection_state_cb = BluetoothHandsfreeCallback::ConnectionState,
|
||||
.audio_state_cb = BluetoothHandsfreeCallback::AudioState,
|
||||
.vr_cmd_cb = BluetoothHandsfreeCallback::VoiceRecognition,
|
||||
.answer_call_cmd_cb = BluetoothHandsfreeCallback::AnswerCall,
|
||||
.hangup_call_cmd_cb = BluetoothHandsfreeCallback::HangupCall,
|
||||
.volume_cmd_cb = BluetoothHandsfreeCallback::Volume,
|
||||
.dial_call_cmd_cb = BluetoothHandsfreeCallback::DialCall,
|
||||
.dtmf_cmd_cb = BluetoothHandsfreeCallback::Dtmf,
|
||||
.nrec_cmd_cb = BluetoothHandsfreeCallback::NoiseReductionEchoCancellation,
|
||||
.chld_cmd_cb = BluetoothHandsfreeCallback::CallHold,
|
||||
.cnum_cmd_cb = BluetoothHandsfreeCallback::Cnum,
|
||||
.cind_cmd_cb = BluetoothHandsfreeCallback::Cind,
|
||||
.cops_cmd_cb = BluetoothHandsfreeCallback::Cops,
|
||||
.clcc_cmd_cb = BluetoothHandsfreeCallback::Clcc,
|
||||
.unknown_at_cmd_cb = BluetoothHandsfreeCallback::UnknownAt,
|
||||
.key_pressed_cmd_cb = BluetoothHandsfreeCallback::KeyPressed
|
||||
sizeof(sCallbacks),
|
||||
BluetoothHandsfreeCallback::ConnectionState,
|
||||
BluetoothHandsfreeCallback::AudioState,
|
||||
BluetoothHandsfreeCallback::VoiceRecognition,
|
||||
BluetoothHandsfreeCallback::AnswerCall,
|
||||
BluetoothHandsfreeCallback::HangupCall,
|
||||
BluetoothHandsfreeCallback::Volume,
|
||||
BluetoothHandsfreeCallback::DialCall,
|
||||
BluetoothHandsfreeCallback::Dtmf,
|
||||
BluetoothHandsfreeCallback::NoiseReductionEchoCancellation,
|
||||
BluetoothHandsfreeCallback::CallHold,
|
||||
BluetoothHandsfreeCallback::Cnum,
|
||||
BluetoothHandsfreeCallback::Cind,
|
||||
BluetoothHandsfreeCallback::Cops,
|
||||
BluetoothHandsfreeCallback::Clcc,
|
||||
BluetoothHandsfreeCallback::UnknownAt,
|
||||
BluetoothHandsfreeCallback::KeyPressed
|
||||
};
|
||||
|
||||
sHandsfreeNotificationHandler = aNotificationHandler;
|
||||
|
@ -26,10 +26,10 @@ using namespace mozilla::dom;
|
||||
NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(nsDOMCameraManager, mWindow)
|
||||
|
||||
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsDOMCameraManager)
|
||||
NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
|
||||
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIObserver)
|
||||
NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference)
|
||||
NS_INTERFACE_MAP_ENTRY(nsIObserver)
|
||||
NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
|
||||
NS_INTERFACE_MAP_END
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTING_ADDREF(nsDOMCameraManager)
|
||||
@ -116,7 +116,16 @@ nsDOMCameraManager::CreateInstance(nsPIDOMWindow* aWindow)
|
||||
new nsDOMCameraManager(aWindow);
|
||||
|
||||
nsCOMPtr<nsIObserverService> obs = services::GetObserverService();
|
||||
obs->AddObserver(cameraManager, "xpcom-shutdown", true);
|
||||
if (!obs) {
|
||||
DOM_CAMERA_LOGE("Camera manager failed to get observer service\n");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
nsresult rv = obs->AddObserver(cameraManager, "xpcom-shutdown", true);
|
||||
if (NS_FAILED(rv)) {
|
||||
DOM_CAMERA_LOGE("Camera manager failed to add 'xpcom-shutdown' observer (0x%x)\n", rv);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return cameraManager.forget();
|
||||
}
|
||||
|
@ -54,6 +54,9 @@
|
||||
SpecialPowers.autoConfirmAppInstall(continueTest);
|
||||
yield undefined;
|
||||
|
||||
SpecialPowers.autoConfirmAppUninstall(continueTest);
|
||||
yield undefined;
|
||||
|
||||
var request = navigator.mozApps.install(gHostedManifestURL);
|
||||
request.onerror = cbError;
|
||||
request.onsuccess = continueTest;
|
||||
|
@ -95,7 +95,8 @@
|
||||
|
||||
// No confirmation needed when an app is installed
|
||||
function() {
|
||||
SpecialPowers.autoConfirmAppInstall(runTest);
|
||||
SpecialPowers.autoConfirmAppInstall(() =>
|
||||
SpecialPowers.autoConfirmAppUninstall(runTest));
|
||||
},
|
||||
|
||||
// Installing the app
|
||||
|
@ -95,7 +95,8 @@
|
||||
|
||||
// No confirmation needed when an app is installed
|
||||
function() {
|
||||
SpecialPowers.autoConfirmAppInstall(runTest);
|
||||
SpecialPowers.autoConfirmAppInstall(() =>
|
||||
SpecialPowers.autoConfirmAppUninstall(runTest));
|
||||
},
|
||||
|
||||
// Installing the app
|
||||
|
@ -95,7 +95,8 @@
|
||||
|
||||
// No confirmation needed when an app is installed
|
||||
function() {
|
||||
SpecialPowers.autoConfirmAppInstall(runTest);
|
||||
SpecialPowers.autoConfirmAppInstall(() =>
|
||||
SpecialPowers.autoConfirmAppUninstall(runTest));
|
||||
},
|
||||
|
||||
// Installing the app
|
||||
|
@ -96,7 +96,8 @@
|
||||
|
||||
// No confirmation needed when an app is installed
|
||||
function() {
|
||||
SpecialPowers.autoConfirmAppInstall(runTest);
|
||||
SpecialPowers.autoConfirmAppInstall(() =>
|
||||
SpecialPowers.autoConfirmAppUninstall(runTest));
|
||||
},
|
||||
|
||||
// Installing the app
|
||||
|
@ -95,7 +95,8 @@
|
||||
|
||||
// No confirmation needed when an app is installed
|
||||
function() {
|
||||
SpecialPowers.autoConfirmAppInstall(runTest);
|
||||
SpecialPowers.autoConfirmAppInstall(() =>
|
||||
SpecialPowers.autoConfirmAppUninstall(runTest));
|
||||
},
|
||||
|
||||
// Installing the app
|
||||
|
@ -112,6 +112,11 @@
|
||||
// Run tests in app
|
||||
testApp,
|
||||
|
||||
// No confirmation needed when an app is installed
|
||||
function() {
|
||||
SpecialPowers.autoConfirmAppUninstall(runTest);
|
||||
},
|
||||
|
||||
// Uninstall the app
|
||||
uninstallApp
|
||||
];
|
||||
|
@ -100,7 +100,8 @@
|
||||
|
||||
// No confirmation needed when an app is installed
|
||||
function() {
|
||||
SpecialPowers.autoConfirmAppInstall(runTest);
|
||||
SpecialPowers.autoConfirmAppInstall(() =>
|
||||
SpecialPowers.autoConfirmAppUninstall(runTest));
|
||||
},
|
||||
|
||||
// Installing the app1
|
||||
|
@ -92,7 +92,8 @@
|
||||
|
||||
// No confirmation needed when an app is installed
|
||||
function() {
|
||||
SpecialPowers.autoConfirmAppInstall(runTest);
|
||||
SpecialPowers.autoConfirmAppInstall(() =>
|
||||
SpecialPowers.autoConfirmAppUninstall(runTest));
|
||||
},
|
||||
|
||||
// Installing the app1
|
||||
|
@ -102,7 +102,8 @@
|
||||
|
||||
// No confirmation needed when an app is installed
|
||||
function() {
|
||||
SpecialPowers.autoConfirmAppInstall(runTest);
|
||||
SpecialPowers.autoConfirmAppInstall(() =>
|
||||
SpecialPowers.autoConfirmAppUninstall(runTest));
|
||||
},
|
||||
|
||||
// Installing the app
|
||||
|
@ -138,7 +138,8 @@
|
||||
|
||||
// No confirmation needed when an app is installed
|
||||
function() {
|
||||
SpecialPowers.autoConfirmAppInstall(runTest);
|
||||
SpecialPowers.autoConfirmAppInstall(() =>
|
||||
SpecialPowers.autoConfirmAppUninstall(runTest));
|
||||
},
|
||||
|
||||
// Installing the app1
|
||||
|
@ -95,7 +95,8 @@
|
||||
|
||||
// No confirmation needed when an app is installed
|
||||
function() {
|
||||
SpecialPowers.autoConfirmAppInstall(runTest);
|
||||
SpecialPowers.autoConfirmAppInstall(() =>
|
||||
SpecialPowers.autoConfirmAppUninstall(runTest));
|
||||
},
|
||||
|
||||
// Installing the app
|
||||
|
@ -95,7 +95,8 @@
|
||||
|
||||
// No confirmation needed when an app is installed
|
||||
function() {
|
||||
SpecialPowers.autoConfirmAppInstall(runTest);
|
||||
SpecialPowers.autoConfirmAppInstall(() =>
|
||||
SpecialPowers.autoConfirmAppUninstall(runTest));
|
||||
},
|
||||
|
||||
// Installing the app
|
||||
|
@ -89,7 +89,9 @@
|
||||
function() {
|
||||
SpecialPowers.setAllAppsLaunchable(true);
|
||||
// No confirmation needed when an app is installed.
|
||||
SpecialPowers.autoConfirmAppInstall(runTest);
|
||||
SpecialPowers.autoConfirmAppInstall(() => {
|
||||
SpecialPowers.autoConfirmAppUninstall(runTest);
|
||||
});
|
||||
},
|
||||
|
||||
function() {
|
||||
|
@ -96,7 +96,8 @@
|
||||
|
||||
// No confirmation needed when an app is installed
|
||||
function() {
|
||||
SpecialPowers.autoConfirmAppInstall(runTest);
|
||||
SpecialPowers.autoConfirmAppInstall(() =>
|
||||
SpecialPowers.autoConfirmAppUninstall(runTest));
|
||||
},
|
||||
|
||||
// Installing the app
|
||||
|
@ -124,7 +124,8 @@
|
||||
|
||||
// No confirmation needed when an app is installed
|
||||
function() {
|
||||
SpecialPowers.autoConfirmAppInstall(runTest);
|
||||
SpecialPowers.autoConfirmAppInstall(() =>
|
||||
SpecialPowers.autoConfirmAppUninstall(runTest));
|
||||
},
|
||||
|
||||
// Installing the apps
|
||||
|
@ -40,6 +40,9 @@
|
||||
SpecialPowers.autoConfirmAppInstall(continueTest);
|
||||
yield undefined;
|
||||
|
||||
SpecialPowers.autoConfirmAppUninstall(continueTest);
|
||||
yield undefined;
|
||||
|
||||
var request = navigator.mozApps.install(gHostedManifestURL);
|
||||
request.onerror = cbError;
|
||||
request.onsuccess = continueTest;
|
||||
|
@ -94,7 +94,8 @@
|
||||
|
||||
// No confirmation needed when an app is installed
|
||||
function() {
|
||||
SpecialPowers.autoConfirmAppInstall(runTest);
|
||||
SpecialPowers.autoConfirmAppInstall(() =>
|
||||
SpecialPowers.autoConfirmAppUninstall(runTest));
|
||||
},
|
||||
|
||||
// Installing the app
|
||||
|
@ -94,7 +94,8 @@
|
||||
|
||||
// No confirmation needed when an app is installed
|
||||
function() {
|
||||
SpecialPowers.autoConfirmAppInstall(runTest);
|
||||
SpecialPowers.autoConfirmAppInstall(() =>
|
||||
SpecialPowers.autoConfirmAppUninstall(runTest));
|
||||
},
|
||||
|
||||
// Installing the app
|
||||
|
@ -95,7 +95,8 @@
|
||||
|
||||
// No confirmation needed when an app is installed
|
||||
function() {
|
||||
SpecialPowers.autoConfirmAppInstall(runTest);
|
||||
SpecialPowers.autoConfirmAppInstall(() =>
|
||||
SpecialPowers.autoConfirmAppUninstall(runTest));
|
||||
},
|
||||
|
||||
// Installing the app
|
||||
|
@ -3746,6 +3746,13 @@ ContentParent::CheckAppHasStatus(unsigned short aStatus)
|
||||
return AssertAppHasStatus(this, aStatus);
|
||||
}
|
||||
|
||||
bool
|
||||
ContentParent::KillChild()
|
||||
{
|
||||
KillHard();
|
||||
return true;
|
||||
}
|
||||
|
||||
PBlobParent*
|
||||
ContentParent::SendPBlobConstructor(PBlobParent* aActor,
|
||||
const BlobConstructorParams& aParams)
|
||||
|
@ -161,6 +161,7 @@ public:
|
||||
virtual bool CheckManifestURL(const nsAString& aManifestURL) MOZ_OVERRIDE;
|
||||
virtual bool CheckAppHasPermission(const nsAString& aPermission) MOZ_OVERRIDE;
|
||||
virtual bool CheckAppHasStatus(unsigned short aStatus) MOZ_OVERRIDE;
|
||||
virtual bool KillChild() MOZ_OVERRIDE;
|
||||
|
||||
/** Notify that a tab is beginning its destruction sequence. */
|
||||
void NotifyTabDestroying(PBrowserParent* aTab);
|
||||
|
@ -4,7 +4,7 @@
|
||||
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
INSTALL_TARGETS += FAKE_GMP_PLUGIN
|
||||
FAKE_GMP_PLUGIN_DEST = $(DEPTH)/dist/bin/gmp-fake
|
||||
FAKE_GMP_PLUGIN_DEST = $(DEPTH)/dist/bin/gmp-fake/1.0
|
||||
FAKE_GMP_PLUGIN_FILES = \
|
||||
$(SHARED_LIBRARY) \
|
||||
$(srcdir)/fake.info
|
||||
|
@ -4292,7 +4292,7 @@ RadioInterface.prototype = {
|
||||
if (!response.errorMsg) {
|
||||
request.notifyGetSmscAddress(response.smscAddress);
|
||||
} else {
|
||||
request.notifyGetSmscAddressFailed(response.errorMsg);
|
||||
request.notifyGetSmscAddressFailed(Ci.nsIMobileMessageCallback.NOT_FOUND_ERROR);
|
||||
}
|
||||
}).bind(this));
|
||||
},
|
||||
|
@ -183,7 +183,9 @@ function browserLoadEvent() {
|
||||
|
||||
addLoadEvent(() =>
|
||||
SpecialPowers.pushPrefEnv({set: [['dom.mozBrowserFramesEnabled', true]]}, () =>
|
||||
SpecialPowers.autoConfirmAppInstall(runTest)
|
||||
SpecialPowers.autoConfirmAppInstall(() =>
|
||||
SpecialPowers.autoConfirmAppUninstall(runTest)
|
||||
)
|
||||
)
|
||||
);
|
||||
|
||||
|
@ -197,7 +197,9 @@ function checks() {
|
||||
|
||||
addLoadEvent(() =>
|
||||
SpecialPowers.pushPrefEnv({set: [['dom.mozBrowserFramesEnabled', true]]}, () =>
|
||||
SpecialPowers.autoConfirmAppInstall(runTest)
|
||||
SpecialPowers.autoConfirmAppInstall(() =>
|
||||
SpecialPowers.autoConfirmAppUninstall(runTest)
|
||||
)
|
||||
)
|
||||
);
|
||||
|
||||
|
@ -19,7 +19,7 @@
|
||||
|
||||
var parent = SpecialPowers.wrap(window).parent;
|
||||
|
||||
confirmNextInstall();
|
||||
confirmNextPopup();
|
||||
navigator.mozApps.install(parent.url2, null).onsuccess = function onInstall() {
|
||||
// Give the test page a reference to the installed app, so it can uninstall it
|
||||
// after it finishes the tests.
|
||||
|
@ -34,19 +34,22 @@ function runAll(steps) {
|
||||
next();
|
||||
}
|
||||
|
||||
function confirmNextInstall() {
|
||||
function confirmNextPopup() {
|
||||
var Ci = SpecialPowers.Ci;
|
||||
|
||||
var popupPanel = SpecialPowers.wrap(window).top.
|
||||
QueryInterface(Ci.nsIInterfaceRequestor).
|
||||
getInterface(Ci.nsIWebNavigation).
|
||||
QueryInterface(Ci.nsIDocShell).
|
||||
chromeEventHandler.ownerDocument.defaultView.
|
||||
PopupNotifications.panel;
|
||||
var popupNotifications = SpecialPowers.wrap(window).top.
|
||||
QueryInterface(Ci.nsIInterfaceRequestor).
|
||||
getInterface(Ci.nsIWebNavigation).
|
||||
QueryInterface(Ci.nsIDocShell).
|
||||
chromeEventHandler.ownerDocument.defaultView.
|
||||
PopupNotifications;
|
||||
|
||||
var popupPanel = popupNotifications.panel;
|
||||
|
||||
function onPopupShown() {
|
||||
popupPanel.removeEventListener("popupshown", onPopupShown, false);
|
||||
SpecialPowers.wrap(this).childNodes[0].button.doCommand();
|
||||
popupNotifications._dismiss();
|
||||
}
|
||||
popupPanel.addEventListener("popupshown", onPopupShown, false);
|
||||
}
|
||||
|
@ -43,7 +43,7 @@ ppmm.addMessageListener("Webapps:Install", mmListener);
|
||||
// We call this here, even though the app is installed by the helper page,
|
||||
// because the helper page redirect would cause its install listener to unload
|
||||
// before it can confirm the install.
|
||||
confirmNextInstall();
|
||||
confirmNextPopup();
|
||||
|
||||
</script>
|
||||
|
||||
|
@ -43,7 +43,7 @@ runAll(steps);
|
||||
* the app itself is from a different origin (http://test1.example.com).
|
||||
*/
|
||||
function installAppFromOwnOrigin(next) {
|
||||
confirmNextInstall();
|
||||
confirmNextPopup();
|
||||
navigator.mozApps.install(url1, null).onsuccess = function onInstall() {
|
||||
app1 = this.result;
|
||||
next();
|
||||
@ -93,7 +93,9 @@ function getAll(next) {
|
||||
}
|
||||
|
||||
function uninstall(next) {
|
||||
confirmNextPopup();
|
||||
navigator.mozApps.mgmt.uninstall(app1).onsuccess = function onUninstallApp1() {
|
||||
confirmNextPopup();
|
||||
navigator.mozApps.mgmt.uninstall(app2).onsuccess = function onUninstallApp2() {
|
||||
next();
|
||||
};
|
||||
|
@ -76,11 +76,11 @@ function getNotInstalled(next) {
|
||||
|
||||
// Add an app to the appregistry
|
||||
function installApp(next) {
|
||||
confirmNextInstall();
|
||||
confirmNextPopup();
|
||||
navigator.mozApps.install(url, null).onsuccess = function onInstall() {
|
||||
app = this.result;
|
||||
next();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
// Call navigator.mozApps.mgmt.getNotInstalled and make sure there is one more.
|
||||
@ -128,6 +128,7 @@ function unmonkeyPatchDOMApplicationRegistry(next) {
|
||||
|
||||
// Remove the app from the appregistry
|
||||
function uninstallApp(next) {
|
||||
confirmNextPopup();
|
||||
window.navigator.mozApps.mgmt.uninstall(app).onsuccess = function onUninstall() {
|
||||
app = null;
|
||||
next();
|
||||
|
@ -45,7 +45,7 @@ function install(next) {
|
||||
var beforehand = Date.now();
|
||||
const fuzzySpan = 250;
|
||||
|
||||
confirmNextInstall();
|
||||
confirmNextPopup();
|
||||
navigator.mozApps.install(url, null).onsuccess = function onInstall() {
|
||||
app = this.result;
|
||||
|
||||
@ -84,6 +84,7 @@ function getSelf(next) {
|
||||
}
|
||||
|
||||
function uninstall(next) {
|
||||
confirmNextPopup();
|
||||
navigator.mozApps.mgmt.uninstall(app).onsuccess = function onUninstall() {
|
||||
// Try to retrieve the app we just uninstalled, to make sure it no longer
|
||||
// exists in the registry.
|
||||
|
@ -69,7 +69,7 @@ function invalidManifest(next) {
|
||||
function permissionDenied(next) {
|
||||
var url = "http://test/chrome/dom/tests/mochitest/webapps/apps/no_delegated_install.webapp";
|
||||
|
||||
confirmNextInstall();
|
||||
confirmNextPopup();
|
||||
var request = navigator.mozApps.install(url, null);
|
||||
|
||||
request.onerror = function onInstallError() {
|
||||
@ -79,6 +79,7 @@ function permissionDenied(next) {
|
||||
|
||||
request.onsuccess = function onInstall() {
|
||||
todo(false, "manifest without installs_allowed_from fails");
|
||||
confirmNextPopup();
|
||||
navigator.mozApps.mgmt.uninstall(this.result).onsuccess = function onUninstall() {
|
||||
next();
|
||||
};
|
||||
@ -97,6 +98,7 @@ function invalidContent(next) {
|
||||
|
||||
request.onsuccess = function onInstall() {
|
||||
ok(false, "manifest with bad content type should fail");
|
||||
confirmNextPopup();
|
||||
navigator.mozApps.mgmt.uninstall(this.result).onsuccess = function onUninstall() {
|
||||
next();
|
||||
};
|
||||
@ -206,6 +208,7 @@ function originNotAllowed(next) {
|
||||
|
||||
request.onsuccess = function onInstall() {
|
||||
ok(false, "test should fail because of installs_allowed_from");
|
||||
confirmNextPopup();
|
||||
navigator.mozApps.mgmt.uninstall(this.result).onsuccess = function onUninstall() {
|
||||
next();
|
||||
};
|
||||
@ -215,7 +218,7 @@ function originNotAllowed(next) {
|
||||
function originAllowed(next) {
|
||||
var url = "http://test/chrome/dom/tests/mochitest/webapps/apps/installs_allowed_from_chrome_mochitests.webapp";
|
||||
|
||||
confirmNextInstall();
|
||||
confirmNextPopup();
|
||||
var request = navigator.mozApps.install(url, null);
|
||||
|
||||
request.onerror = function onInstallError() {
|
||||
@ -225,6 +228,7 @@ function originAllowed(next) {
|
||||
|
||||
request.onsuccess = function onInstall() {
|
||||
ok(true, "test origin is in installs_allowed_from");
|
||||
confirmNextPopup();
|
||||
navigator.mozApps.mgmt.uninstall(this.result).onsuccess = function onUninstall() {
|
||||
next();
|
||||
};
|
||||
|
@ -22,12 +22,13 @@ SimpleTest.waitForExplicitFinish();
|
||||
|
||||
var url = "http://test/chrome/dom/tests/mochitest/webapps/apps/utf8.webapp";
|
||||
|
||||
confirmNextInstall();
|
||||
confirmNextPopup();
|
||||
navigator.mozApps.install(url, null).onsuccess = function onInstall() {
|
||||
is(this.result.manifest.name, "TheBOM ゲゴケ゚セニツ゚ヅヂチ", "manifest.name");
|
||||
is(this.result.manifest.description, "This App is THE BOM, yo. ヅヂチ",
|
||||
"manifest.description");
|
||||
|
||||
confirmNextPopup();
|
||||
navigator.mozApps.mgmt.uninstall(this.result).onsuccess = function onUninstall() {
|
||||
SimpleTest.finish();
|
||||
}
|
||||
|
@ -45,7 +45,7 @@ function install(next) {
|
||||
var beforehand = Date.now();
|
||||
const fuzzySpan = 250;
|
||||
|
||||
confirmNextInstall();
|
||||
confirmNextPopup();
|
||||
navigator.mozApps.install(url, null).onsuccess = function onInstall() {
|
||||
app = this.result;
|
||||
|
||||
@ -84,6 +84,7 @@ function getSelf(next) {
|
||||
}
|
||||
|
||||
function uninstall(next) {
|
||||
confirmNextPopup();
|
||||
navigator.mozApps.mgmt.uninstall(app).onsuccess = function onUninstall() {
|
||||
// Try to retrieve the app we just uninstalled, to make sure it no longer
|
||||
// exists in the registry.
|
||||
|
643
dom/tethering/tests/marionette/head.js
Normal file
643
dom/tethering/tests/marionette/head.js
Normal file
@ -0,0 +1,643 @@
|
||||
/* 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/. */
|
||||
|
||||
const TYPE_WIFI = "wifi";
|
||||
const TYPE_BLUETOOTH = "bt";
|
||||
const TYPE_USB = "usb";
|
||||
|
||||
/**
|
||||
* General tethering setting.
|
||||
*/
|
||||
const TETHERING_SETTING_IP = "192.168.1.1";
|
||||
const TETHERING_SETTNG_PREFIX = "24";
|
||||
const TETHERING_SETTING_START_IP = "192.168.1.10";
|
||||
const TETHERING_SETTING_END_IP = "192.168.1.30";
|
||||
const TETHERING_SETTING_DNS1 = "8.8.8.8";
|
||||
const TETHERING_SETTING_DNS2 = "8.8.4.4";
|
||||
|
||||
/**
|
||||
* Wifi tethering setting.
|
||||
*/
|
||||
const TETHERING_SETTING_SSID = "FirefoxHotSpot";
|
||||
const TETHERING_SETTING_SECURITY = "open";
|
||||
const TETHERING_SETTING_KEY = "1234567890";
|
||||
|
||||
const SETTINGS_RIL_DATA_ENABLED = 'ril.data.enabled';
|
||||
|
||||
let Promise =
|
||||
SpecialPowers.Cu.import("resource://gre/modules/Promise.jsm").Promise;
|
||||
|
||||
let gTestSuite = (function() {
|
||||
let suite = {};
|
||||
|
||||
let tetheringManager;
|
||||
let pendingEmulatorShellCount = 0;
|
||||
|
||||
/**
|
||||
* A wrapper function of "is".
|
||||
*
|
||||
* Calls the marionette function "is" as well as throws an exception
|
||||
* if the givens values are not equal.
|
||||
*
|
||||
* @param value1
|
||||
* Any type of value to compare.
|
||||
*
|
||||
* @param value2
|
||||
* Any type of value to compare.
|
||||
*
|
||||
* @param message
|
||||
* Debug message for this check.
|
||||
*
|
||||
*/
|
||||
function isOrThrow(value1, value2, message) {
|
||||
is(value1, value2, message);
|
||||
if (value1 !== value2) {
|
||||
throw message;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Send emulator shell command with safe guard.
|
||||
*
|
||||
* We should only call |finish()| after all emulator command transactions
|
||||
* end, so here comes with the pending counter. Resolve when the emulator
|
||||
* gives positive response, and reject otherwise.
|
||||
*
|
||||
* Fulfill params:
|
||||
* result -- an array of emulator response lines.
|
||||
* Reject params:
|
||||
* result -- an array of emulator response lines.
|
||||
*
|
||||
* @param aCommand
|
||||
* A string command to be passed to emulator through its telnet console.
|
||||
*
|
||||
* @return A deferred promise.
|
||||
*/
|
||||
function runEmulatorShellSafe(aCommand) {
|
||||
let deferred = Promise.defer();
|
||||
|
||||
++pendingEmulatorShellCount;
|
||||
runEmulatorShell(aCommand, function(aResult) {
|
||||
--pendingEmulatorShellCount;
|
||||
|
||||
ok(true, "Emulator shell response: " + JSON.stringify(aResult));
|
||||
if (Array.isArray(aResult)) {
|
||||
deferred.resolve(aResult);
|
||||
} else {
|
||||
deferred.reject(aResult);
|
||||
}
|
||||
});
|
||||
|
||||
return deferred.promise;
|
||||
}
|
||||
|
||||
/**
|
||||
* Wait for timeout.
|
||||
*
|
||||
* Resolve when the given duration elapsed. Never reject.
|
||||
*
|
||||
* Fulfill params: (none)
|
||||
*
|
||||
* @param aTimeoutMs
|
||||
* The duration after which the timeout event should occurs.
|
||||
*
|
||||
* @return A deferred promise.
|
||||
*/
|
||||
function waitForTimeout(aTimeoutMs) {
|
||||
let deferred = Promise.defer();
|
||||
|
||||
setTimeout(function() {
|
||||
deferred.resolve();
|
||||
}, aTimeoutMs);
|
||||
|
||||
return deferred.promise;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get mozSettings value specified by @aKey.
|
||||
*
|
||||
* Resolve if that mozSettings value is retrieved successfully, reject
|
||||
* otherwise.
|
||||
*
|
||||
* Fulfill params:
|
||||
* The corresponding mozSettings value of the key.
|
||||
* Reject params: (none)
|
||||
*
|
||||
* @param aKey
|
||||
* A string.
|
||||
*
|
||||
* @return A deferred promise.
|
||||
*/
|
||||
function getSettings(aKey) {
|
||||
let request = navigator.mozSettings.createLock().get(aKey);
|
||||
|
||||
return wrapDomRequestAsPromise(request)
|
||||
.then(function resolve(aEvent) {
|
||||
ok(true, "getSettings(" + aKey + ") - success");
|
||||
return aEvent.target.result[aKey];
|
||||
}, function reject(aEvent) {
|
||||
ok(false, "getSettings(" + aKey + ") - error");
|
||||
throw aEvent.target.error;
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Set mozSettings values.
|
||||
*
|
||||
* Resolve if that mozSettings value is set successfully, reject otherwise.
|
||||
*
|
||||
* Fulfill params: (none)
|
||||
* Reject params: (none)
|
||||
*
|
||||
* @param aSettings
|
||||
* An object of format |{key1: value1, key2: value2, ...}|.
|
||||
* @return A deferred promise.
|
||||
*/
|
||||
function setSettings(aSettings) {
|
||||
let request = navigator.mozSettings.createLock().set(aSettings);
|
||||
|
||||
return wrapDomRequestAsPromise(request)
|
||||
.then(function resolve() {
|
||||
ok(true, "setSettings(" + JSON.stringify(aSettings) + ")");
|
||||
}, function reject(aEvent) {
|
||||
ok(false, "setSettings(" + JSON.stringify(aSettings) + ")");
|
||||
throw aEvent.target.error;
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Set mozSettings value with only one key.
|
||||
*
|
||||
* Resolve if that mozSettings value is set successfully, reject otherwise.
|
||||
*
|
||||
* Fulfill params: (none)
|
||||
* Reject params: (none)
|
||||
*
|
||||
* @param aKey
|
||||
* A string key.
|
||||
* @param aValue
|
||||
* An object value.
|
||||
* @param aAllowError [optional]
|
||||
* A boolean value. If set to true, an error response won't be treated
|
||||
* as test failure. Default: false.
|
||||
*
|
||||
* @return A deferred promise.
|
||||
*/
|
||||
function setSettings1(aKey, aValue, aAllowError) {
|
||||
let settings = {};
|
||||
settings[aKey] = aValue;
|
||||
return setSettings(settings, aAllowError);
|
||||
}
|
||||
|
||||
/**
|
||||
* Wrap DOMRequest onsuccess/onerror events to Promise resolve/reject.
|
||||
*
|
||||
* Fulfill params: A DOMEvent.
|
||||
* Reject params: A DOMEvent.
|
||||
*
|
||||
* @param aRequest
|
||||
* A DOMRequest instance.
|
||||
*
|
||||
* @return A deferred promise.
|
||||
*/
|
||||
function wrapDomRequestAsPromise(aRequest) {
|
||||
let deffered = Promise.defer();
|
||||
|
||||
ok(aRequest instanceof DOMRequest,
|
||||
"aRequest is instanceof" + aRequest.constructor);
|
||||
|
||||
aRequest.onsuccess = function(aEvent) {
|
||||
deffered.resolve(aEvent);
|
||||
};
|
||||
aRequest.onerror = function(aEvent) {
|
||||
deffered.reject(aEvent);
|
||||
};
|
||||
|
||||
return deffered.promise;
|
||||
}
|
||||
|
||||
/**
|
||||
* Wait for one named MozMobileConnection event.
|
||||
*
|
||||
* Resolve if that named event occurs. Never reject.
|
||||
*
|
||||
* Fulfill params: the DOMEvent passed.
|
||||
*
|
||||
* @param aEventName
|
||||
* A string event name.
|
||||
*
|
||||
* @return A deferred promise.
|
||||
*/
|
||||
function waitForMobileConnectionEventOnce(aEventName, aServiceId) {
|
||||
aServiceId = aServiceId || 0;
|
||||
|
||||
let deferred = Promise.defer();
|
||||
let mobileconnection = navigator.mozMobileConnections[aServiceId];
|
||||
|
||||
mobileconnection.addEventListener(aEventName, function onevent(aEvent) {
|
||||
mobileconnection.removeEventListener(aEventName, onevent);
|
||||
|
||||
ok(true, "Mobile connection event '" + aEventName + "' got.");
|
||||
deferred.resolve(aEvent);
|
||||
});
|
||||
|
||||
return deferred.promise;
|
||||
}
|
||||
|
||||
/**
|
||||
* Wait for RIL data being connected.
|
||||
*
|
||||
* This function will check |MozMobileConnection.data.connected| on
|
||||
* every 'datachange' event. Resolve when |MozMobileConnection.data.connected|
|
||||
* becomes the expected state. Never reject.
|
||||
*
|
||||
* Fulfill params: (none)
|
||||
* Reject params: (none)
|
||||
*
|
||||
* @param aConnected
|
||||
* Boolean that indicates the desired data state.
|
||||
*
|
||||
* @param aServiceId [optional]
|
||||
* A numeric DSDS service id. Default: 0.
|
||||
*
|
||||
* @return A deferred promise.
|
||||
*/
|
||||
function waitForRilDataConnected(aConnected, aServiceId) {
|
||||
aServiceId = aServiceId || 0;
|
||||
|
||||
return waitForMobileConnectionEventOnce('datachange', aServiceId)
|
||||
.then(function () {
|
||||
let mobileconnection = navigator.mozMobileConnections[aServiceId];
|
||||
if (mobileconnection.data.connected !== aConnected) {
|
||||
return waitForRilDataConnected(aConnected, aServiceId);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Verify everything about routing when the wifi tethering is either on or off.
|
||||
*
|
||||
* We use two unix commands to verify the routing: 'netcfg' and 'ip route'.
|
||||
* For now the following two things will be checked:
|
||||
* 1) The default route interface should be 'rmnet0'.
|
||||
* 2) wlan0 is up and its ip is set to a private subnet.
|
||||
*
|
||||
* We also verify iptables output as netd's NatController will execute
|
||||
* $ iptables -t nat -A POSTROUTING -o rmnet0 -j MASQUERADE
|
||||
*
|
||||
* Resolve when the verification is successful and reject otherwise.
|
||||
*
|
||||
* Fulfill params: (none)
|
||||
* Reject params: String that indicates the reason of rejection.
|
||||
*
|
||||
* @return A deferred promise.
|
||||
*/
|
||||
function verifyTetheringRouting(aEnabled) {
|
||||
let netcfgResult = {};
|
||||
let ipRouteResult = {};
|
||||
|
||||
// Execute 'netcfg' and parse to |netcfgResult|, each key of which is the
|
||||
// interface name and value is { ip(string) }.
|
||||
function exeAndParseNetcfg() {
|
||||
return runEmulatorShellSafe(['netcfg'])
|
||||
.then(function (aLines) {
|
||||
// Sample output:
|
||||
//
|
||||
// lo UP 127.0.0.1/8 0x00000049 00:00:00:00:00:00
|
||||
// eth0 UP 10.0.2.15/24 0x00001043 52:54:00:12:34:56
|
||||
// rmnet1 DOWN 0.0.0.0/0 0x00001002 52:54:00:12:34:58
|
||||
// rmnet2 DOWN 0.0.0.0/0 0x00001002 52:54:00:12:34:59
|
||||
// rmnet3 DOWN 0.0.0.0/0 0x00001002 52:54:00:12:34:5a
|
||||
// wlan0 UP 192.168.1.1/24 0x00001043 52:54:00:12:34:5b
|
||||
// sit0 DOWN 0.0.0.0/0 0x00000080 00:00:00:00:00:00
|
||||
// rmnet0 UP 10.0.2.100/24 0x00001043 52:54:00:12:34:57
|
||||
//
|
||||
aLines.forEach(function (aLine) {
|
||||
let tokens = aLine.split(/\s+/);
|
||||
if (tokens.length < 5) {
|
||||
return;
|
||||
}
|
||||
let ifname = tokens[0];
|
||||
let ip = (tokens[2].split('/'))[0];
|
||||
netcfgResult[ifname] = { ip: ip };
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
// Execute 'ip route' and parse to |ipRouteResult|, each key of which is the
|
||||
// interface name and value is { src(string), default(boolean) }.
|
||||
function exeAndParseIpRoute() {
|
||||
return runEmulatorShellSafe(['ip', 'route'])
|
||||
.then(function (aLines) {
|
||||
// Sample output:
|
||||
//
|
||||
// 10.0.2.4 via 10.0.2.2 dev rmnet0
|
||||
// 10.0.2.3 via 10.0.2.2 dev rmnet0
|
||||
// 192.168.1.0/24 dev wlan0 proto kernel scope link src 192.168.1.1
|
||||
// 10.0.2.0/24 dev eth0 proto kernel scope link src 10.0.2.15
|
||||
// 10.0.2.0/24 dev rmnet0 proto kernel scope link src 10.0.2.100
|
||||
// default via 10.0.2.2 dev rmnet0
|
||||
// default via 10.0.2.2 dev eth0 metric 2
|
||||
//
|
||||
|
||||
// Parse source ip for each interface.
|
||||
aLines.forEach(function (aLine) {
|
||||
let tokens = aLine.trim().split(/\s+/);
|
||||
let srcIndex = tokens.indexOf('src');
|
||||
if (srcIndex < 0 || srcIndex + 1 >= tokens.length) {
|
||||
return;
|
||||
}
|
||||
let ifname = tokens[2];
|
||||
let src = tokens[srcIndex + 1];
|
||||
ipRouteResult[ifname] = { src: src, default: false };
|
||||
});
|
||||
|
||||
// Parse default interfaces.
|
||||
aLines.forEach(function (aLine) {
|
||||
let tokens = aLine.split(/\s+/);
|
||||
if (tokens.length < 2) {
|
||||
return;
|
||||
}
|
||||
if ('default' === tokens[0]) {
|
||||
let ifnameIndex = tokens.indexOf('dev');
|
||||
if (ifnameIndex < 0 || ifnameIndex + 1 >= tokens.length) {
|
||||
return;
|
||||
}
|
||||
let ifname = tokens[ifnameIndex + 1];
|
||||
if (ipRouteResult[ifname]) {
|
||||
ipRouteResult[ifname].default = true;
|
||||
}
|
||||
return;
|
||||
}
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
// Find MASQUERADE in POSTROUTING section. 'MASQUERADE' should be found
|
||||
// when tethering is enabled. 'MASQUERADE' shouldn't be found when tethering
|
||||
// is disabled.
|
||||
function verifyIptables() {
|
||||
return runEmulatorShellSafe(['iptables', '-t', 'nat', '-L', 'POSTROUTING'])
|
||||
.then(function(aLines) {
|
||||
// $ iptables -t nat -L POSTROUTING
|
||||
//
|
||||
// Sample output (tethering on):
|
||||
//
|
||||
// Chain POSTROUTING (policy ACCEPT)
|
||||
// target prot opt source destination
|
||||
// MASQUERADE all -- anywhere anywhere
|
||||
//
|
||||
let found = (function find_MASQUERADE() {
|
||||
// Skip first two lines.
|
||||
for (let i = 2; i < aLines.length; i++) {
|
||||
if (-1 !== aLines[i].indexOf('MASQUERADE')) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
})();
|
||||
|
||||
if ((aEnabled && !found) || (!aEnabled && found)) {
|
||||
throw 'MASQUERADE' + (found ? '' : ' not') + ' found while tethering is ' +
|
||||
(aEnabled ? 'enabled' : 'disabled');
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function verifyDefaultRouteAndIp(aExpectedWifiTetheringIp) {
|
||||
log(JSON.stringify(ipRouteResult));
|
||||
log(JSON.stringify(netcfgResult));
|
||||
|
||||
if (aEnabled) {
|
||||
isOrThrow(ipRouteResult['rmnet0'].src, netcfgResult['rmnet0'].ip, 'rmnet0.ip');
|
||||
isOrThrow(ipRouteResult['rmnet0'].default, true, 'rmnet0.default');
|
||||
|
||||
isOrThrow(ipRouteResult['wlan0'].src, netcfgResult['wlan0'].ip, 'wlan0.ip');
|
||||
isOrThrow(ipRouteResult['wlan0'].src, aExpectedWifiTetheringIp, 'expected ip');
|
||||
isOrThrow(ipRouteResult['wlan0'].default, false, 'wlan0.default');
|
||||
}
|
||||
}
|
||||
|
||||
return verifyIptables()
|
||||
.then(exeAndParseNetcfg)
|
||||
.then(exeAndParseIpRoute)
|
||||
.then(() => verifyDefaultRouteAndIp(TETHERING_SETTING_IP));
|
||||
}
|
||||
|
||||
/**
|
||||
* Request to enable/disable wifi tethering.
|
||||
*
|
||||
* Enable/disable wifi tethering by using setTetheringEnabled API
|
||||
* Resolve when the routing is verified to set up successfully in 20 seconds. The polling
|
||||
* period is 1 second.
|
||||
*
|
||||
* Fulfill params: (none)
|
||||
* Reject params: The error message.
|
||||
*
|
||||
* @param aEnabled
|
||||
* Boolean that indicates to enable or disable wifi tethering.
|
||||
*
|
||||
* @return A deferred promise.
|
||||
*/
|
||||
function setWifiTetheringEnabled(aEnabled) {
|
||||
let RETRY_INTERVAL_MS = 1000;
|
||||
let retryCnt = 20;
|
||||
|
||||
let config = {
|
||||
"ip" : TETHERING_SETTING_IP,
|
||||
"prefix" : TETHERING_SETTNG_PREFIX,
|
||||
"startIp" : TETHERING_SETTING_START_IP,
|
||||
"endIp" : TETHERING_SETTING_END_IP,
|
||||
"dns1" : TETHERING_SETTING_DNS1,
|
||||
"dns2" : TETHERING_SETTING_DNS2,
|
||||
"wifiConfig": {
|
||||
"ssid" : TETHERING_SETTING_SSID,
|
||||
"security" : TETHERING_SETTING_SECURITY
|
||||
}
|
||||
};
|
||||
|
||||
return tetheringManager.setTetheringEnabled(aEnabled, TYPE_WIFI, config)
|
||||
.then(function waitForRoutingVerified() {
|
||||
return verifyTetheringRouting(aEnabled)
|
||||
.then(null, function onreject(aReason) {
|
||||
|
||||
log('verifyTetheringRouting rejected due to ' + aReason +
|
||||
' (' + retryCnt + ')');
|
||||
|
||||
if (!retryCnt--) {
|
||||
throw aReason;
|
||||
}
|
||||
|
||||
return waitForTimeout(RETRY_INTERVAL_MS).then(waitForRoutingVerified);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensure wifi is enabled/disabled.
|
||||
*
|
||||
* Issue a wifi enable/disable request if wifi is not in the desired state;
|
||||
* return a resolved promise otherwise.
|
||||
*
|
||||
* Fulfill params: (none)
|
||||
* Reject params: (none)
|
||||
*
|
||||
* @return a resolved promise or deferred promise.
|
||||
*/
|
||||
function ensureWifiEnabled(aEnabled) {
|
||||
let wifiManager = window.navigator.mozWifiManager;
|
||||
if (wifiManager.enabled === aEnabled) {
|
||||
return Promise.resolve();
|
||||
}
|
||||
let request = wifiManager.setWifiEnabled(aEnabled);
|
||||
return wrapDomRequestAsPromise(request)
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensure tethering manager exists.
|
||||
*
|
||||
* Check navigator property |mozTetheringManager| to ensure we could access
|
||||
* tethering related function.
|
||||
*
|
||||
* Fulfill params: (none)
|
||||
* Reject params: (none)
|
||||
*
|
||||
* @return A deferred promise.
|
||||
*/
|
||||
function ensureTetheringManager() {
|
||||
let deferred = Promise.defer();
|
||||
|
||||
tetheringManager = window.navigator.mozTetheringManager;
|
||||
|
||||
if (tetheringManager instanceof MozTetheringManager) {
|
||||
deferred.resolve();
|
||||
} else {
|
||||
log("navigator.mozTetheringManager is unavailable");
|
||||
deferred.reject();
|
||||
}
|
||||
|
||||
return deferred.promise;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add required permissions for tethering. Never reject.
|
||||
*
|
||||
* The permissions required for wifi testing are 'wifi-manage' and 'settings-write'.
|
||||
* Never reject.
|
||||
*
|
||||
* Fulfill params: (none)
|
||||
*
|
||||
* @return A deferred promise.
|
||||
*/
|
||||
function acquirePermission() {
|
||||
let deferred = Promise.defer();
|
||||
|
||||
let permissions = [{ 'type': 'wifi-manage', 'allow': 1, 'context': window.document },
|
||||
{ 'type': 'settings-write', 'allow': 1, 'context': window.document },
|
||||
{ 'type': 'settings-read', 'allow': 1, 'context': window.document },
|
||||
{ 'type': 'mobileconnection', 'allow': 1, 'context': window.document }];
|
||||
|
||||
SpecialPowers.pushPermissions(permissions, function() {
|
||||
deferred.resolve();
|
||||
});
|
||||
|
||||
return deferred.promise;
|
||||
}
|
||||
|
||||
/**
|
||||
* Common test routine.
|
||||
*
|
||||
* Start a test with the given test case chain. The test environment will be
|
||||
* settled down before the test. After the test, all the affected things will
|
||||
* be restored.
|
||||
*
|
||||
* Fulfill params: (none)
|
||||
* Reject params: (none)
|
||||
*
|
||||
* @param aTestCaseChain
|
||||
* The test case entry point, which can be a function or a promise.
|
||||
*
|
||||
* @return A deferred promise.
|
||||
*/
|
||||
suite.startTest = function(aTestCaseChain) {
|
||||
function setUp() {
|
||||
return ensureTetheringManager()
|
||||
.then(acquirePermission);
|
||||
}
|
||||
|
||||
function tearDown() {
|
||||
waitFor(finish, function() {
|
||||
return pendingEmulatorShellCount === 0;
|
||||
});
|
||||
}
|
||||
|
||||
return setUp()
|
||||
.then(aTestCaseChain)
|
||||
.then(function onresolve() {
|
||||
tearDown();
|
||||
}, function onreject(aReason) {
|
||||
ok(false, 'Promise rejects during test' + (aReason ? '(' + aReason + ')' : ''));
|
||||
tearDown();
|
||||
});
|
||||
};
|
||||
|
||||
//---------------------------------------------------
|
||||
// Public test suite functions
|
||||
//---------------------------------------------------
|
||||
suite.ensureWifiEnabled = ensureWifiEnabled;
|
||||
suite.setWifiTetheringEnabled = setWifiTetheringEnabled;
|
||||
|
||||
/**
|
||||
* The common test routine for wifi tethering.
|
||||
*
|
||||
* Set 'ril.data.enabled' to true
|
||||
* before testing and restore it afterward. It will also verify 'ril.data.enabled'
|
||||
* and 'tethering.wifi.enabled' to be false in the beginning. Note that this routine
|
||||
* will NOT change the state of 'tethering.wifi.enabled' so the user should enable
|
||||
* than disable on his/her own. This routine will only check if tethering is turned
|
||||
* off after testing.
|
||||
*
|
||||
* Fulfill params: (none)
|
||||
* Reject params: (none)
|
||||
*
|
||||
* @param aTestCaseChain
|
||||
* The test case entry point, which can be a function or a promise.
|
||||
*
|
||||
* @return A deferred promise.
|
||||
*/
|
||||
suite.startTetheringTest = function(aTestCaseChain) {
|
||||
let oriDataEnabled;
|
||||
function verifyInitialState() {
|
||||
return getSettings(SETTINGS_RIL_DATA_ENABLED)
|
||||
.then(enabled => initTetheringTestEnvironment(enabled));
|
||||
}
|
||||
|
||||
function initTetheringTestEnvironment(aEnabled) {
|
||||
oriDataEnabled = aEnabled;
|
||||
if (aEnabled) {
|
||||
return Promise.resolve();
|
||||
} else {
|
||||
return Promise.all([waitForRilDataConnected(true),
|
||||
setSettings1(SETTINGS_RIL_DATA_ENABLED, true)]);
|
||||
}
|
||||
}
|
||||
|
||||
function restoreToInitialState() {
|
||||
return setSettings1(SETTINGS_RIL_DATA_ENABLED, oriDataEnabled);
|
||||
}
|
||||
|
||||
return suite.startTest(function() {
|
||||
return verifyInitialState()
|
||||
.then(aTestCaseChain)
|
||||
.then(restoreToInitialState, function onreject(aReason) {
|
||||
return restoreToInitialState()
|
||||
.then(() => { throw aReason; }); // Re-throw the orignal reject reason.
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
return suite;
|
||||
})();
|
6
dom/tethering/tests/marionette/manifest.ini
Normal file
6
dom/tethering/tests/marionette/manifest.ini
Normal file
@ -0,0 +1,6 @@
|
||||
[DEFAULT]
|
||||
b2g = true
|
||||
browser = false
|
||||
qemu = true
|
||||
|
||||
[test_wifi_tethering_enabled.js]
|
@ -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/. */
|
||||
|
||||
MARIONETTE_TIMEOUT = 60000;
|
||||
MARIONETTE_HEAD_JS = 'head.js';
|
||||
|
||||
gTestSuite.startTetheringTest(function() {
|
||||
return gTestSuite.ensureWifiEnabled(false)
|
||||
.then(() => gTestSuite.setWifiTetheringEnabled(true));
|
||||
});
|
@ -172,7 +172,9 @@ function checkCookie() {
|
||||
|
||||
SpecialPowers.pushPrefEnv({set: [['network.cookie.cookieBehavior', 0]]}, () =>
|
||||
SpecialPowers.autoConfirmAppInstall(() =>
|
||||
navigator.mozApps.install(gManifestURL, null).onsuccess = onInstall
|
||||
SpecialPowers.autoConfirmAppUninstall(() =>
|
||||
navigator.mozApps.install(gManifestURL, null).onsuccess = onInstall
|
||||
)
|
||||
)
|
||||
);
|
||||
</script>
|
||||
|
@ -103,7 +103,9 @@ function onInstall() {
|
||||
}
|
||||
|
||||
SpecialPowers.autoConfirmAppInstall(() =>
|
||||
navigator.mozApps.install(gManifestURL, null).onsuccess = onInstall
|
||||
SpecialPowers.autoConfirmAppUninstall(() =>
|
||||
navigator.mozApps.install(gManifestURL, null).onsuccess = onInstall
|
||||
)
|
||||
);
|
||||
|
||||
</script>
|
||||
|
@ -353,6 +353,7 @@ var BrowserApp = {
|
||||
Services.obs.addObserver(this, "webapps-runtime-install", false);
|
||||
Services.obs.addObserver(this, "webapps-runtime-install-package", false);
|
||||
Services.obs.addObserver(this, "webapps-ask-install", false);
|
||||
Services.obs.addObserver(this, "webapps-ask-uninstall", false);
|
||||
Services.obs.addObserver(this, "webapps-launch", false);
|
||||
Services.obs.addObserver(this, "webapps-runtime-uninstall", false);
|
||||
Services.obs.addObserver(this, "Webapps:AutoInstall", false);
|
||||
@ -1707,6 +1708,10 @@ var BrowserApp = {
|
||||
WebappManager.askInstall(JSON.parse(aData));
|
||||
break;
|
||||
|
||||
case "webapps-ask-uninstall":
|
||||
WebappManager.askUninstall(JSON.parse(aData));
|
||||
break;
|
||||
|
||||
case "webapps-launch": {
|
||||
WebappManager.launch(JSON.parse(aData));
|
||||
break;
|
||||
|
@ -194,6 +194,12 @@ this.WebappManager = {
|
||||
});
|
||||
},
|
||||
|
||||
askUninstall: function(aData) {
|
||||
// Android does not currently support automatic uninstalling of apps.
|
||||
// See bug 1019054.
|
||||
DOMApplicationRegistry.denyUninstall(aData, "NOT_SUPPORTED");
|
||||
},
|
||||
|
||||
launch: function({ apkPackageName }) {
|
||||
debug("launch: " + apkPackageName);
|
||||
|
||||
@ -633,8 +639,7 @@ this.WebappManager = {
|
||||
let app = DOMApplicationRegistry.webapps[id];
|
||||
if (aData.apkPackageNames.indexOf(app.apkPackageName) > -1) {
|
||||
debug("attempting to uninstall " + app.name);
|
||||
DOMApplicationRegistry.uninstall(
|
||||
app.manifestURL,
|
||||
DOMApplicationRegistry.uninstall(app.manifestURL).then(
|
||||
function() {
|
||||
debug("success uninstalling " + app.name);
|
||||
},
|
||||
|
@ -28,6 +28,7 @@ skip = false
|
||||
[include:../../../../../dom/events/test/marionette/manifest.ini]
|
||||
[include:../../../../../dom/wifi/test/marionette/manifest.ini]
|
||||
[include:../../../../../dom/cellbroadcast/tests/marionette/manifest.ini]
|
||||
[include:../../../../../dom/tethering/tests/marionette/manifest.ini]
|
||||
|
||||
; layout tests
|
||||
[include:../../../../../layout/base/tests/marionette/manifest.ini]
|
||||
|
@ -176,7 +176,7 @@ $(_DEST_DIR):
|
||||
$(NSINSTALL) -D $@
|
||||
|
||||
stage-package:
|
||||
$(NSINSTALL) -D $(PKG_STAGE)/mochitest && $(NSINSTALL) -D $(PKG_STAGE)/bin/plugins && $(NSINSTALL) -D $(DIST)/plugins && $(NSINSTALL) -D $(PKG_STAGE)/bin/plugins/gmp-fake
|
||||
$(NSINSTALL) -D $(PKG_STAGE)/mochitest && $(NSINSTALL) -D $(PKG_STAGE)/bin/plugins && $(NSINSTALL) -D $(DIST)/plugins && $(NSINSTALL) -D $(PKG_STAGE)/bin/plugins/gmp-fake/1.0
|
||||
cp $(DEPTH)/mozinfo.json $(PKG_STAGE)/mochitest
|
||||
(cd $(DEPTH)/_tests/testing && tar $(TAR_CREATE_FLAGS) - mochitest) | (cd $(PKG_STAGE) && tar -xf -)
|
||||
@cp $(DEPTH)/mozinfo.json $(PKG_STAGE)/mochitest
|
||||
@ -184,4 +184,4 @@ stage-package:
|
||||
@(cd $(DIST_BIN)/components && tar $(TAR_CREATE_FLAGS) - $(TEST_HARNESS_COMPONENTS)) | (cd $(PKG_STAGE)/bin/components && tar -xf -)
|
||||
(cd $(topsrcdir)/build/pgo && tar $(TAR_CREATE_FLAGS) - certs) | (cd $(PKG_STAGE) && tar -xf -)
|
||||
@(cd $(DIST)/plugins && tar $(TAR_CREATE_FLAGS) - $(TEST_HARNESS_PLUGINS)) | (cd $(PKG_STAGE)/bin/plugins && tar -xf -)
|
||||
$(foreach x,$(GMP_TEST_FILES),cp $(x) $(PKG_STAGE)/bin/plugins/gmp-fake;)
|
||||
$(foreach x,$(GMP_TEST_FILES),cp $(x) $(PKG_STAGE)/bin/plugins/gmp-fake/1.0;)
|
||||
|
@ -363,7 +363,7 @@ class MochitestRunner(MozbuildObject):
|
||||
if options.gmp_path is None:
|
||||
# Need to fix the location of gmp_fake which might not be shipped in the binary
|
||||
bin_path = self.get_binary_path()
|
||||
options.gmp_path = os.path.join(os.path.dirname(bin_path), 'gmp-fake')
|
||||
options.gmp_path = os.path.join(os.path.dirname(bin_path), 'gmp-fake', '1.0')
|
||||
|
||||
|
||||
logger_options = {key: value for key, value in vars(options).iteritems() if key.startswith('log')}
|
||||
|
@ -1166,12 +1166,12 @@ class Mochitest(MochitestUtilsMixin):
|
||||
return options.gmp_path
|
||||
|
||||
# For local builds, gmp-fake will be under dist/bin.
|
||||
gmp_path = os.path.join(options.xrePath, 'gmp-fake')
|
||||
gmp_path = os.path.join(options.xrePath, 'gmp-fake', '1.0')
|
||||
if os.path.isdir(gmp_path):
|
||||
return gmp_path
|
||||
|
||||
# For packaged builds, gmp-fake will get copied under $profile/plugins.
|
||||
gmp_path = os.path.join(self.profile.profile, 'plugins', 'gmp-fake')
|
||||
gmp_path = os.path.join(self.profile.profile, 'plugins', 'gmp-fake', '1.0')
|
||||
if os.path.isdir(gmp_path):
|
||||
return gmp_path
|
||||
# This is fatal for desktop environments.
|
||||
|
@ -1077,6 +1077,10 @@ SpecialPowersAPI.prototype = {
|
||||
this.pushPrefEnv({set: [['dom.mozApps.auto_confirm_install', true]]}, cb);
|
||||
},
|
||||
|
||||
autoConfirmAppUninstall: function(cb) {
|
||||
this.pushPrefEnv({set: [['dom.mozApps.auto_confirm_uninstall', true]]}, cb);
|
||||
},
|
||||
|
||||
// Allow tests to disable the per platform app validity checks so we can
|
||||
// test higher level WebApp functionality without full platform support.
|
||||
setAllAppsLaunchable: function(launchable) {
|
||||
|
@ -12,6 +12,11 @@ const { ActorPool, appendExtraActors, createExtraActors } = require("devtools/se
|
||||
const { DebuggerServer } = require("devtools/server/main");
|
||||
const { dumpProtocolSpec } = require("devtools/server/protocol");
|
||||
const makeDebugger = require("./utils/make-debugger");
|
||||
const DevToolsUtils = require("devtools/toolkit/DevToolsUtils");
|
||||
|
||||
DevToolsUtils.defineLazyGetter(this, "StyleSheetActor", () => {
|
||||
return require("devtools/server/actors/stylesheets").StyleSheetActor;
|
||||
});
|
||||
|
||||
/* Root actor for the remote debugging protocol. */
|
||||
|
||||
@ -94,6 +99,9 @@ function RootActor(aConnection, aParameters) {
|
||||
this._onAddonListChanged = this.onAddonListChanged.bind(this);
|
||||
this._extraActors = {};
|
||||
|
||||
// Map of DOM stylesheets to StyleSheetActors
|
||||
this._styleSheetActors = new Map();
|
||||
|
||||
// This creates a Debugger instance for chrome debugging all globals.
|
||||
this.makeDebugger = makeDebugger.bind(null, {
|
||||
findDebuggees: dbg => dbg.findAllGlobals(),
|
||||
@ -226,6 +234,8 @@ RootActor.prototype = {
|
||||
this._parameters.onShutdown();
|
||||
}
|
||||
this._extraActors = null;
|
||||
this._styleSheetActors.clear();
|
||||
this._styleSheetActors = null;
|
||||
},
|
||||
|
||||
/* The 'listTabs' request and the 'tabListChanged' notification. */
|
||||
@ -387,6 +397,28 @@ RootActor.prototype = {
|
||||
windowUtils.resumeTimeouts();
|
||||
windowUtils.suppressEventHandling(false);
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Create or return the StyleSheetActor for a style sheet. This method
|
||||
* is here because the Style Editor and Inspector share style sheet actors.
|
||||
*
|
||||
* @param DOMStyleSheet styleSheet
|
||||
* The style sheet to creat an actor for.
|
||||
* @return StyleSheetActor actor
|
||||
* The actor for this style sheet.
|
||||
*
|
||||
*/
|
||||
createStyleSheetActor: function(styleSheet) {
|
||||
if (this._styleSheetActors.has(styleSheet)) {
|
||||
return this._styleSheetActors.get(styleSheet);
|
||||
}
|
||||
let actor = new StyleSheetActor(styleSheet, this);
|
||||
this._styleSheetActors.set(styleSheet, actor);
|
||||
|
||||
this._globalActorPool.addActor(actor);
|
||||
|
||||
return actor;
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -12,7 +12,9 @@ const {Arg, Option, method, RetVal, types} = protocol;
|
||||
const events = require("sdk/event/core");
|
||||
const object = require("sdk/util/object");
|
||||
const { Class } = require("sdk/core/heritage");
|
||||
const { StyleSheetActor } = require("devtools/server/actors/stylesheets");
|
||||
|
||||
// This will add the "stylesheet" actor type for protocol.js to recognize
|
||||
require("devtools/server/actors/stylesheets");
|
||||
|
||||
loader.lazyGetter(this, "CssLogic", () => require("devtools/styleinspector/css-logic").CssLogic);
|
||||
loader.lazyGetter(this, "DOMUtils", () => Cc["@mozilla.org/inspector/dom-utils;1"].getService(Ci.inIDOMUtils));
|
||||
@ -112,17 +114,15 @@ var PageStyleActor = protocol.ActorClass({
|
||||
},
|
||||
|
||||
/**
|
||||
* Return or create a StyleSheetActor for the given
|
||||
* nsIDOMCSSStyleSheet
|
||||
* Return or create a StyleSheetActor for the given nsIDOMCSSStyleSheet.
|
||||
* @param {DOMStyleSheet} sheet
|
||||
* The style sheet to create an actor for.
|
||||
* @return {StyleSheetActor}
|
||||
* The actor for this style sheet
|
||||
*/
|
||||
_sheetRef: function(sheet) {
|
||||
if (this.refMap.has(sheet)) {
|
||||
return this.refMap.get(sheet);
|
||||
}
|
||||
let actor = new StyleSheetActor(sheet, this, this.walker.rootWin);
|
||||
this.manage(actor);
|
||||
this.refMap.set(sheet, actor);
|
||||
|
||||
let tabActor = this.inspector.tabActor;
|
||||
let actor = tabActor.createStyleSheetActor(sheet);
|
||||
return actor;
|
||||
},
|
||||
|
||||
@ -975,6 +975,7 @@ var StyleRuleFront = protocol.FrontClass(StyleRuleActor, {
|
||||
get location()
|
||||
{
|
||||
return {
|
||||
source: this.parentStyleSheet,
|
||||
href: this.href,
|
||||
line: this.line,
|
||||
column: this.column
|
||||
@ -992,12 +993,15 @@ var StyleRuleFront = protocol.FrontClass(StyleRuleActor, {
|
||||
return promise.resolve(this.location);
|
||||
}
|
||||
return parentSheet.getOriginalLocation(this.line, this.column)
|
||||
.then(({ source, line, column }) => {
|
||||
.then(({ fromSourceMap, source, line, column }) => {
|
||||
let location = {
|
||||
href: source,
|
||||
line: line,
|
||||
column: column
|
||||
}
|
||||
if (fromSourceMap === false) {
|
||||
location.source = this.parentStyleSheet;
|
||||
}
|
||||
if (!source) {
|
||||
location.href = this.href;
|
||||
}
|
||||
|
@ -74,17 +74,6 @@ let StyleSheetsActor = protocol.ActorClass({
|
||||
protocol.Actor.prototype.initialize.call(this, null);
|
||||
|
||||
this.parentActor = tabActor;
|
||||
|
||||
// keep a map of sheets-to-actors so we don't create two actors for one sheet
|
||||
this._sheets = new Map();
|
||||
},
|
||||
|
||||
/**
|
||||
* Destroy the current StyleSheetsActor instance.
|
||||
*/
|
||||
destroy: function()
|
||||
{
|
||||
this._sheets.clear();
|
||||
},
|
||||
|
||||
/**
|
||||
@ -156,7 +145,7 @@ let StyleSheetsActor = protocol.ActorClass({
|
||||
return Task.spawn(function() {
|
||||
let actors = [];
|
||||
for (let i = 0; i < styleSheets.length; i++) {
|
||||
let actor = this._createStyleSheetActor(styleSheets[i]);
|
||||
let actor = this.parentActor.createStyleSheetActor(styleSheets[i]);
|
||||
actors.push(actor);
|
||||
|
||||
// Get all sheets, including imported ones
|
||||
@ -188,7 +177,7 @@ let StyleSheetsActor = protocol.ActorClass({
|
||||
if (!rule.styleSheet) {
|
||||
continue;
|
||||
}
|
||||
let actor = this._createStyleSheetActor(rule.styleSheet);
|
||||
let actor = this.parentActor.createStyleSheetActor(rule.styleSheet);
|
||||
imported.push(actor);
|
||||
|
||||
// recurse imports in this stylesheet as well
|
||||
@ -205,36 +194,6 @@ let StyleSheetsActor = protocol.ActorClass({
|
||||
}.bind(this));
|
||||
},
|
||||
|
||||
/**
|
||||
* Create a new actor for a style sheet, if it hasn't already been created.
|
||||
*
|
||||
* @param {DOMStyleSheet} styleSheet
|
||||
* The style sheet to create an actor for.
|
||||
* @return {StyleSheetActor}
|
||||
* The actor for this style sheet
|
||||
*/
|
||||
_createStyleSheetActor: function(styleSheet)
|
||||
{
|
||||
if (this._sheets.has(styleSheet)) {
|
||||
return this._sheets.get(styleSheet);
|
||||
}
|
||||
let actor = new StyleSheetActor(styleSheet, this);
|
||||
|
||||
this.manage(actor);
|
||||
this._sheets.set(styleSheet, actor);
|
||||
|
||||
return actor;
|
||||
},
|
||||
|
||||
/**
|
||||
* Clear all the current stylesheet actors in map.
|
||||
*/
|
||||
_clearStyleSheetActors: function() {
|
||||
for (let actor in this._sheets) {
|
||||
this.unmanage(this._sheets[actor]);
|
||||
}
|
||||
this._sheets.clear();
|
||||
},
|
||||
|
||||
/**
|
||||
* Create a new style sheet in the document with the given text.
|
||||
@ -255,7 +214,7 @@ let StyleSheetsActor = protocol.ActorClass({
|
||||
}
|
||||
parent.appendChild(style);
|
||||
|
||||
let actor = this._createStyleSheetActor(style.sheet);
|
||||
let actor = this.parentActor.createStyleSheetActor(style.sheet);
|
||||
return actor;
|
||||
}, {
|
||||
request: { text: Arg(0, "string") },
|
||||
@ -323,6 +282,8 @@ let MediaRuleActor = protocol.ActorClass({
|
||||
if (this.mql) {
|
||||
this.mql.removeListener(this._matchesChange);
|
||||
}
|
||||
|
||||
protocol.Actor.prototype.destroy.call(this);
|
||||
},
|
||||
|
||||
form: function(detail) {
|
||||
@ -420,16 +381,6 @@ let StyleSheetActor = protocol.ActorClass({
|
||||
*/
|
||||
get document() this.window.document,
|
||||
|
||||
/**
|
||||
* Browser for the target.
|
||||
*/
|
||||
get browser() {
|
||||
if (this.parentActor.parentActor) {
|
||||
return this.parentActor.parentActor.browser;
|
||||
}
|
||||
return null;
|
||||
},
|
||||
|
||||
get ownerNode() this.rawSheet.ownerNode,
|
||||
|
||||
/**
|
||||
@ -768,6 +719,7 @@ let StyleSheetActor = protocol.ActorClass({
|
||||
return sourceMap.originalPositionFor({ line: line, column: column });
|
||||
}
|
||||
return {
|
||||
fromSourceMap: false,
|
||||
source: this.href,
|
||||
line: line,
|
||||
column: column
|
||||
@ -998,7 +950,6 @@ var StyleSheetFront = protocol.FrontClass(StyleSheetActor, {
|
||||
|
||||
destroy: function() {
|
||||
events.off(this, "property-change", this._onPropertyChange);
|
||||
|
||||
protocol.Front.prototype.destroy.call(this);
|
||||
},
|
||||
|
||||
|
@ -705,23 +705,11 @@ WebappsActor.prototype = {
|
||||
|
||||
let manifestURL = aRequest.manifestURL;
|
||||
if (!manifestURL) {
|
||||
return { error: "missingParameter",
|
||||
message: "missing parameter manifestURL" };
|
||||
return Promise.resolve({ error: "missingParameter",
|
||||
message: "missing parameter manifestURL" });
|
||||
}
|
||||
|
||||
let deferred = promise.defer();
|
||||
let reg = DOMApplicationRegistry;
|
||||
reg.uninstall(
|
||||
manifestURL,
|
||||
function onsuccess() {
|
||||
deferred.resolve({});
|
||||
},
|
||||
function onfailure(reason) {
|
||||
deferred.resolve({ error: reason });
|
||||
}
|
||||
);
|
||||
|
||||
return deferred.promise;
|
||||
return DOMApplicationRegistry.uninstall(manifestURL);
|
||||
},
|
||||
|
||||
_findManifestByURL: function wa__findManifestByURL(aManifestURL) {
|
||||
|
@ -29,6 +29,10 @@ XPCOMUtils.defineLazyGetter(this, "events", () => {
|
||||
return require("sdk/event/core");
|
||||
});
|
||||
|
||||
XPCOMUtils.defineLazyGetter(this, "StyleSheetActor", () => {
|
||||
return require("devtools/server/actors/stylesheets").StyleSheetActor;
|
||||
});
|
||||
|
||||
// Also depends on following symbols, shared by common scope with main.js:
|
||||
// DebuggerServer, CommonCreateExtraActors, CommonAppendExtraActors, ActorPool,
|
||||
// ThreadActor
|
||||
@ -545,6 +549,9 @@ function TabActor(aConnection)
|
||||
this._extraActors = {};
|
||||
this._exited = false;
|
||||
|
||||
// Map of DOM stylesheets to StyleSheetActors
|
||||
this._styleSheetActors = new Map();
|
||||
|
||||
this._shouldAddNewGlobalAsDebuggee = this._shouldAddNewGlobalAsDebuggee.bind(this);
|
||||
|
||||
this.makeDebugger = makeDebugger.bind(null, {
|
||||
@ -722,6 +729,7 @@ TabActor.prototype = {
|
||||
disconnect: function BTA_disconnect() {
|
||||
this._detach();
|
||||
this._extraActors = null;
|
||||
this._styleSheetActors.clear();
|
||||
this._exited = true;
|
||||
},
|
||||
|
||||
@ -1059,6 +1067,12 @@ TabActor.prototype = {
|
||||
}
|
||||
}
|
||||
|
||||
for (let sheetActor of this._styleSheetActors.values()) {
|
||||
this._tabPool.removeActor(sheetActor);
|
||||
}
|
||||
this._styleSheetActors.clear();
|
||||
|
||||
|
||||
// Refresh the debuggee list when a new window object appears (top window or
|
||||
// iframe).
|
||||
if (threadActor.attached) {
|
||||
@ -1175,6 +1189,28 @@ TabActor.prototype = {
|
||||
}
|
||||
catch (ex) { }
|
||||
return isNative;
|
||||
},
|
||||
|
||||
/**
|
||||
* Create or return the StyleSheetActor for a style sheet. This method
|
||||
* is here because the Style Editor and Inspector share style sheet actors.
|
||||
*
|
||||
* @param DOMStyleSheet styleSheet
|
||||
* The style sheet to creat an actor for.
|
||||
* @return StyleSheetActor actor
|
||||
* The actor for this style sheet.
|
||||
*
|
||||
*/
|
||||
createStyleSheetActor: function BTA_createStyleSheetActor(styleSheet) {
|
||||
if (this._styleSheetActors.has(styleSheet)) {
|
||||
return this._styleSheetActors.get(styleSheet);
|
||||
}
|
||||
let actor = new StyleSheetActor(styleSheet, this);
|
||||
this._styleSheetActors.set(styleSheet, actor);
|
||||
|
||||
this._tabPool.addActor(actor);
|
||||
|
||||
return actor;
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -107,7 +107,6 @@ let GMPPrefs = {
|
||||
*/
|
||||
KEY_LOG_ENABLED: "media.gmp-manager.log",
|
||||
KEY_ADDON_LAST_UPDATE: "media.{0}.lastUpdate",
|
||||
KEY_ADDON_PATH: "media.{0}.path",
|
||||
KEY_ADDON_VERSION: "media.{0}.version",
|
||||
KEY_ADDON_AUTOUPDATE: "media.{0}.autoupdate",
|
||||
KEY_URL: "media.gmp-manager.url",
|
||||
@ -889,7 +888,9 @@ GMPDownloader.prototype = {
|
||||
let gmpAddon = this._gmpAddon;
|
||||
let installToDirPath = Cc["@mozilla.org/file/local;1"].
|
||||
createInstance(Ci.nsIFile);
|
||||
let path = OS.Path.join(OS.Constants.Path.profileDir, gmpAddon.id);
|
||||
let path = OS.Path.join(OS.Constants.Path.profileDir,
|
||||
gmpAddon.id,
|
||||
gmpAddon.version);
|
||||
installToDirPath.initWithPath(path);
|
||||
log.info("install to directory path: " + installToDirPath.path);
|
||||
let gmpInstaller = new GMPExtractor(zipPath, installToDirPath.path);
|
||||
@ -898,12 +899,10 @@ GMPDownloader.prototype = {
|
||||
// Success, set the prefs
|
||||
let now = Math.round(Date.now() / 1000);
|
||||
GMPPrefs.set(GMPPrefs.KEY_ADDON_LAST_UPDATE, now, gmpAddon.id);
|
||||
// Setting the path pref signals installation completion to consumers,
|
||||
// so set the version and potential other information they use first.
|
||||
// Setting the version pref signals installation completion to consumers,
|
||||
// if you need to set other prefs etc. do it before this.
|
||||
GMPPrefs.set(GMPPrefs.KEY_ADDON_VERSION, gmpAddon.version,
|
||||
gmpAddon.id);
|
||||
GMPPrefs.set(GMPPrefs.KEY_ADDON_PATH,
|
||||
installToDirPath.path, gmpAddon.id);
|
||||
this._deferred.resolve(extractedPaths);
|
||||
}, err => {
|
||||
this._deferred.reject(err);
|
||||
|
@ -29,11 +29,9 @@ add_test(function test_prefs() {
|
||||
GMPPrefs.set(GMPPrefs.KEY_URL, "http://not-really-used");
|
||||
GMPPrefs.set(GMPPrefs.KEY_URL_OVERRIDE, "http://not-really-used-2");
|
||||
GMPPrefs.set(GMPPrefs.KEY_ADDON_LAST_UPDATE, "1", addon1);
|
||||
GMPPrefs.set(GMPPrefs.KEY_ADDON_PATH, "2", addon1);
|
||||
GMPPrefs.set(GMPPrefs.KEY_ADDON_VERSION, "3", addon1);
|
||||
GMPPrefs.set(GMPPrefs.KEY_ADDON_LAST_UPDATE, "4", addon2);
|
||||
GMPPrefs.set(GMPPrefs.KEY_ADDON_PATH, "5", addon2);
|
||||
GMPPrefs.set(GMPPrefs.KEY_ADDON_VERSION, "6", addon2);
|
||||
GMPPrefs.set(GMPPrefs.KEY_ADDON_VERSION, "2", addon1);
|
||||
GMPPrefs.set(GMPPrefs.KEY_ADDON_LAST_UPDATE, "3", addon2);
|
||||
GMPPrefs.set(GMPPrefs.KEY_ADDON_VERSION, "4", addon2);
|
||||
GMPPrefs.set(GMPPrefs.KEY_ADDON_AUTOUPDATE, false, addon2);
|
||||
GMPPrefs.set(GMPPrefs.KEY_CERT_CHECKATTRS, true);
|
||||
|
||||
@ -41,11 +39,9 @@ add_test(function test_prefs() {
|
||||
do_check_eq(GMPPrefs.get(GMPPrefs.KEY_URL), "http://not-really-used");
|
||||
do_check_eq(GMPPrefs.get(GMPPrefs.KEY_URL_OVERRIDE), "http://not-really-used-2");
|
||||
do_check_eq(GMPPrefs.get(GMPPrefs.KEY_ADDON_LAST_UPDATE, addon1), "1");
|
||||
do_check_eq(GMPPrefs.get(GMPPrefs.KEY_ADDON_PATH, addon1), "2");
|
||||
do_check_eq(GMPPrefs.get(GMPPrefs.KEY_ADDON_VERSION, addon1), "3");
|
||||
do_check_eq(GMPPrefs.get(GMPPrefs.KEY_ADDON_LAST_UPDATE, addon2), "4");
|
||||
do_check_eq(GMPPrefs.get(GMPPrefs.KEY_ADDON_PATH, addon2), "5");
|
||||
do_check_eq(GMPPrefs.get(GMPPrefs.KEY_ADDON_VERSION, addon2), "6");
|
||||
do_check_eq(GMPPrefs.get(GMPPrefs.KEY_ADDON_VERSION, addon1), "2");
|
||||
do_check_eq(GMPPrefs.get(GMPPrefs.KEY_ADDON_LAST_UPDATE, addon2), "3");
|
||||
do_check_eq(GMPPrefs.get(GMPPrefs.KEY_ADDON_VERSION, addon2), "4");
|
||||
do_check_eq(GMPPrefs.get(GMPPrefs.KEY_ADDON_AUTOUPDATE, addon2), false);
|
||||
do_check_true(GMPPrefs.get(GMPPrefs.KEY_CERT_CHECKATTRS));
|
||||
GMPPrefs.set(GMPPrefs.KEY_ADDON_AUTOUPDATE, true, addon2);
|
||||
@ -435,7 +431,7 @@ function test_checkForAddons_installAddon(id, includeSize,wantInstallReject) {
|
||||
let readData = readStringFromFile(extractedFile);
|
||||
do_check_eq(readData, data);
|
||||
|
||||
// Check that the downloaded zip mathces the offered zip exactly
|
||||
// Check that the downloaded zip matches the offered zip exactly
|
||||
let downloadedGMPFile = FileUtils.getFile("TmpD",
|
||||
[gmpAddon.id + ".zip"]);
|
||||
do_check_true(downloadedGMPFile.exists());
|
||||
@ -446,8 +442,6 @@ function test_checkForAddons_installAddon(id, includeSize,wantInstallReject) {
|
||||
// Make sure the prefs are set correctly
|
||||
do_check_true(!!GMPPrefs.get(GMPPrefs.KEY_ADDON_LAST_UPDATE,
|
||||
gmpAddon.id, ""));
|
||||
do_check_eq(GMPPrefs.get(GMPPrefs.KEY_ADDON_PATH, gmpAddon.id, ""),
|
||||
extractedFile.parent.path);
|
||||
do_check_eq(GMPPrefs.get(GMPPrefs.KEY_ADDON_VERSION, gmpAddon.id, ""),
|
||||
"1.1");
|
||||
// Make sure it reports as being installed
|
||||
|
@ -29,7 +29,6 @@ const SEC_IN_A_DAY = 24 * 60 * 60;
|
||||
const OPENH264_PLUGIN_ID = "gmp-gmpopenh264";
|
||||
const OPENH264_PREF_BRANCH = "media." + OPENH264_PLUGIN_ID + ".";
|
||||
const OPENH264_PREF_ENABLED = "enabled";
|
||||
const OPENH264_PREF_PATH = "path";
|
||||
const OPENH264_PREF_VERSION = "version";
|
||||
const OPENH264_PREF_LASTUPDATE = "lastUpdate";
|
||||
const OPENH264_PREF_AUTOUPDATE = "autoupdate";
|
||||
@ -94,12 +93,7 @@ let OpenH264Wrapper = {
|
||||
|
||||
get description() { return pluginsBundle.GetStringFromName("openH264_description"); },
|
||||
|
||||
get version() {
|
||||
if (this.isInstalled) {
|
||||
return prefs.get(OPENH264_PREF_VERSION, "");
|
||||
}
|
||||
return "";
|
||||
},
|
||||
get version() { return prefs.get(OPENH264_PREF_VERSION, ""); },
|
||||
|
||||
get isActive() { return !this.userDisabled; },
|
||||
get appDisabled() { return false; },
|
||||
@ -223,17 +217,24 @@ let OpenH264Wrapper = {
|
||||
|
||||
get pluginMimeTypes() { return []; },
|
||||
get pluginLibraries() {
|
||||
let path = prefs.get(OPENH264_PREF_PATH, null);
|
||||
return path && path.length ? [OS.Path.basename(path)] : [];
|
||||
if (this.isInstalled) {
|
||||
let path = this.version;
|
||||
return [path];
|
||||
}
|
||||
return [];
|
||||
},
|
||||
get pluginFullpath() {
|
||||
let path = prefs.get(OPENH264_PREF_PATH, null);
|
||||
return path && path.length ? [path] : [];
|
||||
if (this.isInstalled) {
|
||||
let path = OS.Path.join(OS.Constants.Path.profileDir,
|
||||
OPENH264_PLUGIN_ID,
|
||||
this.version);
|
||||
return [path];
|
||||
}
|
||||
return [];
|
||||
},
|
||||
|
||||
get isInstalled() {
|
||||
let path = prefs.get(OPENH264_PREF_PATH, "");
|
||||
return path.length > 0;
|
||||
return this.version.length > 0;
|
||||
},
|
||||
};
|
||||
|
||||
@ -244,14 +245,19 @@ let OpenH264Provider = {
|
||||
"OpenH264Provider" + "::");
|
||||
OpenH264Wrapper._log = Log.repository.getLoggerWithMessagePrefix("Toolkit.OpenH264Provider",
|
||||
"OpenH264Wrapper" + "::");
|
||||
this.gmpPath = prefs.get(OPENH264_PREF_PATH, null);
|
||||
this.gmpPath = null;
|
||||
if (OpenH264Wrapper.isInstalled) {
|
||||
this.gmpPath = OS.Path.join(OS.Constants.Path.profileDir,
|
||||
OPENH264_PLUGIN_ID,
|
||||
prefs.get(OPENH264_PREF_VERSION, null));
|
||||
}
|
||||
let enabled = prefs.get(OPENH264_PREF_ENABLED, true);
|
||||
this._log.trace("startup() - enabled=" + enabled + ", gmpPath="+this.gmpPath);
|
||||
|
||||
|
||||
Services.obs.addObserver(this, AddonManager.OPTIONS_NOTIFICATION_DISPLAYED, false);
|
||||
prefs.observe(OPENH264_PREF_ENABLED, this.onPrefEnabledChanged, this);
|
||||
prefs.observe(OPENH264_PREF_PATH, this.onPrefPathChanged, this);
|
||||
prefs.observe(OPENH264_PREF_VERSION, this.onPrefVersionChanged, this);
|
||||
prefs.observe(OPENH264_PREF_LOGGING, configureLogging);
|
||||
|
||||
if (this.gmpPath && enabled) {
|
||||
@ -264,7 +270,7 @@ let OpenH264Provider = {
|
||||
this._log.trace("shutdown()");
|
||||
Services.obs.removeObserver(this, AddonManager.OPTIONS_NOTIFICATION_DISPLAYED);
|
||||
prefs.ignore(OPENH264_PREF_ENABLED, this.onPrefEnabledChanged, this);
|
||||
prefs.ignore(OPENH264_PREF_PATH, this.onPrefPathChanged, this);
|
||||
prefs.ignore(OPENH264_PREF_VERSION, this.onPrefVersionChanged, this);
|
||||
prefs.ignore(OPENH264_PREF_LOGGING, configureLogging);
|
||||
|
||||
return OpenH264Wrapper._updateTask;
|
||||
@ -290,20 +296,25 @@ let OpenH264Provider = {
|
||||
wrapper);
|
||||
},
|
||||
|
||||
onPrefPathChanged: function() {
|
||||
onPrefVersionChanged: function() {
|
||||
let wrapper = OpenH264Wrapper;
|
||||
|
||||
AddonManagerPrivate.callAddonListeners("onUninstalling", wrapper, false);
|
||||
if (this.gmpPath) {
|
||||
this._log.info("onPrefPathChanged() - removing gmp directory " + this.gmpPath);
|
||||
this._log.info("onPrefVersionChanged() - unregistering gmp directory " + this.gmpPath);
|
||||
gmpService.removePluginDirectory(this.gmpPath);
|
||||
}
|
||||
AddonManagerPrivate.callAddonListeners("onUninstalled", wrapper);
|
||||
|
||||
AddonManagerPrivate.callInstallListeners("onExternalInstall", null, wrapper, null, false);
|
||||
this.gmpPath = prefs.get(OPENH264_PREF_PATH, null);
|
||||
this.gmpPath = null;
|
||||
if (OpenH264Wrapper.isInstalled) {
|
||||
this.gmpPath = OS.Path.join(OS.Constants.Path.profileDir,
|
||||
OPENH264_PLUGIN_ID,
|
||||
prefs.get(OPENH264_PREF_VERSION, null));
|
||||
}
|
||||
if (this.gmpPath && wrapper.isActive) {
|
||||
this._log.info("onPrefPathChanged() - adding gmp directory " + this.gmpPath);
|
||||
this._log.info("onPrefVersionChanged() - registering gmp directory " + this.gmpPath);
|
||||
gmpService.addPluginDirectory(this.gmpPath);
|
||||
}
|
||||
AddonManagerPrivate.callAddonListeners("onInstalled", wrapper);
|
||||
|
@ -11,7 +11,6 @@ let OpenH264Scope = Cu.import("resource://gre/modules/addons/OpenH264Provider.js
|
||||
const OPENH264_PLUGIN_ID = "gmp-gmpopenh264";
|
||||
const OPENH264_PREF_BRANCH = "media." + OPENH264_PLUGIN_ID + ".";
|
||||
const OPENH264_PREF_ENABLED = OPENH264_PREF_BRANCH + "enabled";
|
||||
const OPENH264_PREF_PATH = OPENH264_PREF_BRANCH + "path";
|
||||
const OPENH264_PREF_VERSION = OPENH264_PREF_BRANCH + "version";
|
||||
const OPENH264_PREF_LASTUPDATE = OPENH264_PREF_BRANCH + "lastUpdate";
|
||||
const OPENH264_PREF_AUTOUPDATE = OPENH264_PREF_BRANCH + "autoupdate";
|
||||
@ -99,7 +98,6 @@ add_task(function* initializeState() {
|
||||
Services.obs.removeObserver(gOptionsObserver, AddonManager.OPTIONS_NOTIFICATION_DISPLAYED);
|
||||
|
||||
Services.prefs.clearUserPref(OPENH264_PREF_ENABLED);
|
||||
Services.prefs.clearUserPref(OPENH264_PREF_PATH);
|
||||
Services.prefs.clearUserPref(OPENH264_PREF_VERSION);
|
||||
Services.prefs.clearUserPref(OPENH264_PREF_LASTUPDATE);
|
||||
Services.prefs.clearUserPref(OPENH264_PREF_AUTOUPDATE);
|
||||
@ -116,10 +114,9 @@ add_task(function* initializeState() {
|
||||
|
||||
// Start out with OpenH264 not being installed, disabled and automatic updates disabled.
|
||||
Services.prefs.setBoolPref(OPENH264_PREF_ENABLED, false);
|
||||
Services.prefs.setCharPref(OPENH264_PREF_VERSION, "");
|
||||
Services.prefs.setCharPref(OPENH264_PREF_LASTUPDATE, "");
|
||||
Services.prefs.setIntPref (OPENH264_PREF_LASTUPDATE, 0);
|
||||
Services.prefs.setBoolPref(OPENH264_PREF_AUTOUPDATE, false);
|
||||
Services.prefs.setCharPref(OPENH264_PREF_PATH, "");
|
||||
Services.prefs.setCharPref(OPENH264_PREF_VERSION, "");
|
||||
});
|
||||
|
||||
add_task(function* testNotInstalled() {
|
||||
@ -162,10 +159,9 @@ add_task(function* testNotInstalledDetails() {
|
||||
|
||||
add_task(function* testInstalled() {
|
||||
Services.prefs.setBoolPref(OPENH264_PREF_ENABLED, true);
|
||||
Services.prefs.setBoolPref(OPENH264_PREF_VERSION, "1.2.3.4");
|
||||
Services.prefs.setBoolPref(OPENH264_PREF_LASTUPDATE, "" + TEST_DATE.getTime());
|
||||
Services.prefs.setIntPref (OPENH264_PREF_LASTUPDATE, TEST_DATE.getTime());
|
||||
Services.prefs.setBoolPref(OPENH264_PREF_AUTOUPDATE, false);
|
||||
Services.prefs.setCharPref(OPENH264_PREF_PATH, "foo/bar");
|
||||
Services.prefs.setCharPref(OPENH264_PREF_VERSION, "1.2.3.4");
|
||||
|
||||
yield gCategoryUtilities.openType("plugin");
|
||||
|
||||
@ -204,20 +200,17 @@ add_task(function* testInstalledDetails() {
|
||||
});
|
||||
|
||||
add_task(function* testPreferencesButton() {
|
||||
let file = Services.dirsvc.get("ProfD", Ci.nsIFile);
|
||||
file.append("openh264");
|
||||
file.append("testDir");
|
||||
|
||||
let prefValues = [
|
||||
{ enabled: false, path: "" },
|
||||
{ enabled: false, path: file.path },
|
||||
{ enabled: true, path: "" },
|
||||
{ enabled: true, path: file.path },
|
||||
{ enabled: false, version: "" },
|
||||
{ enabled: false, version: "1.2.3.4" },
|
||||
{ enabled: true, version: "" },
|
||||
{ enabled: true, version: "1.2.3.4" },
|
||||
];
|
||||
|
||||
for (let prefs of prefValues) {
|
||||
dump("Testing preferences button with pref settings: " + JSON.stringify(prefs) + "\n");
|
||||
Services.prefs.setCharPref(OPENH264_PREF_PATH, prefs.path);
|
||||
Services.prefs.setCharPref(OPENH264_PREF_VERSION, prefs.version);
|
||||
Services.prefs.setBoolPref(OPENH264_PREF_ENABLED, prefs.enabled);
|
||||
|
||||
yield gCategoryUtilities.openType("plugin");
|
||||
|
@ -8,7 +8,6 @@ const {classes: Cc, interfaces: Ci, utils: Cu} = Components;
|
||||
const OPENH264_PLUGIN_ID = "gmp-gmpopenh264";
|
||||
const OPENH264_PREF_BRANCH = "media." + OPENH264_PLUGIN_ID + ".";
|
||||
const OPENH264_PREF_ENABLED = OPENH264_PREF_BRANCH + "enabled";
|
||||
const OPENH264_PREF_PATH = OPENH264_PREF_BRANCH + "path";
|
||||
const OPENH264_PREF_VERSION = OPENH264_PREF_BRANCH + "version";
|
||||
const OPENH264_PREF_LASTUPDATE = OPENH264_PREF_BRANCH + "lastUpdate";
|
||||
const OPENH264_PREF_AUTOUPDATE = OPENH264_PREF_BRANCH + "autoupdate";
|
||||
@ -55,7 +54,7 @@ function run_test() {
|
||||
}
|
||||
|
||||
add_task(function* test_notInstalled() {
|
||||
Services.prefs.setCharPref(OPENH264_PREF_PATH, "");
|
||||
Services.prefs.setCharPref(OPENH264_PREF_VERSION, "");
|
||||
Services.prefs.setBoolPref(OPENH264_PREF_ENABLED, false);
|
||||
|
||||
let addons = yield promiseAddonsByIDs([OPENH264_PLUGIN_ID]);
|
||||
@ -106,13 +105,12 @@ add_task(function* test_installed() {
|
||||
const TEST_TIME_SEC = Math.round(TEST_DATE.getTime() / 1000);
|
||||
|
||||
let file = Services.dirsvc.get("ProfD", Ci.nsIFile);
|
||||
file.append("openh264");
|
||||
file.append("testDir");
|
||||
file.append(OPENH264_PLUGIN_ID);
|
||||
file.append(TEST_VERSION);
|
||||
|
||||
Services.prefs.setBoolPref(OPENH264_PREF_ENABLED, false);
|
||||
Services.prefs.setCharPref(OPENH264_PREF_LASTUPDATE, "" + TEST_TIME_SEC);
|
||||
Services.prefs.setCharPref(OPENH264_PREF_VERSION, TEST_VERSION);
|
||||
Services.prefs.setCharPref(OPENH264_PREF_PATH, file.path);
|
||||
|
||||
let addons = yield promiseAddonsByIDs([OPENH264_PLUGIN_ID]);
|
||||
Assert.equal(addons.length, 1);
|
||||
@ -139,7 +137,7 @@ add_task(function* test_installed() {
|
||||
let libraries = addon.pluginLibraries;
|
||||
Assert.ok(libraries);
|
||||
Assert.equal(libraries.length, 1);
|
||||
Assert.equal(libraries[0], "testDir");
|
||||
Assert.equal(libraries[0], TEST_VERSION);
|
||||
let fullpath = addon.pluginFullpath;
|
||||
Assert.equal(fullpath.length, 1);
|
||||
Assert.equal(fullpath[0], file.path);
|
||||
@ -179,9 +177,11 @@ add_task(function* test_autoUpdatePrefPersistance() {
|
||||
});
|
||||
|
||||
add_task(function* test_pluginRegistration() {
|
||||
const TEST_VERSION = "1.2.3.4";
|
||||
|
||||
let file = Services.dirsvc.get("ProfD", Ci.nsIFile);
|
||||
file.append("openh264");
|
||||
file.append("testDir");
|
||||
file.append(OPENH264_PLUGIN_ID);
|
||||
file.append(TEST_VERSION);
|
||||
|
||||
let addedPath = null
|
||||
let removedPath = null;
|
||||
@ -197,35 +197,37 @@ add_task(function* test_pluginRegistration() {
|
||||
Services.prefs.setBoolPref(OPENH264_PREF_ENABLED, true);
|
||||
|
||||
// Check that the OpenH264 plugin gets registered after startup.
|
||||
Services.prefs.setCharPref(OPENH264_PREF_PATH, file.path);
|
||||
Services.prefs.setCharPref(OPENH264_PREF_VERSION, TEST_VERSION);
|
||||
clearPaths();
|
||||
yield promiseRestartManager();
|
||||
Assert.equal(addedPath, file.path);
|
||||
Assert.equal(removedPath, null);
|
||||
|
||||
// Check that clearing the path doesn't trigger registration.
|
||||
// Check that clearing the version doesn't trigger registration.
|
||||
clearPaths();
|
||||
Services.prefs.clearUserPref(OPENH264_PREF_PATH);
|
||||
Services.prefs.clearUserPref(OPENH264_PREF_VERSION);
|
||||
Assert.equal(addedPath, null);
|
||||
Assert.equal(removedPath, file.path);
|
||||
|
||||
// Restarting with no path set should not trigger registration.
|
||||
// Restarting with no version set should not trigger registration.
|
||||
clearPaths();
|
||||
yield promiseRestartManager();
|
||||
Assert.equal(addedPath, null);
|
||||
Assert.equal(removedPath, null);
|
||||
|
||||
// Changing the pref mid-session should cause unregistration and registration.
|
||||
Services.prefs.setCharPref(OPENH264_PREF_PATH, file.path);
|
||||
Services.prefs.setCharPref(OPENH264_PREF_VERSION, TEST_VERSION);
|
||||
clearPaths();
|
||||
let file2 = file.clone();
|
||||
file2.append("foo");
|
||||
Services.prefs.setCharPref(OPENH264_PREF_PATH, file2.path);
|
||||
const TEST_VERSION_2 = "5.6.7.8";
|
||||
let file2 = Services.dirsvc.get("ProfD", Ci.nsIFile);
|
||||
file2.append(OPENH264_PLUGIN_ID);
|
||||
file2.append(TEST_VERSION_2);
|
||||
Services.prefs.setCharPref(OPENH264_PREF_VERSION, TEST_VERSION_2);
|
||||
Assert.equal(addedPath, file2.path);
|
||||
Assert.equal(removedPath, file.path);
|
||||
|
||||
// Disabling OpenH264 should cause unregistration.
|
||||
Services.prefs.setCharPref(OPENH264_PREF_PATH, file.path);
|
||||
Services.prefs.setCharPref(OPENH264_PREF_VERSION, TEST_VERSION);
|
||||
clearPaths();
|
||||
Services.prefs.setBoolPref(OPENH264_PREF_ENABLED, false);
|
||||
Assert.equal(addedPath, null);
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user