Bug 962626 - Browser API: mozmetachanged triggered when a meta element is added to the dom., r=ehsan

--HG--
rename : dom/browser-element/mochitest/test_browserElement_inproc_Iconchange.html => dom/browser-element/mochitest/test_browserElement_inproc_Metachange.html
rename : dom/browser-element/mochitest/test_browserElement_oop_Iconchange.html => dom/browser-element/mochitest/test_browserElement_oop_Metachange.html
This commit is contained in:
Andrea Marchesini 2014-01-30 09:31:34 -08:00
parent 8fa8e93746
commit 2238cbd2d8
8 changed files with 258 additions and 0 deletions

View File

@ -186,6 +186,11 @@ BrowserElementChild.prototype = {
/* useCapture = */ true,
/* wantsUntrusted = */ false);
addEventListener('DOMMetaAdded',
this._metaAddedHandler.bind(this),
/* useCapture = */ true,
/* wantsUntrusted = */ false);
// This listens to unload events from our message manager, but /not/ from
// the |content| window. That's because the window's unload event doesn't
// bubble, and we're not using a capturing listener. If we'd used
@ -501,6 +506,54 @@ BrowserElementChild.prototype = {
}, this);
},
_metaAddedHandler: function(e) {
let win = e.target.ownerDocument.defaultView;
// Ignore metas which don't come from the top-level
// <iframe mozbrowser> window.
if (win != content) {
debug('Not top level!');
return;
}
if (!e.target.name) {
return;
}
debug('Got metaAdded: (' + e.target.name + ') ' + e.target.content);
if (e.target.name == 'application-name') {
let meta = { name: e.target.name,
content: e.target.content };
let lang;
let elm;
for (elm = e.target;
!lang && elm && elm.nodeType == e.target.ELEMENT_NODE;
elm = elm.parentNode) {
if (elm.hasAttribute('lang')) {
lang = elm.getAttribute('lang');
continue;
}
if (elm.hasAttributeNS('http://www.w3.org/XML/1998/namespace', 'lang')) {
lang = elm.getAttributeNS('http://www.w3.org/XML/1998/namespace', 'lang');
continue;
}
}
// No lang has been detected.
if (!lang && elm.nodeType == e.target.DOCUMENT_NODE) {
lang = elm.contentLanguage;
}
if (lang) {
meta.lang = lang;
}
sendAsyncMsg('metachange', meta);
}
},
_addMozAfterPaintHandler: function(callback) {
function onMozAfterPaint() {
let uri = docShell.QueryInterface(Ci.nsIWebNavigation).currentURI;

View File

@ -258,6 +258,7 @@ BrowserElementParent.prototype = {
"loadend": this._fireEventFromMsg,
"titlechange": this._fireEventFromMsg,
"iconchange": this._fireEventFromMsg,
"metachange": this._fireEventFromMsg,
"close": this._fireEventFromMsg,
"resize": this._fireEventFromMsg,
"activitydone": this._fireEventFromMsg,

View File

@ -34,8 +34,11 @@ MOCHITEST_FILES = \
test_browserElement_inproc_BrowserWindowNamespace.html \
file_browserElement_BrowserWindowNamespace.html \
browserElement_Iconchange.js \
browserElement_Metachange.js \
file_browserElement_Metachange.sjs \
browserElement_Opensearch.js \
test_browserElement_inproc_Iconchange.html \
test_browserElement_inproc_Metachange.html \
test_browserElement_inproc_Opensearch.html \
browserElement_GetScreenshot.js \
test_browserElement_inproc_GetScreenshot.html \
@ -206,6 +209,7 @@ MOCHITEST_FILES += \
test_browserElement_oop_BrowserWindowNamespace.html \
test_browserElement_oop_TopBarrier.html \
test_browserElement_oop_Iconchange.html \
test_browserElement_oop_Metachange.html \
test_browserElement_oop_Opensearch.html \
test_browserElement_oop_GetScreenshot.html \
test_browserElement_oop_BadScreenshot.html \

View File

@ -0,0 +1,153 @@
/* Any copyright is dedicated to the public domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
// Test that the onmozbrowsermetachange event works.
"use strict";
SimpleTest.waitForExplicitFinish();
browserElementTestHelpers.setEnabledPref(true);
browserElementTestHelpers.addPermission();
function createHtml(meta) {
return 'data:text/html,<html xmlns:xml="http://www.w3.org/XML/1998/namespace"><head>' + meta + '<body></body></html>';
}
function createHtmlWithLang(meta, lang) {
return 'data:text/html,<html xmlns:xml="http://www.w3.org/XML/1998/namespace" lang="' + lang + '"><head>' + meta + '<body></body></html>';
}
function createMeta(name, content) {
return '<meta name="' + name + '" content="' + content + '">';
}
function createMetaWithLang(name, content, lang) {
return '<meta name="' + name + '" content="' + content + '" lang="' + lang + '">';
}
function runTest() {
var iframe1 = document.createElement('iframe');
SpecialPowers.wrap(iframe1).mozbrowser = true;
document.body.appendChild(iframe1);
// iframe2 is a red herring; we modify its meta elements but don't listen for
// metachanges; we want to make sure that its metachange events aren't
// picked up by the listener on iframe1.
var iframe2 = document.createElement('iframe');
SpecialPowers.wrap(iframe2).mozbrowser = true;
document.body.appendChild(iframe2);
// iframe3 is another red herring. It's not a mozbrowser, so we shouldn't
// get any metachange events on it.
var iframe3 = document.createElement('iframe');
document.body.appendChild(iframe3);
var numMetaChanges = 0;
iframe1.addEventListener('mozbrowsermetachange', function(e) {
numMetaChanges++;
if (numMetaChanges == 1) {
is(e.detail.name, 'application-name');
is(e.detail.content, 'foobar');
// We should recieve metachange events when the user creates new metas
SpecialPowers.getBrowserFrameMessageManager(iframe1)
.loadFrameScript("data:,content.document.title='New title';",
/* allowDelayedLoad = */ false);
SpecialPowers.getBrowserFrameMessageManager(iframe1)
.loadFrameScript("data:,content.document.head.insertAdjacentHTML('beforeend', '<meta name=application-name content=new_foobar>')",
/* allowDelayedLoad = */ false);
SpecialPowers.getBrowserFrameMessageManager(iframe2)
.loadFrameScript("data:,content.document.head.insertAdjacentHTML('beforeend', '<meta name=application-name content=new_foobar>')",
/* allowDelayedLoad = */ false);
}
else if (numMetaChanges == 2) {
is(e.detail.name, 'application-name', 'name matches');
is(e.detail.content, 'new_foobar', 'content matches');
ok(!("lang" in e.detail), 'lang not present');
// Full new pages should trigger metachange events
iframe1.src = createHtml(createMeta('application-name', '3rd_foobar'));
}
else if (numMetaChanges == 3) {
is(e.detail.name, 'application-name', 'name matches');
is(e.detail.content, '3rd_foobar', 'content matches');
ok(!("lang" in e.detail), 'lang not present');
// Test setting a page with multiple meta elements
iframe1.src = createHtml(createMeta('application-name', 'foobar_1') + createMeta('application-name', 'foobar_2'));
}
else if (numMetaChanges == 4) {
is(e.detail.name, 'application-name', 'name matches');
is(e.detail.content, 'foobar_1', 'content matches');
ok(!("lang" in e.detail), 'lang not present');
// 2 events will be triggered by previous test, wait for next
}
else if (numMetaChanges == 5) {
is(e.detail.name, 'application-name', 'name matches');
is(e.detail.content, 'foobar_2', 'content matches');
ok(!("lang" in e.detail), 'lang not present');
// Test the language
iframe1.src = createHtml(createMetaWithLang('application-name', 'foobar_lang_1', 'en'));
}
else if (numMetaChanges == 6) {
is(e.detail.name, 'application-name', 'name matches');
is(e.detail.content, 'foobar_lang_1', 'content matches');
is(e.detail.lang, 'en', 'language matches');
// Test the language in the ancestor element
iframe1.src = createHtmlWithLang(createMeta('application-name', 'foobar_lang_2'), 'es');
}
else if (numMetaChanges == 7) {
is(e.detail.name, 'application-name', 'name matches');
is(e.detail.content, 'foobar_lang_2', 'content matches');
is(e.detail.lang, 'es', 'language matches');
// Test the language in the ancestor element
iframe1.src = createHtmlWithLang(createMetaWithLang('application-name', 'foobar_lang_3', 'it'), 'fi');
}
else if (numMetaChanges == 8) {
is(e.detail.name, 'application-name', 'name matches');
is(e.detail.content, 'foobar_lang_3', 'content matches');
is(e.detail.lang, 'it', 'language matches');
// Test the content-language
iframe1.src = "http://test/tests/dom/browser-element/mochitest/file_browserElement_Metachange.sjs?ru";
}
else if (numMetaChanges == 9) {
is(e.detail.name, 'application-name', 'name matches');
is(e.detail.content, 'sjs', 'content matches');
is(e.detail.lang, 'ru', 'language matches');
// Test the content-language
iframe1.src = "http://test/tests/dom/browser-element/mochitest/file_browserElement_Metachange.sjs?ru|dk";
}
else if (numMetaChanges == 10) {
is(e.detail.name, 'application-name', 'name matches');
is(e.detail.content, 'sjs', 'content matches');
is(e.detail.lang, 'dk', 'language matches');
// Test the language
SimpleTest.finish();
} else {
ok(false, 'Too many metachange events.');
}
});
iframe3.addEventListener('mozbrowsermetachange', function(e) {
ok(false, 'Should not get a metachange event for iframe3.');
});
iframe1.src = createHtml(createMeta('application-name', 'foobar'));
// We should not recieve meta change events for either of the below iframes
iframe2.src = createHtml(createMeta('application-name', 'foobar'));
iframe3.src = createHtml(createMeta('application-name', 'foobar'));
}
addEventListener('testready', runTest);

