Skip to content

Commit

Permalink
Firefox WebExtension Support - Part 2
Browse files Browse the repository at this point in the history
  • Loading branch information
teddyzeenny committed Sep 22, 2017
1 parent faf6828 commit 21b91dc
Show file tree
Hide file tree
Showing 19 changed files with 259 additions and 389 deletions.
24 changes: 10 additions & 14 deletions Gruntfile.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,6 @@ module.exports = function(grunt) {
var config = {
pkg: packageJson,
env: process.env,
"jpm": {
options: {
src: "dist/firefox",
xpi: "tmp/xpi"
}
},
"s3": {
options: {
bucket: 'ember-extension',
Expand All @@ -29,14 +23,22 @@ module.exports = function(grunt) {
}
},
"compress": {
main: {
chrome: {
options: {
archive: 'dist/chrome/ember-inspector.zip'
},
expand: true,
pretty: true,
src: 'dist/chrome/**/*'
},
firefox: {
options: {
archive: 'dist/firefox/ember-inspector.zip'
},
expand: true,
pretty: true,
src: 'dist/firefox/**/*'
},
"chrome-pane": {
options: {
archive: 'dist/chrome-pane.zip'
Expand All @@ -52,7 +54,7 @@ module.exports = function(grunt) {
},
expand: true,
pretty: true,
cwd: 'dist/firefox/data/' + versionedPane,
cwd: 'dist/firefox/' + versionedPane,
src: ['**/*']
},
"bookmarklet-pane": {
Expand All @@ -68,15 +70,9 @@ module.exports = function(grunt) {
};

grunt.initConfig(config);

grunt.loadNpmTasks('grunt-jpm');
grunt.loadNpmTasks('grunt-s3');
grunt.loadNpmTasks('grunt-contrib-compress');

grunt.registerTask('build-xpi', ['jpm:xpi']);

grunt.registerTask('run-xpi', ['jpm:run']);

grunt.registerTask('clean-tmp', function() {
grunt.file.delete('./tmp');
});
Expand Down
119 changes: 9 additions & 110 deletions app/adapters/chrome.js
Original file line number Diff line number Diff line change
@@ -1,122 +1,21 @@
/* globals chrome */
import BasicAdapter from "./basic";
import Ember from 'ember';
import config from 'ember-inspector/config/environment';
const { computed } = Ember;

let emberDebug = null;

export default BasicAdapter.extend({
/**
* Called when the adapter is created.
*
* @method init
*/
init() {
this._connect();
this._handleReload();
this._injectDebugger();
return this._super(...arguments);
},
import WebExtension from "./web-extension";

export default WebExtension.extend({
name: 'chrome',

sendMessage(options) {
options = options || {};
this.get('_chromePort').postMessage(options);
},

_chromePort: computed(function() {
return chrome.extension.connect();
}),

_connect() {
let chromePort = this.get('_chromePort');
chromePort.postMessage({ appId: chrome.devtools.inspectedWindow.tabId });

chromePort.onMessage.addListener(message => {
if (typeof message.type === 'string' && message.type === 'iframes') {
sendIframes(message.urls);
}
this._messageReceived(message);
});
},
canOpenResource: true,

_handleReload() {
let self = this;
chrome.devtools.network.onNavigated.addListener(function() {
self._injectDebugger();
location.reload(true);
});
openResource(file, line) {
/*global chrome */
// For some reason it opens the line after the one specified
chrome.devtools.panels.openResource(file, line - 1);
},

_injectDebugger() {
chrome.devtools.inspectedWindow.eval(loadEmberDebug());
onResourceAdded() {
chrome.devtools.inspectedWindow.onResourceAdded.addListener(function(opts) {
if (opts.type === 'document') {
sendIframes([opts.url]);
this.sendIframes([opts.url]);
}
});
},

willReload() {
this._injectDebugger();
},

/**
* Open the devtools "Elements" tab and select a specific DOM element.
*
* @method inspectDOMElement
* @param {String} selector jQuery selector
*/
inspectDOMElement(selector) {
chrome.devtools.inspectedWindow.eval(`inspect($('${selector}')[0])`);
},

/**
* Redirect to the correct inspector version.
*
* @method onVersionMismatch
* @param {String} goToVersion
*/
onVersionMismatch(goToVersion) {
window.location.href = `../panes-${goToVersion.replace(/\./g, '-')}/index.html`;
},

/**
We handle the reload here so we can inject
scripts as soon as possible into the new page.
*/
reloadTab() {
chrome.devtools.inspectedWindow.reload({
injectedScript: loadEmberDebug()
});
},

canOpenResource: true,

openResource(file, line) {
/*global chrome */
// For some reason it opens the line after the one specified
chrome.devtools.panels.openResource(file, line - 1);
}

});

function sendIframes(urls) {
urls.forEach(url => {
chrome.devtools.inspectedWindow.eval(loadEmberDebug(), { frameURL: url });
});
}

function loadEmberDebug() {
let minimumVersion = config.emberVersionsSupported[0].replace(/\./g, '-');
let xhr;
if (!emberDebug) {
xhr = new XMLHttpRequest();
xhr.open("GET", chrome.extension.getURL(`/panes-${minimumVersion}/ember_debug.js`), false);
xhr.send();
emberDebug = xhr.responseText;
}
return emberDebug;
}
79 changes: 3 additions & 76 deletions app/adapters/firefox.js
Original file line number Diff line number Diff line change
@@ -1,78 +1,5 @@
import Ember from "ember";
import BasicAdapter from "./basic";

export default BasicAdapter.extend({
name: 'firefox',

/**
* Called when the adapter is created.
*
* @method init
*/
init() {
this._connect();
return this._super(...arguments);
},

sendMessage(options) {
options = options || {};
window.parent.postMessage(options, "*");
},

/**
* Redirects to the correct inspector version.
* Also re-injects the correct EmberDebug version.
*
* @method onVersionMismatch
* @param {String} goToVersion
*/
onVersionMismatch(version) {
this.sendMessage({ type: `injectEmberDebug`, version });
window.location.href = `../panes-${version.replace(/\./g, '-')}/index.html`;
},

_connect() {
// NOTE: chrome adapter sends a appId message on connect (not needed on firefox)
//this.sendMessage({ appId: "test" });
this._onMessage = this._onMessage.bind(this);
window.addEventListener("message", this._onMessage, false);
},

_onMessage(evt) {
if (this.isDestroyed || this.isDestroying) {
window.removeEventListener("message", this._onMessage, false);
return;
}

const message = evt.data;
// check if the event is originated by our privileged ember inspector code
if (evt.isTrusted) {
if (typeof message.type === 'string' && message.type === 'iframes') {
this._sendIframes(message.urls);
} else {
// We clone the object so that Ember prototype extensions
// are applied.
this._messageReceived(Ember.$.extend(true, {}, message));
}
} else {
console.log("EMBER INSPECTOR: ignored post message", evt);
}
},

_sendIframes(urls) {
urls.forEach(url => {
this.sendMessage({ type: 'injectEmberDebug', frameURL: url });
});
},

canOpenResource: true,

openResource(file, line) {
this.sendMessage({
type: 'devtools:openSource',
url: file,
line
});
}
import WebExtension from "./web-extension";

export default WebExtension.extend({
name: 'firefox'
});
113 changes: 113 additions & 0 deletions app/adapters/web-extension.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
/* globals chrome */
import BasicAdapter from "./basic";
import Ember from 'ember';
import config from 'ember-inspector/config/environment';
const { computed } = Ember;

let emberDebug = null;

export default BasicAdapter.extend({
/**
* Called when the adapter is created.
*
* @method init
*/
init() {
this._connect();
this._handleReload();
this._injectDebugger();
return this._super(...arguments);
},

name: 'web-extension',

sendMessage(options) {
options = options || {};
this.get('_chromePort').postMessage(options);
},

_chromePort: computed(function() {
return chrome.runtime.connect();
}),

_connect() {
let chromePort = this.get('_chromePort');
chromePort.postMessage({ appId: chrome.devtools.inspectedWindow.tabId });

chromePort.onMessage.addListener(message => {
if (typeof message.type === 'string' && message.type === 'iframes') {
this.sendIframes(message.urls);
}
this._messageReceived(message);
});
},

_handleReload() {
let self = this;
chrome.devtools.network.onNavigated.addListener(function() {
self._injectDebugger();
location.reload(true);
});
},

_injectDebugger() {
chrome.devtools.inspectedWindow.eval(loadEmberDebug());
this.onResourceAdded();
},

onResourceAdded(/*callback*/) {},

willReload() {
this._injectDebugger();
},

/**
* Open the devtools "Elements" tab and select a specific DOM element.
*
* @method inspectDOMElement
* @param {String} selector jQuery selector
*/
inspectDOMElement(selector) {
chrome.devtools.inspectedWindow.eval(`inspect($('${selector}')[0])`);
},

/**
* Redirect to the correct inspector version.
*
* @method onVersionMismatch
* @param {String} goToVersion
*/
onVersionMismatch(goToVersion) {
window.location.href = `../panes-${goToVersion.replace(/\./g, '-')}/index.html`;
},

/**
We handle the reload here so we can inject
scripts as soon as possible into the new page.
*/
reloadTab() {
chrome.devtools.inspectedWindow.reload({
injectedScript: loadEmberDebug()
});
},

canOpenResource: false,

sendIframes(urls) {
urls.forEach(url => {
chrome.devtools.inspectedWindow.eval(loadEmberDebug(), { frameURL: url });
});
}
});

function loadEmberDebug() {
let minimumVersion = config.emberVersionsSupported[0].replace(/\./g, '-');
let xhr;
if (!emberDebug) {
xhr = new XMLHttpRequest();
xhr.open("GET", chrome.runtime.getURL(`/panes-${minimumVersion}/ember_debug.js`), false);
xhr.send();
emberDebug = xhr.responseText;
}
return emberDebug;
}
Loading

0 comments on commit 21b91dc

Please sign in to comment.