Skip to content
This repository has been archived by the owner on Nov 3, 2021. It is now read-only.

Commit

Permalink
Merge pull request #9069 from KevinGrandon/vingtetun-desktop-helper
Browse files Browse the repository at this point in the history
Bug 847566 - Developing in the browser is painful. r=kgrandon
  • Loading branch information
KevinGrandon committed Apr 9, 2013
2 parents e0c0f9d + c21bbaa commit 68efb2e
Show file tree
Hide file tree
Showing 24 changed files with 1,451 additions and 0 deletions.
8 changes: 8 additions & 0 deletions build/preferences.js
Expand Up @@ -45,12 +45,20 @@ if (DEBUG) {

prefs.push(["dom.mozBrowserFramesEnabled", true]);
prefs.push(["b2g.ignoreXFrameOptions", true]);
prefs.push(["network.disable.ipc.security", true]);
prefs.push(["dom.sms.enabled", true]);
prefs.push(["dom.mozContacts.enabled", true]);
prefs.push(["dom.mozSettings.enabled", true]);
prefs.push(["dom.mozTCPSocket.enabled", true]);
prefs.push(["device.storage.enabled", true]);
prefs.push(["devtools.chrome.enabled", true]);
prefs.push(["webgl.verbose", true]);
prefs.push(["ui.click_hold_context_menus", true]);

// Disable HTTP caching for now
// This makes working with the system app much easier, due to the iframe
// caching issue.
prefs.push(['network.http.use-cache', false]);

// Preferences for httpd
// (Use JSON.stringify in order to avoid taking care of `\` escaping)
Expand Down
80 changes: 80 additions & 0 deletions tools/extensions/desktop-helper/bootstrap.js
@@ -0,0 +1,80 @@
/* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- /
/* vim: set shiftwidth=2 tabstop=2 autoindent cindent expandtab: */

'use strict';

function debug(data) {
dump('desktop-helper: ' + data + '\n');
}

function startup(data, reason) {
const CC = Components.Constructor;
const Cc = Components.classes;
const Ci = Components.interfaces;
const Cu = Components.utils;

Cu.import('resource://gre/modules/Services.jsm');
Cu.import('resource://gre/modules/PermissionPromptHelper.jsm');
Cu.import('resource://gre/modules/ContactService.jsm');

/**
* Mappings of permissions we need to add to the chrome
* XXX This should be replaced by a manifest parser
*/
const kPermissions = {
browser: ['browser', 'systemXHR', 'settings-read', 'geolocation', 'desktop-notification'],
calendar: ['systemXHR', 'tcp-socket'],
camera: ['camera'],
communications: ['contacts-read', 'contacts-write', 'contacts-create', 'settings-read', 'settings-write'],
email: ['contacts-read', 'contacts-write', 'desktop-notification', 'settings-read', 'settings-write', 'systemXHR', 'tcp-socket'],
homescreen: ['settings-read', 'settings-write', 'systemXHR', 'tcp-socket', 'webapps-manage'],
gallery: ['settings-read', 'device-storage:pictures-read', 'device-storage:pictures-write'],
keyboard: ['settings-read', 'settings-write', 'keyboard'],
system: ['settings-read', 'settings-write', 'webapps-manage'],
sms: ['contacts-read', 'contacts-write', 'contacts-create']
};

try {
// Add permissions
for (var app in kPermissions) {
// XXX The domain name should be generic to not be tied to gaiamobile.org
// and the random port number.
var host = 'http://' + app + '.gaiamobile.org:8080';
var uri = Services.io.newURI(host, null, null);

var perms = kPermissions[app];
for (var i = 0, eachPerm; eachPerm = perms[i]; i++) {
Services.perms.add(uri, eachPerm, 1);
}
}

// Then inject the missing contents inside apps.
Cc["@mozilla.org/globalmessagemanager;1"]
.getService(Ci.nsIMessageBroadcaster)
.loadFrameScript("chrome://desktop-helper.js/content/content.js", true);

// Start the responsive UI
Services.obs.addObserver(function() {
let browserWindow = Services.wm.getMostRecentWindow('navigator:browser');
let args = {'width': 320, 'height': 480};
let mgr = browserWindow.ResponsiveUI.ResponsiveUIManager;
mgr.handleGcliCommand(browserWindow,
browserWindow.gBrowser.selectedTab,
'resize to',
args);
}, 'sessionstore-windows-restored', false)

} catch(e) {
debug("Something went wrong while trying to start desktop-helper: " + e);
}
}

function shutdown(data, reason) {
}

function install(data, reason) {
}

function uninstall(data, reason) {
}

1 change: 1 addition & 0 deletions tools/extensions/desktop-helper/chrome.manifest
@@ -0,0 +1 @@
content desktop-helper.js content/
121 changes: 121 additions & 0 deletions tools/extensions/desktop-helper/content/content.js
@@ -0,0 +1,121 @@

dump("======== desktop-helper: content.js loaded ========\n")

function debug(str) {
dump("desktop-helper (frame-script): " + str + "\n");
}

const CC = Components.Constructor;
const Cc = Components.classes;
const Ci = Components.interfaces;
const Cu = Components.utils;
const Cr = Components.results;

Cu.import('resource://gre/modules/Services.jsm');

const kChromeRootPath = 'chrome://desktop-helper.js/content/data/';

// XXX Scripts should be loaded based on the permissions of the apps not
// based on the domain.
const kScriptsPerDomain = {
'.gaiamobile.org': [
'ffos_runtime.js',
'hardware.js',
'lib/activity.js',
'lib/apps.js',
'lib/bluetooth.js',
'lib/cameras.js',
'lib/getdevicestorage.js',
'lib/idle.js',
'lib/keyboard.js',
'lib/mobile_connection.js',
'lib/power.js',
'lib/set_message_handler.js',
'lib/settings.js',
'lib/wifi.js'
],

// App specific includes
'.communications.gaiamobile.org': [
'workloads/contacts.js'
],

'.sms.gaiamobile.org': [
'workloads/contacts.js'
],

'.fm.gaiamobile.org': [
'apps/fm.js'
],

'.homescreen.gaiamobile.org' :[
'apps/homescreen.js'
],

'.calendar.gaiamobile.org': [
'lib/alarm.js'
]
};


var LoadListener = {
init: function ll_init() {
let flags = Ci.nsIWebProgress.NOTIFY_LOCATION |
Ci.nsIWebProgress.NOTIFY_STATE_WINDOW |
Ci.nsIWebProgress.NOTIFY_STATE_DOCUMENT |
Ci.nsIWebProgress.NOTIFY_STATE_ALL;
let webProgress = docShell.QueryInterface(Ci.nsIInterfaceRequestor)
.getInterface(Ci.nsIWebProgress);
webProgress.addProgressListener(this, flags);
},

onStateChange: function ll_onStateChange(webProgress, request, stateFlags, status) {
this.onPageLoad(webProgress.DOMWindow);
},

onLocationChange: function ll_locationChange(webProgress, request, locationURI, flags) {
this.onPageLoad(webProgress.DOMWindow);
},

onPageLoad: function ll_onPageLoad(currentWindow) {
// XXX Right now the progress listener is really agressive and try to inject
// mocks/content/whatever on way too many operations.
if (currentWindow.alreadyMocked)
return;
currentWindow.alreadyMocked = true;

try {
let currentDomain = currentWindow.location.toString();
if (currentDomain == 'about:blank')
return;

debug('loading scripts for app: ' + currentDomain);
for (let domain in kScriptsPerDomain) {
if (currentDomain.indexOf(domain) == -1)
continue;

let includes = kScriptsPerDomain[domain];
for (let i = 0; i < includes.length; i++) {
debug('loading ' + includes[i] + '...');

Services.scriptloader.loadSubScript(kChromeRootPath + includes[i],
currentWindow.wrappedJSObject);
}
}
} catch(e) {
debug(e);
}
},

QueryInterface: function ll_QueryInterface(iid) {
if (iid.equals(Ci.nsIWebProgressListener) ||
iid.equals(Ci.nsISupportsWeakReference) ||
iid.equals(Ci.nsISupports)) {
return this;
}
throw Cr.NS_ERROR_NO_INTERFACE;
}
};

LoadListener.init();

11 changes: 11 additions & 0 deletions tools/extensions/desktop-helper/content/data/apps/fm.js
@@ -0,0 +1,11 @@
!function() {

if (!(/fm.gaiamobile.org/.test(location.href))) { return }

// FM radio has a hidden body attribute for some reason?
// Remove it so we can at least use the UI
// TODO: Figure out why this is needed
setTimeout(function() {
window.document.body.removeAttribute('hidden');
}, 500);
}();
21 changes: 21 additions & 0 deletions tools/extensions/desktop-helper/content/data/apps/homescreen.js
@@ -0,0 +1,21 @@
/**
* Special Homescreen App message behavior
*/
!function() {

// Hack to disable context menus so we can move icons on the homescreen
setTimeout(function() {

function addListener(el) {
el.addEventListener('contextmenu', function(e) {
e.preventDefault();
});
}

var allLists = window.document.querySelectorAll('ol');

for (var i = 0, ilen = allLists.length; i < ilen; i++) {
addListener(allLists[i]);
}
}, 1000);
}();
110 changes: 110 additions & 0 deletions tools/extensions/desktop-helper/content/data/ffos_runtime.js
@@ -0,0 +1,110 @@
FFOS_RUNTIME = {

/**
* This is so we have a single entry-point for the APP window
* This is needed as the interface to window may be changing soon
*/
getAppWindow: function(callback) {
callback(window);
},

/**
* Proxies console.log statements to the app window
*/
debug: function() {
var args = Array.slice(arguments);

this.getAppWindow(function(win) {
win.console.log.apply(win.console, args);
});
},

/**
* Creates a navigator shim on the window
* @param {String} property name.
* @param {Object} property definition.
* @param {Boolean} if true, makes a navigator setter for this object. Useful for testing.
*/
makeNavigatorShim: function(property, definition, makeSetter) {
try {
window.navigator.__defineGetter__(property, function() {
return definition;
});

if (makeSetter) {
window.navigator.__defineSetter__(property, function(prop) {
definition = prop;
});
}

} catch (e) {
alert('Error intializing shim (' + property + '): ' + e);
}
},

/**
* Sends an event to the system frame
* This is frame independent, and can be triggered from the system app itself
* @param {Object} The e.detail object passed to the event.
*/
sendFrameEvent: function(data) {

var eventDetail = {
detail: data
};

var targetFrame;
if (/system.gaiamobile.org/.test(location.href)) {
targetFrame = window;
var evtObject = new CustomEvent('mozChromeEvent', eventDetail);
window.dispatchEvent(evtObject);

return;
}

targetFrame = parent;

targetFrame.postMessage({
action: 'dispatchMessage',
payload: eventDetail
}, 'http://system.gaiamobile.org:8080');

}
};
var debug = FFOS_RUNTIME.debug;

/**
* Special System App message behavior
*/
if (/system.gaiamobile.org/.test(location.href)) {

/**
* Handle messages for mozChromeEvent from iframes
*/
window.addEventListener('message', function(e) {

if (e.data.action == 'dispatchMessage') {
FFOS_RUNTIME.getAppWindow(function(win) {
var evtObject = new CustomEvent('mozChromeEvent', e.data.payload);
win.dispatchEvent(evtObject);
});
}
});
}

FFOS_RUNTIME.getAppWindow(function(win) {
/**
* Adds a nextPaintListener
* Proxies to setTimeout
**/
win.HTMLIFrameElement.prototype.addNextPaintListener = function(callback) {
setTimeout(callback, 100);
};

/**
* Remove the nextPaintListener
**/
win.HTMLIFrameElement.prototype.removeNextPaintListener = function(callback) {

};
});

0 comments on commit 68efb2e

Please sign in to comment.