Merge m-c to inbound.

This commit is contained in:
Ryan VanderMeulen 2013-09-11 22:20:33 -04:00
commit 10c13ed83a
226 changed files with 4811 additions and 1775 deletions

View File

@ -523,6 +523,9 @@ pref("app.update.log", true);
pref("shutdown.watchdog.timeoutSecs", -1);
#endif
// Check daily for apps updates.
pref("webapps.update.interval", 86400);
// Extensions preferences
pref("extensions.update.enabled", false);
pref("extensions.getAddons.cache.enabled", false);
@ -605,15 +608,15 @@ pref("hal.processPriorityManager.gonk.FOREGROUND.OomScoreAdjust", 134);
pref("hal.processPriorityManager.gonk.FOREGROUND.KillUnderMB", 6);
pref("hal.processPriorityManager.gonk.FOREGROUND.Nice", 1);
pref("hal.processPriorityManager.gonk.BACKGROUND_PERCEIVABLE.OomScoreAdjust", 200);
pref("hal.processPriorityManager.gonk.BACKGROUND_PERCEIVABLE.OomScoreAdjust", 400);
pref("hal.processPriorityManager.gonk.BACKGROUND_PERCEIVABLE.KillUnderMB", 7);
pref("hal.processPriorityManager.gonk.BACKGROUND_PERCEIVABLE.Nice", 7);
pref("hal.processPriorityManager.gonk.BACKGROUND_HOMESCREEN.OomScoreAdjust", 267);
pref("hal.processPriorityManager.gonk.BACKGROUND_HOMESCREEN.OomScoreAdjust", 534);
pref("hal.processPriorityManager.gonk.BACKGROUND_HOMESCREEN.KillUnderMB", 8);
pref("hal.processPriorityManager.gonk.BACKGROUND_HOMESCREEN.Nice", 18);
pref("hal.processPriorityManager.gonk.BACKGROUND.OomScoreAdjust", 400);
pref("hal.processPriorityManager.gonk.BACKGROUND.OomScoreAdjust", 667);
pref("hal.processPriorityManager.gonk.BACKGROUND.KillUnderMB", 20);
pref("hal.processPriorityManager.gonk.BACKGROUND.Nice", 18);

View File