View File

@ -0,0 +1,7 @@
function handleRequest(request, response)
{
var p = request.queryString.split('|');
response.setHeader('Content-Language', p[0], false);
response.write('<html><head><meta name="application-name" content="sjs"' +
(p.length > 1 ? (' lang="' + p[1] + '"') : '') + '></head><body></body></html>');
}

View File

@ -0,0 +1,19 @@
<!DOCTYPE HTML>
<html>
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=962626
-->
<head>
<title>Test for Bug 962626</title>
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<script type="application/javascript" src="browserElementTestHelpers.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
</head>
<body>
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=962626">Mozilla Bug 962626</a>
<script type="application/javascript;version=1.7" src="browserElement_Metachange.js">
</script>
</body>
</html>

View File

@ -0,0 +1,19 @@
<!DOCTYPE HTML>
<html>
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=962626
-->
<head>
<title>Test for Bug 962626</title>
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<script type="application/javascript" src="browserElementTestHelpers.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
</head>
<body>
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=962626">Mozilla Bug 962626</a>
<script type="application/javascript;version=1.7" src="browserElement_Metachange.js">
</script>
</body>
</html>

View File

@ -341,6 +341,8 @@ partial interface Document {
void obsoleteSheet(DOMString sheetURI);
[ChromeOnly] readonly attribute nsIDocShell? docShell;
[ChromeOnly] readonly attribute DOMString contentLanguage;
};
// Extension to give chrome JS the ability to determine when a document was