Bug 1265279 - Web Manifest: Implement window.oninstall. r=baku

* Add tests for window.oninstall
* Teach manifestMessages how to fire install event
* Test that the install event fired from Parent process
This commit is contained in:
Marcos Caceres 2016-05-30 18:52:00 +02:00
parent 17aef34672
commit 095622d6de
11 changed files with 177 additions and 0 deletions

View File

@ -493,6 +493,7 @@ GK_ATOM(inputmode, "inputmode")
GK_ATOM(ins, "ins")
GK_ATOM(insertafter, "insertafter")
GK_ATOM(insertbefore, "insertbefore")
GK_ATOM(install, "install")
GK_ATOM(instanceOf, "instanceOf")
GK_ATOM(int32, "int32")
GK_ATOM(int64, "int64")

View File

@ -588,6 +588,13 @@ WINDOW_ONLY_EVENT(devicelight,
EventNameType_None,
eBasicEventClass)
// Install events as per W3C Manifest spec
WINDOW_ONLY_EVENT(install,
eInstall,
EventNameType_None,
eBasicEventClass)
#ifdef MOZ_B2G
WINDOW_ONLY_EVENT(moztimechange,
eTimeChange,

View File

@ -30,6 +30,10 @@ const MessageHandler = {
"DOM:ManifestObtainer:Obtain",
this.obtainManifest.bind(this)
);
addMessageListener(
"DOM:Manifest:FireInstallEvent",
this.fireInstallEvent.bind(this)
);
},
/**
@ -60,6 +64,19 @@ const MessageHandler = {
}
sendAsyncMessage("DOM:ManifestObtainer:Obtain", response);
}),
fireInstallEvent({data: {id}}){
const ev = new Event("install");
const response = makeMsgResponse(id);
if (!content || content.top !== content) {
const msg = "Can only dispatch install event on top-level browsing contexts.";
response.result = serializeError(new Error(msg));
} else {
response.success = true;
content.dispatchEvent(ev);
}
sendAsyncMessage("DOM:Manifest:FireInstallEvent", response);
}
};
/**
* Utility function to Serializes an JS Error, so it can be transferred over

View File

@ -1,3 +1,8 @@
[DEFAULT]
support-files =
manifestLoader.html
file_reg_install_event.html
file_testserver.sjs
[browser_ManifestFinder_browserHasManifestLink.js]
[browser_ManifestObtainer_obtain.js]
[browser_fire_install_event.js]

View File

@ -0,0 +1,33 @@
//Used by JSHint:
/*global Cu, BrowserTestUtils, ok, add_task, PromiseMessage, gBrowser */
"use strict";
const { PromiseMessage } = Cu.import("resource://gre/modules/PromiseMessage.jsm", {});
const testPath = "/browser/dom/manifest/test/file_reg_install_event.html";
const defaultURL = new URL("http://example.org/browser/dom/manifest/test/file_testserver.sjs");
const testURL = new URL(defaultURL);
testURL.searchParams.append("file", testPath);
// Send a message for the even to be fired.
// This cause file_reg_install_event.html to be dynamically change.
function* theTest(aBrowser) {
const mm = aBrowser.messageManager;
const msgKey = "DOM:Manifest:FireInstallEvent";
const initialText = aBrowser.contentWindowAsCPOW.document.body.innerHTML.trim()
is(initialText, '<h1 id="output">waiting for event</h1>', "should be waiting for event");
const { data: { success } } = yield PromiseMessage.send(mm, msgKey);
ok(success, "message sent and received successfully.");
const eventText = aBrowser.contentWindowAsCPOW.document.body.innerHTML.trim();
is(eventText, '<h1 id="output">event received!</h1>', "text of the page should have changed.");
};
// Open a tab and run the test
add_task(function*() {
let tabOptions = {
gBrowser: gBrowser,
url: testURL.href,
};
yield BrowserTestUtils.withNewTab(
tabOptions,
theTest
);
});

View File

@ -0,0 +1,9 @@
<script>
window.addEventListener("install", (ev) => {
document
.querySelector("#output")
.innerHTML = "event received!"
});
</script>
<link rel="manifest" href="file_manifest.json">
<h1 id=output>waiting for event</h1>

View File

