Created
October 21, 2013 16:02
-
-
Save bebef1987/7086369 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* 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'; | |
var GaiaApps = { | |
normalizeName: function(name) { | |
return name.replace(/[- ]+/g, '').toLowerCase(); | |
}, | |
getRunningApps: function() { | |
let runningApps = window.wrappedJSObject.WindowManager.getRunningApps(); | |
// Return a simplified version of the runningApps object which can be | |
// JSON-serialized. | |
let apps = {}; | |
for (let app in runningApps) { | |
let anApp = {}; | |
for (let key in runningApps[app]) { | |
if (["name", "origin", "manifest"].indexOf(key) > -1) { | |
anApp[key] = runningApps[app][key]; | |
} | |
} | |
apps[app] = anApp; | |
} | |
return apps; | |
}, | |
getRunningAppOrigin: function(name) { | |
let runningApps = window.wrappedJSObject.WindowManager.getRunningApps(); | |
let origin; | |
for (let property in runningApps) { | |
if (runningApps[property].name == name) { | |
origin = property; | |
} | |
} | |
return origin; | |
}, | |
getPermission: function(appName, permissionName) { | |
GaiaApps.locateWithName(appName, function(app) { | |
console.log("Getting permission '" + permissionName + "' for " + appName); | |
var mozPerms = navigator.mozPermissionSettings; | |
var result = mozPerms.get( | |
permissionName, app.manifestURL, app.origin, false | |
); | |
marionetteScriptFinished(result); | |
}); | |
}, | |
setPermission: function(appName, permissionName, value) { | |
GaiaApps.locateWithName(appName, function(app) { | |
console.log("Setting permission '" + permissionName + "' for " + | |
appName + "to '" + value + "'"); | |
var mozPerms = navigator.mozPermissionSettings; | |
mozPerms.set( | |
permissionName, value, app.manifestURL, app.origin, false | |
); | |
marionetteScriptFinished(); | |
}); | |
}, | |
locateWithName: function(name, aCallback) { | |
var callback = aCallback || marionetteScriptFinished; | |
function sendResponse(app, appName, entryPoint) { | |
if (callback === marionetteScriptFinished) { | |
if (typeof(app) === 'object') { | |
var result = { | |
name: app.manifest.name, | |
origin: app.origin, | |
entryPoint: entryPoint || null, | |
normalizedName: appName | |
}; | |
callback(result); | |
} else { | |
callback(false); | |
} | |
} else { | |
callback(app, appName, entryPoint); | |
} | |
} | |
let appsReq = navigator.mozApps.mgmt.getAll(); | |
appsReq.onsuccess = function() { | |
let apps = appsReq.result; | |
let normalizedSearchName = GaiaApps.normalizeName(name); | |
for (let i = 0; i < apps.length; i++) { | |
let app = apps[i]; | |
let origin = null; | |
let entryPoints = app.manifest.entry_points; | |
if (entryPoints) { | |
for (let ep in entryPoints) { | |
let currentEntryPoint = entryPoints[ep]; | |
let appName = currentEntryPoint.name; | |
if (normalizedSearchName === GaiaApps.normalizeName(appName)) { | |
return sendResponse(app, appName, ep); | |
} | |
} | |
} else { | |
let appName = app.manifest.name; | |
if (normalizedSearchName === GaiaApps.normalizeName(appName)) { | |
return sendResponse(app, appName); | |
} | |
} | |
} | |
callback(false); | |
} | |
}, | |
// Returns the number of running apps. | |
numRunningApps: function() { | |
let count = 0; | |
let runningApps = window.wrappedJSObject.WindowManager.getRunningApps(); | |
for (let origin in runningApps) { | |
count++; | |
} | |
return count; | |
}, | |
// Kills the specified app. | |
kill: function(aOrigin, aCallback) { | |
var callback = aCallback || marionetteScriptFinished; | |
let runningApps = window.wrappedJSObject.WindowManager.getRunningApps(); | |
if (!runningApps.hasOwnProperty(aOrigin)) { | |
callback(false); | |
} | |
else { | |
window.addEventListener('appterminated', function gt_onAppTerminated() { | |
window.removeEventListener('appterminated', gt_onAppTerminated); | |
waitFor( | |
function() { | |
console.log("app with origin '" + aOrigin + "' has terminated"); | |
callback(true); | |
}, | |
function() { | |
let runningApps = | |
window.wrappedJSObject.WindowManager.getRunningApps(); | |
return !runningApps.hasOwnProperty(aOrigin); | |
} | |
); | |
}); | |
console.log("terminating app with origin '" + aOrigin + "'"); | |
window.wrappedJSObject.WindowManager.kill(aOrigin); | |
} | |
}, | |
// Kills all running apps, except the homescreen. | |
killAll: function() { | |
let originsToClose = []; | |
let that = this; | |
let runningApps = window.wrappedJSObject.WindowManager.getRunningApps(); | |
for (let origin in runningApps) { | |
if (origin.indexOf('homescreen') == -1) { | |
originsToClose.push(origin); | |
} | |
} | |
if (!originsToClose.length) { | |
marionetteScriptFinished(true); | |
return; | |
} | |
originsToClose.slice(0).forEach(function(origin) { | |
GaiaApps.kill(origin, function() {}); | |
}); | |
// Even after the 'appterminated' event has been fired for an app, | |
// it can still exist in the apps list, so wait until 1 or fewer | |
// apps are running (since we don't close the homescreen app). | |
waitFor( | |
function() { marionetteScriptFinished(true); }, | |
function() { return that.numRunningApps() <= 1; } | |
); | |
}, | |
// Launches app with the specified name (e.g., 'Calculator'); returns the | |
// app frame's id if successful, false if the app can't be found, or times | |
// out if the app frame can't be found after launching the app. | |
launchWithName: function(name) { | |
GaiaApps.locateWithName(name, function(app, appName, entryPoint) { | |
if (app) { | |
let windowManager = window.wrappedJSObject.WindowManager; | |
let runningApps = windowManager.getRunningApps(); | |
let origin = GaiaApps.getRunningAppOrigin(appName); | |
let sendResponse = function() { | |
let app = runningApps[origin]; | |
let result = {frame: app.frame.firstChild, | |
src: app.iframe.src, | |
name: app.name, | |
origin: origin}; | |
marionetteScriptFinished(result); | |
}; | |
if (windowManager.getDisplayedApp() == origin) { | |
console.log("app with origin '" + origin + "' is already running"); | |
sendResponse(); | |
} | |
else { | |
window.addEventListener('apploadtime', function apploadtime() { | |
window.removeEventListener('apploadtime', apploadtime); | |
waitFor( | |
function() { | |
console.log("app with origin '" + origin + "' has launched"); | |
sendResponse(); | |
}, | |
function() { | |
origin = GaiaApps.getRunningAppOrigin(appName); | |
return windowManager.getDisplayedApp() == origin; | |
} | |
); | |
}); | |
console.log("launching app with name '" + appName + "'"); | |
app.launch(entryPoint || null); | |
} | |
} else { | |
marionetteScriptFinished(false); | |
} | |
}); | |
}, | |
/** | |
* Returns the currently displayed app. | |
*/ | |
displayedApp: function() { | |
let windowManager = window.wrappedJSObject.WindowManager; | |
let runningApps = windowManager.getRunningApps(); | |
let origin = windowManager.getDisplayedApp(); | |
console.log("app with origin '" + origin + "' is displayed"); | |
let app = runningApps[origin]; | |
let result = {frame: app.frame.firstChild, | |
src: app.iframe.src, | |
name: app.name, | |
origin: origin}; | |
marionetteScriptFinished(result); | |
}, | |
/** | |
* Uninstalls the app with the specified name. | |
*/ | |
uninstallWithName: function(name) { | |
GaiaApps.locateWithName(name, function uninstall(app) { | |
navigator.mozApps.mgmt.uninstall(app); | |
marionetteScriptFinished(false); | |
}); | |
} | |
}; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class GaiaApps(object): | |
def __init__(self, marionette): | |
self.marionette = marionette | |
js = os.path.abspath(os.path.join(__file__, os.path.pardir, 'atoms', "gaia_apps.js")) | |
self.marionette.import_script(js) | |
def get_permission(self, app_name, permission_name): | |
return self.marionette.execute_async_script("return GaiaApps.getPermission('%s', '%s')" % (app_name, permission_name)) | |
def set_permission(self, app_name, permission_name, value): | |
return self.marionette.execute_async_script("return GaiaApps.setPermission('%s', '%s', '%s')" % | |
(app_name, permission_name, value)) | |
def launch(self, name, switch_to_frame=True, url=None, launch_timeout=None): | |
self.marionette.switch_to_frame() | |
result = self.marionette.execute_async_script("GaiaApps.launchWithName('%s')" % name, script_timeout=launch_timeout) | |
assert result, "Failed to launch app with name '%s'" % name | |
app = GaiaApp(frame=result.get('frame'), | |
src=result.get('src'), | |
name=result.get('name'), | |
origin=result.get('origin')) | |
if app.frame_id is None: | |
raise Exception("App failed to launch; there is no app frame") | |
if switch_to_frame: | |
self.switch_to_frame(app.frame_id, url) | |
return app | |
@property | |
def displayed_app(self): | |
self.marionette.switch_to_frame() | |
result = self.marionette.execute_async_script('return GaiaApps.displayedApp();') | |
return GaiaApp(frame=result.get('frame'), | |
src=result.get('src'), | |
name=result.get('name'), | |
origin=result.get('origin')) | |
def is_app_installed(self, app_name): | |
self.marionette.switch_to_frame() | |
return self.marionette.execute_async_script("GaiaApps.locateWithName('%s')" % app_name) | |
def uninstall(self, name): | |
self.marionette.switch_to_frame() | |
self.marionette.execute_async_script("GaiaApps.uninstallWithName('%s')" % name) | |
def kill(self, app): | |
self.marionette.switch_to_frame() | |
js = os.path.abspath(os.path.join(__file__, os.path.pardir, 'atoms', "gaia_apps.js")) | |
self.marionette.import_script(js) | |
result = self.marionette.execute_async_script("GaiaApps.kill('%s');" % app.origin) | |
assert result, "Failed to kill app with name '%s'" % app.name | |
def kill_all(self): | |
self.marionette.switch_to_frame() | |
js = os.path.abspath(os.path.join(__file__, os.path.pardir, 'atoms', "gaia_apps.js")) | |
self.marionette.import_script(js) | |
self.marionette.execute_async_script("GaiaApps.killAll()") | |
def runningApps(self): | |
return self.marionette.execute_script("return GaiaApps.getRunningApps()") | |
def switch_to_frame(self, app_frame, url=None, timeout=30): | |
self.marionette.switch_to_frame(app_frame) | |
start = time.time() | |
if not url: | |
def check(now): | |
return "about:blank" not in now | |
else: | |
def check(now): | |
return url in now | |
while (time.time() - start < timeout): | |
if check(self.marionette.get_url()): | |
return | |
time.sleep(2) | |
raise TimeoutException('Could not switch to app frame %s in time' % app_frame) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment