mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 770695: land support for Social "service window" - chromeless window opened by social provider, r=gavin
--HG-- extra : rebase_source : a3994283b352378358ad3c0a8de1fa7c3c984a2d
This commit is contained in:
parent
7c29aed7d0
commit
447632fc11
@ -261,6 +261,7 @@ _BROWSER_FILES = \
|
||||
browser_social_mozSocial_API.js \
|
||||
social_panel.html \
|
||||
social_sidebar.html \
|
||||
social_window.html \
|
||||
social_worker.js \
|
||||
$(NULL)
|
||||
|
||||
|
@ -10,7 +10,6 @@ function test() {
|
||||
ok(true, "can't run social sidebar test in debug builds because they falsely report leaks");
|
||||
return;
|
||||
}
|
||||
|
||||
waitForExplicitFinish();
|
||||
|
||||
let manifest = { // normal provider
|
||||
@ -20,68 +19,116 @@ function test() {
|
||||
workerURL: "http://example.com/browser/browser/base/content/test/social_worker.js",
|
||||
iconURL: "chrome://branding/content/icon48.png"
|
||||
};
|
||||
runSocialTestWithProvider(manifest, doTest);
|
||||
runSocialTestWithProvider(manifest, function () {
|
||||
runSocialTests(tests, undefined, undefined, function () {
|
||||
SocialService.removeProvider(Social.provider.origin, finish);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function doTest() {
|
||||
let iconsReady = false;
|
||||
let gotSidebarMessage = false;
|
||||
var tests = {
|
||||
testStatusIcons: function(next) {
|
||||
let iconsReady = false;
|
||||
let gotSidebarMessage = false;
|
||||
|
||||
function checkNext() {
|
||||
if (iconsReady && gotSidebarMessage)
|
||||
triggerIconPanel();
|
||||
}
|
||||
function checkNext() {
|
||||
if (iconsReady && gotSidebarMessage)
|
||||
triggerIconPanel();
|
||||
}
|
||||
|
||||
function triggerIconPanel() {
|
||||
let statusIcons = document.getElementById("social-status-iconbox");
|
||||
ok(!statusIcons.firstChild.collapsed, "status icon is visible");
|
||||
// Click the button to trigger its contentPanel
|
||||
let panel = document.getElementById("social-notification-panel");
|
||||
EventUtils.synthesizeMouseAtCenter(statusIcons.firstChild, {});
|
||||
}
|
||||
function triggerIconPanel() {
|
||||
let statusIcons = document.getElementById("social-status-iconbox");
|
||||
ok(!statusIcons.firstChild.collapsed, "status icon is visible");
|
||||
// Click the button to trigger its contentPanel
|
||||
let panel = document.getElementById("social-notification-panel");
|
||||
EventUtils.synthesizeMouseAtCenter(statusIcons.firstChild, {});
|
||||
}
|
||||
|
||||
let port = Social.provider.port;
|
||||
ok(port, "provider has a port");
|
||||
port.postMessage({topic: "test-init"});
|
||||
Social.provider.port.onmessage = function (e) {
|
||||
let topic = e.data.topic;
|
||||
switch (topic) {
|
||||
case "got-panel-message":
|
||||
ok(true, "got panel message");
|
||||
// Wait for the panel to close before ending the test
|
||||
let panel = document.getElementById("social-notification-panel");
|
||||
panel.addEventListener("popuphidden", function hiddenListener() {
|
||||
panel.removeEventListener("popuphidden", hiddenListener);
|
||||
SocialService.removeProvider(Social.provider.origin, finish);
|
||||
let port = Social.provider.port;
|
||||
ok(port, "provider has a port");
|
||||
port.postMessage({topic: "test-init"});
|
||||
Social.provider.port.onmessage = function (e) {
|
||||
let topic = e.data.topic;
|
||||
switch (topic) {
|
||||
case "got-panel-message":
|
||||
ok(true, "got panel message");
|
||||
// Wait for the panel to close before ending the test
|
||||
let panel = document.getElementById("social-notification-panel");
|
||||
panel.addEventListener("popuphidden", function hiddenListener() {
|
||||
panel.removeEventListener("popuphidden", hiddenListener);
|
||||
next();
|
||||
});
|
||||
panel.hidePopup();
|
||||
break;
|
||||
case "got-sidebar-message":
|
||||
// The sidebar message will always come first, since it loads by default
|
||||
ok(true, "got sidebar message");
|
||||
gotSidebarMessage = true;
|
||||
checkNext();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Our worker sets up ambient notification at the same time as it responds to
|
||||
// the workerAPI initialization. If it's already initialized, we can
|
||||
// immediately check the icons, otherwise wait for initialization by
|
||||
// observing the topic sent out by the social service.
|
||||
if (Social.provider.workerAPI.initialized) {
|
||||
iconsReady = true;
|
||||
checkNext();
|
||||
} else {
|
||||
Services.obs.addObserver(function obs() {
|
||||
Services.obs.removeObserver(obs, "social:ambient-notification-changed");
|
||||
// Let the other observers (like the one that updates the UI) run before
|
||||
// checking the icons.
|
||||
executeSoon(function () {
|
||||
iconsReady = true;
|
||||
checkNext();
|
||||
});
|
||||
panel.hidePopup();
|
||||
break;
|
||||
case "got-sidebar-message":
|
||||
// The sidebar message will always come first, since it loads by default
|
||||
ok(true, "got sidebar message");
|
||||
info(topic);
|
||||
gotSidebarMessage = true;
|
||||
checkNext();
|
||||
break;
|
||||
}, "social:ambient-notification-changed", false);
|
||||
}
|
||||
},
|
||||
|
||||
testServiceWindow: function(next) {
|
||||
// our test provider was initialized in the test above, we just
|
||||
// initiate our specific test now.
|
||||
let port = Social.provider.port;
|
||||
ok(port, "provider has a port");
|
||||
port.postMessage({topic: "test-service-window"});
|
||||
port.onmessage = function (e) {
|
||||
let topic = e.data.topic;
|
||||
switch (topic) {
|
||||
case "got-service-window-message":
|
||||
// The sidebar message will always come first, since it loads by default
|
||||
ok(true, "got service window message");
|
||||
port.postMessage({topic: "test-close-service-window"});
|
||||
break;
|
||||
case "got-service-window-closed-message":
|
||||
ok(true, "got service window closed message");
|
||||
next();
|
||||
break;
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
testServiceWindowTwice: function(next) {
|
||||
let port = Social.provider.port;
|
||||
port.postMessage({topic: "test-service-window-twice"});
|
||||
Social.provider.port.onmessage = function (e) {
|
||||
let topic = e.data.topic;
|
||||
switch (topic) {
|
||||
case "test-service-window-twice-result":
|
||||
is(e.data.result, "ok", "only one window should open when name is reused");
|
||||
break;
|
||||
case "got-service-window-message":
|
||||
ok(true, "got service window message");
|
||||
port.postMessage({topic: "test-close-service-window"});
|
||||
break;
|
||||
case "got-service-window-closed-message":
|
||||
ok(true, "got service window closed message");
|
||||
next();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Our worker sets up ambient notification at the same time as it responds to
|
||||
// the workerAPI initialization. If it's already initialized, we can
|
||||
// immediately check the icons, otherwise wait for initialization by
|
||||
// observing the topic sent out by the social service.
|
||||
if (Social.provider.workerAPI.initialized) {
|
||||
iconsReady = true;
|
||||
checkNext();
|
||||
} else {
|
||||
Services.obs.addObserver(function obs() {
|
||||
Services.obs.removeObserver(obs, "social:ambient-notification-changed");
|
||||
// Let the other observers (like the one that updates the UI) run before
|
||||
// checking the icons.
|
||||
executeSoon(function () {
|
||||
iconsReady = true;
|
||||
checkNext();
|
||||
});
|
||||
}, "social:ambient-notification-changed", false);
|
||||
}
|
||||
}
|
||||
|
@ -14,7 +14,7 @@ function test() {
|
||||
iconURL: "chrome://branding/content/icon48.png"
|
||||
};
|
||||
runSocialTestWithProvider(manifest, function () {
|
||||
runTests(tests, undefined, undefined, function () {
|
||||
runSocialTests(tests, undefined, undefined, function () {
|
||||
SocialService.removeProvider(Social.provider.origin, finish);
|
||||
});
|
||||
});
|
||||
@ -74,42 +74,3 @@ var tests = {
|
||||
}
|
||||
}
|
||||
|
||||
function runTests(tests, cbPreTest, cbPostTest, cbFinish) {
|
||||
let testIter = Iterator(tests);
|
||||
|
||||
if (cbPreTest === undefined) {
|
||||
cbPreTest = function(cb) {cb()};
|
||||
}
|
||||
if (cbPostTest === undefined) {
|
||||
cbPostTest = function(cb) {cb()};
|
||||
}
|
||||
|
||||
function runNextTest() {
|
||||
let name, func;
|
||||
try {
|
||||
[name, func] = testIter.next();
|
||||
} catch (err if err instanceof StopIteration) {
|
||||
// out of items:
|
||||
(cbFinish || finish)();
|
||||
return;
|
||||
}
|
||||
// We run on a timeout as the frameworker also makes use of timeouts, so
|
||||
// this helps keep the debug messages sane.
|
||||
executeSoon(function() {
|
||||
function cleanupAndRunNextTest() {
|
||||
info("sub-test " + name + " complete");
|
||||
cbPostTest(runNextTest);
|
||||
}
|
||||
cbPreTest(function() {
|
||||
info("sub-test " + name + " starting");
|
||||
try {
|
||||
func.call(tests, cleanupAndRunNextTest);
|
||||
} catch (ex) {
|
||||
ok(false, "sub-test " + name + " failed: " + ex.toString() +"\n"+ex.stack);
|
||||
cleanupAndRunNextTest();
|
||||
}
|
||||
})
|
||||
});
|
||||
}
|
||||
runNextTest();
|
||||
}
|
||||
|
@ -118,3 +118,44 @@ function runSocialTestWithProvider(manifest, callback) {
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
function runSocialTests(tests, cbPreTest, cbPostTest, cbFinish) {
|
||||
let testIter = Iterator(tests);
|
||||
|
||||
if (cbPreTest === undefined) {
|
||||
cbPreTest = function(cb) {cb()};
|
||||
}
|
||||
if (cbPostTest === undefined) {
|
||||
cbPostTest = function(cb) {cb()};
|
||||
}
|
||||
|
||||
function runNextTest() {
|
||||
let name, func;
|
||||
try {
|
||||
[name, func] = testIter.next();
|
||||
} catch (err if err instanceof StopIteration) {
|
||||
// out of items:
|
||||
(cbFinish || finish)();
|
||||
return;
|
||||
}
|
||||
// We run on a timeout as the frameworker also makes use of timeouts, so
|
||||
// this helps keep the debug messages sane.
|
||||
executeSoon(function() {
|
||||
function cleanupAndRunNextTest() {
|
||||
info("sub-test " + name + " complete");
|
||||
cbPostTest(runNextTest);
|
||||
}
|
||||
cbPreTest(function() {
|
||||
info("sub-test " + name + " starting");
|
||||
try {
|
||||
func.call(tests, cleanupAndRunNextTest);
|
||||
} catch (ex) {
|
||||
ok(false, "sub-test " + name + " failed: " + ex.toString() +"\n"+ex.stack);
|
||||
cleanupAndRunNextTest();
|
||||
}
|
||||
})
|
||||
});
|
||||
}
|
||||
runNextTest();
|
||||
}
|
||||
|
@ -2,8 +2,34 @@
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<script>
|
||||
var win;
|
||||
function pingWorker() {
|
||||
var port = navigator.mozSocial.getWorker().port;
|
||||
port.onmessage = function(e) {
|
||||
var topic = e.data.topic;
|
||||
switch (topic) {
|
||||
case "test-service-window":
|
||||
win = navigator.mozSocial.openServiceWindow("social_window.html", "test-service-window", "width=300,height=300");
|
||||
break;
|
||||
case "test-service-window-twice":
|
||||
win = navigator.mozSocial.openServiceWindow("social_window.html", "test-service-window", "width=300,height=300");
|
||||
var win2 = navigator.mozSocial.openServiceWindow("social_window.html", "test-service-window", "");
|
||||
var result;
|
||||
if (win == win2)
|
||||
result = "ok";
|
||||
else
|
||||
result = "not ok: " + win2 + " != " + win;
|
||||
port.postMessage({topic: "test-service-window-twice-result", result: result});
|
||||
break;
|
||||
case "test-close-service-window":
|
||||
win.addEventListener("unload", function watchClose() {
|
||||
win.removeEventListener("unload", watchClose);
|
||||
port.postMessage({topic: "service-window-closed-message", result: "ok"});
|
||||
}, false)
|
||||
win.close();
|
||||
break;
|
||||
}
|
||||
}
|
||||
port.postMessage({topic: "sidebar-message", result: "ok"});
|
||||
}
|
||||
</script>
|
||||
|
14
browser/base/content/test/social_window.html
Normal file
14
browser/base/content/test/social_window.html
Normal file
@ -0,0 +1,14 @@
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<script>
|
||||
function pingWorker() {
|
||||
var port = navigator.mozSocial.getWorker().port;
|
||||
port.postMessage({topic: "service-window-message", result: "ok"});
|
||||
}
|
||||
</script>
|
||||
</head>
|
||||
<body onload="pingWorker();">
|
||||
<p>This is a test social service window.</p>
|
||||
</body>
|
||||
</html>
|
@ -2,7 +2,7 @@
|
||||
* 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 testPort;
|
||||
let testPort, sidebarPort;
|
||||
|
||||
onconnect = function(e) {
|
||||
let port = e.ports[0];
|
||||
@ -13,9 +13,28 @@ onconnect = function(e) {
|
||||
testPort = port;
|
||||
break;
|
||||
case "sidebar-message":
|
||||
sidebarPort = port;
|
||||
if (testPort && event.data.result == "ok")
|
||||
testPort.postMessage({topic:"got-sidebar-message"});
|
||||
break;
|
||||
case "service-window-message":
|
||||
testPort.postMessage({topic:"got-service-window-message"});
|
||||
break;
|
||||
case "service-window-closed-message":
|
||||
testPort.postMessage({topic:"got-service-window-closed-message"});
|
||||
break;
|
||||
case "test-service-window":
|
||||
sidebarPort.postMessage({topic:"test-service-window"});
|
||||
break;
|
||||
case "test-service-window-twice":
|
||||
sidebarPort.postMessage({topic:"test-service-window-twice"});
|
||||
break;
|
||||
case "test-service-window-twice-result":
|
||||
testPort.postMessage({topic: "test-service-window-twice-result", result: event.data.result })
|
||||
break;
|
||||
case "test-close-service-window":
|
||||
sidebarPort.postMessage({topic:"test-close-service-window"});
|
||||
break;
|
||||
case "panel-message":
|
||||
if (testPort && event.data.result == "ok")
|
||||
testPort.postMessage({topic:"got-panel-message"});
|
||||
|
@ -41,15 +41,6 @@ function injectController(doc, topic, data) {
|
||||
.QueryInterface(Ci.nsIDocShell)
|
||||
.chromeEventHandler;
|
||||
|
||||
// If the containing browser isn't one of the social browsers, nothing to
|
||||
// do here.
|
||||
// XXX this is app-specific, might want some mechanism for consumers to
|
||||
// whitelist other IDs/windowtypes
|
||||
if (!(containingBrowser.id == "social-sidebar-browser" ||
|
||||
containingBrowser.id == "social-notification-browser")) {
|
||||
return;
|
||||
}
|
||||
|
||||
let origin = containingBrowser.getAttribute("origin");
|
||||
if (!origin) {
|
||||
return;
|
||||
@ -92,6 +83,18 @@ function attachToWindow(provider, targetWindow) {
|
||||
},
|
||||
hasBeenIdleFor: function () {
|
||||
return false;
|
||||
},
|
||||
openServiceWindow: function(toURL, name, options) {
|
||||
return openServiceWindow(provider, targetWindow, toURL, name, options);
|
||||
},
|
||||
getAttention: function() {
|
||||
let mainWindow = targetWindow.QueryInterface(Components.interfaces.nsIInterfaceRequestor)
|
||||
.getInterface(Components.interfaces.nsIWebNavigation)
|
||||
.QueryInterface(Components.interfaces.nsIDocShellTreeItem)
|
||||
.rootTreeItem
|
||||
.QueryInterface(Components.interfaces.nsIInterfaceRequestor)
|
||||
.getInterface(Components.interfaces.nsIDOMWindow);
|
||||
mainWindow.getAttention();
|
||||
}
|
||||
};
|
||||
|
||||
@ -128,3 +131,59 @@ function attachToWindow(provider, targetWindow) {
|
||||
function schedule(callback) {
|
||||
Services.tm.mainThread.dispatch(callback, Ci.nsIThread.DISPATCH_NORMAL);
|
||||
}
|
||||
|
||||
function openServiceWindow(provider, contentWindow, url, name, options) {
|
||||
// resolve partial URLs and check prePath matches
|
||||
let uri;
|
||||
let fullURL;
|
||||
try {
|
||||
fullURL = contentWindow.document.documentURIObject.resolve(url);
|
||||
uri = Services.io.newURI(fullURL, null, null);
|
||||
} catch (ex) {
|
||||
Cu.reportError("openServiceWindow: failed to resolve window URL: " + url + "; " + ex);
|
||||
return null;
|
||||
}
|
||||
|
||||
if (provider.origin != uri.prePath) {
|
||||
Cu.reportError("openServiceWindow: unable to load new location, " +
|
||||
provider.origin + " != " + uri.prePath);
|
||||
return null;
|
||||
}
|
||||
|
||||
function getChromeWindow(contentWin) {
|
||||
return contentWin.QueryInterface(Ci.nsIInterfaceRequestor)
|
||||
.getInterface(Ci.nsIWebNavigation)
|
||||
.QueryInterface(Ci.nsIDocShellTreeItem)
|
||||
.rootTreeItem
|
||||
.QueryInterface(Ci.nsIInterfaceRequestor)
|
||||
.getInterface(Ci.nsIDOMWindow);
|
||||
|
||||
}
|
||||
let chromeWindow = Services.ww.getWindowByName("social-service-window-" + name,
|
||||
getChromeWindow(contentWindow));
|
||||
let tabbrowser = chromeWindow && chromeWindow.gBrowser;
|
||||
if (tabbrowser &&
|
||||
tabbrowser.selectedBrowser.getAttribute("origin") == provider.origin) {
|
||||
return tabbrowser.contentWindow;
|
||||
}
|
||||
|
||||
let serviceWindow = contentWindow.openDialog(fullURL, name,
|
||||
"chrome=no,dialog=no" + options);
|
||||
|
||||
// Get the newly opened window's containing XUL window
|
||||
chromeWindow = getChromeWindow(serviceWindow);
|
||||
|
||||
// set the window's name and origin attribute on its browser, so that it can
|
||||
// be found via getWindowByName
|
||||
chromeWindow.name = "social-service-window-" + name;
|
||||
chromeWindow.gBrowser.selectedBrowser.setAttribute("origin", provider.origin);
|
||||
|
||||
// we dont want the default title the browser produces, we'll fixup whenever
|
||||
// it changes.
|
||||
serviceWindow.addEventListener("DOMTitleChanged", function() {
|
||||
let sep = xulWindow.document.documentElement.getAttribute("titlemenuseparator");
|
||||
xulWindow.document.title = provider.name + sep + serviceWindow.document.title;
|
||||
});
|
||||
|
||||
return serviceWindow;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user