@ -0,0 +1,49 @@
"use strict";
Components.utils.import("resource://gre/modules/NetUtil.jsm");
Components.utils.importGlobalProperties(["URLSearchParams"]);
function loadHTMLFromFile(path) {
// Load the HTML to return in the response from file.
// Since it's relative to the cwd of the test runner, we start there and
// append to get to the actual path of the file.
const testHTMLFile =
Components.classes["@mozilla.org/file/directory_service;1"].
getService(Components.interfaces.nsIProperties).
get("CurWorkD", Components.interfaces.nsILocalFile);
const testHTMLFileStream =
Components.classes["@mozilla.org/network/file-input-stream;1"].
createInstance(Components.interfaces.nsIFileInputStream);
path
.split("/")
.filter(path => path)
.reduce((file, path) => {
testHTMLFile.append(path)
return testHTMLFile;
}, testHTMLFile);
testHTMLFileStream.init(testHTMLFile, -1, 0, 0);
const isAvailable = testHTMLFileStream.available();
return NetUtil.readInputStreamToString(testHTMLFileStream, isAvailable);
}
function handleRequest(request, response) {
const query = new URLSearchParams(request.queryString);
// avoid confusing cache behaviors
response.setHeader("Cache-Control", "no-cache", false);
// Deliver the CSP policy encoded in the URL
if(query.has("csp")){
response.setHeader("Content-Security-Policy", query.get("csp"), false);
}
// Deliver the CORS header in the URL
if(query.has("cors")){
response.setHeader("Access-Control-Allow-Origin", query.get("cors"), false);
}
// Send HTML to test allowed/blocked behaviors
response.setHeader("Content-Type", "text/html", false);
response.write(loadHTMLFromFile(query.get("file")));
}

View File

@ -3,6 +3,8 @@ support-files =
common.js
resource.sjs
manifestLoader.html
file_reg_install_event.html
file_testserver.sjs
[test_ImageObjectProcessor_sizes.html]
[test_ImageObjectProcessor_src.html]
[test_ImageObjectProcessor_type.html]
@ -18,3 +20,4 @@ support-files =
[test_ManifestProcessor_start_url.html]
[test_ManifestProcessor_theme_color.html]
[test_ManifestProcessor_warnings.html]
[test_window_oninstall_event.html]

View File

@ -0,0 +1,44 @@
<!DOCTYPE HTML>
<html>
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=1265279
-->
<head>
<meta charset="utf-8">
<title>Test for Bug 1265279 - Web Manifest: Implement window.oninstall</title>
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
<script>
"use strict";
SimpleTest.waitForExplicitFinish();
is(window.hasOwnProperty("oninstall"), true, "window has own oninstall property");
is(window.oninstall, null, "window install is initially set to null");
// Check that enumerable, configurable, and has a getter and setter
const objDescriptor = Object.getOwnPropertyDescriptor(window, "oninstall");
is(objDescriptor.enumerable, true, "is enumerable");
is(objDescriptor.configurable, true, "is configurable");
is(objDescriptor.hasOwnProperty("get"), true, "has getter");
is(objDescriptor.hasOwnProperty("set"), true, "has setter");
// Test is we receive the event on window.install
const customEv = new CustomEvent("install");
window.oninstall = function handler(ev){
window.oninstall = null;
is(ev, customEv, "The events should be the same");
testAddEventListener();
};
window.dispatchEvent(customEv);
// Test that it works with .addEventListener("install", f);
function testAddEventListener(){
const customEv2 = new CustomEvent("install");
window.addEventListener("install", function handler2(ev2) {
window.removeEventListener("install", handler2);
is(ev2, customEv2, "The events should be the same");
SimpleTest.finish();
});
window.dispatchEvent(customEv2);
}
</script>
</head>

View File

@ -89,6 +89,12 @@ typedef any Transferable;
Window implements GlobalEventHandlers;
Window implements WindowEventHandlers;
[NoInterfaceObject, Exposed=(Window)]
interface AppInstallEventHandlersMixin {
attribute EventHandler oninstall;
};
Window implements AppInstallEventHandlersMixin;
// http://www.whatwg.org/specs/web-apps/current-work/
[NoInterfaceObject, Exposed=(Window,Worker)]
interface WindowTimers {

View File

@ -61,6 +61,9 @@ NS_EVENT_MESSAGE(eAccessKeyNotFound)
NS_EVENT_MESSAGE(eResize)
NS_EVENT_MESSAGE(eScroll)
// Application installation
NS_EVENT_MESSAGE(eInstall)
// A plugin was clicked or otherwise focused. ePluginActivate should be
// used when the window is not active. ePluginFocus should be used when
// the window is active. In the latter case, the dispatcher of the event