mirror of
https://github.com/mozilla/gecko-dev.git
synced 2025-01-30 01:59:29 +00:00
Bug 771980: provider must be re-usable, r=jaws
--HG-- extra : transplant_source : s%94%84%C2%7C%27%A3%B0%DB%5B%7F%40%96%A4S%21%FFcSA
This commit is contained in:
parent
2c31655232
commit
ed5fdc5f5a
@ -3621,3 +3621,5 @@ pref("memory.low_memory_notification_interval_ms", 10000);
|
|||||||
// likely leak)? This should be longer than it usually takes for an eligible
|
// likely leak)? This should be longer than it usually takes for an eligible
|
||||||
// window to be collected via the GC/CC.
|
// window to be collected via the GC/CC.
|
||||||
pref("memory.ghost_window_timeout_seconds", 60);
|
pref("memory.ghost_window_timeout_seconds", 60);
|
||||||
|
|
||||||
|
pref("social.enabled", false);
|
||||||
|
@ -18,8 +18,9 @@ const EXPORTED_SYMBOLS = ["SocialProvider"];
|
|||||||
*
|
*
|
||||||
* @constructor
|
* @constructor
|
||||||
* @param {jsobj} object representing the manifest file describing this provider
|
* @param {jsobj} object representing the manifest file describing this provider
|
||||||
|
* @param {bool} whether the provider should be initially enabled (defaults to true)
|
||||||
*/
|
*/
|
||||||
function SocialProvider(input) {
|
function SocialProvider(input, enabled) {
|
||||||
if (!input.name)
|
if (!input.name)
|
||||||
throw new Error("SocialProvider must be passed a name");
|
throw new Error("SocialProvider must be passed a name");
|
||||||
if (!input.origin)
|
if (!input.origin)
|
||||||
@ -29,16 +30,53 @@ function SocialProvider(input) {
|
|||||||
this.workerURL = input.workerURL;
|
this.workerURL = input.workerURL;
|
||||||
this.origin = input.origin;
|
this.origin = input.origin;
|
||||||
|
|
||||||
let workerAPIPort = this.getWorkerPort();
|
// If enabled is |undefined|, default to true.
|
||||||
if (workerAPIPort)
|
this._enabled = !(enabled == false);
|
||||||
this.workerAPI = new WorkerAPI(workerAPIPort);
|
if (this._enabled)
|
||||||
|
this._activate();
|
||||||
}
|
}
|
||||||
|
|
||||||
SocialProvider.prototype = {
|
SocialProvider.prototype = {
|
||||||
/**
|
// Provider enabled/disabled state. Disabled providers do not have active
|
||||||
* Terminates the provider's FrameWorker, if it has one.
|
// connections to their FrameWorkers.
|
||||||
*/
|
_enabled: true,
|
||||||
terminate: function terminate() {
|
get enabled() {
|
||||||
|
return this._enabled;
|
||||||
|
},
|
||||||
|
set enabled(val) {
|
||||||
|
let enable = !!val;
|
||||||
|
if (enable == this._enabled)
|
||||||
|
return;
|
||||||
|
|
||||||
|
this._enabled = enable;
|
||||||
|
|
||||||
|
if (enable) {
|
||||||
|
this._activate();
|
||||||
|
} else {
|
||||||
|
this._terminate();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
// Active port to the provider's FrameWorker. Null if the provider has no
|
||||||
|
// FrameWorker, or is disabled.
|
||||||
|
port: null,
|
||||||
|
|
||||||
|
// Reference to a workerAPI object for this provider. Null if the provider has
|
||||||
|
// no FrameWorker, or is disabled.
|
||||||
|
workerAPI: null,
|
||||||
|
|
||||||
|
// Internal helper methods
|
||||||
|
_activate: function _activate() {
|
||||||
|
// Initialize the workerAPI and its port first, so that its initialization
|
||||||
|
// occurs before any other messages are processed by other ports.
|
||||||
|
let workerAPIPort = this._getWorkerPort();
|
||||||
|
if (workerAPIPort)
|
||||||
|
this.workerAPI = new WorkerAPI(workerAPIPort);
|
||||||
|
|
||||||
|
this.port = this._getWorkerPort();
|
||||||
|
},
|
||||||
|
|
||||||
|
_terminate: function _terminate() {
|
||||||
if (this.workerURL) {
|
if (this.workerURL) {
|
||||||
try {
|
try {
|
||||||
getFrameWorkerHandle(this.workerURL, null).terminate();
|
getFrameWorkerHandle(this.workerURL, null).terminate();
|
||||||
@ -46,18 +84,20 @@ SocialProvider.prototype = {
|
|||||||
Cu.reportError("SocialProvider FrameWorker termination failed: " + e);
|
Cu.reportError("SocialProvider FrameWorker termination failed: " + e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
this.port = null;
|
||||||
|
this.workerAPI = null;
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Instantiates a FrameWorker for the provider if one doesn't exist, and
|
* Instantiates a FrameWorker for the provider if one doesn't exist, and
|
||||||
* returns a reference to a port to that FrameWorker.
|
* returns a reference to a new port to that FrameWorker.
|
||||||
*
|
*
|
||||||
* Returns null if this provider has no workerURL.
|
* Returns null if this provider has no workerURL, or is disabled.
|
||||||
*
|
*
|
||||||
* @param {DOMWindow} window (optional)
|
* @param {DOMWindow} window (optional)
|
||||||
*/
|
*/
|
||||||
getWorkerPort: function getWorkerPort(window) {
|
_getWorkerPort: function _getWorkerPort(window) {
|
||||||
if (!this.workerURL)
|
if (!this.workerURL || !this.enabled)
|
||||||
return null;
|
return null;
|
||||||
try {
|
try {
|
||||||
return getFrameWorkerHandle(this.workerURL, window).port;
|
return getFrameWorkerHandle(this.workerURL, window).port;
|
||||||
|
@ -10,30 +10,68 @@ Cu.import("resource://gre/modules/Services.jsm");
|
|||||||
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||||
Cu.import("resource://gre/modules/SocialProvider.jsm");
|
Cu.import("resource://gre/modules/SocialProvider.jsm");
|
||||||
|
|
||||||
const MANIFEST_PREFS = Services.prefs.getBranch("social.manifest.");
|
// Internal helper methods and state
|
||||||
|
let SocialServiceInternal = {
|
||||||
let SocialServiceInternal = {};
|
enabled: Services.prefs.getBoolPref("social.enabled"),
|
||||||
|
get providerArray() {
|
||||||
|
return [p for ([, p] of Iterator(this.providers))];
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
XPCOMUtils.defineLazyGetter(SocialServiceInternal, "providers", function () {
|
XPCOMUtils.defineLazyGetter(SocialServiceInternal, "providers", function () {
|
||||||
|
// Initialize the service (add a pref observer)
|
||||||
|
function prefObserver(subject, topic, data) {
|
||||||
|
SocialService._setEnabled(Services.prefs.getBoolPref(data));
|
||||||
|
}
|
||||||
|
Services.prefs.addObserver("social.enabled", prefObserver, false);
|
||||||
|
Services.obs.addObserver(function xpcomShutdown() {
|
||||||
|
Services.obs.removeObserver(xpcomShutdown, "xpcom-shutdown");
|
||||||
|
Services.prefs.removeObserver("social.enabled", prefObserver);
|
||||||
|
}, "xpcom-shutdown", false);
|
||||||
|
|
||||||
|
// Now retrieve the providers
|
||||||
let providers = {};
|
let providers = {};
|
||||||
|
let MANIFEST_PREFS = Services.prefs.getBranch("social.manifest.");
|
||||||
let prefs = MANIFEST_PREFS.getChildList("", {});
|
let prefs = MANIFEST_PREFS.getChildList("", {});
|
||||||
prefs.forEach(function (pref) {
|
prefs.forEach(function (pref) {
|
||||||
try {
|
try {
|
||||||
var manifest = JSON.parse(MANIFEST_PREFS.getCharPref(pref));
|
var manifest = JSON.parse(MANIFEST_PREFS.getCharPref(pref));
|
||||||
if (manifest && typeof(manifest) == "object") {
|
if (manifest && typeof(manifest) == "object") {
|
||||||
let provider = new SocialProvider(manifest);
|
let provider = new SocialProvider(manifest, SocialServiceInternal.enabled);
|
||||||
providers[provider.origin] = provider;
|
providers[provider.origin] = provider;
|
||||||
}
|
}
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
Cu.reportError("SocialService: failed to load provider: " + pref +
|
Cu.reportError("SocialService: failed to load provider: " + pref +
|
||||||
", exception: " + err);
|
", exception: " + err);
|
||||||
}
|
}
|
||||||
}, this);
|
});
|
||||||
|
|
||||||
return providers;
|
return providers;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
function schedule(callback) {
|
||||||
|
Services.tm.mainThread.dispatch(callback, Ci.nsIThread.DISPATCH_NORMAL);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Public API
|
||||||
const SocialService = {
|
const SocialService = {
|
||||||
|
get enabled() {
|
||||||
|
return SocialServiceInternal.enabled;
|
||||||
|
},
|
||||||
|
set enabled(val) {
|
||||||
|
let enable = !!val;
|
||||||
|
if (enable == SocialServiceInternal.enabled)
|
||||||
|
return;
|
||||||
|
|
||||||
|
Services.prefs.setBoolPref("social.enabled", enable);
|
||||||
|
this._setEnabled(enable);
|
||||||
|
},
|
||||||
|
_setEnabled: function _setEnabled(enable) {
|
||||||
|
SocialServiceInternal.providerArray.forEach(function (p) p.enabled = enable);
|
||||||
|
SocialServiceInternal.enabled = enable;
|
||||||
|
},
|
||||||
|
|
||||||
|
// Returns a single provider object with the specified origin.
|
||||||
getProvider: function getProvider(origin, onDone) {
|
getProvider: function getProvider(origin, onDone) {
|
||||||
schedule((function () {
|
schedule((function () {
|
||||||
onDone(SocialServiceInternal.providers[origin] || null);
|
onDone(SocialServiceInternal.providers[origin] || null);
|
||||||
@ -42,13 +80,8 @@ const SocialService = {
|
|||||||
|
|
||||||
// Returns an array of installed provider origins.
|
// Returns an array of installed provider origins.
|
||||||
getProviderList: function getProviderList(onDone) {
|
getProviderList: function getProviderList(onDone) {
|
||||||
let providers = [p for each (p in SocialServiceInternal.providers)];
|
schedule(function () {
|
||||||
schedule((function () {
|
onDone(SocialServiceInternal.providerArray);
|
||||||
onDone(providers);
|
});
|
||||||
}).bind(this));
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
function schedule(callback) {
|
|
||||||
Services.tm.mainThread.dispatch(callback, Ci.nsIThread.DISPATCH_NORMAL);
|
|
||||||
}
|
|
||||||
|
@ -21,6 +21,7 @@ MOCHITEST_BROWSER_FILES = \
|
|||||||
relative_import.js \
|
relative_import.js \
|
||||||
browser_workerAPI.js \
|
browser_workerAPI.js \
|
||||||
worker_social.js \
|
worker_social.js \
|
||||||
|
browser_SocialProvider.js \
|
||||||
$(NULL)
|
$(NULL)
|
||||||
|
|
||||||
include $(topsrcdir)/config/rules.mk
|
include $(topsrcdir)/config/rules.mk
|
||||||
|
@ -0,0 +1,35 @@
|
|||||||
|
/* 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/. */
|
||||||
|
|
||||||
|
let SocialProvider = Components.utils.import("resource://gre/modules/SocialProvider.jsm", {}).SocialProvider;
|
||||||
|
|
||||||
|
function test() {
|
||||||
|
// This test creates a SocialProvider object directly - it would be nicer to
|
||||||
|
// go through the SocialService, but adding a test provider before the service
|
||||||
|
// has been initialized can be tricky.
|
||||||
|
let provider = new SocialProvider({
|
||||||
|
origin: 'http://example.com',
|
||||||
|
name: "Example Provider",
|
||||||
|
workerURL: "http://example.com/browser/toolkit/components/social/test/browser/worker_social.js"
|
||||||
|
});
|
||||||
|
|
||||||
|
ok(provider.enabled, "provider is initially enabled");
|
||||||
|
ok(provider.port, "should be able to get a port from enabled provider");
|
||||||
|
ok(provider.workerAPI, "should be able to get a workerAPI from enabled provider");
|
||||||
|
|
||||||
|
provider.enabled = false;
|
||||||
|
|
||||||
|
ok(!provider.enabled, "provider is now disabled");
|
||||||
|
ok(!provider.port, "shouldn't be able to get a port from disabled provider");
|
||||||
|
ok(!provider.workerAPI, "shouldn't be able to get a workerAPI from disabled provider");
|
||||||
|
|
||||||
|
provider.enabled = true;
|
||||||
|
|
||||||
|
ok(provider.enabled, "provider is re-enabled");
|
||||||
|
ok(provider.port, "should be able to get a port from re-enabled provider");
|
||||||
|
ok(provider.workerAPI, "should be able to get a workerAPI from re-enabled provider");
|
||||||
|
|
||||||
|
// Terminate the provider
|
||||||
|
provider.enabled = false;
|
||||||
|
}
|
@ -19,14 +19,15 @@ function test() {
|
|||||||
ok(provider.workerAPI, "provider has a workerAPI");
|
ok(provider.workerAPI, "provider has a workerAPI");
|
||||||
is(provider.workerAPI.initialized, false, "workerAPI is not yet initialized");
|
is(provider.workerAPI.initialized, false, "workerAPI is not yet initialized");
|
||||||
|
|
||||||
let port = provider.getWorkerPort();
|
let port = provider.port;
|
||||||
ok(port, "should be able to get a port from the provider");
|
ok(port, "should be able to get a port from the provider");
|
||||||
|
|
||||||
port.onmessage = function onMessage(event) {
|
port.onmessage = function onMessage(event) {
|
||||||
let {topic, data} = event.data;
|
let {topic, data} = event.data;
|
||||||
if (topic == "test-initialization-complete") {
|
if (topic == "test-initialization-complete") {
|
||||||
is(provider.workerAPI.initialized, true, "workerAPI is now initialized");
|
is(provider.workerAPI.initialized, true, "workerAPI is now initialized");
|
||||||
provider.terminate();
|
// Terminate the provider
|
||||||
|
provider.enabled = false;
|
||||||
finish();
|
finish();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,6 +2,8 @@
|
|||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
* 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/. */
|
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
|
Cu.import("resource://gre/modules/Services.jsm");
|
||||||
|
|
||||||
function run_test() {
|
function run_test() {
|
||||||
let manifests = [
|
let manifests = [
|
||||||
{ // normal provider
|
{ // normal provider
|
||||||
@ -18,14 +20,16 @@ function run_test() {
|
|||||||
manifests.forEach(function (manifest) {
|
manifests.forEach(function (manifest) {
|
||||||
MANIFEST_PREFS.setCharPref(manifest.origin, JSON.stringify(manifest));
|
MANIFEST_PREFS.setCharPref(manifest.origin, JSON.stringify(manifest));
|
||||||
});
|
});
|
||||||
do_register_cleanup(function () MANIFEST_PREFS.deleteBranch(""));
|
|
||||||
|
|
||||||
|
// Enable the service for this test
|
||||||
|
Services.prefs.setBoolPref("social.enabled", true);
|
||||||
Cu.import("resource://gre/modules/SocialService.jsm");
|
Cu.import("resource://gre/modules/SocialService.jsm");
|
||||||
|
|
||||||
let runner = new AsyncRunner();
|
let runner = new AsyncRunner();
|
||||||
let next = runner.next.bind(runner);
|
let next = runner.next.bind(runner);
|
||||||
runner.appendIterator(testGetProvider(manifests, next));
|
runner.appendIterator(testGetProvider(manifests, next));
|
||||||
runner.appendIterator(testGetProviderList(manifests, next));
|
runner.appendIterator(testGetProviderList(manifests, next));
|
||||||
|
runner.appendIterator(testEnabled(manifests, next));
|
||||||
runner.next();
|
runner.next();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -48,7 +52,31 @@ function testGetProviderList(manifests, next) {
|
|||||||
let providerIdx = providers.map(function (p) p.origin).indexOf(manifests[i].origin);
|
let providerIdx = providers.map(function (p) p.origin).indexOf(manifests[i].origin);
|
||||||
let provider = providers[providerIdx];
|
let provider = providers[providerIdx];
|
||||||
do_check_true(!!provider);
|
do_check_true(!!provider);
|
||||||
|
do_check_true(provider.enabled);
|
||||||
do_check_eq(provider.workerURL, manifests[i].workerURL);
|
do_check_eq(provider.workerURL, manifests[i].workerURL);
|
||||||
do_check_eq(provider.name, manifests[i].name);
|
do_check_eq(provider.name, manifests[i].name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function testEnabled(manifests, next) {
|
||||||
|
let providers = yield SocialService.getProviderList(next);
|
||||||
|
do_check_true(providers.length >= manifests.length);
|
||||||
|
do_check_true(SocialService.enabled);
|
||||||
|
providers.forEach(function (provider) {
|
||||||
|
do_check_true(provider.enabled);
|
||||||
|
});
|
||||||
|
|
||||||
|
SocialService.enabled = false;
|
||||||
|
do_check_true(!Services.prefs.getBoolPref("social.enabled"));
|
||||||
|
do_check_true(!SocialService.enabled);
|
||||||
|
providers.forEach(function (provider) {
|
||||||
|
do_check_true(!provider.enabled);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Check that setting the pref directly updates things accordingly
|
||||||
|
Services.prefs.setBoolPref("social.enabled", true);
|
||||||
|
do_check_true(SocialService.enabled);
|
||||||
|
providers.forEach(function (provider) {
|
||||||
|
do_check_true(provider.enabled);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user