@ -318,7 +318,7 @@ let AdbController = {
// Check if we have a remote debugging session going on. If so, we won't
// disable adb even if the screen is locked.
let isDebugging = Object.keys(DebuggerServer._connections).length > 0;
debug("isDebugging=" + isDebugging);
this.debug("isDebugging=" + isDebugging);
let enableAdb = this.remoteDebuggerEnabled &&
(!(this.lockEnabled && this.locked) || isDebugging);

View File

@ -1135,6 +1135,9 @@ window.addEventListener('ContentStart', function cr_onContentStart() {
});
window.addEventListener('ContentStart', function update_onContentStart() {
Cu.import('resource://gre/modules/WebappsUpdater.jsm');
WebappsUpdater.handleContentStart(shell);
let promptCc = Cc["@mozilla.org/updates/update-prompt;1"];
if (!promptCc) {
return;

View File

@ -73,3 +73,8 @@ contract @mozilla.org/network/protocol/about;1?what=certerror {920400b1-cf8f-476
# FilePicker.js
component {436ff8f9-0acc-4b11-8ec7-e293efba3141} FilePicker.js
contract @mozilla.org/filepicker;1 {436ff8f9-0acc-4b11-8ec7-e293efba3141}
# WebappsUpdateTimer.js
component {637b0f77-2429-49a0-915f-abf5d0db8b9a} WebappsUpdateTimer.js
contract @mozilla.org/b2g/webapps-update-timer;1 {637b0f77-2429-49a0-915f-abf5d0db8b9a}
category update-timer WebappsUpdateTimer @mozilla.org/b2g/webapps-update-timer;1,getService,background-update-timer,webapps.update.interval,86400

View File

@ -12,6 +12,7 @@ const Cr = Components.results;
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
Cu.import("resource://gre/modules/Services.jsm");
Cu.import("resource://gre/modules/WebappsUpdater.jsm");
const VERBOSE = 1;
let log =
@ -449,61 +450,6 @@ UpdatePrompt.prototype = {
}
},
appsUpdated: function UP_appsUpdated(aApps) {
log("appsUpdated: " + aApps.length + " apps to update");
let lock = Services.settings.createLock();
lock.set("apps.updateStatus", "check-complete", null);
this.sendChromeEvent("apps-update-check", { apps: aApps });
this._checkingApps = false;
},
// Trigger apps update check and wait for all to be done before
// notifying gaia.
onUpdateCheckStart: function UP_onUpdateCheckStart() {
log("onUpdateCheckStart (" + this._checkingApps + ")");
// Don't start twice.
if (this._checkingApps) {
return;
}
this._checkingApps = true;
let self = this;
let window = Services.wm.getMostRecentWindow("navigator:browser");
let all = window.navigator.mozApps.mgmt.getAll();
all.onsuccess = function() {
let appsCount = this.result.length;
let appsChecked = 0;
let appsToUpdate = [];
this.result.forEach(function updateApp(aApp) {
let update = aApp.checkForUpdate();
update.onsuccess = function() {
if (aApp.downloadAvailable) {
appsToUpdate.push(aApp.manifestURL);
}
appsChecked += 1;
if (appsChecked == appsCount) {
self.appsUpdated(appsToUpdate);
}
}
update.onerror = function() {
appsChecked += 1;
if (appsChecked == appsCount) {
self.appsUpdated(appsToUpdate);
}
}
});
}
all.onerror = function() {
// Could not get the app list, just notify to update nothing.
self.appsUpdated([]);
}
},
// nsIObserver
observe: function UP_observe(aSubject, aTopic, aData) {
@ -517,7 +463,7 @@ UpdatePrompt.prototype = {
Services.obs.removeObserver(this, "quit-application");
break;
case "update-check-start":
this.onUpdateCheckStart();
WebappsUpdater.updateApps();
break;
}
},

View File

@ -0,0 +1,67 @@
/* 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/. */
/**
* This component triggers an app update check even when system updates are
* disabled to make sure we always check for app updates.
*/
"use strict";
const Cc = Components.classes;
const Ci = Components.interfaces;
const Cu = Components.utils;
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
Cu.import("resource://gre/modules/Services.jsm");
Cu.import("resource://gre/modules/WebappsUpdater.jsm");
function debug(aStr) {
//dump("--*-- WebappsUpdateTimer: " + aStr);
}
function WebappsUpdateTimer() {
}
WebappsUpdateTimer.prototype = {
QueryInterface: XPCOMUtils.generateQI([Ci.nsITimerCallback]),
classID: Components.ID("{637b0f77-2429-49a0-915f-abf5d0db8b9a}"),
notify: function(aTimer) {
try {
// We want to check app updates if system updates are disabled or
// if they update frecency is not daily.
if (Services.prefs.getBoolPref("app.update.enabled") === true &&
Services.prefs.getIntPref("app.update.interval") === 86400) {
return;
}
} catch(e) {
// That should never happen..
}
// If we are offline, wait to be online to start the update check.
if (Services.io.offline) {
debug("Network is offline. Setting up an offline status observer.");
Services.obs.addObserver(this, "network:offline-status-changed", false);
return;
}
// This will trigger app updates in b2g/components/WebappsUpdater.jsm
// that also takes care of notifying gaia.
WebappsUpdater.updateApps();
},
observe: function(aSubject, aTopic, aData) {
if (aTopic !== "network:offline-status-changed" ||
aData !== "online") {
return;
}
debug("Network is online. Checking updates.");
Services.obs.removeObserver(this, "network:offline-status-changed");
WebappsUpdater.updateApps();
}
};
this.NSGetFactory = XPCOMUtils.generateNSGetFactory([WebappsUpdateTimer]);

View File

@ -0,0 +1,95 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
"use strict";
this.EXPORTED_SYMBOLS = ["WebappsUpdater"];
const Cc = Components.classes;
const Cu = Components.utils;
Cu.import("resource://gre/modules/Services.jsm");
this.WebappsUpdater = {
_checkingApps: false,
_pendingEvents: [],
handleContentStart: function(aShell) {
let content = aShell.contentBrowser.contentWindow;
this._pendingEvents.forEach(aShell.sendChromeEvent);
this._pendingEvents.length = 0;
},
sendChromeEvent: function(aType, aDetail) {
let detail = aDetail || {};
detail.type = aType;
let browser = Services.wm.getMostRecentWindow("navigator:browser");
if (!browser) {
this._pendingEvents.push(detail);
dump("Warning: Couldn't send update event " + aType +
": no content browser. Will send again when content becomes available.");
return false;
}
browser.shell.sendChromeEvent(detail);
return true;
},
_appsUpdated: function(aApps) {
dump("appsUpdated: " + aApps.length + " apps to update");
let lock = Services.settings.createLock();
lock.set("apps.updateStatus", "check-complete", null);
this.sendChromeEvent("apps-update-check", { apps: aApps });
this._checkingApps = false;
},
// Trigger apps update check and wait for all to be done before
// notifying gaia.
updateApps: function() {
dump("updateApps (" + this._checkingApps + ")");
// Don't start twice.
if (this._checkingApps) {
return;
}
this._checkingApps = true;
let self = this;
let window = Services.wm.getMostRecentWindow("navigator:browser");
let all = window.navigator.mozApps.mgmt.getAll();
all.onsuccess = function() {
let appsCount = this.result.length;
let appsChecked = 0;
let appsToUpdate = [];
this.result.forEach(function updateApp(aApp) {
let update = aApp.checkForUpdate();
update.onsuccess = function() {
if (aApp.downloadAvailable) {
appsToUpdate.push(aApp.manifestURL);
}
appsChecked += 1;
if (appsChecked == appsCount) {
self._appsUpdated(appsToUpdate);
}
}
update.onerror = function() {
appsChecked += 1;
if (appsChecked == appsCount) {
self._appsUpdated(appsToUpdate);
}
}
});
}
all.onerror = function() {
// Could not get the app list, just notify to update nothing.
self._appsUpdated([]);
}
}
};

View File

@ -25,6 +25,7 @@ EXTRA_COMPONENTS += [
'ProcessGlobal.js',
'SmsProtocolHandler.js',
'TelProtocolHandler.js',
'WebappsUpdateTimer.js',
'YoutubeProtocolHandler.js',
]
@ -44,4 +45,5 @@ EXTRA_JS_MODULES += [
'Keyboard.jsm',
'SignInToWebsite.jsm',
'TelURIParser.jsm',
'WebappsUpdater.jsm',
]

View File

@ -1,4 +1,4 @@
{
"revision": "e3d925b497f5b996c9c397c200805fbcc62bc823",
"revision": "9e3d2b3f6706916168b9ad9bb96084c01df8771f",
"repo_path": "/integration/gaia-central"
}

View File

@ -733,6 +733,7 @@ bin/components/@DLL_PREFIX@nkgnomevfs@DLL_SUFFIX@
#ifdef MOZ_UPDATER
@BINPATH@/components/UpdatePrompt.js
#endif
@BINPATH@/components/WebappsUpdateTimer.js
@BINPATH@/components/MozKeyboard.js
@BINPATH@/components/DirectoryProvider.js
@BINPATH@/components/ActivitiesGlue.js

View File

@ -1067,7 +1067,8 @@ pref("devtools.gcli.allowSet", false);
pref("devtools.commands.dir", "");
// Disable the app manager
pref("devtools.appmanager.enabled", false);
pref("devtools.appmanager.enabled", true);
pref("devtools.appmanager.simulatorInstallPage", "https://addons.mozilla.org/firefox/addon/firefox-os-simulator/");
// Toolbox preferences
pref("devtools.toolbox.footer.height", 250);

View File

@ -46,7 +46,7 @@
accesskey="&saveLinkCmd.accesskey;"
oncommand="gContextMenu.saveLink();"/>
<menu id="context-marklinkMenu" label="&social.marklinkMenu.label;"
accesskey="&social.marklink.accesskey;">
accesskey="&social.marklinkMenu.accesskey;">
<menupopup/>
</menu>
<menuitem id="context-copyemail"
@ -252,7 +252,7 @@
accesskey="&savePageCmd.accesskey2;"
oncommand="gContextMenu.savePageAs();"/>
<menu id="context-markpageMenu" label="&social.markpageMenu.label;"
accesskey="&social.markpage.accesskey;">
accesskey="&social.markpageMenu.accesskey;">
<menupopup/>
</menu>
<menuseparator id="context-sep-viewbgimage"/>

View File

@ -1658,12 +1658,12 @@ SocialMarks = {
{
type: "link",
id: "context-marklinkMenu",
label: "social.marklink.label"
label: "social.marklinkMenu.label"
},
{
type: "page",
id: "context-markpageMenu",
label: "social.markpage.label"
label: "social.markpageMenu.label"
}
];
for (let cfg of contextMenus) {

View File

@ -252,12 +252,12 @@ function checkSocialUI(win) {
{
type: "link",
id: "context-marklinkMenu",
label: "social.marklink.label"
label: "social.marklinkMenu.label"
},
{
type: "page",
id: "context-markpageMenu",
label: "social.markpage.label"
label: "social.markpageMenu.label"
}
];

View File

@ -90,6 +90,8 @@ static RedirEntry kRedirMap[] = {
{ "healthreport", "chrome://browser/content/abouthealthreport/abouthealth.xhtml",
nsIAboutModule::ALLOW_SCRIPT },
#endif
{ "app-manager", "chrome://browser/content/devtools/app-manager/index.xul",
nsIAboutModule::ALLOW_SCRIPT },
};
static const int kRedirTotal = NS_ARRAY_LENGTH(kRedirMap);

View File

@ -109,6 +109,7 @@ static const mozilla::Module::ContractIDEntry kBrowserContracts[] = {
#ifdef MOZ_SERVICES_HEALTHREPORT
{ NS_ABOUT_MODULE_CONTRACTID_PREFIX "healthreport", &kNS_BROWSER_ABOUT_REDIRECTOR_CID },
#endif
{ NS_ABOUT_MODULE_CONTRACTID_PREFIX "app-manager", &kNS_BROWSER_ABOUT_REDIRECTOR_CID },
#if defined(XP_WIN)
{ NS_IEHISTORYENUMERATOR_CONTRACTID, &kNS_WINIEHISTORYENUMERATOR_CID },
#elif defined(XP_MACOSX)

View File

@ -678,12 +678,12 @@ let SessionStoreInternal = {
break;
case "TabPinned":
// If possible, update cached data without having to invalidate it
TabStateCache.update(aEvent.originalTarget, "pinned", true);
TabStateCache.updateField(aEvent.originalTarget, "pinned", true);
this.saveStateDelayed(win);
break;
case "TabUnpinned":
// If possible, update cached data without having to invalidate it
TabStateCache.update(aEvent.originalTarget, "pinned", false);
TabStateCache.updateField(aEvent.originalTarget, "pinned", false);
this.saveStateDelayed(win);
break;
}
@ -1330,7 +1330,7 @@ let SessionStoreInternal = {
}
// If possible, update cached data without having to invalidate it
TabStateCache.update(aTab, "hidden", false);
TabStateCache.updateField(aTab, "hidden", false);
// Default delay of 2 seconds gives enough time to catch multiple TabShow
// events due to changing groups in Panorama.
@ -1345,7 +1345,7 @@ let SessionStoreInternal = {
}
// If possible, update cached data without having to invalidate it
TabStateCache.update(aTab, "hidden", true);
TabStateCache.updateField(aTab, "hidden", true);
// Default delay of 2 seconds gives enough time to catch multiple TabHide
// events due to changing groups in Panorama.
@ -1665,7 +1665,6 @@ let SessionStoreInternal = {
},
setTabValue: function ssi_setTabValue(aTab, aKey, aStringValue) {
TabStateCache.delete(aTab);
// If the tab hasn't been restored, then set the data there, otherwise we
// could lose newly added data.
let saveTo;
@ -1679,12 +1678,13 @@ let SessionStoreInternal = {
aTab.__SS_extdata = {};
saveTo = aTab.__SS_extdata;
}
saveTo[aKey] = aStringValue;
TabStateCache.updateField(aTab, "extData", saveTo);
this.saveStateDelayed(aTab.ownerDocument.defaultView);
},
deleteTabValue: function ssi_deleteTabValue(aTab, aKey) {
TabStateCache.delete(aTab);
// We want to make sure that if data is accessed early, we attempt to delete
// that data from __SS_data as well. Otherwise we'll throw in cases where
// data can be set or read.
@ -1696,9 +1696,19 @@ let SessionStoreInternal = {
deleteFrom = aTab.linkedBrowser.__SS_data.extData;
}
if (deleteFrom && deleteFrom[aKey])
if (deleteFrom && aKey in deleteFrom) {
delete deleteFrom[aKey];
this.saveStateDelayed(aTab.ownerDocument.defaultView);
// Keep the extData object only if it is not empty, to save
// a little disk space when serializing the tab state later.
if (Object.keys(deleteFrom).length) {
TabStateCache.updateField(aTab, "extData", deleteFrom);
} else {
TabStateCache.removeField(aTab, "extData");
}
this.saveStateDelayed(aTab.ownerDocument.defaultView);
}
},
persistTabAttribute: function ssi_persistTabAttribute(aName) {
@ -4639,7 +4649,7 @@ let TabStateCache = {
* @param {string} aField The field to update.
* @param {*} aValue The new value to place in the field.
*/
update: function(aKey, aField, aValue) {
updateField: function(aKey, aField, aValue) {
let key = this._normalizeToBrowser(aKey);
let data = this._data.get(key);
if (data) {
@ -4648,6 +4658,22 @@ let TabStateCache = {
TabStateCacheTelemetry.recordAccess(!!data);
},
/**
* Remove a given field from a cached tab state.
*
* @param {XULElement} aKey The tab or the associated browser.
* If the tab/browser is not present, do nothing.
* @param {string} aField The field to remove.
*/
removeField: function(aKey, aField) {
let key = this._normalizeToBrowser(aKey);
let data = this._data.get(key);
if (data && aField in data) {
delete data[aField];
}
TabStateCacheTelemetry.recordAccess(!!data);
},
_normalizeToBrowser: function(aKey) {
let nodeName = aKey.localName;
if (nodeName == "tab") {

View File

@ -3,6 +3,7 @@ const ObservableObject = require("devtools/shared/observable-object");
const promise = require("sdk/core/promise");
const {EventEmitter} = Cu.import("resource:///modules/devtools/shared/event-emitter.js");
const {generateUUID} = Cc['@mozilla.org/uuid-generator;1'].getService(Ci.nsIUUIDGenerator);
/**
* IndexedDB wrapper that just save project objects
@ -96,7 +97,13 @@ const AppProjects = {
addPackaged: function(folder) {
let project = {
type: "packaged",
location: folder.path
location: folder.path,
// We need a unique id, that is the app origin,
// in order to identify the app when being installed on the device.
// The packaged app local path is a valid id, but only on the client.
// This origin will be used to generate the true id of an app:
// its manifest URL.
packagedAppOrigin: generateUUID().toString().slice(1, -1)
};
return IDB.add(project).then(function () {
store.object.projects.push(project);

View File

@ -7,12 +7,14 @@ const Ci = Components.interfaces;
Cu.import("resource://gre/modules/Services.jsm");
Cu.import("resource:///modules/devtools/gDevTools.jsm");
const {Simulator} = Cu.import("resource://gre/modules/devtools/Simulator.jsm")
const {devtools} = Cu.import("resource://gre/modules/devtools/Loader.jsm", {});
const {require} = devtools;
const {ConnectionManager, Connection} = require("devtools/client/connection-manager");
const ConnectionStore = require("devtools/app-manager/connection-store");
const DeviceStore = require("devtools/app-manager/device-store");
const simulatorsStore = require("devtools/app-manager/simulators-store");
let UI = {
init: function() {
@ -43,6 +45,7 @@ let UI = {
this.store = Utils.mergeStores({
"device": new DeviceStore(this.connection),
"connection": new ConnectionStore(this.connection),
"simulators": simulatorsStore,
});
let pre = document.querySelector("#logs > pre");
@ -96,4 +99,47 @@ let UI = {
Services.prefs.setCharPref("devtools.debugger.remote-host", host);
Services.prefs.setIntPref("devtools.debugger.remote-port", port);
},
showSimulatorList: function() {
document.body.classList.add("show-simulators");
},
cancelShowSimulatorList: function() {
document.body.classList.remove("show-simulators");
},
installSimulator: function() {
let url = Services.prefs.getCharPref("devtools.appmanager.simulatorInstallPage");
window.open(url);
},
startSimulator: function(version) {
let port = ConnectionManager.getFreeTCPPort();
let simulator = Simulator.getByVersion(version);
if (!simulator) {
this.connection.log("Error: can't find simulator: " + version);
return;
}
if (!simulator.launch) {
this.connection.log("Error: invalid simulator: " + version);
return;
}
this.connection.log("Found simulator: " + version);
this.connection.log("Starting simulator...");
this.simulator = simulator;
this.simulator.launch({ port: port })
.then(() => {
this.connection.log("Simulator ready. Connecting.");
this.connection.port = port;
this.connection.host = "localhost";
this.connection.once("connected", function() {
this.connection.log("Connected to simulator.");
this.connection.keepConnecting = false;
});
this.connection.keepConnecting = true;
this.connection.connect();
});
document.body.classList.remove("show-simulators");
},
}

View File

@ -38,9 +38,9 @@
<span>&connection.notConnected;</span>
<button class="action-primary left" onclick="UI.connect()" id="connect-button" template='{"type":"localizedContent","property":"connection.connectTo","paths":["connection.host","connection.port"]}'></button>
<button class="right" onclick="UI.editConnectionParameters()">&connection.changeHostAndPort;</button>
<div id="start-simulator-box" template='{"type":"attribute","path":"simulators.versions.length","name":"simulators-count"}'>
<div id="start-simulator-box">
<span>&connection.or;</span>
<button id="start-simulator-button" class="action-primary" onclick="UI.startSimulator()">&connection.startSimulator;</button>
<button id="start-simulator-button" class="action-primary" onclick="UI.showSimulatorList()">&connection.startSimulator;</button>
</div>
</div>
</div>
@ -81,6 +81,25 @@
</div>
</div>
<!-- Simulator -->
<div id="banner-simulators" class="banner" template='{"type":"attribute","path":"simulators.versions.length","name":"simulator-count"}'>
<div class="connected-indicator"></div>
<div class="banner-box">
<div class="banner-content">
<div class="no-simulator">
<span>&connection.noSimulatorInstalled;</span>
<button class="action-primary" onclick="UI.installSimulator()">&connection.installFirstSimulator;</button>
</div>
<div class="found-simulator">
<span template-loop='{"arrayPath":"simulators.versions","childSelector":"#simulator-item-template"}'></span>
<button class="action-primary" onclick="UI.installSimulator()">&connection.installAnotherSimulator;</button>
</div>
<button class="action-cancel" onclick="UI.cancelShowSimulatorList()">&connection.cancel;</button>
</div>
</div>
</div>
<!-- Logs -->
<div id="banner-logs">
<div id="logs" class="banner-box">
@ -92,6 +111,14 @@
</div>
</body>
<template id="simulator-item-template">
<span>
<button class="simulator-item" onclick="UI.startSimulator(this.dataset.version)" template='{"type":"attribute","path":"version","name":"data-version"}'>
<span template='{"type":"textContent", "path":"version"}'></span>
</button>
</span>
</template>
<script type="application/javascript;version=1.8" src="utils.js"></script>
<script type="application/javascript;version=1.8" src="template.js"></script>
<script type="application/javascript;version=1.8" src="connection-footer.js"></script>

View File

@ -167,7 +167,13 @@ let UI = {
openToolbox: function(manifest) {
this._getTargetForApp(manifest).then((target) => {
gDevTools.showToolbox(target, "webconsole", devtools.Toolbox.HostType.WINDOW);
gDevTools.showToolbox(target,
null,
devtools.Toolbox.HostType.WINDOW).then(toolbox => {
this.connection.once(Connection.Events.DISCONNECTED, () => {
toolbox.destroy();
});
});
}, console.error);
},

View File

@ -14,6 +14,8 @@ const {AppProjects} = require("devtools/app-manager/app-projects");
const {AppValidator} = require("devtools/app-manager/app-validator");
const {Services} = Cu.import("resource://gre/modules/Services.jsm");
const {FileUtils} = Cu.import("resource://gre/modules/FileUtils.jsm");
const {installHosted, installPackaged} = require("devtools/app-actor-front");
const promise = require("sdk/core/promise");
window.addEventListener("message", function(event) {
@ -163,6 +165,39 @@ let UI = {
}
},
install: function(button, location) {
button.dataset.originalTextContent = button.textContent;
button.textContent = Utils.l10n("project.installing");
button.disabled = true;
let project = AppProjects.get(location);
let install;
if (project.type == "packaged") {
install = installPackaged(this.connection.client, this.listTabsResponse.webappsActor, project.location, project.packagedAppOrigin);
} else {
let manifestURLObject = Services.io.newURI(project.location, null, null);
let origin = Services.io.newURI(manifestURLObject.prePath, null, null);
let appId = origin.host;
let metadata = {
origin: origin.spec,
manifestURL: project.location
};
install = installHosted(this.connection.client, this.listTabsResponse.webappsActor, appId, metadata, project.manifest);
}
install.then(function () {
button.disabled = false;
button.textContent = Utils.l10n("project.installed");
setTimeout(function() {
button.textContent = button.dataset.originalTextContent;
}, 1500);
},
function (res) {
button.disabled = false;
let message = res.error + ": " + res.message;
alert(message);
this.connection.log(message);
});
},
start: function(location) {
let project = AppProjects.get(location);
let request = {
@ -223,8 +258,11 @@ let UI = {
this._getTargetForApp(manifest).then((target) => {
gDevTools.showToolbox(target,
null,
devtools.Toolbox.HostType.WINDOW,
this.connection.uid);
devtools.Toolbox.HostType.WINDOW).then(toolbox => {
this.connection.once(Connection.Events.DISCONNECTED, () => {
toolbox.destroy();
});
});
}, console.error);
},

View File

@ -25,7 +25,7 @@
<div id="new-packaged-project" onclick="UI.addPackaged()">&projects.addPackaged;</div>
<div id="new-hosted-project">&projects.addHosted;
<form onsubmit="UI.addHosted(); return false;" id="new-hosted-project-wrapper">
<input value="" id="url-input" type="url" pattern="https?://.+" placeholder="&projects.hostedManifestPlaceHolder;" size="50" />
<input value="" id="url-input" type="url" pattern="https?://.+" placeholder="&projects.hostedManifestPlaceHolder2;" size="50" />
<div onclick="UI.addHosted()" id="new-hosted-project-click"></div>
<input type="submit" hidden="true"></input>
</form>
@ -71,14 +71,10 @@
</div>
<div class="project-buttons">
<button class="project-button-refresh" onclick="UI.update(this.dataset.location)" template='{"type":"attribute","path":"location","name":"data-location"}'>&projects.reloadFiles;</button>
<!-- Not available until bug 911785 is fixed
<button class="device-action project-button-install" onclick="UI.install(this, this.dataset.location)" template='{"type":"attribute","path":"location","name":"data-location"}'>&projects.installApp;</button>
-->
<button class="device-action project-button-start" onclick="UI.start(this.dataset.location)" template='{"type":"attribute","path":"location","name":"data-location"}'>&projects.startApp;</button>
<button class="device-action project-button-stop" onclick="UI.stop(this.dataset.location)" template='{"type":"attribute","path":"location","name":"data-location"}'>&projects.stopApp;</button>
<!-- Not available until bug 911785 is fixed
<button class="device-action project-button-debug" onclick="UI.openToolbox(this.dataset.location)" template='{"type":"attribute","path":"location","name":"data-location"}'>&projects.debugApp;</button>
-->
</div>
<div class="project-errors" template='{"type":"textContent","path":"errors"}'></div>
<div class="project-warnings" template='{"type":"textContent","path":"warnings"}'></div>

View File

@ -0,0 +1,21 @@
/* 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 {Cu} = require("chrome");
const ObservableObject = require("devtools/shared/observable-object");
const {Simulator} = Cu.import("resource://gre/modules/devtools/Simulator.jsm");
let store = new ObservableObject({versions:[]});
function feedStore() {
store.object.versions = Simulator.availableVersions().map(v => {
return {version:v}
});
}
Simulator.on("register", feedStore);
Simulator.on("unregister", feedStore);
feedStore();
module.exports = store;

View File

@ -378,7 +378,7 @@ let gDevToolsBrowser = {
* Open the App Manager
*/
openAppManager: function(gBrowser) {
gBrowser.selectedTab = gBrowser.addTab("chrome://browser/content/devtools/app-manager/index.xul");
gBrowser.selectedTab = gBrowser.addTab("about:app-manager");
},
/**

View File

@ -1,14 +1,21 @@
<!DOCTYPE html>
<div id="id1"></div>
<div id="id2"></div>
<div id="id3">
<ul class="aList">
<li class="item"></li>
<li class="item"></li>
<li class="item"></li>
<li class="item">
<span id="id4"></span>
</li>
</ul>
</div>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>select last selected test</title>
</head>
<body>
<div id="id1"></div>
<div id="id2"></div>
<div id="id3">
<ul class="aList">
<li class="item"></li>
<li class="item"></li>
<li class="item"></li>
<li class="item">
<span id="id4"></span>
</li>
</ul>
</div>
</body>
</html>

View File

@ -30,23 +30,39 @@ function test() {
}
function endTests() {
toolbox.destroy();
toolbox = inspector = page1 = page2 = null;
gBrowser.removeCurrentTab();
finish();
executeSoon(() => {
toolbox.destroy();
toolbox = inspector = page1 = page2 = null;
gBrowser.removeCurrentTab();
finish();
});
}
function testReSelectingAnElement(id, callback) {
function loadPageAnd(page, callback) {
inspector.once("markuploaded", () => {
executeSoon(callback);
});
if (page) {
content.location = page;
} else {
content.location.reload();
}
}
function reloadAndReselect(id, callback) {
let div = content.document.getElementById(id);
inspector.selection.setNode(div);
inspector.once("inspector-updated", () => {
is(inspector.selection.node, div);
inspector.once("markuploaded", () => {
loadPageAnd(false, () => {
is(inspector.selection.node.id, id, "Node re-selected after reload");
callback();
executeSoon(callback);
});
content.location.reload();
});
inspector.selection.setNode(div);
}
// Test that nodes selected on the test page remain selected after reload
@ -54,10 +70,10 @@ function test() {
{
// Select a few nodes and check they are re-selected after reload of the same
// page
testReSelectingAnElement("id1", () => {
testReSelectingAnElement("id2", () => {
testReSelectingAnElement("id3", () => {
testReSelectingAnElement("id4", testBodySelectedOnNavigate);
reloadAndReselect("id1", () => {
reloadAndReselect("id2", () => {
reloadAndReselect("id3", () => {
reloadAndReselect("id4", testBodySelectedOnNavigate);
});
});
});
@ -68,15 +84,16 @@ function test() {
function testBodySelectedOnNavigate() {
// Last node selected was id4, go to a different page and check body is
// selected
inspector.once("markuploaded", () => {
is(
inspector.selection.node.tagName.toLowerCase(),
"body",
"Node not found, selecting body"
);
testSameNodeSelectedOnNavigateAwayAndBack();
loadPageAnd(page2, () => {
executeSoon(() => {
is(
inspector.selection.node.tagName.toLowerCase(),
"body",
"Node not found, body selected"
);
executeSoon(testSameNodeSelectedOnNavigateAwayAndBack);
});
});
content.location = page2;
}
// Test that the node selected on page 1 gets selected again after a navigation
@ -85,19 +102,25 @@ function test() {
// On page2, select id5
let id = "id5";
let div = content.document.getElementById(id);
inspector.selection.setNode(div);
inspector.once("inspector-updated", () => {
is(inspector.selection.node.id, id);
// go to page1 but do not select anything
inspector.once("markuploaded", () => {
// go back to page2 and check id5 is still the current selection
inspector.once("markuploaded", () => {
is(inspector.selection.node.id, id, "Node re-selected after navigation");
endTests();
executeSoon(() => {
// go to page1 but do not select anything
loadPageAnd(page1, () => {
executeSoon(() => {
// go back to page2 and check id5 is still the current selection
loadPageAnd(page2, () => {
is(inspector.selection.node.id, id, "Node re-selected after navigation");
executeSoon(endTests);
});
});
});
content.location = page2;
});
content.location = page1;
});
inspector.selection.setNode(div);
}
}

View File

@ -1,3 +1,10 @@
<!DOCTYPE html>
<div id="id5"></div>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>select last selected test</title>
</head>
<body>
<div id="id5"></div>
</body>
</html>

View File

@ -234,9 +234,11 @@ ResponsiveUI.prototype = {
onPageUnload: function() {
if (this.closing)
return;
this.touchEnableBefore = this.touchEventHandler.enabled;
this.disableTouch();
delete this.touchEventHandler;
if (this.touchEventHandler) {
this.touchEnableBefore = this.touchEventHandler.enabled;
this.disableTouch();
delete this.touchEventHandler;
}
},
/**

View File

@ -1041,7 +1041,9 @@ CssRuleView.prototype = {
this.element.parentNode.removeChild(this.element);
}
this.elementStyle.destroy();
if (this.elementStyle) {
this.elementStyle.destroy();
}
this.popup.destroy();
},
@ -1210,6 +1212,11 @@ CssRuleView.prototype = {
return this._showPseudoElements;
},
_getRuleViewHeaderClassName: function(isPseudo) {
let baseClassName = "theme-gutter ruleview-header";
return isPseudo ? baseClassName + " ruleview-expandable-header" : baseClassName;
},
/**
* Creates editor UI for each of the rules in _elementStyle.
*/
@ -1230,7 +1237,7 @@ CssRuleView.prototype = {
if (seenPseudoElement && !seenNormalElement && !rule.pseudoElement) {
seenNormalElement = true;
let div = this.doc.createElementNS(HTML_NS, "div");
div.className = "theme-gutter ruleview-header";
div.className = this._getRuleViewHeaderClassName();
div.textContent = this.selectedElementLabel;
this.element.appendChild(div);
}
@ -1238,7 +1245,7 @@ CssRuleView.prototype = {
let inheritedSource = rule.inheritedSource;
if (inheritedSource != lastInheritedSource) {
let div = this.doc.createElementNS(HTML_NS, "div");
div.className = "theme-gutter ruleview-header";
div.className = this._getRuleViewHeaderClassName();
div.textContent = inheritedSource;
lastInheritedSource = inheritedSource;
this.element.appendChild(div);
@ -1248,8 +1255,11 @@ CssRuleView.prototype = {
seenPseudoElement = true;
let div = this.doc.createElementNS(HTML_NS, "div");
div.className = "theme-gutter ruleview-header";
div.className = this._getRuleViewHeaderClassName(true);
div.textContent = this.pseudoElementLabel;
div.addEventListener("dblclick", () => {
this.togglePseudoElementVisibility(!this.showPseudoElements);
}, false);
let twisty = this.pseudoElementTwisty =
this.doc.createElementNS(HTML_NS, "span");

View File

@ -50,7 +50,11 @@
}
.ruleview-header {
vertical-align:middle;
vertical-align: middle;
height: 1.5em;
line-height: 1.5em;
}
}
.ruleview-header.ruleview-expandable-header {
cursor: pointer;
}

View File

@ -48,7 +48,10 @@ function testTopLeft()
ok (!view.element.classList.contains("show-pseudo-elements"), "Pseudo Elements are collapsed by twisty");
expander.click();
ok (view.element.classList.contains("show-pseudo-elements"), "Pseudo Elements are expanded again");
expander.click();
// Make sure that dblclicking on the header container also toggles the pseudo elements
EventUtils.synthesizeMouseAtCenter(gutters[0], {clickCount: 2}, inspector.sidebar.getWindowForTab("ruleview"));
ok (!view.element.classList.contains("show-pseudo-elements"), "Pseudo Elements are collapsed by dblclicking");
let defaultView = element.ownerDocument.defaultView;
let elementRule = elementRules[0];

View File

@ -645,9 +645,9 @@ just addresses the organization to follow, e.g. "This site is run by " -->
<!ENTITY social.chatBar.label "Focus chats">
<!ENTITY social.chatBar.accesskey "c">
<!ENTITY social.markpage.accesskey "P">
<!ENTITY social.markpageMenu.accesskey "P">
<!ENTITY social.markpageMenu.label "Save Page To…">
<!ENTITY social.marklink.accesskey "L">
<!ENTITY social.marklinkMenu.accesskey "L">
<!ENTITY social.marklinkMenu.label "Save Link To…">
<!ENTITY getUserMedia.selectCamera.label "Camera to share:">

View File

@ -430,10 +430,10 @@ social.turnOff.accesskey=T
social.turnOn.label=Turn on %S
social.turnOn.accesskey=T
# LOCALIZATION NOTE (social.markpage.label): %S is the name of the social provider
social.markpage.label=Save Page to %S
# LOCALIZATION NOTE (social.marklink.label): %S is the name of the social provider
social.marklink.label=Save Link to %S
# LOCALIZATION NOTE (social.markpageMenu.label): %S is the name of the social provider
social.markpageMenu.label=Save Page to %S
# LOCALIZATION NOTE (social.marklinkMenu.label): %S is the name of the social provider
social.marklinkMenu.label=Save Link to %S
# LOCALIZATION NOTE (social.error.message): %1$S is brandShortName (e.g. Firefox), %2$S is the name of the social provider
social.error.message=%1$S is unable to connect with %2$S right now.

View File

@ -32,6 +32,9 @@
<!ENTITY connection.disconnecting "Disconnecting…">
<!ENTITY connection.cancel "Cancel">
<!ENTITY connection.or "or">
<!ENTITY connection.noSimulatorInstalled "No simulator installed.">
<!ENTITY connection.installFirstSimulator "Install simulator.">
<!ENTITY connection.installAnotherSimulator "Add">
<!ENTITY projects.localApps "Local Apps">
<!ENTITY projects.addApp "Add">
@ -45,5 +48,5 @@
<!ENTITY projects.startApp "Start">
<!ENTITY projects.stopApp "Stop">
<!ENTITY projects.debugApp "Debug">
<!ENTITY projects.hostedManifestPlaceHolder "http://example.com/app/webapp.manifest">
<!ENTITY projects.hostedManifestPlaceHolder2 "http://example.com/app/manifest.webapp">
<!ENTITY projects.noProject "No project linked. Add a new packaged app below (a directory) or a hosted app (link to a manifest file).">

View File

@ -11,6 +11,8 @@ device.deviceSize=Device size: %1$Sx%2$S (%3$S DPI)
connection.connectedToDevice=Connected to %1$S
connection.connectTo=Connect to %1$S:%2$S
project.filePickerTitle=Select a webapp folder
project.installing=Installing...
project.installed=Installed!
validator.nonExistingFolder=The project folder doesn't exists
validator.expectProjectFolder=The project folder ends up being a file
validator.wrongManifestFileName=Packaged apps require a manifest file that can only be named 'manifest.webapp' at project root folder

View File

@ -20,6 +20,8 @@ var ContextUI = {
init: function init() {
Elements.browsers.addEventListener('URLChanged', this, true);
Elements.browsers.addEventListener("AlertActive", this, true);
Elements.browsers.addEventListener("AlertClose", this, true);
Elements.tabList.addEventListener('TabSelect', this, true);
Elements.panelUI.addEventListener('ToolPanelShown', this, false);
Elements.panelUI.addEventListener('ToolPanelHidden', this, false);
@ -325,6 +327,10 @@ var ContextUI = {
case "ToolPanelHidden":
this.dismiss();
break;
case "AlertActive":
case "AlertClose":
ContentAreaObserver.updateContentArea();
break;
case "touchstart":
if (!BrowserUI.isStartTabVisible) {
this.dismiss();

View File

@ -53,6 +53,7 @@
// Fire notification closed event.
let event = new Event('AlertClose');
event.notification = aItem;
this.dispatchEvent(event);
return aItem;

View File

@ -1143,9 +1143,12 @@ Browser.MainDragger.prototype = {
},
_hideScrollbars: function _hideScrollbars() {
this._scrollScales.x = 0, this._scrollScales.y = 0;
this._scrollScales.x = 0;
this._scrollScales.y = 0;
this._horizontalScrollbar.removeAttribute("panning");
this._verticalScrollbar.removeAttribute("panning");
this._horizontalScrollbar.removeAttribute("width");
this._verticalScrollbar.removeAttribute("height");
this._horizontalScrollbar.style.MozTransform = "";
this._verticalScrollbar.style.MozTransform = "";
}

View File

@ -57,6 +57,7 @@ var Downloads = {
Services.obs.addObserver(this, "dl-request", true);
this._notificationBox = Browser.getNotificationBox();
this._notificationBox.addEventListener('AlertClose', this.handleEvent, true);
this._progress = new DownloadProgressListener(this);
this.manager.addListener(this._progress);
@ -225,6 +226,7 @@ var Downloads = {
accessKey: "",
callback: function() {
Downloads.cancelDownload(aDownload);
Downloads._downloadProgressIndicator.reset();
}
}
];
@ -397,6 +399,7 @@ var Downloads = {
accessKey: "",
callback: function() {
Downloads.cancelDownloads();
Downloads._downloadProgressIndicator.reset();
}
}
];
@ -431,6 +434,17 @@ var Downloads = {
}
},
handleEvent: function handleEvent(aEvent) {
switch (aEvent.type) {
case "AlertClose":
if (aEvent.notification.value == "download-complete" &&
!Downloads._notificationBox.getNotificationWithValue("download-complete")) {
Downloads._downloadProgressIndicator.reset();
}
break;
}
},
observe: function (aSubject, aTopic, aData) {
let message = "";
let msgTitle = "";
@ -459,7 +473,6 @@ var Downloads = {
this._showDownloadCompleteToast(download);
this._showDownloadCompleteNotification(download);
}
this._downloadProgressIndicator.reset();
this._progressNotificationInfo.clear();
this._downloadCount = 0;
this._notificationBox.removeNotification(this._progressNotification);
@ -469,7 +482,6 @@ var Downloads = {
case "dl-failed":
download = aSubject.QueryInterface(Ci.nsIDownload);
this._showDownloadFailedNotification(download);
this._downloadProgressIndicator.reset();
break;
case "dl-request":
setTimeout(function() {

View File

@ -46,7 +46,8 @@
.ruleview-warning {
background: url("chrome://browser/skin/devtools/alerticon-warning.png");
-moz-margin-start: 5px;
vertical-align: middle;
display: inline-block;
vertical-align: top;
width: 13px;
height: 12px;
}

View File

@ -50,7 +50,8 @@
.ruleview-warning {
background: url("chrome://browser/skin/devtools/alerticon-warning.png");
-moz-margin-start: 5px;
vertical-align: middle;
display: inline-block;
vertical-align: top;
width: 13px;
height: 12px;
}

View File

@ -33,10 +33,12 @@
display: flex;
}
body.show-simulators .banner,
body.edit-connection .banner {
display: none !important;
}
body.show-simulators #banner-simulators,
body.edit-connection #banner-editing {
display: flex !important;
}
@ -70,10 +72,6 @@ body.edit-connection #banner-editing {
display: inline;
}
#start-simulator-box[simulators-count="0"] {
display: none;
}
/************** PIXELS **************/
* {
@ -193,8 +191,18 @@ button.action-cancel {
background: linear-gradient(to bottom, #69B8FF, #339FFF );
}
#banner-simulators .connected-indicator,
#banner-disconnected .connected-indicator,
#banner-editing .connected-indicator,
#banner-disconnecting .connected-indicator {
background: linear-gradient(to bottom, #375A87, #1C4375 );
}
#banner-simulators .banner-content > * {
display: inline-block;
}
#banner-simulators[simulator-count="0"] .found-simulator,
#banner-simulators:not([simulator-count="0"]) .no-simulator {
display: none;
}

View File

@ -46,7 +46,8 @@
.ruleview-warning {
background: url("chrome://browser/skin/devtools/alerticon-warning.png");
-moz-margin-start: 5px;
vertical-align: middle;
display: inline-block;
vertical-align: top;
width: 13px;
height: 12px;
}

View File

@ -21,10 +21,8 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=470804
Passing a null targetURL to checkLoadURIWithPrincipal shouldn't crash
**/
netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect');
const nsIScriptSecurityManager = Components.interfaces.nsIScriptSecurityManager;
var secMan = SpecialPowers.Cc["@mozilla.org/scriptsecuritymanager;1"]
.getService(nsIScriptSecurityManager);
const nsIScriptSecurityManager = SpecialPowers.Ci.nsIScriptSecurityManager;
var secMan = SpecialPowers.Services.scriptSecurityManager;
var principal = SpecialPowers.wrap(document).nodePrincipal;
isnot(principal, undefined, "Should have a principal");
isnot(principal, null, "Should have a non-null principal");

View File

@ -30,12 +30,10 @@ function getLoadContext() {
}
function testCopyPaste (isXHTML) {
netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
var suppressUnicodeCheckIfHidden = !!isXHTML;
var suppressHTMLCheck = !!isXHTML;
var webnav = window.QueryInterface(SpecialPowers.Ci.nsIInterfaceRequestor)
var webnav = SpecialPowers.wrap(window).QueryInterface(SpecialPowers.Ci.nsIInterfaceRequestor)
.getInterface(SpecialPowers.Ci.nsIWebNavigation)
var docShell = webnav.QueryInterface(SpecialPowers.Ci.nsIDocShell);
@ -43,8 +41,7 @@ function testCopyPaste (isXHTML) {
var documentViewer = docShell.contentViewer
.QueryInterface(SpecialPowers.Ci.nsIContentViewerEdit);
var clipboard = SpecialPowers.Cc["@mozilla.org/widget/clipboard;1"]
.getService(SpecialPowers.Ci.nsIClipboard);
var clipboard = SpecialPowers.Services.clipboard;
var textarea = SpecialPowers.wrap(document.getElementById('input'));
@ -88,14 +85,14 @@ function testCopyPaste (isXHTML) {
transferable.init(getLoadContext());
transferable.addDataFlavor(mime);
clipboard.getData(transferable, 1);
var data = {};
var data = SpecialPowers.createBlankObject();
transferable.getTransferData(mime, data, {}) ;
return data;
}
function testClipboardValue(mime, expected) {
if (suppressHTMLCheck && mime == "text/html")
return null;
var data = getClipboardData(mime);
var data = SpecialPowers.wrap(getClipboardData(mime));
is (data.value == null ? data.value :
data.value.QueryInterface(SpecialPowers.Ci.nsISupportsString).data,
expected,

View File

@ -12,11 +12,8 @@ function run() {
}
function forcegc(){
netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
Components.utils.forceGC();
var wu = window.QueryInterface(Components.interfaces.nsIInterfaceRequestor)
.getInterface(Components.interfaces.nsIDOMWindowUtils);
wu.garbageCollect();
SpecialPowers.forceGC();
SpecialPowers.gc();
}
</script>

View File

@ -38,8 +38,6 @@ testDoc2.appendChild(testDoc2.createElement("res"));
testDoc2.documentElement.appendChild(testDoc2.createTextNode("text"));
is(testDoc2.inputEncoding, null, "wrong encoding");
netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
var testData = "blahblahblahblahblahblahblaaaaaaaah. blah.";
var extensions = [".txt",".png",".jpg",".gif",".xml", "noext"];
var fileTypes = ["text/plain", "image/png", "image/jpeg", "image/gif", "text/xml", null];
@ -72,14 +70,13 @@ extensions.forEach(
testFiles.push(testFile);
var fileList = document.getElementById('fileList');
fileList.value = testFile.path;
SpecialPowers.wrap(fileList).value = testFile.path;
testDOMFiles.push(fileList.files[0]);
}
);
function createFileWithDataExt(fileData, extension) {
var dirSvc = SpecialPowers.Cc["@mozilla.org/file/directory_service;1"].getService(SpecialPowers.Ci.nsIProperties);
var testFile = dirSvc.get("ProfD", SpecialPowers.Ci.nsIFile);
var testFile = SpecialPowers.Services.dirsvc.get("ProfD", SpecialPowers.Ci.nsIFile);
testFile.append("testfile" + extension);
var outStream = SpecialPowers.Cc["@mozilla.org/network/file-output-stream;1"].createInstance(SpecialPowers.Ci.nsIFileOutputStream);
outStream.init(testFile, 0x02 | 0x08 | 0x20, 0666, 0);

View File

@ -65,8 +65,6 @@ function runNextTest() {
if (tests.length > 0) {
var test = tests.shift();
netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
// Initialize state variables
testName = test[0]
currentState = 0;

View File

@ -33,10 +33,7 @@ function runTest() {
xhr.open("GET", "test_bug382871.html");
xhr.send();
xhr = null;
netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
window.QueryInterface(Components.interfaces.nsIInterfaceRequestor)
.getInterface(Components.interfaces.nsIDOMWindowUtils)
.garbageCollect();
SpecialPowers.gc();
}
SimpleTest.waitForExplicitFinish();

View File

@ -21,14 +21,11 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=403852
<pre id="test">
<script class="testbody" type="text/javascript">
netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
var dirSvc = SpecialPowers.Cc["@mozilla.org/file/directory_service;1"].getService(SpecialPowers.Ci.nsIProperties);
var testFile = dirSvc.get("ProfD", SpecialPowers.Ci.nsIFile);
var testFile = SpecialPowers.Services.dirsvc.get("ProfD", SpecialPowers.Ci.nsIFile);
testFile.append("prefs.js");
var fileList = document.getElementById('fileList');
fileList.value = testFile.path;
SpecialPowers.wrap(fileList).value = testFile.path;
// Make sure the file is accessible with indexed notation
var domFile = fileList.files[0];

View File

@ -21,16 +21,13 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=416383
/** Test for Bug 416383 **/
function runTest() {
netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
var testParent = document.getElementById("test_parent");
var attrs = testParent.firstChild.attributes;
ok(attrs != null, "Element should have attributes!");
var attr = testParent.firstChild.getAttributeNode("someattr");
ok(attr.value == "foo", "The value of the attribute should be 'foo'!");
testParent.removeChild(testParent.firstChild);
window.QueryInterface(Components.interfaces.nsIInterfaceRequestor)
.getInterface(Components.interfaces.nsIDOMWindowUtils)
.garbageCollect();
SpecialPowers.gc();
ok(true, "Browser should not crash!")
}

View File

@ -23,13 +23,6 @@ SimpleTest.waitForExplicitFinish();
var img1loaded = false;
var img1errored = false;
function gc() {
netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
window.QueryInterface(Components.interfaces.nsIInterfaceRequestor)
.getInterface(Components.interfaces.nsIDOMWindowUtils)
.garbageCollect();
}
// Our test image
function loadTestImage() {
var img1 = new Image();
@ -46,7 +39,7 @@ function loadTestImage() {
loadTestImage();
// Probably overkill to gc() more than once, but let's be safe
gc(); gc(); gc();
SpecialPowers.gc(); SpecialPowers.gc(); SpecialPowers.gc();
function finishTest() {
is(img1errored, true, "Image 1 should error");

View File

@ -19,13 +19,6 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=448993
/** Test for Bug 448993 **/
function gc() {
netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
window.QueryInterface(Components.interfaces.nsIInterfaceRequestor)
.getInterface(Components.interfaces.nsIDOMWindowUtils)
.garbageCollect();
}
function runTest() {
var a = document.getElementById("a");
var b = document.getElementById("b");
@ -37,7 +30,7 @@ function runTest() {
r.extractContents();
var s = document.createRange();
s.setEnd(b, 0);
gc();
SpecialPowers.gc();
s.deleteContents();
ok(true, "test did not crash");
SimpleTest.finish();

View File

@ -20,14 +20,11 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=456262
/** Test for Bug 456262 **/
function runTest() {
netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
document.expando = document;
document.documentElement.expando = document;
document.documentElement.setAttribute("foo", "bar");
document.documentElement.getAttributeNode("foo").expando = document;
window.QueryInterface(Components.interfaces.nsIInterfaceRequestor)
.getInterface(Components.interfaces.nsIDOMWindowUtils)
.garbageCollect();
SpecialPowers.gc();
ok(document.expando, "Should have preserved the expando!");
ok(document.documentElement.expando, "Should have preserved the expando!");
ok(document.documentElement.getAttributeNode('foo').expando,

View File

@ -20,16 +20,9 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=459424
/** Test for Bug 459424 **/
SimpleTest.waitForExplicitFinish();
addLoadEvent(function() {
netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect');
var viewer =
window.QueryInterface(Components.interfaces.nsIInterfaceRequestor)
.getInterface(Components.interfaces.nsIWebNavigation)
.QueryInterface(Components.interfaces.nsIDocShell)
.contentViewer
.QueryInterface(Components.interfaces.nsIMarkupDocumentViewer);
viewer.fullZoom = 2;
SpecialPowers.setFullZoom(window, 2);
is(true, true, "Gotta test something");
viewer.fullZoom = 1;
SpecialPowers.setFullZoom(window, 1);
SimpleTest.finish();
});
</script>

View File

@ -19,19 +19,12 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=465767
/** Test for Bug 465767 **/
function CC() {
netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
window.QueryInterface(Components.interfaces.nsIInterfaceRequestor)
.getInterface(Components.interfaces.nsIDOMWindowUtils)
.garbageCollect();
}
function runTest() {
var node = document.createElement("div");
var e = null;
try {
document.implementation.createDocument("", "", null).adoptNode(node);
CC();
SpecialPowers.gc();
document.implementation.createDocument("", "", null).adoptNode(node);
} catch(ex) {
e = ex;

View File

@ -19,12 +19,10 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=592829
// If we ever change how DOMParser initilization works, just update this code
// to create a DOMParser which is not allowed to parse XUL.
netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
var isXUL = true;
try {
var x =
Components.classes["@mozilla.org/xmlextras/domparser;1"]
SpecialPowers.Cc
.getService(Components.interfaces.nsIDOMParser)
.parseFromString('<overlay xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"/>', "text/xml");
isXUL = x.documentElement.namespaceURI ==

View File

@ -209,10 +209,8 @@ function getFile(name) {
basePath = xhr.responseText;
}
netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
var fileList = document.getElementById('fileList');
fileList.value = basePath + name;
SpecialPowers.wrap(fileList).value = basePath + name;
return fileList.files[0];
}

View File

@ -90,10 +90,7 @@ function start() {
kOS = OS_WINDOWS;
// code borrowed from browser/modules/test/browser_taskbar_preview.js
netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect');
var version = SpecialPowers.Cc['@mozilla.org/system-info;1']
.getService(SpecialPowers.Ci.nsIPropertyBag2)
.getProperty('version');
var version = SpecialPowers.Services.sysinfo.getProperty('version');
kOSVersion = parseFloat(version);
// Version 6.0 is Vista, 6.1 is 7.
} else if (navigator.platform.indexOf('Mac') == 0) {
@ -139,7 +136,6 @@ function start() {
requestLongerTimeoutLen = 6;
function getEnv(env) {
netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
var envsvc = SpecialPowers.Cc["@mozilla.org/process/environment;1"].getService(SpecialPowers.Ci.nsIEnvironment);
var val = envsvc.get(env);
if (val == "")

View File

@ -49,8 +49,7 @@ function isRectContainedInRectFromRegion(rect, region) {
}
function paintListener(e) {
netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
if (isRectContainedInRectFromRegion(buttonRect(), e.clientRects)) {
if (isRectContainedInRectFromRegion(buttonRect(), SpecialPowers.wrap(e).clientRects)) {
gNeedsPaint = false;
currentSnapshot = takeSnapshot();
}

View File

@ -65,8 +65,7 @@ function isRectContainedInRectFromRegion(rect, region) {
}
function paintListener(e) {
netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
if (isRectContainedInRectFromRegion(buttonRect(), e.clientRects)) {
if (isRectContainedInRectFromRegion(buttonRect(), SpecialPowers.wrap(e).clientRects)) {
gNeedsPaint = false;
currentSnapshot = takeSnapshot();
}

View File

@ -52,9 +52,7 @@ function clickHandler(e) {
function doTest() {
window.addEventListener("click", clickHandler, true);
netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect');
var utils = window.QueryInterface(Components.interfaces.nsIInterfaceRequestor).
getInterface(Components.interfaces.nsIDOMWindowUtils);
var utils = SpecialPowers.getDOMWindowUtils(window);
utils.sendMouseEvent("mousedown", 1, 1, 0, 1, 0);
utils.sendMouseEvent("mouseup", 1, 1, 0, 1, 0);

View File

@ -151,8 +151,7 @@ function runTests() {
}
function dispatchTrusted(t, o) {
netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
t.dispatchEvent(new Event("testevent", o));
SpecialPowers.dispatchEvent(window, t, new Event("testevent", o));
}
function testAllListener() {

View File

@ -20,14 +20,11 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=450876
/** Test for Bug 450876 **/
function doTest() {
netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
is(document.activeElement, document.body, "body element should be focused");
document.getElementById('a').focus();
is(document.activeElement, document.getElementById('a'), "link should have focus");
var wu = window.QueryInterface(Components.interfaces.nsIInterfaceRequestor)
.getInterface(Components.interfaces.nsIDOMWindowUtils);
is(document.hasFocus(), true, "document should be focused");
wu.sendKeyEvent('keypress', 9, 0, 0);
SpecialPowers.DOMWindowUtils.sendKeyEvent('keypress', 9, 0, 0);
is(document.activeElement, document.getElementById('a'), "body element should be focused");
is(document.hasFocus(), false, "document should not be focused");

View File

@ -23,12 +23,11 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=456273
/** Test for Bug 456273 **/
function doTest() {
netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect');
var ev = document.createEvent('KeyEvents');
ev.initKeyEvent("keypress", true, true, null, true, false,
false, false, 0, "z".charCodeAt(0));
document.getElementById('edit456273').dispatchEvent(ev);
SpecialPowers.dispatchEvent(window, document.getElementById('edit456273'), ev);
ok(true, "PASS");
SimpleTest.finish();
}

View File

@ -21,19 +21,14 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=605242
SimpleTest.waitForExplicitFinish();
var utils = SpecialPowers.getDOMWindowUtils(window);
function sendMouseDown(el) {
netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
var rect = el.getBoundingClientRect();
var utils = window.QueryInterface(Components.interfaces.nsIInterfaceRequestor)
.getInterface(Components.interfaces.nsIDOMWindowUtils);
utils.sendMouseEvent('mousedown', rect.left + 5, rect.top + 5, 0, 1, 0);
}
function sendMouseUp(el) {
netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
var rect = el.getBoundingClientRect();
var utils = window.QueryInterface(Components.interfaces.nsIInterfaceRequestor)
.getInterface(Components.interfaces.nsIDOMWindowUtils);
utils.sendMouseEvent('mouseup', rect.left + 5, rect.top + 5, 0, 1, 0);
}

View File

@ -87,6 +87,7 @@ function runTest()
"[" + element.tagName + "] witness should still be focused");
// Cleanup.
element.hidden = true;
witness.focus();
}

View File

@ -34,11 +34,6 @@ function invalidEventHandler(e)
function completeValidityCheck(element, alwaysValid, isBarred)
{
if (element.type == 'file') {
// Need privileges to set a filename with .value.
netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
}
// Check when pattern matches.
if (element.type == 'email') {
element.pattern = ".*@bar.com";
@ -48,7 +43,7 @@ function completeValidityCheck(element, alwaysValid, isBarred)
element.value = "http://mozilla.com";
} else {
element.pattern = "foo";
element.value = "foo";
SpecialPowers.wrap(element).value = "foo";
}
checkValidPattern(element, true, isBarred);
@ -63,7 +58,7 @@ function completeValidityCheck(element, alwaysValid, isBarred)
element.value = "http://mozilla.org";
} else {
element.pattern = "foo";
element.value = "bar";
SpecialPowers.wrap(element).value = "bar";
}
if (!alwaysValid) {

View File

@ -268,10 +268,8 @@ function checkValidityStateObjectAliveWithoutElement(element)
// Then, we make sure it is removed by the garbage collector and we check the
// ValidityState default values (it should not crash).
netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
var v = document.createElement(element).validity;
window.QueryInterface(Components.interfaces.nsIInterfaceRequestor).
getInterface(Components.interfaces.nsIDOMWindowUtils).garbageCollect();
SpecialPowers.gc();
ok(!v.valueMissing,
"When the element is not alive, it shouldn't suffer from constraint validation");

View File

@ -77,9 +77,7 @@ function link123HrefIs(href, testNum) {
var gGen;
function visitedDependentComputedStyle(win, elem, property) {
netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
var utils = win.QueryInterface(Components.interfaces.nsIInterfaceRequestor).
getInterface(Components.interfaces.nsIDOMWindowUtils);
var utils = SpecialPowers.getDOMWindowUtils(window);
return utils.getVisitedDependentComputedStyle(elem, "", property);
}

View File

@ -25,9 +25,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=406596
/** Test for Bug 406596 **/
function testTabbing(click, focus, selectionOffset) {
netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
var wu = window.QueryInterface(Components.interfaces.nsIInterfaceRequestor)
.getInterface(Components.interfaces.nsIDOMWindowUtils);
var wu = SpecialPowers.getDOMWindowUtils(window);
var elem = document.getElementById(click);
var rect = elem.getBoundingClientRect();

View File

@ -21,9 +21,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=421640
/** Test for Bug 421640 **/
function test(click, focus, nextFocus) {
netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
var wu = window.QueryInterface(Components.interfaces.nsIInterfaceRequestor)
.getInterface(Components.interfaces.nsIDOMWindowUtils);
var wu = SpecialPowers.getDOMWindowUtils(window);
var selection = window.getSelection();
var edit = document.getElementById("edit");

View File

@ -36,15 +36,14 @@ function runTest()
range.selectNodeContents(editor);
var prevStr = range.toString();
netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect');
var docShell =
window.QueryInterface(Components.interfaces.nsIInterfaceRequestor)
.getInterface(Components.interfaces.nsIWebNavigation)
.QueryInterface(Components.interfaces.nsIDocShell);
var docShell = SpecialPowers.wrap(window)
.QueryInterface(SpecialPowers.Ci.nsIInterfaceRequestor)
.getInterface(SpecialPowers.Ci.nsIWebNavigation)
.QueryInterface(SpecialPowers.Ci.nsIDocShell);
var controller =
docShell.QueryInterface(Components.interfaces.nsIInterfaceRequestor)
.getInterface(Components.interfaces.nsISelectionDisplay)
.QueryInterface(Components.interfaces.nsISelectionController);
docShell.QueryInterface(SpecialPowers.Ci.nsIInterfaceRequestor)
.getInterface(SpecialPowers.Ci.nsISelectionDisplay)
.QueryInterface(SpecialPowers.Ci.nsISelectionController);
var sel = controller.getSelection(controller.SELECTION_NORMAL);
sel.collapse(anchorInEditor, 0);
synthesizeKey('a', {});

View File

@ -51,10 +51,7 @@ function checkLinkColor(aElmId, aExpectedColor, aMessage) {
// Because link coloring is asynchronous, we wait until we get the right
// result, or we will time out (resulting in a failure).
function getColor() {
netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
var utils = document.defaultView.
QueryInterface(Components.interfaces.nsIInterfaceRequestor).
getInterface(Components.interfaces.nsIDOMWindowUtils);
var utils = SpecialPowers.getDOMWindowUtils(window);
return utils.getVisitedDependentComputedStyle($(aElmId), "", "color");
}
while (getColor() != aExpectedColor) {

View File

@ -152,10 +152,7 @@ function clickImage(aTarget, aX, aY)
aTarget.style.left = "0";
aTarget.offsetTop;
netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
var wu = aTarget.ownerDocument.defaultView
.QueryInterface(Components.interfaces.nsIInterfaceRequestor)
.getInterface(Components.interfaces.nsIDOMWindowUtils);
var wu = SpecialPowers.getDOMWindowUtils(aTarget.ownerDocument.defaultView);
wu.sendMouseEvent('mousedown', aX, aY, 0, 1, 0);
wu.sendMouseEvent('mouseup', aX, aY, 0, 0, 0);

View File

@ -20,10 +20,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=446483
/** Test for Bug 446483 **/
function gc() {
netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
window.QueryInterface(Components.interfaces.nsIInterfaceRequestor)
.getInterface(Components.interfaces.nsIDOMWindowUtils)
.garbageCollect();
SpecialPowers.gc();
}
function runTest() {

View File

@ -27,10 +27,7 @@ function testViewport() {
netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect');
/* Grab Viewport Metadata from the document header. */
var iRequester =
window.QueryInterface(Components.interfaces.nsIInterfaceRequestor);
var windowUtils =
iRequester.getInterface(Components.interfaces.nsIDOMWindowUtils);
var windowUtils = SpecialPowers.getDOMWindowUtils(window);
var vpWidth =
parseInt(windowUtils.getDocumentMetadata("viewport-width"));
var vpHeight =

View File

@ -93,6 +93,7 @@ this.AppsUtils = {
installerIsBrowser: !!aApp.installerIsBrowser,
storeId: aApp.storeId || "",
storeVersion: aApp.storeVersion || 0,
role: aApp.role || "",
redirects: aApp.redirects
};
},
@ -320,6 +321,10 @@ this.AppsUtils = {
}
}
// The 'role' field must be a string.
if (aManifest.role && (typeof aManifest.role !== "string")) {
return false;
}
return true;
},
@ -639,5 +644,9 @@ ManifestHelper.prototype = {
fullPackagePath: function() {
let packagePath = this._localeProp("package_path");
return this._origin.resolve(packagePath ? packagePath : "");
},
get role() {
return this._manifest.role || "";
}
}

View File

@ -190,6 +190,11 @@ this.DOMApplicationRegistry = {
this.webapps[id].storeVersion = 0;
}
// Default role to "".
if (this.webapps[id].role === undefined) {
this.webapps[id].role = "";
}
// At startup we can't be downloading, and the $TMP directory
// will be empty so we can't just apply a staged update.
app.downloading = false;
@ -242,13 +247,14 @@ this.DOMApplicationRegistry = {
if (supportSystemMessages()) {
this._processManifestForIds(ids, aRunUpdate);
} else {
// Read the CSPs. If MOZ_SYS_MSG is defined this is done on
// Read the CSPs and roles. If MOZ_SYS_MSG is defined this is done on
// _processManifestForIds so as to not reading the manifests
// twice
this._readManifests(ids, (function readCSPs(aResults) {
aResults.forEach(function registerManifest(aResult) {
let app = this.webapps[aResult.id];
app.csp = aResult.manifest.csp || "";
app.role = aResult.manifest.role || "";
if (app.appStatus >= Ci.nsIPrincipal.APP_STATUS_PRIVILEGED) {
app.redirects = this.sanitizeRedirects(aResult.redirects);
}
@ -734,6 +740,7 @@ this.DOMApplicationRegistry = {
let manifest = aResult.manifest;
app.name = manifest.name;
app.csp = manifest.csp || "";
app.role = manifest.role || "";
if (app.appStatus >= Ci.nsIPrincipal.APP_STATUS_PRIVILEGED) {
app.redirects = this.sanitizeRedirects(manifest.redirects);
}
@ -1345,6 +1352,7 @@ this.DOMApplicationRegistry = {
if (array.length == CHUNK_SIZE) {
readChunk();
} else {
file.close();
// We're passing false to get the binary hash and not base64.
let hash = hasher.finish(false);
// convert the binary hash data to a hex string.
@ -1477,6 +1485,7 @@ this.DOMApplicationRegistry = {
app.name = manifest.name;
app.csp = manifest.csp || "";
app.role = manifest.role || "";
app.updateTime = Date.now();
} else {
manifest = new ManifestHelper(aOldManifest, app.origin);
@ -2057,6 +2066,7 @@ this.DOMApplicationRegistry = {
appObject.name = manifest.name;
appObject.csp = manifest.csp || "";
appObject.role = manifest.role || "";
appObject.installerAppId = aData.appId;
appObject.installerIsBrowser = aData.isBrowser;
@ -2411,10 +2421,25 @@ this.DOMApplicationRegistry = {
app.downloadSize = 0;
app.installState = "installed";
app.readyToApplyDownload = false;
if (app.staged && app.staged.manifestHash) {
// If we're here then the manifest has changed but the package
// hasn't. Let's clear this, so we don't keep offering
// a bogus update to the user
app.manifestHash = app.staged.manifestHash;
app.etag = app.staged.etag || app.etag;
app.staged = {};
// Move the staged update manifest to a non staged one.
let dirPath = self._getAppDir(id).path;
// We don't really mind much if this fails.
OS.File.move(OS.Path.join(dirPath, "staged-update.webapp"),
OS.Path.join(dirPath, "update.webapp"));
}
self.broadcastMessage("Webapps:PackageEvent", {
type: "downloaded",
manifestURL: aApp.manifestURL,
app: app })
app: app });
self.broadcastMessage("Webapps:PackageEvent", {
type: "applied",
manifestURL: aApp.manifestURL,

View File

@ -13,6 +13,8 @@ MOCHITEST_FILES = \
file_packaged_app.template.webapp \
file_packaged_app.template.html \
test_packaged_app_install.html \
test_packaged_app_update.html \
test_packaged_app_common.js \
$(NULL)
MOCHITEST_CHROME_FILES = \

View File

@ -32,34 +32,37 @@ function handleRequest(request, response) {
if ("setVersion" in query) {
var version = query.setVersion;
setState("version", version);
var packageVersion = ("dontUpdatePackage" in query) ? version - 1 : version;
var packageName = "test_packaged_app_" + packageVersion + ".zip";
var packageName = "test_packaged_app_" + version + ".zip";
setState("packageName", packageName);
var packagePath = "/" + gBasePath + "file_packaged_app.sjs?getPackage=" +
packageName;
setState("packagePath", packagePath);
// Create the application package.
var zipWriter = Cc["@mozilla.org/zipwriter;1"]
.createInstance(Ci.nsIZipWriter);
var zipFile = FileUtils.getFile("TmpD", [packageName]);
zipWriter.open(zipFile, PR_RDWR | PR_CREATE_FILE | PR_TRUNCATE);
if (version == packageVersion) {
// Create the application package.
var zipWriter = Cc["@mozilla.org/zipwriter;1"]
.createInstance(Ci.nsIZipWriter);
var zipFile = FileUtils.getFile("TmpD", [packageName]);
zipWriter.open(zipFile, PR_RDWR | PR_CREATE_FILE | PR_TRUNCATE);
// We want to run some tests without the manifest included in the zip.
if (version != "0") {
var manifestTemplate = gBasePath + gMiniManifestTemplate;
var manifest = makeResource(manifestTemplate, version, packagePath,
packageSize, appName, devName, devUrl);
addZipEntry(zipWriter, manifest, "manifest.webapp");
// We want to run some tests without the manifest included in the zip.
if (version != "0") {
var manifestTemplate = gBasePath + gMiniManifestTemplate;
var manifest = makeResource(manifestTemplate, version, packagePath,
packageSize, appName, devName, devUrl);
addZipEntry(zipWriter, manifest, "manifest.webapp");
}
var appTemplate = gBasePath + gAppTemplate;
var app = makeResource(appTemplate, version, packagePath, packageSize,
appName, devName, devUrl);
addZipEntry(zipWriter, app, "index.html");
zipWriter.close();
}
var appTemplate = gBasePath + gAppTemplate;
var app = makeResource(appTemplate, version, packagePath, packageSize,
appName, devName, devUrl);
addZipEntry(zipWriter, app, "index.html");
zipWriter.close();
response.setHeader("Content-Type", "text/html", false);
response.write("OK");
return;

View File

@ -0,0 +1,229 @@
/* 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/. */
var PackagedTestHelper = (function PackagedTestHelper() {
"use strict";
var launchableValue;
var steps;
var index = -1;
var gSJSPath = "tests/dom/apps/tests/file_packaged_app.sjs";
var gSJS = "http://test/" + gSJSPath;
var gAppName = "appname";
var gApp = null;
var gInstallOrigin = "http://mochi.test:8888";
function debug(aMsg) {
//dump("== PackageTestHelper debug == " + aMsg + "\n");
}
function next() {
index += 1;
if (index >= steps.length) {
ok(false, "Shouldn't get here!");
return;
}
try {
steps[index]();
} catch(ex) {
ok(false, "Caught exception", ex);
}
}
function start() {
next();
}
function finish() {
SpecialPowers.setAllAppsLaunchable(launchableValue);
SpecialPowers.removePermission("webapps-manage", document);
SimpleTest.finish();
}
function mozAppsError() {
ok(false, "mozApps error: " + self.error.name);
finish();
}
function xhrError(event, url) {
var xhr = event.target;
ok(false, "XHR error loading " + url + ": " + xhr.status + " - " +
xhr.statusText);
finish();
}
function xhrAbort(url) {
ok(false, "XHR abort loading " + url);
finish();
}
function setAppVersion(aVersion, aCb, aDontUpdatePackage) {
var xhr = new XMLHttpRequest();
var dontUpdate = "";
if (aDontUpdatePackage) {
dontUpdate = "&dontUpdatePackage=1";
}
var url = gSJS + "?setVersion=" + aVersion + dontUpdate;
xhr.addEventListener("load", function() {
is(xhr.responseText, "OK", "setAppVersion OK");
aCb();
});
xhr.addEventListener("error", event => xhrError(event, url));
xhr.addEventListener("abort", event => xhrAbort(url));
xhr.open("GET", url, true);
xhr.send();
}
function checkAppDownloadError(aMiniManifestURL,
aExpectedError,
aVersion,
aUninstall,
aDownloadAvailable,
aName,
aCb) {
var req = navigator.mozApps.installPackage(aMiniManifestURL);
req.onsuccess = function(evt) {
ok(true, "App installed");
if (!aUninstall) {
// Save it for later.
gApp = req.result;
}
};
req.onerror = function(evt) {
ok(false, "Got unexpected " + evt.target.error.name);
finish();
};
navigator.mozApps.mgmt.oninstall = function(evt) {
var aApp = evt.application;
aApp.ondownloaderror = function(evt) {
var error = aApp.downloadError.name;
if (error == aExpectedError) {
ok(true, "Got expected " + aExpectedError);
var expected = {
name: aName,
manifestURL: aMiniManifestURL,
installOrigin: gInstallOrigin,
progress: 0,
installState: "pending",
downloadAvailable: aDownloadAvailable,
downloading: false,
downloadSize: 0,
size: 0,
readyToApplyDownload: false
};
checkAppState(aApp, aVersion, expected, false, aUninstall,
aCb || next);
} else {
ok(false, "Got unexpected " + error);
finish();
}
};
aApp.ondownloadsuccess = function(evt) {
ok(false, "We are supposed to throw " + aExpectedError);
finish();
};
};
}
function checkAppState(aApp,
aVersion,
aExpectedApp,
aLaunchable,
aUninstall,
aCb) {
debug(JSON.stringify(aApp, null, 2));
if (aApp.manifest) {
debug(JSON.stringify(aApp.manifest, null, 2));
}
if (aExpectedApp.name) {
if (aApp.manifest) {
is(aApp.manifest.name, aExpectedApp.name, "Check name");
}
is(aApp.updateManifest.name, aExpectedApp.name, "Check name mini-manifest");
}
if (aApp.manifest) {
is(aApp.manifest.version, aVersion, "Check version");
}
if (typeof aExpectedApp.size !== "undefined" && aApp.manifest) {
is(aApp.manifest.size, aExpectedApp.size, "Check size");
}
if (aApp.manifest) {
is(aApp.manifest.launch_path, gSJSPath, "Check launch path");
}
if (aExpectedApp.manifestURL) {
is(aApp.manifestURL, aExpectedApp.manifestURL, "Check manifestURL");
}
if (aExpectedApp.installOrigin) {
is(aApp.installOrigin, aExpectedApp.installOrigin, "Check installOrigin");
}
ok(aApp.removable, "Removable app");
if (typeof aExpectedApp.progress !== "undefined") {
todo(aApp.progress == aExpectedApp.progress, "Check progress");
}
if (aExpectedApp.installState) {
is(aApp.installState, aExpectedApp.installState, "Check installState");
}
if (typeof aExpectedApp.downloadAvailable !== "undefined") {
is(aApp.downloadAvailable, aExpectedApp.downloadAvailable,
"Check download available");
}
if (typeof aExpectedApp.downloading !== "undefined") {
is(aApp.downloading, aExpectedApp.downloading, "Check downloading");
}
if (typeof aExpectedApp.downloadSize !== "undefined") {
is(aApp.downloadSize, aExpectedApp.downloadSize, "Check downloadSize");
}
if (typeof aExpectedApp.readyToApplyDownload !== "undefined") {
is(aApp.readyToApplyDownload, aExpectedApp.readyToApplyDownload,
"Check readyToApplyDownload");
}
if (aLaunchable) {
if (aUninstall) {
checkUninstallApp(aApp);
} else if (aCb && typeof aCb === "function") {
aCb();
}
return;
}
// Check if app is not launchable.
var req = aApp.launch();
req.onsuccess = function () {
ok(false, "We shouldn't be here");
finish();
};
req.onerror = function() {
ok(true, "App is not launchable");
if (aUninstall) {
checkUninstallApp(aApp);
} else if (aCb && typeof aCb === "function") {
aCb();
}
return;
};
}
return {
setSteps: function (aSteps) {
steps = aSteps;
},
next: next,
start: start,
finish: finish,
mozAppsError: mozAppsError,
setAppVersion: setAppVersion,
checkAppState: checkAppState,
checkAppDownloadError: checkAppDownloadError,
get gSJSPath() { return gSJSPath; },
get gSJS() { return gSJS; },
get gAppName() { return gAppName;},
get gApp() { return gApp; },
set gApp(aValue) { gApp = aValue; },
gInstallOrigin: gInstallOrigin,
launchableValue: launchableValue
};
})();

View File

@ -7,6 +7,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id={821589}
<title>Test for Bug {821589} Packaged apps installation and update</title>
<script type="text/javascript" src="/MochiKit/MochiKit.js"></script>
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<script type="text/javascript" src="test_packaged_app_common.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
</head>
<body>
@ -18,90 +19,26 @@ https://bugzilla.mozilla.org/show_bug.cgi?id={821589}
</div>
<pre id="test">
<script class="testbody" type="text/javascript">
"use strict";
var gInstallOrigin = "http://mochi.test:8888";
var gSJSPath = "tests/dom/apps/tests/file_packaged_app.sjs";
var gSJS = "http://test/" + gSJSPath;
var gAppName = "appname";
var gApp = null;
var launchableValue = undefined;
var index = -1;
function debug(aMsg) {
//dump("== Tests debug == " + aMsg + "\n");
}
function next() {
index += 1;
if (index >= steps.length) {
ok(false, "Shouldn't get here!");
return;
}
try {
steps[index]();
} catch(ex) {
ok(false, "Caught exception", ex);
}
}
function go() {
next();
}
function finish() {
SpecialPowers.setAllAppsLaunchable(launchableValue);
SpecialPowers.removePermission("webapps-manage", document);
SimpleTest.finish();
}
function mozAppsError() {
ok(false, "mozApps error: " + this.error.name);
finish();
}
function xhrError(event, url) {
var xhr = event.target;
ok(false, "XHR error loading " + url + ": " + xhr.status + " - " +
xhr.statusText);
finish();
}
function xhrAbort(url) {
ok(false, "XHR abort loading " + url);
finish();
}
function setAppVersion(aVersion, aCb) {
var xhr = new XMLHttpRequest();
var url = gSJS + "?setVersion=" + aVersion;
xhr.addEventListener("load", function() {
is(xhr.responseText, "OK", "setAppVersion OK");
aCb();
});
xhr.addEventListener("error", event => xhrError(event, url));
xhr.addEventListener("abort", event => xhrAbort(url));
xhr.open("GET", url, true);
xhr.send();
}
function checkAppInstallError(aMiniManifestURL, aExpectedError) {
var req = navigator.mozApps.installPackage(aMiniManifestURL);
req.onsuccess = function() {
ok(false, "We are supposed to throw " + aExpectedError);
finish();
PackagedTestHelper.finish();
};
req.onerror = function(evt) {
var error = evt.target.error.name;
if (error == aExpectedError) {
ok(true, "Got expected " + aExpectedError);
next();
PackagedTestHelper.next();
} else {
ok(false, "Got unexpected " + aError);
finish();
PackagedTestHelper.finish();
}
};
}
@ -113,57 +50,11 @@ function checkUninstallApp(aApp) {
aApp.ondownloadsuccess = null;
aApp.ondownloaderror = null;
aApp.onprogress = null;
next();
PackagedTestHelper.next();
};
req.onerror = function(evt) {
ok(false, "Got unexpected " + evt.target.error.name);
finish();
};
}
function checkAppDownloadError(aMiniManifestURL,
aExpectedError,
aVersion,
aUninstall,
aDownloadAvailable,
aName) {
var req = navigator.mozApps.installPackage(aMiniManifestURL);
req.onsuccess = function() {
ok(true, "App installed");
};
req.onerror = function(evt) {
ok(false, "Got unexpected " + evt.target.error.name);
finish();
};
navigator.mozApps.mgmt.oninstall = function(evt) {
var aApp = evt.application;
aApp.ondownloaderror = function(evt) {
var error = aApp.downloadError.name;
if (error == aExpectedError) {
ok(true, "Got expected " + aExpectedError);
var expected = {
name: aName,
manifestURL: aMiniManifestURL,
installOrigin: gInstallOrigin,
progress: 0,
installState: "pending",
downloadAvailable: aDownloadAvailable,
downloading: false,
downloadSize: 0,
size: 0,
readyToApplyDownload: false,
};
checkAppState(aApp, aVersion, expected, false, aUninstall, next);
} else {
ok(false, "Got unexpected " + error);
finish();
}
};
aApp.ondownloadsuccess = function(evt) {
ok(false, "We are supposed to throw " + aExpectedError);
finish();
};
PackagedTestHelper.finish();
};
}
@ -175,91 +66,12 @@ function checkInstalledApp(aMiniManifestURL,
var req = navigator.mozApps.checkInstalled(aMiniManifestURL);
req.onsuccess = function(evt) {
ok(true, "The app is installed");
checkAppState(evt.application, aVersion, aExpectedApp, aLaunchable,
false, aCb);
PackagedTestHelper.checkAppState(evt.application, aVersion, aExpectedApp,
aLaunchable, false, aCb);
};
req.onerror = function() {
ok(false, "The app is not installed");
finish();
};
}
function checkAppState(aApp,
aVersion,
aExpectedApp,
aLaunchable,
aUninstall,
aCb) {
debug(JSON.stringify(aApp, null, 2));
if (aApp.manifest) {
debug(JSON.stringify(aApp.manifest, null, 2));
}
if (aExpectedApp.name) {
if (aApp.manifest) {
is(aApp.manifest.name, aExpectedApp.name, "Check name");
}
is(aApp.updateManifest.name, aExpectedApp.name, "Check name mini-manifest");
}
if (aApp.manifest) {
is(aApp.manifest.version, aVersion, "Check version");
}
if (typeof aExpectedApp.size !== "undefined" && aApp.manifest) {
is(aApp.manifest.size, aExpectedApp.size, "Check size");
}
if (aApp.manifest) {
is(aApp.manifest.launch_path, gSJSPath, "Check launch path");
}
if (aExpectedApp.manifestURL) {
is(aApp.manifestURL, aExpectedApp.manifestURL, "Check manifestURL");
}
if (aExpectedApp.installOrigin) {
is(aApp.installOrigin, aExpectedApp.installOrigin, "Check installOrigin");
}
ok(aApp.removable, "Removable app");
if (typeof aExpectedApp.progress !== "undefined") {
todo(aApp.progress == aExpectedApp.progress, "Check progress");
}
if (aExpectedApp.installState) {
is(aApp.installState, aExpectedApp.installState, "Check installState");
}
if (typeof aExpectedApp.downloadAvailable !== "undefined") {
is(aApp.downloadAvailable, aExpectedApp.downloadAvailable,
"Check download available");
}
if (typeof aExpectedApp.downloading !== "undefined") {
is(aApp.downloading, aExpectedApp.downloading, "Check downloading");
}
if (typeof aExpectedApp.downloadSize !== "undefined") {
is(aApp.downloadSize, aExpectedApp.downloadSize, "Check downloadSize");
}
if (typeof aExpectedApp.readyToApplyDownload !== "undefined") {
is(aApp.readyToApplyDownload, aExpectedApp.readyToApplyDownload,
"Check readyToApplyDownload");
}
if (aLaunchable) {
if (aUninstall) {
checkUninstallApp(aApp);
} else if (aCb && typeof aCb === 'function') {
aCb();
}
return;
}
// Check if app is not launchable.
var req = aApp.launch();
req.onsuccess = function () {
ok(false, "We shouldn't be here");
finish();
};
req.onerror = function() {
ok(true, "App is not launchable");
if (aUninstall) {
checkUninstallApp(aApp);
} else if (aCb && typeof aCb === 'function') {
aCb();
}
return;
PackagedTestHelper.finish();
};
}
@ -268,17 +80,18 @@ SimpleTest.waitForExplicitFinish();
var steps = [
function() {
// Set up
launchableValue = SpecialPowers.setAllAppsLaunchable(true);
PackagedTestHelper.launchableValue =
SpecialPowers.setAllAppsLaunchable(true);
SpecialPowers.addPermission("webapps-manage", true, document);
ok(true, "Set up");
next();
PackagedTestHelper.next();
},
function() {
ok(true, "autoConfirmAppInstall");
SpecialPowers.autoConfirmAppInstall(next);
SpecialPowers.autoConfirmAppInstall(PackagedTestHelper.next);
},
function() {
setAppVersion(0, next);
PackagedTestHelper.setAppVersion(0, PackagedTestHelper.next);
},
function() {
// Test network error.
@ -288,7 +101,7 @@ var steps = [
function() {
// Test wrong mini-manifest content type.
ok(true, "== TEST == Not valid mini-manifest content type");
var miniManifestURL = gSJS +
var miniManifestURL = PackagedTestHelper.gSJS +
"?getManifest=true" +
"&noManifestContentType=true";
checkAppInstallError(miniManifestURL, "INVALID_MANIFEST");
@ -296,7 +109,7 @@ var steps = [
function() {
// Test mini-manifest 'size' value is not number. Bug 839435.
ok(true, "== TEST == Size value is not a number");
var miniManifestURL = gSJS +
var miniManifestURL = PackagedTestHelper.gSJS +
"?getManifest=true" +
"&packageSize=\"NotANumber\"";
checkAppInstallError(miniManifestURL, "INVALID_MANIFEST");
@ -304,7 +117,7 @@ var steps = [
function() {
// Test mini-manifest negative 'size' value. Bug 839435.
ok(true, "== TEST == Negative size value");
var miniManifestURL = gSJS +
var miniManifestURL = PackagedTestHelper.gSJS +
"?getManifest=true" +
"&packageSize=-1";
checkAppInstallError(miniManifestURL, "INVALID_MANIFEST");
@ -312,7 +125,7 @@ var steps = [
function() {
// Test wrong package path
ok(true, "== TEST == Installing app with wrong package path");
var miniManifestURL = gSJS +
var miniManifestURL = PackagedTestHelper.gSJS +
"?getManifest=true" +
"&wrongPackagePath=true";
checkAppInstallError(miniManifestURL, "INVALID_MANIFEST");
@ -320,91 +133,99 @@ var steps = [
function() {
// Test no manifest in zip file.
ok(true, "== TEST == No manifest in the zip file");
var miniManifestURL = gSJS + "?getManifest=true";
checkAppDownloadError(miniManifestURL, "MISSING_MANIFEST", 0, true, true,
gAppName);
var miniManifestURL = PackagedTestHelper.gSJS + "?getManifest=true";
PackagedTestHelper.checkAppDownloadError(miniManifestURL,
"MISSING_MANIFEST", 0, true, true,
PackagedTestHelper.gAppName);
},
function() {
setAppVersion(1, next);
PackagedTestHelper.setAppVersion(1, PackagedTestHelper.next);
},
function() {
// Test mini-manifest app name is different from the webapp manifest name.
// Bug 844243.
ok(true, "== TEST == Mini-manifest app name is different from webapp " +
"manifest name");
var miniManifestURL = gSJS +
var miniManifestURL = PackagedTestHelper.gSJS +
"?getManifest=true" +
"&appName=arandomname";
checkAppDownloadError(miniManifestURL, "MANIFEST_MISMATCH", 1, true, true,
"arandomname");
PackagedTestHelper.checkAppDownloadError(miniManifestURL,
"MANIFEST_MISMATCH", 1, true, true,
"arandomname");
},
function() {
// Test mini-manifest dev name is different from the webapp manifest dev
// name.
ok (true, "== TEST == Mini-manifest dev name is different from manifest " +
"dev name");
var miniManifestURL = gSJS +
var miniManifestURL = PackagedTestHelper.gSJS +
"?getManifest=true" +
"&devName=arandomdevname";
checkAppDownloadError(miniManifestURL, "MANIFEST_MISMATCH", 1, true, true,
gAppName);
PackagedTestHelper.checkAppDownloadError(miniManifestURL,
"MANIFEST_MISMATCH", 1, true, true,
PackagedTestHelper.gAppName);
},
function() {
// Test mini-manifest dev url is different from the webapp manifest dev
// url.
ok (true, "== TEST == Mini-manifest dev url is different from manifest " +
"dev url");
var miniManifestURL = gSJS +
var miniManifestURL = PackagedTestHelper.gSJS +
"?getManifest=true" +
"&devUrl=arandomdevurl";
checkAppDownloadError(miniManifestURL, "MANIFEST_MISMATCH", 1, true, true,
gAppName);
PackagedTestHelper.checkAppDownloadError(miniManifestURL,
"MANIFEST_MISMATCH", 1, true, true,
PackagedTestHelper.gAppName);
},
function() {
setAppVersion(2, next);
PackagedTestHelper.setAppVersion(2, PackagedTestHelper.next);
},
function() {
ok(true, "== TEST == Install packaged app");
var miniManifestURL = gSJS +
var miniManifestURL = PackagedTestHelper.gSJS +
"?getManifest=true";
navigator.mozApps.mgmt.oninstall = function(evt) {
ok(true, "Got oninstall event");
gApp = evt.application;
gApp.ondownloaderror = function() {
ok(false, "Download error " + gApp.downloadError.name);
finish();
PackagedTestHelper.gApp = evt.application;
PackagedTestHelper.gApp.ondownloaderror = function() {
ok(false, "Download error " +
PackagedTestHelper.gApp.downloadError.name);
PackagedTestHelper.finish();
};
gApp.ondownloadsuccess = function() {
PackagedTestHelper.gApp.ondownloadsuccess = function() {
ok(true, "App downloaded");
var expected = {
name: gAppName,
name: PackagedTestHelper.gAppName,
manifestURL: miniManifestURL,
installOrigin: gInstallOrigin,
installOrigin: PackagedTestHelper.gInstallOrigin,
progress: 0,
installState: "installed",
downloadAvailable: false,
downloading: false,
downloadSize: 0,
size: 0,
readyToApplyDownload: false,
readyToApplyDownload: false
};
checkAppState(gApp, 2, expected, true, false, next);
PackagedTestHelper.checkAppState(PackagedTestHelper.gApp, 2, expected,
true, false, PackagedTestHelper.next);
};
};
var request = navigator.mozApps.installPackage(miniManifestURL);
request.onerror = mozAppsError;
request.onerror = PackagedTestHelper.mozAppsError;
request.onsuccess = function() {
ok(true, "Application installed");
};
},
function() {
ok(true, "all done!\n");
SimpleTest.finish();
PackagedTestHelper.finish();
}
];
addLoadEvent(go);
PackagedTestHelper.setSteps(steps);
addLoadEvent(PackagedTestHelper.start);
</script>
</pre>

View File

@ -0,0 +1,192 @@
<!DOCTYPE html>
<html>
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id={900533}
-->
<head>
<title>Test for Bug {900533} Packaged app update tests</title>
<script type="text/javascript" src="/MochiKit/MochiKit.js"></script>
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<script type="text/javascript" src="test_packaged_app_common.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
</head>
<body>
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id={900533}">Mozilla Bug {900533}</a>
<p id="display"></p>
<div id="content" style="display: none">
</div>
<pre id="test">
<script class="testbody" type="text/javascript">
"use strict";
function debug(aMsg) {
//dump("== Tests debug == " + aMsg + "\n");
}
var miniManifestURL;
SimpleTest.waitForExplicitFinish();
function checkForUpdate(aExpected, aOnSuccess, aOnApplied, aLaunchDownload, aOnError) {
var lApp = PackagedTestHelper.gApp;
lApp.ondownloadsuccess = aOnSuccess || null;
lApp.ondownloadapplied = aOnApplied || null;
var request = lApp.checkForUpdate();
request.onerror = aOnError ? aOnError.bind(undefined, request) :
PackagedTestHelper.mozAppsError;
request.onsuccess = function(event) {
var expectingDownload = aExpected ? "": "not ";
ok(lApp.downloadAvailable === aExpected,
"Download should " + expectingDownload + "be available");
if (aLaunchDownload && lApp.downloadAvailable) {
lApp.download();
} else {
PackagedTestHelper.next();
}
};
}
function checkLastAppState(aMiniManifestURL, aExpectedReady, aExpectedDownload,
aExpectedVersion, aCb) {
ok(true, aExpectedReady ? "App downloaded" : "App download applied");
var expected = {
name: PackagedTestHelper.gAppName,
manifestURL: aMiniManifestURL,
installOrigin: PackagedTestHelper.gInstallOrigin,
progress: 0,
installState: aExpectedReady ? "updating" : "installed",
downloadAvailable: aExpectedDownload,
downloading: false,
size: 0,
readyToApplyDownload: aExpectedReady
};
PackagedTestHelper.checkAppState(PackagedTestHelper.gApp, aExpectedVersion,
expected, true, false, aCb);
}
function updateApp(aExpectedReady, aPreviousVersion, aNextVersion) {
var lApp = PackagedTestHelper.gApp;
var ondownloadappliedhandler =
checkLastAppState.bind(PackagedTestHelper, miniManifestURL, false, false,
aNextVersion, PackagedTestHelper.next);
var ondownloadsuccesshandler =
checkLastAppState.bind(undefined, miniManifestURL,
aExpectedReady, false, aPreviousVersion,
function() {
navigator.mozApps.mgmt.applyDownload(lApp);
});
checkForUpdate(true, ondownloadsuccesshandler, ondownloadappliedhandler,
true);
}
var steps = [
function() {
// Set up
PackagedTestHelper.launchableValue =
SpecialPowers.setAllAppsLaunchable(true);
SpecialPowers.addPermission("webapps-manage", true, document);
ok(true, "Set up");
PackagedTestHelper.next();
},
function() {
ok(true, "autoConfirmAppInstall");
SpecialPowers.autoConfirmAppInstall(PackagedTestHelper.next);
},
function() {
PackagedTestHelper.setAppVersion(2, PackagedTestHelper.next);
},
function() {
ok(true, "== TEST == Install packaged app");
navigator.mozApps.mgmt.oninstall = function(evt) {
ok(true, "Got oninstall event");
PackagedTestHelper.gApp = evt.application;
PackagedTestHelper.gApp.ondownloaderror = function() {
ok(false, "Download error " + PackagedTestHelper.gApp.downloadError.name);
PackagedTestHelper.finish();
};
PackagedTestHelper.gApp.ondownloadsuccess =
checkLastAppState.bind(undefined, miniManifestURL, false, false,
2, PackagedTestHelper.next);
};
var request = navigator.mozApps.installPackage(miniManifestURL);
request.onerror = PackagedTestHelper.mozAppsError;
request.onsuccess = function() {
ok(true, "Application installed");
};
},
function() {
PackagedTestHelper.setAppVersion(3, PackagedTestHelper.next);
},
function() {
ok(true, "== TEST == Update packaged app");
updateApp(true, 2, 3);
},
function() {
ok(true, "== TEST == Check for Update after getting a new package");
checkForUpdate(false);
},
function() {
PackagedTestHelper.setAppVersion(4, PackagedTestHelper.next, true);
},
function() {
ok(true, "== TEST == Update packaged app - same package");
updateApp(false, 3, 4);
},
function() {
ok(true, "== TEST == Check for Update after getting the same package");
checkForUpdate(false);
},
function() {
PackagedTestHelper.setAppVersion(1, PackagedTestHelper.next);
},
function() {
ok(true, "== TEST == Update packaged app - Updating a pending app");
miniManifestURL = PackagedTestHelper.gSJS +
"?getManifest=true" +
"&appName=arandomname" +
"&appToFail1";
PackagedTestHelper.checkAppDownloadError(miniManifestURL,
"MANIFEST_MISMATCH", 2, false, true,
"arandomname",
function () {
checkForUpdate(false, null, null, false,
function (request) {
if (request.error.name === "PENDING_APP_NOT_UPDATABLE") {
ok(true, "Got expected PENDING_APP_NOT_UPDATEABLE");
} else {
ok(false, "Got unexpected " + request.error.name);
}
PackagedTestHelper.next();
});
});
},
function() {
ok(true, "all done!\n");
PackagedTestHelper.finish();
}
];
PackagedTestHelper.setSteps(steps);
// appToUpdate added to the URL so we get a unique URL for this app.
// Unique in this case meaning different from the ones used on the
// install tests
miniManifestURL = PackagedTestHelper.gSJS + "?getManifest=true&appToUpdate";
addLoadEvent(PackagedTestHelper.start);
</script>
</pre>
</body>
</html>

View File

@ -54,7 +54,7 @@
#include "MediaManager.h"
#endif
#ifdef MOZ_B2G_RIL
#include "mozilla/dom/telephony/Telephony.h"
#include "mozilla/dom/Telephony.h"
#endif
#ifdef MOZ_B2G_BT
#include "BluetoothManager.h"
@ -1166,7 +1166,7 @@ Navigator::GetMozCellBroadcast(ErrorResult& aRv)
return mCellBroadcast;
}
telephony::Telephony*
Telephony*
Navigator::GetMozTelephony(ErrorResult& aRv)
{
if (!mTelephony) {
@ -1174,7 +1174,7 @@ Navigator::GetMozTelephony(ErrorResult& aRv)
aRv.Throw(NS_ERROR_UNEXPECTED);
return nullptr;
}
mTelephony = telephony::Telephony::Create(mWindow, aRv);
mTelephony = Telephony::Create(mWindow, aRv);
}
return mTelephony;
@ -1696,7 +1696,7 @@ bool
Navigator::HasTelephonySupport(JSContext* /* unused */, JSObject* aGlobal)
{
nsCOMPtr<nsPIDOMWindow> win = GetWindowFromGlobal(aGlobal);
return win && telephony::Telephony::CheckPermission(win);
return win && Telephony::CheckPermission(win);
}
/* static */

View File

@ -80,13 +80,6 @@ class MobileConnection;
#endif
} // namespace Connection;
#ifdef MOZ_B2G_RIL
namespace telephony {
class Telephony;
} // namespace Telephony;
class CellBroadcast;
#endif
#ifdef MOZ_B2G_BT
namespace bluetooth {
class BluetoothManager;
@ -94,6 +87,8 @@ class BluetoothManager;
#endif // MOZ_B2G_BT
#ifdef MOZ_B2G_RIL
class CellBroadcast;
class Telephony;
class Voicemail;
#endif
@ -223,7 +218,7 @@ public:
ErrorResult& aRv);
bool MozHasPendingMessage(const nsAString& aType, ErrorResult& aRv);
#ifdef MOZ_B2G_RIL
telephony::Telephony* GetMozTelephony(ErrorResult& aRv);
Telephony* GetMozTelephony(ErrorResult& aRv);
nsIDOMMozMobileConnection* GetMozMobileConnection(ErrorResult& aRv);
CellBroadcast* GetMozCellBroadcast(ErrorResult& aRv);
Voicemail* GetMozVoicemail(ErrorResult& aRv);
@ -328,7 +323,7 @@ private:
nsRefPtr<PowerManager> mPowerManager;
nsRefPtr<MobileMessageManager> mMobileMessageManager;
#ifdef MOZ_B2G_RIL
nsRefPtr<telephony::Telephony> mTelephony;
nsRefPtr<Telephony> mTelephony;
nsRefPtr<Voicemail> mVoicemail;
#endif
nsRefPtr<network::Connection> mConnection;

View File

@ -164,15 +164,9 @@ DOMInterfaces = {
'headerFile': 'BluetoothManager.h'
},
'CallEvent': {
'nativeType': 'mozilla::dom::telephony::CallEvent',
'headerFile': 'mozilla/dom/telephony/CallEvent.h',
},
'CallEvent': {},
'CallsList': {
'nativeType': 'mozilla::dom::telephony::CallsList',
'headerFile': 'mozilla/dom/telephony/CallsList.h',
},
'CallsList': {},
'CameraControl': {
'nativeType': 'mozilla::nsDOMCameraControl',
@ -1181,20 +1175,11 @@ DOMInterfaces = {
'concrete': False,
},
'Telephony' : {
'nativeType': 'mozilla::dom::telephony::Telephony',
'headerFile': 'mozilla/dom/telephony/Telephony.h',
},
'Telephony' : {},
'TelephonyCall' : {
'nativeType': 'mozilla::dom::telephony::TelephonyCall',
'headerFile': 'mozilla/dom/telephony/TelephonyCall.h',
},
'TelephonyCall' : {},
'TelephonyCallGroup' : {
'nativeType': 'mozilla::dom::telephony::TelephonyCallGroup',
'headerFile': 'mozilla/dom/telephony/TelephonyCallGroup.h',
},
'TelephonyCallGroup' : {},
'Text': {
# Total hack to allow binding code to realize that nsTextNode can

View File

@ -299,7 +299,6 @@ BluetoothA2dpManager::HandleSinkPropertyChanged(const BluetoothSignal& aSignal)
mA2dpConnected = true;
mDeviceAddress = address;
NotifyConnectionStatusChanged();
DispatchConnectionStatusChanged();
OnConnect(EmptyString());
break;
@ -319,7 +318,6 @@ BluetoothA2dpManager::HandleSinkPropertyChanged(const BluetoothSignal& aSignal)
mA2dpConnected = false;
NotifyConnectionStatusChanged();
DispatchConnectionStatusChanged();
mDeviceAddress.Truncate();
// case 7 only
@ -330,36 +328,11 @@ BluetoothA2dpManager::HandleSinkPropertyChanged(const BluetoothSignal& aSignal)
}
}
void
BluetoothA2dpManager::DispatchConnectionStatusChanged()
{
MOZ_ASSERT(NS_IsMainThread());
DispatchStatusChangedEvent(
NS_LITERAL_STRING(A2DP_STATUS_CHANGED_ID), mDeviceAddress, mA2dpConnected);
}
void
BluetoothA2dpManager::NotifyConnectionStatusChanged()
{
MOZ_ASSERT(NS_IsMainThread());
// Broadcast system message to Gaia
NS_NAMED_LITERAL_STRING(type, BLUETOOTH_A2DP_STATUS_CHANGED_ID);
InfallibleTArray<BluetoothNamedValue> parameters;
BluetoothValue v = mA2dpConnected;
parameters.AppendElement(
BluetoothNamedValue(NS_LITERAL_STRING("connected"), v));
v = mDeviceAddress;
parameters.AppendElement(
BluetoothNamedValue(NS_LITERAL_STRING("address"), v));
if (!BroadcastSystemMessage(type, parameters)) {
NS_WARNING("Failed to broadcast system message to settings");
}
// Notify Gecko observers
nsCOMPtr<nsIObserverService> obs =
do_GetService("@mozilla.org/observer-service;1");
@ -370,6 +343,10 @@ BluetoothA2dpManager::NotifyConnectionStatusChanged()
mDeviceAddress.get()))) {
NS_WARNING("Failed to notify bluetooth-a2dp-status-changed observsers!");
}
// Dispatch an event of status change
DispatchStatusChangedEvent(
NS_LITERAL_STRING(A2DP_STATUS_CHANGED_ID), mDeviceAddress, mA2dpConnected);
}
void

View File

@ -71,8 +71,6 @@ private:
bool Init();
void HandleShutdown();
void DispatchConnectionStatusChanged();
void NotifyConnectionStatusChanged();
nsString mDeviceAddress;

View File

@ -442,50 +442,11 @@ BluetoothHfpManager::Get()
return sBluetoothHfpManager;
}
void
BluetoothHfpManager::DispatchConnectionStatusChanged(const nsAString& aType)
{
MOZ_ASSERT(NS_IsMainThread());
bool status = false;
if (aType.EqualsLiteral(HFP_STATUS_CHANGED_ID)) {
status = IsConnected();
} else if (aType.EqualsLiteral(SCO_STATUS_CHANGED_ID)) {
status = IsScoConnected();
} else {
BT_WARNING("Wrong type for DispatchConnectionStatusChanged");
return;
}
DispatchStatusChangedEvent(aType, mDeviceAddress, status);
}
void
BluetoothHfpManager::NotifyConnectionStatusChanged(const nsAString& aType)
{
MOZ_ASSERT(NS_IsMainThread());
BluetoothValue v;
InfallibleTArray<BluetoothNamedValue> parameters;
nsString name = NS_LITERAL_STRING("connected");
if (aType.EqualsLiteral(BLUETOOTH_HFP_STATUS_CHANGED_ID)) {
v = IsConnected();
} else if (aType.EqualsLiteral(BLUETOOTH_SCO_STATUS_CHANGED_ID)) {
v = IsScoConnected();
} else {
BT_WARNING("Wrong type for NotifyConnectionStatusChanged");
return;
}
parameters.AppendElement(BluetoothNamedValue(name, v));
name.AssignLiteral("address");
v = mDeviceAddress;
parameters.AppendElement(BluetoothNamedValue(name, v));
if (!BroadcastSystemMessage(aType, parameters)) {
NS_WARNING("Failed to broadcast system message to settings");
}
// Notify Gecko observers
nsCOMPtr<nsIObserverService> obs =
do_GetService("@mozilla.org/observer-service;1");
@ -495,6 +456,22 @@ BluetoothHfpManager::NotifyConnectionStatusChanged(const nsAString& aType)
mDeviceAddress.get()))) {
NS_WARNING("Failed to notify observsers!");
}
// Dispatch an event of status change
bool status;
nsAutoString eventName;
if (aType.EqualsLiteral(BLUETOOTH_HFP_STATUS_CHANGED_ID)) {
status = IsConnected();
eventName.AssignLiteral(HFP_STATUS_CHANGED_ID);
} else if (aType.EqualsLiteral(BLUETOOTH_SCO_STATUS_CHANGED_ID)) {
status = IsScoConnected();
eventName.AssignLiteral(SCO_STATUS_CHANGED_ID);
} else {
MOZ_ASSERT(false);
return;
}
DispatchStatusChangedEvent(eventName, mDeviceAddress, status);
}
void
@ -1481,8 +1458,8 @@ BluetoothHfpManager::OnSocketConnectSuccess(BluetoothSocket* aSocket)
// Cache device path for NotifySettings() since we can't get socket address
// when a headset disconnect with us
mSocket->GetAddress(mDeviceAddress);
NotifyConnectionStatusChanged(NS_LITERAL_STRING(BLUETOOTH_HFP_STATUS_CHANGED_ID));
DispatchConnectionStatusChanged(NS_LITERAL_STRING(HFP_STATUS_CHANGED_ID));
NotifyConnectionStatusChanged(
NS_LITERAL_STRING(BLUETOOTH_HFP_STATUS_CHANGED_ID));
ListenSco();
@ -1522,8 +1499,8 @@ BluetoothHfpManager::OnSocketDisconnect(BluetoothSocket* aSocket)
DisconnectSco();
NotifyConnectionStatusChanged(NS_LITERAL_STRING(BLUETOOTH_HFP_STATUS_CHANGED_ID));
DispatchConnectionStatusChanged(NS_LITERAL_STRING(HFP_STATUS_CHANGED_ID));
NotifyConnectionStatusChanged(
NS_LITERAL_STRING(BLUETOOTH_HFP_STATUS_CHANGED_ID));
OnDisconnect(EmptyString());
Reset();
@ -1592,8 +1569,8 @@ BluetoothHfpManager::OnScoConnectSuccess()
mScoRunnable = nullptr;
}
NotifyConnectionStatusChanged(NS_LITERAL_STRING(BLUETOOTH_SCO_STATUS_CHANGED_ID));
DispatchConnectionStatusChanged(NS_LITERAL_STRING(SCO_STATUS_CHANGED_ID));
NotifyConnectionStatusChanged(
NS_LITERAL_STRING(BLUETOOTH_SCO_STATUS_CHANGED_ID));
mScoSocketStatus = mScoSocket->GetConnectionStatus();
}
@ -1616,8 +1593,8 @@ BluetoothHfpManager::OnScoDisconnect()
{
if (mScoSocketStatus == SocketConnectionStatus::SOCKET_CONNECTED) {
ListenSco();
NotifyConnectionStatusChanged(NS_LITERAL_STRING(BLUETOOTH_SCO_STATUS_CHANGED_ID));
DispatchConnectionStatusChanged(NS_LITERAL_STRING(SCO_STATUS_CHANGED_ID));
NotifyConnectionStatusChanged(
NS_LITERAL_STRING(BLUETOOTH_SCO_STATUS_CHANGED_ID));
}
}

View File

@ -121,9 +121,8 @@ private:
uint32_t FindFirstCall(uint16_t aState);
uint32_t GetNumberOfCalls(uint16_t aState);
void DispatchConnectionStatusChanged(const nsAString& aType);
void NotifyDialer(const nsAString& aCommand);
void NotifyConnectionStatusChanged(const nsAString& aType);
void NotifyDialer(const nsAString& aCommand);
bool SendCommand(const char* aCommand, uint32_t aValue = 0);
bool SendLine(const char* aMessage);

View File

@ -21,9 +21,10 @@ BluetoothProfileController::BluetoothProfileController(
const nsAString& aDeviceAddress,
BluetoothReplyRunnable* aRunnable,
BluetoothProfileControllerCallback aCallback)
: mDeviceAddress(aDeviceAddress)
: mCallback(aCallback)
, mDeviceAddress(aDeviceAddress)
, mRunnable(aRunnable)
, mCallback(aCallback)
, mSuccess(false)
{
MOZ_ASSERT(!aDeviceAddress.IsEmpty());
MOZ_ASSERT(aRunnable);
@ -152,7 +153,12 @@ BluetoothProfileController::ConnectNext()
// The action has been completed, so the dom request is replied and then
// the callback is invoked
DispatchBluetoothReply(mRunnable, BluetoothValue(true), EmptyString());
if (mSuccess) {
DispatchBluetoothReply(mRunnable, BluetoothValue(true), EmptyString());
} else {
DispatchBluetoothReply(mRunnable, BluetoothValue(),
NS_LITERAL_STRING(ERR_CONNECTION_FAILED));
}
mCallback();
}
@ -163,6 +169,8 @@ BluetoothProfileController::OnConnect(const nsAString& aErrorStr)
if (!aErrorStr.IsEmpty()) {
BT_WARNING(NS_ConvertUTF16toUTF8(aErrorStr).get());
} else {
mSuccess = true;
}
ConnectNext();
@ -203,7 +211,12 @@ BluetoothProfileController::DisconnectNext()
// The action has been completed, so the dom request is replied and then
// the callback is invoked
DispatchBluetoothReply(mRunnable, BluetoothValue(true), EmptyString());
if (mSuccess) {
DispatchBluetoothReply(mRunnable, BluetoothValue(true), EmptyString());
} else {
DispatchBluetoothReply(mRunnable, BluetoothValue(),
NS_LITERAL_STRING(ERR_DISCONNECTION_FAILED));
}
mCallback();
}
@ -214,6 +227,8 @@ BluetoothProfileController::OnDisconnect(const nsAString& aErrorStr)
if (!aErrorStr.IsEmpty()) {
BT_WARNING(NS_ConvertUTF16toUTF8(aErrorStr).get());
} else {
mSuccess = true;
}
DisconnectNext();

View File

@ -93,10 +93,11 @@ private:
int8_t mProfilesIndex;
nsTArray<BluetoothProfileManagerBase*> mProfiles;
BluetoothProfileControllerCallback mCallback;
uint32_t mCod;
nsString mDeviceAddress;
nsRefPtr<BluetoothReplyRunnable> mRunnable;
BluetoothProfileControllerCallback mCallback;
bool mSuccess;
};
END_BLUETOOTH_NAMESPACE

View File

@ -14,6 +14,8 @@
*/
#define ERR_ALREADY_CONNECTED "AlreadyConnectedError"
#define ERR_ALREADY_DISCONNECTED "AlreadyDisconnectedError"
#define ERR_CONNECTION_FAILED "ConnectionFailedError"
#define ERR_DISCONNECTION_FAILED "DisconnectionFailedError"
#define ERR_NO_AVAILABLE_RESOURCE "NoAvailableResourceError"
#define ERR_REACHED_CONNECTION_LIMIT "ReachedConnectionLimitError"
#define ERR_SERVICE_CHANNEL_NOT_FOUND "DeviceChannelRetrievalError"

View File

@ -11,7 +11,7 @@
* We expose Gecko-internal helpers related to "web apps" through this
* sub-interface.
*/
[scriptable, uuid(05c57885-27cf-47fc-8da7-eeec9eb853a7)]
[scriptable, uuid(11322d0c-e98e-442d-97a6-8b197d5b888e)]
interface mozIApplication: mozIDOMApplication
{
/* Return true if this app has |permission|. */
@ -40,4 +40,7 @@ interface mozIApplication: mozIDOMApplication
/* Store version if the app is installed from a store */
readonly attribute unsigned long storeVersion;
/* role copied from the manifest */
readonly attribute DOMString role;
};

View File

@ -427,8 +427,11 @@ TabChild::Observe(nsISupports *aSubject,
mLastMetrics.mZoom = mLastMetrics.CalculateIntrinsicScale();
// We use ScreenToLayerScale(1) below in order to turn the
// async zoom amount into the gecko zoom amount.
mLastMetrics.mResolution =
mLastMetrics.mCumulativeResolution =
mLastMetrics.mZoom / mLastMetrics.mDevPixelsPerCSSPixel * ScreenToLayerScale(1);
// This is the root layer, so the cumulative resolution is the same
// as the resolution.
mLastMetrics.mResolution = mLastMetrics.mCumulativeResolution / LayoutDeviceToParentLayerScale(1);
mLastMetrics.mScrollOffset = CSSPoint(0, 0);
utils->SetResolution(mLastMetrics.mResolution.scale,
@ -692,7 +695,10 @@ TabChild::HandlePossibleViewportChange()
// new CSS viewport, so we know that there's no velocity, acceleration, and
// we have no idea how long painting will take.
metrics, gfx::Point(0.0f, 0.0f), gfx::Point(0.0f, 0.0f), 0.0);
metrics.mResolution = metrics.mZoom / metrics.mDevPixelsPerCSSPixel * ScreenToLayerScale(1);
metrics.mCumulativeResolution = metrics.mZoom / metrics.mDevPixelsPerCSSPixel * ScreenToLayerScale(1);
// This is the root layer, so the cumulative resolution is the same
// as the resolution.
metrics.mResolution = metrics.mCumulativeResolution / LayoutDeviceToParentLayerScale(1);
utils->SetResolution(metrics.mResolution.scale, metrics.mResolution.scale);
// Force a repaint with these metrics. This, among other things, sets the
@ -1616,8 +1622,10 @@ TabChild::ProcessUpdateFrame(const FrameMetrics& aFrameMetrics)
}
// set the resolution
LayoutDeviceToLayerScale resolution = aFrameMetrics.mZoom
/ aFrameMetrics.mDevPixelsPerCSSPixel * ScreenToLayerScale(1);
ParentLayerToLayerScale resolution = aFrameMetrics.mZoom
/ aFrameMetrics.mDevPixelsPerCSSPixel
/ aFrameMetrics.GetParentResolution()
* ScreenToLayerScale(1);
utils->SetResolution(resolution.scale, resolution.scale);
// and set the display port

View File

@ -37,21 +37,9 @@ this.SystemMessagePermissionsTable = {
"bluetooth-cancel": {
"bluetooth": []
},
"bluetooth-pairedstatuschanged": {
"bluetooth": []
},
"bluetooth-a2dp-status-changed": {
"bluetooth": []
},
"bluetooth-hfp-status-changed": {
"bluetooth": []
},
"bluetooth-hid-status-changed": {
"bluetooth": []
},
"bluetooth-sco-status-changed": {
"bluetooth": []
},
"bluetooth-pairing-request": {
"bluetooth": []
},
@ -99,6 +87,9 @@ this.SystemMessagePermissionsTable = {
"wappush-received": {
"wappush": []
},
"cdma-info-rec-received": {
"mobileconnection": []
},
};
this.SystemMessagePermissionsChecker = {

View File

@ -2,35 +2,6 @@
# 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/.
VPATH = \
$(srcdir) \
$(srcdir)/ipc \
$(NULL)
ifeq (android,$(MOZ_WIDGET_TOOLKIT))
VPATH += $(srcdir)/android
else ifdef MOZ_B2G_RIL
VPATH += $(srcdir)/gonk
else
VPATH += $(srcdir)/fallback
endif
include $(topsrcdir)/dom/dom-config.mk
LOCAL_INCLUDES = \
-I$(topsrcdir)/content/events/src \
-I$(topsrcdir)/dom/base \
$(NULL)
# Add VPATH to LOCAL_INCLUDES so we are going to include the correct backend
# subdirectory (and the ipc one).
LOCAL_INCLUDES += $(VPATH:%=-I%)
ifdef MOZ_B2G_RIL
LOCAL_INCLUDES += \
-I$(topsrcdir)/dom/system/gonk \
$(NULL)
endif
include $(topsrcdir)/config/rules.mk
include $(topsrcdir)/ipc/chromium/chromium-config.mk

View File

@ -8,11 +8,11 @@
#include "jsapi.h" // For OBJECT_TO_JSVAL and JS_NewDateObjectMsec
#include "jsfriendapi.h" // For js_DateGetMsecSinceEpoch
#include "nsJSUtils.h"
#include "Constants.h"
#include "nsContentUtils.h"
#include "nsIDOMFile.h"
#include "nsTArrayHelpers.h"
#include "mozilla/dom/ContentParent.h"
#include "mozilla/dom/mobilemessage/Constants.h" // For MessageType
#include "mozilla/dom/mobilemessage/SmsTypes.h"
#include "nsDOMFile.h"

Some files were not shown because too many files have changed in this diff Show More