Merge from mozilla-central.

This commit is contained in:
Jan de Mooij 2013-03-06 16:18:00 +01:00
commit 983c973cfe
253 changed files with 8282 additions and 2860 deletions

View File

@ -348,6 +348,19 @@ DocManager::AddListeners(nsIDocument* aDocument,
}
}
void
DocManager::RemoveListeners(nsIDocument* aDocument)
{
nsPIDOMWindow* window = aDocument->GetWindow();
nsIDOMEventTarget* target = window->GetChromeEventHandler();
nsEventListenerManager* elm = target->GetListenerManager(true);
elm->RemoveEventListenerByType(this, NS_LITERAL_STRING("pagehide"),
dom::TrustedEventsAtCapture());
elm->RemoveEventListenerByType(this, NS_LITERAL_STRING("DOMContentLoaded"),
dom::TrustedEventsAtCapture());
}
DocAccessible*
DocManager::CreateDocOrRootAccessible(nsIDocument* aDocument)
{

View File

@ -65,6 +65,7 @@ public:
inline void NotifyOfDocumentShutdown(nsIDocument* aDocument)
{
mDocAccessibleCache.Remove(aDocument);
RemoveListeners(aDocument);
}
#ifdef DEBUG
@ -101,9 +102,10 @@ private:
uint32_t aLoadEventType);
/**
* Add 'pagehide' and 'DOMContentLoaded' event listeners.
* Add/remove 'pagehide' and 'DOMContentLoaded' event listeners.
*/
void AddListeners(nsIDocument *aDocument, bool aAddPageShowListener);
void RemoveListeners(nsIDocument* aDocument);
/**
* Create document or root accessible.

View File

@ -107,7 +107,9 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(DocAccessible, Accessible)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mNotificationController)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mVirtualCursor)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mChildDocuments)
tmp->mDependentIDsHash.EnumerateRead(CycleCollectorTraverseDepIDsEntry, &cb);
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mAccessibleCache)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mAnchorJumpElm)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(DocAccessible, Accessible)
@ -117,6 +119,7 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(DocAccessible, Accessible)
tmp->mDependentIDsHash.Clear();
tmp->mNodeToAccessibleMap.Clear();
NS_IMPL_CYCLE_COLLECTION_UNLINK(mAccessibleCache)
NS_IMPL_CYCLE_COLLECTION_UNLINK(mAnchorJumpElm)
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(DocAccessible)
@ -1981,3 +1984,25 @@ DocAccessible::IsLoadEventTarget() const
return (contentType == nsIDocShellTreeItem::typeContent);
}
PLDHashOperator
DocAccessible::CycleCollectorTraverseDepIDsEntry(const nsAString& aKey,
AttrRelProviderArray* aProviders,
void* aUserArg)
{
nsCycleCollectionTraversalCallback* cb =
static_cast<nsCycleCollectionTraversalCallback*>(aUserArg);
for (int32_t jdx = aProviders->Length() - 1; jdx >= 0; jdx--) {
NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(*cb,
"content of dependent ids hash entry of document accessible");
AttrRelProvider* provider = (*aProviders)[jdx];
cb->NoteXPCOMChild(provider->mContent);
NS_ASSERTION(provider->mContent->IsInDoc(),
"Referred content is not in document!");
}
return PL_DHASH_NEXT;
}

View File

@ -561,11 +561,19 @@ protected:
AttrRelProvider& operator =(const AttrRelProvider&);
};
typedef nsTArray<nsAutoPtr<AttrRelProvider> > AttrRelProviderArray;
typedef nsClassHashtable<nsStringHashKey, AttrRelProviderArray>
DependentIDsHashtable;
/**
* The cache of IDs pointed by relation attributes.
*/
typedef nsTArray<nsAutoPtr<AttrRelProvider> > AttrRelProviderArray;
nsClassHashtable<nsStringHashKey, AttrRelProviderArray> mDependentIDsHash;
DependentIDsHashtable mDependentIDsHash;
static PLDHashOperator
CycleCollectorTraverseDepIDsEntry(const nsAString& aKey,
AttrRelProviderArray* aProviders,
void* aUserArg);
friend class RelatedAccIterator;

View File

@ -3,10 +3,10 @@
* 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/. */
#include "mozilla/DebugOnly.h"
#include "HTMLTableAccessible.h"
#include "mozilla/DebugOnly.h"
#include "Accessible-inl.h"
#include "nsAccessibilityService.h"
#include "nsAccUtils.h"
@ -18,6 +18,7 @@
#include "States.h"
#include "TreeWalker.h"
#include "mozilla/dom/HTMLTableElement.h"
#include "nsIDOMElement.h"
#include "nsIDOMDocument.h"
#include "nsIDOMRange.h"
@ -25,10 +26,6 @@
#include "nsINameSpaceManager.h"
#include "nsIDOMNodeList.h"
#include "nsIDOMHTMLCollection.h"
#include "nsIDOMHTMLTableCellElement.h"
#include "nsIDOMHTMLTableElement.h"
#include "nsIDOMHTMLTableRowElement.h"
#include "nsIDOMHTMLTableSectionElement.h"
#include "nsIDocument.h"
#include "nsIMutableArray.h"
#include "nsIPresShell.h"
@ -455,7 +452,7 @@ HTMLTableAccessible::Caption()
void
HTMLTableAccessible::Summary(nsString& aSummary)
{
nsCOMPtr<nsIDOMHTMLTableElement> table(do_QueryInterface(mContent));
dom::HTMLTableElement* table = dom::HTMLTableElement::FromContent(mContent);
if (table)
table->GetSummary(aSummary);

View File

@ -42,11 +42,12 @@
////////////////////////////////////////////////////////////////////////////
// Test
//gA11yEventDumpToConsole = true; // debug stuff
gA11yEventDumpToConsole = true; // debug stuff
var gQueue = null;
function doTest()
{
enableLogging("tree");
gQueue = new eventQueue();
gQueue.push(new takeFocusInvoker("aria-link"));
@ -57,6 +58,7 @@
gQueue.push(new takeFocusInvoker(document));
gQueue.push(new takeFocusInvoker("lb_item2"));
gQueue.onFinish = function() { disableLogging(); }
gQueue.invoke(); // Will call SimpleTest.finish();
}

View File

@ -59,6 +59,8 @@
var gQueue = null;
function doTests()
{
disableLogging(); // from test_takeFocus.html
// Test focus events.
gQueue = new eventQueue();

View File

@ -86,7 +86,7 @@ let gObserver = new MutationObserver(function (mutations) {
if (mutation.attributeName == "searchEngineURL") {
gObserver.disconnect();
setupSearchEngine();
loadSnippets();
ensureSnippetsMapThen(loadSnippets);
return;
}
}
@ -100,6 +100,70 @@ window.addEventListener("load", function () {
window.addEventListener("resize", fitToWidth);
});
// This object has the same interface as Map and is used to store and retrieve
// the snippets data. It is lazily initialized by ensureSnippetsMapThen(), so
// be sure its callback returned before trying to use it.
let gSnippetsMap;
let gSnippetsMapCallbacks = [];
/**
* Ensure the snippets map is properly initialized.
*
* @param aCallback
* Invoked once the map has been initialized, gets the map as argument.
* @note Snippets should never directly manage the underlying storage, since
* it may change inadvertently.
*/
function ensureSnippetsMapThen(aCallback)
{
if (gSnippetsMap) {
aCallback(gSnippetsMap);
return;
}
// Handle multiple requests during the async initialization.
gSnippetsMapCallbacks.push(aCallback);
if (gSnippetsMapCallbacks.length > 1) {
// We are already updating, the callbacks will be invoked when done.
return;
}
// TODO (bug 789348): use a real asynchronous storage here. This setTimeout
// is done just to catch bugs with the asynchronous behavior.
setTimeout(function() {
// Populate the cache from the persistent storage.
let cache = new Map();
for (let key of [ "snippets-last-update",
"snippets-cached-version",
"snippets" ]) {
cache.set(key, localStorage[key]);
}
gSnippetsMap = Object.freeze({
get: function (aKey) cache.get(aKey),
set: function (aKey, aValue) {
localStorage[aKey] = aValue;
return cache.set(aKey, aValue);
},
has: function(aKey) cache.has(aKey),
delete: function(aKey) {
delete localStorage[aKey];
return cache.delete(aKey);
},
clear: function() {
localStorage.clear();
return cache.clear();
},
get size() cache.size
});
for (let callback of gSnippetsMapCallbacks) {
callback(gSnippetsMap);
}
gSnippetsMapCallbacks.length = 0;
}, 0);
}
function onSearchSubmit(aEvent)
{
let searchTerms = document.getElementById("searchText").value;
@ -157,13 +221,29 @@ function setupSearchEngine()
}
/**
* Update the local snippets from the remote storage, then show them through
* showSnippets.
*/
function loadSnippets()
{
if (!gSnippetsMap)
throw new Error("Snippets map has not properly been initialized");
// Check cached snippets version.
let cachedVersion = gSnippetsMap.get("snippets-cached-version") || 0;
let currentVersion = document.documentElement.getAttribute("snippetsVersion");
if (cachedVersion < currentVersion) {
// The cached snippets are old and unsupported, restart from scratch.
gSnippetsMap.clear();
}
// Check last snippets update.
let lastUpdate = localStorage["snippets-last-update"];
let lastUpdate = gSnippetsMap.get("snippets-last-update");
let updateURL = document.documentElement.getAttribute("snippetsURL");
if (updateURL && (!lastUpdate ||
Date.now() - lastUpdate > SNIPPETS_UPDATE_INTERVAL_MS)) {
let shouldUpdate = !lastUpdate ||
Date.now() - lastUpdate > SNIPPETS_UPDATE_INTERVAL_MS;
if (updateURL && shouldUpdate) {
// Try to update from network.
let xhr = new XMLHttpRequest();
try {
@ -174,14 +254,15 @@ function loadSnippets()
}
// Even if fetching should fail we don't want to spam the server, thus
// set the last update time regardless its results. Will retry tomorrow.
localStorage["snippets-last-update"] = Date.now();
gSnippetsMap.set("snippets-last-update", Date.now());
xhr.onerror = function (event) {
showSnippets();
};
xhr.onload = function (event)
{
if (xhr.status == 200) {
localStorage["snippets"] = xhr.responseText;
gSnippetsMap.set("snippets", xhr.responseText);
gSnippetsMap.set("snippets-cached-version", currentVersion);
}
showSnippets();
};
@ -191,10 +272,27 @@ function loadSnippets()
}
}
/**
* Shows locally cached remote snippets, or default ones when not available.
*
* @note: snippets should never invoke showSnippets(), or they may cause
* a "too much recursion" exception.
*/
let _snippetsShown = false;
function showSnippets()
{
if (!gSnippetsMap)
throw new Error("Snippets map has not properly been initialized");
if (_snippetsShown) {
// There's something wrong with the remote snippets, just in case fall back
// to the default snippets.
showDefaultSnippets();
throw new Error("showSnippets should never be invoked multiple times");
}
_snippetsShown = true;
let snippetsElt = document.getElementById("snippets");
let snippets = localStorage["snippets"];
let snippets = gSnippetsMap.get("snippets");
// If there are remotely fetched snippets, try to to show them.
if (snippets) {
// Injecting snippets can throw if they're invalid XML.
@ -214,7 +312,19 @@ function showSnippets()
}
}
// Show default snippets otherwise.
showDefaultSnippets();
}
/**
* Clear snippets element contents and show default snippets.
*/
function showDefaultSnippets()
{
// Clear eventual contents...
let snippetsElt = document.getElementById("snippets");
snippetsElt.innerHTML = "";
// ...then show default snippets.
let defaultSnippetsElt = document.getElementById("defaultSnippets");
let entries = defaultSnippetsElt.querySelectorAll("span");
// Choose a random snippet. Assume there is always at least one.

View File

@ -351,14 +351,15 @@ let SocialChatBar = {
return !!this.chatbar.firstElementChild;
},
openChat: function(aProvider, aURL, aCallback, aMode) {
if (this.isAvailable) {
this.chatbar.openChat(aProvider, aURL, aCallback, aMode);
// We only want to focus the chat if it is as a result of user input.
let dwu = window.QueryInterface(Ci.nsIInterfaceRequestor)
.getInterface(Ci.nsIDOMWindowUtils);
if (dwu.isHandlingUserInput)
this.chatbar.focus();
}
if (!this.isAvailable)
return false;
this.chatbar.openChat(aProvider, aURL, aCallback, aMode);
// We only want to focus the chat if it is as a result of user input.
let dwu = window.QueryInterface(Ci.nsIInterfaceRequestor)
.getInterface(Ci.nsIDOMWindowUtils);
if (dwu.isHandlingUserInput)
this.chatbar.focus();
return true;
},
update: function() {
let command = document.getElementById("Social:FocusChat");

View File

@ -627,4 +627,5 @@ chatbox {
chatbar {
-moz-binding: url("chrome://browser/content/socialchat.xml#chatbar");
height: 0;
max-height: 0;
}

View File

@ -2630,6 +2630,7 @@ function BrowserOnAboutPageLoad(doc) {
// Inject search engine and snippets URL.
let docElt = doc.documentElement;
docElt.setAttribute("snippetsURL", AboutHomeUtils.snippetsURL);
docElt.setAttribute("snippetsVersion", AboutHomeUtils.snippetsVersion);
docElt.setAttribute("searchEngineName",
AboutHomeUtils.defaultSearchEngine.name);
docElt.setAttribute("searchEngineURL",

View File

@ -2,6 +2,13 @@
* http://creativecommons.org/publicdomain/zero/1.0/
*/
XPCOMUtils.defineLazyModuleGetter(this, "Promise",
"resource://gre/modules/commonjs/sdk/core/promise.js");
XPCOMUtils.defineLazyModuleGetter(this, "Task",
"resource://gre/modules/Task.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "AboutHomeUtils",
"resource:///modules/AboutHomeUtils.jsm");
registerCleanupFunction(function() {
// Ensure we don't pollute prefs for next tests.
try {
@ -22,56 +29,48 @@ let gTests = [
.getService(Ci.nsIObserver)
.observe(null, "cookie-changed", "cleared");
},
run: function ()
run: function (aSnippetsMap)
{
let storage = getStorage();
isnot(storage.getItem("snippets-last-update"), null);
executeSoon(runNextTest);
isnot(aSnippetsMap.get("snippets-last-update"), null);
}
},
{
desc: "Check default snippets are shown",
setup: function ()
{
},
setup: function () { },
run: function ()
{
let doc = gBrowser.selectedTab.linkedBrowser.contentDocument;
let snippetsElt = doc.getElementById("snippets");
ok(snippetsElt, "Found snippets element")
is(snippetsElt.getElementsByTagName("span").length, 1,
"A default snippet is visible.");
executeSoon(runNextTest);
"A default snippet is present.");
}
},
{
desc: "Check default snippets are shown if snippets are invalid xml",
setup: function ()
setup: function (aSnippetsMap)
{
let storage = getStorage();
// This must be some incorrect xhtml code.
storage.setItem("snippets", "<p><b></p></b>");
aSnippetsMap.set("snippets", "<p><b></p></b>");
},
run: function ()
run: function (aSnippetsMap)
{
let doc = gBrowser.selectedTab.linkedBrowser.contentDocument;
let snippetsElt = doc.getElementById("snippets");
ok(snippetsElt, "Found snippets element");
is(snippetsElt.getElementsByTagName("span").length, 1,
"A default snippet is visible.");
let storage = getStorage();
storage.removeItem("snippets");
executeSoon(runNextTest);
"A default snippet is present.");
aSnippetsMap.delete("snippets");
}
},
{
desc: "Check that search engine logo has alt text",
setup: function ()
{
},
setup: function () { },
run: function ()
{
let doc = gBrowser.selectedTab.linkedBrowser.contentDocument;
@ -85,27 +84,29 @@ let gTests = [
isnot(altText, "undefined",
"Search engine logo's alt text shouldn't be the string 'undefined'");
executeSoon(runNextTest);
}
},
{
desc: "Check that performing a search fires a search event.",
setup: function () { },
run: function () {
let deferred = Promise.defer();
let doc = gBrowser.contentDocument;
doc.addEventListener("AboutHomeSearchEvent", function onSearch(e) {
is(e.detail, doc.documentElement.getAttribute("searchEngineName"), "Detail is search engine name");
gBrowser.stop();
executeSoon(runNextTest);
deferred.resolve();
}, true, true);
doc.getElementById("searchText").value = "it works";
doc.getElementById("searchSubmit").click();
},
return deferred.promise;
}
},
{
desc: "Check that performing a search records to Firefox Health Report.",
setup: function () { },
@ -115,10 +116,10 @@ let gTests = [
cm.getCategoryEntry("healthreport-js-provider", "SearchesProvider");
} catch (ex) {
// Health Report disabled, or no SearchesProvider.
runNextTest();
return;
}
let deferred = Promise.defer();
let doc = gBrowser.contentDocument;
// We rely on the listener in browser.js being installed and fired before
@ -149,7 +150,7 @@ let gTests = [
// Note the search from the previous test.
is(day.get(field), 2, "Have searches recorded.");
executeSoon(runNextTest);
deferred.resolve();
});
});
@ -157,62 +158,156 @@ let gTests = [
doc.getElementById("searchText").value = "a search";
doc.getElementById("searchSubmit").click();
},
return deferred.promise;
}
},
{
desc: "Check snippets map is cleared if cached version is old",
setup: function (aSnippetsMap)
{
aSnippetsMap.set("snippets", "test");
aSnippetsMap.set("snippets-cached-version", 0);
},
run: function (aSnippetsMap)
{
ok(!aSnippetsMap.has("snippets"), "snippets have been properly cleared");
ok(!aSnippetsMap.has("snippets-cached-version"),
"cached-version has been properly cleared");
}
},
{
desc: "Check cached snippets are shown if cached version is current",
setup: function (aSnippetsMap)
{
aSnippetsMap.set("snippets", "test");
},
run: function (aSnippetsMap)
{
let doc = gBrowser.selectedTab.linkedBrowser.contentDocument;
let snippetsElt = doc.getElementById("snippets");
ok(snippetsElt, "Found snippets element");
is(snippetsElt.innerHTML, "test", "Cached snippet is present.");
is(aSnippetsMap.get("snippets"), "test", "snippets still cached");
is(aSnippetsMap.get("snippets-cached-version"),
AboutHomeUtils.snippetsVersion,
"cached-version is correct");
ok(aSnippetsMap.has("snippets-last-update"), "last-update still exists");
}
},
];
function test()
{
waitForExplicitFinish();
// Ensure that by default we don't try to check for remote snippets since that
// could be tricky due to network bustages or slowness.
let storage = getStorage();
storage.setItem("snippets-last-update", Date.now());
storage.removeItem("snippets");
Task.spawn(function () {
for (let test of gTests) {
info(test.desc);
executeSoon(runNextTest);
}
let tab = yield promiseNewTabLoadEvent("about:home", "DOMContentLoaded");
function runNextTest()
{
while (gBrowser.tabs.length > 1) {
gBrowser.removeCurrentTab();
}
// Must wait for both the snippets map and the browser attributes, since
// can't guess the order they will happen.
// So, start listening now, but verify the promise is fulfilled only
// after the snippets map setup.
let promise = promiseBrowserAttributes(tab);
// Prepare the snippets map with default values, then run the test setup.
let snippetsMap = yield promiseSetupSnippetsMap(tab, test.setup);
// Ensure browser has set attributes already, or wait for them.
yield promise;
if (gTests.length) {
let test = gTests.shift();
info(test.desc);
test.setup();
let tab = gBrowser.selectedTab = gBrowser.addTab("about:home");
tab.linkedBrowser.addEventListener("load", function load(event) {
tab.linkedBrowser.removeEventListener("load", load, true);
yield test.run(snippetsMap);
gBrowser.removeCurrentTab();
}
let observer = new MutationObserver(function (mutations) {
for (let mutation of mutations) {
if (mutation.attributeName == "searchEngineURL") {
observer.disconnect();
executeSoon(test.run);
return;
}
}
});
let docElt = tab.linkedBrowser.contentDocument.documentElement;
observer.observe(docElt, { attributes: true });
}, true);
}
else {
finish();
}
});
}
function getStorage()
/**
* Creates a new tab and waits for a load event.
*
* @param aUrl
* The url to load in a new tab.
* @param aEvent
* The load event type to wait for. Defaults to "load".
* @return {Promise} resolved when the event is handled. Gets the new tab.
*/
function promiseNewTabLoadEvent(aUrl, aEventType="load")
{
let aboutHomeURI = Services.io.newURI("moz-safe-about:home", null, null);
let principal = Components.classes["@mozilla.org/scriptsecuritymanager;1"].
getService(Components.interfaces.nsIScriptSecurityManager).
getNoAppCodebasePrincipal(Services.io.newURI("about:home", null, null));
let dsm = Components.classes["@mozilla.org/dom/storagemanager;1"].
getService(Components.interfaces.nsIDOMStorageManager);
return dsm.getLocalStorageForPrincipal(principal, "");
};
let deferred = Promise.defer();
let tab = gBrowser.selectedTab = gBrowser.addTab(aUrl);
tab.linkedBrowser.addEventListener(aEventType, function load(event) {
tab.linkedBrowser.removeEventListener(aEventType, load, true);
deferred.resolve(tab);
}, true);
return deferred.promise;
}
/**
* Cleans up snippets and ensures that by default we don't try to check for
* remote snippets since that may cause network bustage or slowness.
*
* @param aTab
* The tab containing about:home.
* @param aSetupFn
* The setup function to be run.
* @return {Promise} resolved when the snippets are ready. Gets the snippets map.
*/
function promiseSetupSnippetsMap(aTab, aSetupFn)
{
let deferred = Promise.defer();
let cw = aTab.linkedBrowser.contentWindow.wrappedJSObject;
cw.ensureSnippetsMapThen(function (aSnippetsMap) {
// Don't try to update.
aSnippetsMap.set("snippets-last-update", Date.now());
aSnippetsMap.set("snippets-cached-version", AboutHomeUtils.snippetsVersion);
// Clear snippets.
aSnippetsMap.delete("snippets");
aSetupFn(aSnippetsMap);
// Must be sure to continue after the page snippets map setup.
executeSoon(function() deferred.resolve(aSnippetsMap));
});
return deferred.promise;
}
/**
* Waits for the attributes being set by browser.js and overwrites snippetsURL
* to ensure we won't try to hit the network and we can force xhr to throw.
*
* @param aTab
* The tab containing about:home.
* @return {Promise} resolved when the attributes are ready.
*/
function promiseBrowserAttributes(aTab)
{
let deferred = Promise.defer();
let docElt = aTab.linkedBrowser.contentDocument.documentElement;
//docElt.setAttribute("snippetsURL", "nonexistent://test");
let observer = new MutationObserver(function (mutations) {
for (let mutation of mutations) {
if (mutation.attributeName == "snippetsURL" &&
docElt.getAttribute("snippetsURL") != "nonexistent://test") {
docElt.setAttribute("snippetsURL", "nonexistent://test");
}
// Now we just have to wait for the last attribute.
if (mutation.attributeName == "searchEngineURL") {
observer.disconnect();
// Must be sure to continue after the page mutation observer.
executeSoon(function() deferred.resolve());
break;
}
}
});
observer.observe(docElt, { attributes: true });
return deferred.promise;
}

View File

@ -248,6 +248,19 @@ var tests = {
// cause focus to move between all elements in our chat window before moving
// to the next chat window.
testTab: function(next) {
function sendTabAndWaitForFocus(chat, eltid, callback) {
// ideally we would use the 'focus' event here, but that doesn't work
// as expected for the iframe - the iframe itself never gets the focus
// event (apparently the sub-document etc does.)
// So just poll for the correct element getting focus...
let doc = chat.iframe.contentDocument;
EventUtils.sendKey("tab");
waitForCondition(function() {
let elt = eltid ? doc.getElementById(eltid) : doc.documentElement;
return doc.activeElement == elt;
}, callback, "element " + eltid + " never got focus");
}
let chatbar = SocialChatBar.chatbar;
startTestAndWaitForSidebar(function(port) {
openChatViaSidebarMessage(port, {id: 1}, function() {
@ -259,22 +272,27 @@ var tests = {
ok(isChatFocused(chat2), "new chat is focused");
// Our chats have 3 focusable elements, so it takes 4 TABs to move
// to the new chat.
EventUtils.sendKey("tab");
ok(isChatFocused(chat2), "new chat still focused after first tab");
is(chat2.iframe.contentDocument.activeElement.getAttribute("id"), "input1",
"first input field has focus");
EventUtils.sendKey("tab");
ok(isChatFocused(chat2), "new chat still focused after tab");
is(chat2.iframe.contentDocument.activeElement.getAttribute("id"), "input2",
"second input field has focus");
EventUtils.sendKey("tab");
ok(isChatFocused(chat2), "new chat still focused after tab");
is(chat2.iframe.contentDocument.activeElement.getAttribute("id"), "iframe",
"iframe has focus");
// this tab now should move to the next chat.
EventUtils.sendKey("tab");
ok(isChatFocused(chat1), "first chat is focused");
next();
sendTabAndWaitForFocus(chat2, "input1", function() {
is(chat2.iframe.contentDocument.activeElement.getAttribute("id"), "input1",
"first input field has focus");
ok(isChatFocused(chat2), "new chat still focused after first tab");
sendTabAndWaitForFocus(chat2, "input2", function() {
ok(isChatFocused(chat2), "new chat still focused after tab");
is(chat2.iframe.contentDocument.activeElement.getAttribute("id"), "input2",
"second input field has focus");
sendTabAndWaitForFocus(chat2, "iframe", function() {
ok(isChatFocused(chat2), "new chat still focused after tab");
is(chat2.iframe.contentDocument.activeElement.getAttribute("id"), "iframe",
"iframe has focus");
// this tab now should move to the next chat, but focus the
// document element itself (hence the null eltid)
sendTabAndWaitForFocus(chat1, null, function() {
ok(isChatFocused(chat1), "first chat is focused");
next();
});
});
});
});
});
});
});

View File

@ -13,9 +13,10 @@
!define URLInfoAbout "http://www.mozilla.com/${AB_CD}/"
!define URLUpdateInfo "http://www.mozilla.com/${AB_CD}/firefox/"
; Prevents the beta channel urls in stub.nsi from being used when not using
; official branding
!define Official
; The OFFICIAL define is a workaround to support different urls for Release and
; Beta since they share the same branding when building with other branches that
; set the update channel to beta.
!define OFFICIAL
!define URLStubDownload "http://download.mozilla.org/?product=firefox-latest&os=win&lang=${AB_CD}"
!define URLManualDownload "https://www.mozilla.org/firefox/installer-help/?channel=release"
!define Channel "release"

View File

@ -122,7 +122,7 @@ var MigrationWizard = {
this._selectedProfile = null;
}
this._source = newSource;
// check for more than one source profile
var sourceProfiles = this._migrator.sourceProfiles;
if (sourceProfiles && sourceProfiles.length > 1) {

View File

@ -11,6 +11,9 @@ var gTab = null;
var gDebuggee = null;
function test() {
// Windows XP test slaves are terribly slow at this test.
requestLongerTimeout(2);
debug_chrome(STACK_URL, aOnClosing, function(aTab, aDebuggee, aProcess) {
gTab = aTab;
gDebuggee = aDebuggee;

View File

@ -29,13 +29,19 @@
# The value below removes all LSP categories previously set.
!define LSP_CATEGORIES "0x00000000"
!if "@MOZ_UPDATE_CHANNEL@" == ""
!define UpdateChannel "Unknown"
!else
!define UpdateChannel "@MOZ_UPDATE_CHANNEL@"
!endif
# Due to official and beta using the same branding this is needed to
# differentiante between the url used by the stub for downloading.
!if "@MOZ_UPDATE_CHANNEL@" == "beta"
!define BETA_UPDATE_CHANNEL
!endif
!define BaseURLStubPing "http://download-stats.mozilla.org/stub/v4/"
!define BaseURLStubPing "http://download-stats.mozilla.org/stub"
# NO_INSTDIR_FROM_REG is defined for pre-releases which have a PreReleaseSuffix
# (e.g. Alpha X, Beta X, etc.) to prevent finding a non-default installation

View File

@ -56,7 +56,7 @@ Var CanWriteToInstallDir
Var HasRequiredSpaceAvailable
Var IsDownloadFinished
Var Initialized
Var DownloadSize
Var DownloadSizeBytes
Var HalfOfDownload
Var DownloadReset
Var ExistingTopDir
@ -64,33 +64,111 @@ Var SpaceAvailableBytes
Var InitialInstallDir
Var HandleDownload
Var CanSetAsDefault
Var TmpVal
Var InstallCounterStep
Var TmpVal
Var ExitCode
Var StartTickCount
Var DownloadTickCount
Var InstallTickCount
Var FinishTickCount
Var FirefoxLaunchCode
; The first three tick counts are for the start of a phase and equate equate to
; the display of individual installer pages.
Var StartIntroPhaseTickCount
Var StartOptionsPhaseTickCount
Var StartDownloadPhaseTickCount
; Since the Intro and Options pages can be displayed multiple times the total
; seconds spent on each of these pages is reported.
Var IntroPhaseSeconds
Var OptionsPhaseSeconds
; The tick count for the last download
Var StartLastDownloadTickCount
; The number of seconds from the start of the download phase until the first
; bytes are received. This is only recorded for first request so it is possible
; to determine connection issues for the first request.
Var DownloadFirstTransferSeconds
; The last four tick counts are for the end of a phase in the installation page.
; the options phase when it isn't entered.
Var EndDownloadPhaseTickCount
Var EndPreInstallPhaseTickCount
Var EndInstallPhaseTickCount
Var EndFinishPhaseTickCount
Var IntroPageShownCount
Var OptionsPageShownCount
Var InitialInstallRequirementsCode
Var ExistingProfile
Var ExistingInstall
Var DownloadedAmount
Var FirefoxLaunch
Var ExistingVersion
Var ExistingBuildID
Var DownloadedBytes
Var DownloadRetryCount
Var OpenedDownloadPage
Var DownloadServerIP
Var HEIGHT_PX
Var CTL_RIGHT_PX
Var ControlHeightPX
Var ControlRightPX
; Uncomment the following to prevent pinging the metrics server when testing
; the stub installer
;!define STUB_DEBUG
!define StubURLVersion "v5"
; Successful install exit code
!define ERR_SUCCESS 0
!define ERR_CANCEL_DOWNLOAD 10
!define ERR_INVALID_HANDLE 11
!define ERR_CERT_UNTRUSTED 12
!define ERR_CERT_ATTRIBUTES 13
!define ERR_CERT_UNTRUSTED_AND_ATTRIBUTES 14
!define ERR_CHECK_INSTALL_TIMEOUT 15
!define ERR_UNKNOWN 99
!define DownloadIntervalMS 200 ; Interval for the download timer
!define InstallIntervalMS 100 ; Interval for the install timer
/**
* The following errors prefixed with ERR_DOWNLOAD apply to the download phase.
*/
; The download was cancelled by the user
!define ERR_DOWNLOAD_CANCEL 10
; Too many attempts to download. The maximum attempts is defined in
; DownloadMaxRetries.
!define ERR_DOWNLOAD_TOO_MANY_RETRIES 11
/**
* The following errors prefixed with ERR_PREINSTALL apply to the pre-install
* check phase.
*/
; Unable to acquire a file handle to the downloaded file
!define ERR_PREINSTALL_INVALID_HANDLE 20
; The downloaded file's certificate is not trusted by the certificate store.
!define ERR_PREINSTALL_CERT_UNTRUSTED 21
; The downloaded file's certificate attribute values were incorrect.
!define ERR_PREINSTALL_CERT_ATTRIBUTES 22
; The downloaded file's certificate is not trusted by the certificate store and
; certificate attribute values were incorrect.
!define ERR_PREINSTALL_CERT_UNTRUSTED_AND_ATTRIBUTES 23
/**
* The following errors prefixed with ERR_INSTALL apply to the install phase.
*/
; The installation timed out. The installation timeout is defined by the number
; of progress steps defined in InstallProgresSteps and the install timer
; interval defined in InstallIntervalMS
!define ERR_INSTALL_TIMEOUT 30
; Maximum times to retry the download before displaying an error
!define DownloadMaxRetries 9
; Minimum size expected to download in bytes
!define DownloadMinSizeBytes 15728640 ; 15 MB
; Maximum size expected to download in bytes
!define DownloadMaxSizeBytes 36700160 ; 35 MB
; Interval before retrying to download. 3 seconds is used along with 10
; attempted downloads (the first attempt along with 9 retries) to give a
; minimum of 30 seconds or retrying before giving up.
!define DownloadRetryIntervalMS 3000
; Interval for the download timer
!define DownloadIntervalMS 200
; Interval for the install timer
!define InstallIntervalMS 100
; Number of steps for the install progress.
; This is 120 seconds with a 100 millisecond timer and a first step of 20 as
@ -99,10 +177,14 @@ Var CTL_RIGHT_PX
; if it reaches this number. The size of the install progress step increases
; when the full installer finishes instead of waiting the entire 120 seconds.
!define InstallProgresSteps 1220
; The first step for the install progress bar. By starting with a large step
; immediate feedback is given to the user.
!define InstallProgressFirstStep 20
; The interval in MS used for the progress bars set as marquee.
!define ProgressbarMarqueeIntervalMS 10
; On Vista and above attempt to elevate Standard Users in addition to users that
; are a member of the Administrators group.
!define NONADMIN_ELEVATE
@ -114,10 +196,7 @@ Var CTL_RIGHT_PX
!define FILE_SHARE_READ 1
!define GENERIC_READ 0x80000000
!define OPEN_EXISTING 3
!define FILE_BEGIN 0
!define FILE_END 2
!define INVALID_HANDLE_VALUE -1
!define INVALID_FILE_SIZE 0xffffffff
!include "nsDialogs.nsh"
!include "LogicLib.nsh"
@ -134,9 +213,10 @@ Var CTL_RIGHT_PX
!include "defines.nsi"
; Workaround to support different urls for Official and Beta since they share
; the same branding.
!ifdef Official
; The OFFICIAL define is a workaround to support different urls for Release and
; Beta since they share the same branding when building with other branches that
; set the update channel to beta.
!ifdef OFFICIAL
!ifdef BETA_UPDATE_CHANNEL
!undef URLStubDownload
!define URLStubDownload "http://download.mozilla.org/?product=firefox-beta-latest&os=win&lang=${AB_CD}"
@ -202,7 +282,7 @@ Caption "$(WIN_CAPTION)"
Page custom createDummy ; Needed to enable the Intro page's back button
Page custom createIntro leaveIntro ; Introduction page
Page custom createOptions leaveOptions ; Options page
Page custom createInstall leaveInstall ; Download / Installation page
Page custom createInstall ; Download / Installation page
Function .onInit
; Remove the current exe directory from the search order.
@ -240,7 +320,7 @@ Function .onInit
; and possibly the IsWinXP test as well. To work around this also
; check if the Windows NT registry Key exists and if it does if the
; first char in CurrentVersion is equal to 3 (Windows NT 3.5 and
; 3.5.1), to 4 (Windows NT 4) or 5 (Windows 2000 and Windows XP).
; 3.5.1), 4 (Windows NT 4), or 5 (Windows 2000 and Windows XP).
StrCpy $R8 ""
ClearErrors
ReadRegStr $R8 HKLM "SOFTWARE\Microsoft\Windows NT\CurrentVersion" "CurrentVersion"
@ -318,9 +398,17 @@ Function .onInit
StrCpy $CanSetAsDefault "true"
${EndIf}
; Initialize the majority of variables except those that need to be reset
; when a page is displayed.
StrCpy $IntroPhaseSeconds "0"
StrCpy $OptionsPhaseSeconds "0"
StrCpy $EndPreInstallPhaseTickCount "0"
StrCpy $EndInstallPhaseTickCount "0"
StrCpy $IntroPageShownCount "0"
StrCpy $OptionsPageShownCount "0"
StrCpy $InitialInstallRequirementsCode ""
StrCpy $IsDownloadFinished ""
StrCpy $FirefoxLaunch "0"
StrCpy $ExitCode "${ERR_UNKNOWN}"
StrCpy $FirefoxLaunchCode "0"
CreateFont $FontBlurb "$(^Font)" "12" "500"
CreateFont $FontNormal "$(^Font)" "11" "500"
@ -352,45 +440,6 @@ FunctionEnd
!endif
Function .onGUIEnd
; Try to send a ping if a download was attempted
${If} $IsDownloadFinished != ""
${AndIf} $CheckboxSendPing == 1
${If} $IsDownloadFinished == "false"
; When the value of $IsDownloadFinished is false the download was started
; but didn't finish and GetTickCount needs to be called to determine how
; long the download was in progress.
System::Call "kernel32::GetTickCount()l .s"
Pop $DownloadTickCount
StrCpy $1 "0"
StrCpy $2 "0"
; Cancel the download in progress
InetBgDL::Get /RESET /END
${Else}
; Get the tick count for when the installer closes.
System::Call "kernel32::GetTickCount()l .s"
Pop $FinishTickCount
; Get the time from the end of the install to close the installer.
${GetSecondsElapsed} "$InstallTickCount" "$FinishTickCount" $2
; Get the time from the end of the download to the completion of the
; installation.
${GetSecondsElapsed} "$DownloadTickCount" "$InstallTickCount" $1
${EndIf}
; Get the time from the start of the download to the end of the download.
${GetSecondsElapsed} "$StartTickCount" "$DownloadTickCount" $0
System::Int64Op $DownloadedAmount / 1024
Pop $DownloadedAmount
InetBgDL::Get "${BaseURLStubPing}${Channel}/${AB_CD}/$ExitCode/$FirefoxLaunch/$DownloadedAmount/$0/$1/$2/$ExistingProfile/$ExistingInstall/" \
"$PLUGINSDIR\_temp" /END
${ElseIf} $IsDownloadFinished == "false"
; Cancel the download in progress
InetBgDL::Get /RESET /END
${EndIf}
${UnloadUAC}
FunctionEnd
@ -405,6 +454,183 @@ Function .onUserAbort
Delete "$PLUGINSDIR\_temp"
Delete "$PLUGINSDIR\download.exe"
Delete "$PLUGINSDIR\${CONFIG_INI}"
${If} "$IsDownloadFinished" == ""
${OrIf} $CheckboxSendPing != 1
; When not sending a ping cancel the download if it is in progress and exit
; the installer.
${If} "$IsDownloadFinished" == "false"
HideWindow
InetBgDL::Get /RESET /END
${EndIf}
${Else}
Call SendPing
; Aborting the abort will allow SendPing to hide the installer window and
; close the installer after it sends the metrics ping.
Abort
${EndIf}
FunctionEnd
Function SendPing
HideWindow
; Try to send a ping if a download was attempted
${If} $CheckboxSendPing == 1
${AndIf} $IsDownloadFinished != ""
; Get the tick count for the completion of all phases.
System::Call "kernel32::GetTickCount()l .s"
Pop $EndFinishPhaseTickCount
; When the value of $IsDownloadFinished is false the download was started
; but didn't finish. In this case the tick count stored in
; $EndFinishPhaseTickCount is used to determine how long the download was
; in progress.
${If} "$IsDownloadFinished" == "false"
StrCpy $EndDownloadPhaseTickCount "$EndFinishPhaseTickCount"
; Cancel the download in progress
InetBgDL::Get /RESET /END
${EndIf}
; When $DownloadFirstTransferSeconds equals an empty string the download
; never successfully started so set the value to 0. It will be possible to
; determine that the download didn't successfully start from the seconds for
; the last download.
${If} "$DownloadFirstTransferSeconds" == ""
StrCpy $DownloadFirstTransferSeconds "0"
${EndIf}
; When $StartLastDownloadTickCount equals 0 the download never successfully
; started so set the value to $EndDownloadPhaseTickCount to compute the
; correct value.
${If} $StartLastDownloadTickCount == "0"
; This could happen if the download never successfully starts
StrCpy $StartLastDownloadTickCount "$EndDownloadPhaseTickCount"
${EndIf}
; When $EndPreInstallPhaseTickCount equals 0 the installation phase was
; never completed so set its value to $EndFinishPhaseTickCount to compute
; the correct value.
${If} "$EndPreInstallPhaseTickCount" == "0"
StrCpy $EndPreInstallPhaseTickCount "$EndFinishPhaseTickCount"
${EndIf}
; When $EndInstallPhaseTickCount equals 0 the installation phase was never
; completed so set its value to $EndFinishPhaseTickCount to compute the
; correct value.
${If} "$EndInstallPhaseTickCount" == "0"
StrCpy $EndInstallPhaseTickCount "$EndFinishPhaseTickCount"
${EndIf}
; Get the seconds elapsed from the start of the download phase to the end of
; the download phase.
${GetSecondsElapsed} "$StartDownloadPhaseTickCount" "$EndDownloadPhaseTickCount" $0
; Get the seconds elapsed from the start of the last download to the end of
; the last download.
${GetSecondsElapsed} "$StartLastDownloadTickCount" "$EndDownloadPhaseTickCount" $1
; Get the seconds elapsed from the end of the download phase to the
; completion of the pre-installation check phase.
${GetSecondsElapsed} "$EndDownloadPhaseTickCount" "$EndPreInstallPhaseTickCount" $2
; Get the seconds elapsed from the end of the pre-installation check phase
; to the completion of the installation phase.
${GetSecondsElapsed} "$EndPreInstallPhaseTickCount" "$EndInstallPhaseTickCount" $3
; Get the seconds elapsed from the end of the installation phase to the
; completion of all phases.
${GetSecondsElapsed} "$EndInstallPhaseTickCount" "$EndFinishPhaseTickCount" $4
!ifdef HAVE_64BIT_OS
StrCpy $R0 "1"
!else
StrCpy $R0 "0"
!endif
${If} ${RunningX64}
StrCpy $R1 "1"
${Else}
StrCpy $R1 "0"
${EndIf}
${WinVerGetMajor} $R2
${WinVerGetMinor} $R3
${WinVerGetBuild} $R4
${If} "$ExitCode" == "${ERR_SUCCESS}"
ReadINIStr $R5 "$INSTDIR\application.ini" "App" "Version"
ReadINIStr $R6 "$INSTDIR\application.ini" "App" "BuildID"
${Else}
StrCpy $R5 "0"
StrCpy $R6 "0"
${EndIf}
; Whether installed into the default installation directory
${GetLongPath} "$INSTDIR" $R7
${GetLongPath} "$InitialInstallDir" $R8
${If} "$R7" == "$R8"
StrCpy $R7 "1"
${Else}
StrCpy $R7 "0"
${EndIf}
ClearErrors
WriteRegStr HKLM "Software\Mozilla" "${BrandShortName}InstallerTest" \
"Write Test"
${If} ${Errors}
StrCpy $R8 "0"
${Else}
DeleteRegValue HKLM "Software\Mozilla" "${BrandShortName}InstallerTest"
StrCpy $R8 "1"
${EndIf}
${If} "$DownloadServerIP" == ""
StrCpy $DownloadServerIP "Unknown"
${EndIf}
!ifdef STUB_DEBUG
MessageBox MB_OK "${BaseURLStubPing} \
$\nStub URL Version = ${StubURLVersion} \
$\nBuild Channel = ${Channel} \
$\nUpdate Channel = ${UpdateChannel} \
$\nLocale = ${AB_CD} \
$\nFirefox x64 = $R0 \
$\nRunning x64 Windows = $R1 \
$\nMajor = $R2 \
$\nMinor = $R3 \
$\nBuild = $R4 \
$\nExit Code = $ExitCode \
$\nFirefox Launch Code = $FirefoxLaunchCode \
$\nDownload Retry Count = $DownloadRetryCount \
$\nDownloaded Bytes = $DownloadedBytes \
$\nIntroduction Phase Seconds = $IntroPhaseSeconds \
$\nOptions Phase Seconds = $OptionsPhaseSeconds \
$\nDownload Phase Seconds = $0 \
$\nDownload First Transfer Seconds = $DownloadFirstTransferSeconds \
$\nLast Download Seconds = $1 \
$\nPreinstall Phase Seconds = $2 \
$\nInstall Phase Seconds = $3 \
$\nFinish Phase Seconds = $4 \
$\nIntro Page Shown Count = $IntroPageShownCount \
$\nOptions Page Shown Count = $OptionsPageShownCount \
$\nInitial Install Requirements Code = $InitialInstallRequirementsCode \
$\nOpened Download Page = $OpenedDownloadPage \
$\nExisting Profile = $ExistingProfile \
$\nExisting Version = $ExistingVersion \
$\nExisting Build ID = $ExistingBuildID \
$\nNew Version = $R5 \
$\nNew Build ID = $R6 \
$\nDefault Install Dir = $R7 \
$\nHas Admin = $R8 \
$\nDownload Server IP = $DownloadServerIP"
!else
${NSD_CreateTimer} OnPing ${DownloadIntervalMS}
InetBgDL::Get "${BaseURLStubPing}/${StubURLVersion}/${Channel}/${UpdateChannel}/${AB_CD}/$R0/$R1/$R2/$R3/$R4/$ExitCode/$FirefoxLaunchCode/$DownloadRetryCount/$DownloadedBytes/$IntroPhaseSeconds/$OptionsPhaseSeconds/$0/$1/$DownloadFirstTransferSeconds/$2/$3/$4/$IntroPageShownCount/$OptionsPageShownCount/$InitialInstallRequirementsCode/$OpenedDownloadPage/$ExistingProfile/$ExistingVersion/$ExistingBuildID/$R5/$R6/$R7/$R8/$DownloadServerIP" \
"$PLUGINSDIR\_temp" /END
!endif
${ElseIf} "$IsDownloadFinished" == "false"
; Cancel the download in progress
InetBgDL::Get /RESET /END
${EndIf}
FunctionEnd
Function createDummy
@ -422,12 +648,11 @@ Function createIntro
!else
StrCpy $CheckboxInstallMaintSvc "0"
!endif
StrCpy $WasOptionsButtonClicked "0"
nsDialogs::Create /NOUNLOAD 1018
Pop $Dialog
StrCpy $WasOptionsButtonClicked ""
GetFunctionAddress $0 OnBack
nsDialogs::OnBack /NOUNLOAD $0
@ -443,12 +668,20 @@ Function createIntro
SendMessage $0 ${WM_SETFONT} $FontBlurb 0
SetCtlColors $0 ${INTRO_BLURB_TEXT_COLOR} transparent
${Unless} $Initialized == "true"
${If} "$Initialized" == "true"
; When the user clicked back from the options page.
System::Call "kernel32::GetTickCount()l .s"
Pop $0
${GetSecondsElapsed} "$StartOptionsPhaseTickCount" "$0" $1
; This is added to the previous value of $OptionsPhaseSeconds because the
; options page can be displayed multiple times.
IntOp $OptionsPhaseSeconds $OptionsPhaseSeconds + $1
${Else}
SetCtlColors $HWNDPARENT ${FOOTER_CONTROL_TEXT_COLOR_NORMAL} ${FOOTER_BKGRD_COLOR}
GetDlgItem $0 $HWNDPARENT 10 ; Default browser checkbox
; Set as default is not supported in the installer for Win8 and above so
; only display it on Windows 7 and below
${If} $CanSetAsDefault == "true"
${If} "$CanSetAsDefault" == "true"
; The uxtheme must be disabled on checkboxes in order to override the
; system font color.
System::Call 'uxtheme::SetWindowTheme(i $0 , w " ", w " ")'
@ -461,7 +694,7 @@ Function createIntro
${EndIf}
GetDlgItem $0 $HWNDPARENT 11
ShowWindow $0 ${SW_HIDE}
${EndUnless}
${EndIf}
${NSD_CreateBitmap} ${APPNAME_BMP_EDGE_DU} ${APPNAME_BMP_TOP_DU} \
${APPNAME_BMP_WIDTH_DU} ${APPNAME_BMP_HEIGHT_DU} ""
@ -482,6 +715,11 @@ Function createIntro
GetDlgItem $0 $HWNDPARENT 3 ; Back and Options button
SendMessage $0 ${WM_SETTEXT} 0 "STR:$(OPTIONS_BUTTON)"
IntOp $IntroPageShownCount $IntroPageShownCount + 1
System::Call "kernel32::GetTickCount()l .s"
Pop $StartIntroPhaseTickCount
LockWindow off
nsDialogs::Show
@ -493,6 +731,14 @@ FunctionEnd
Function leaveIntro
LockWindow on
System::Call "kernel32::GetTickCount()l .s"
Pop $0
${GetSecondsElapsed} "$StartIntroPhaseTickCount" "$0" $1
; This is added to the previous value of $IntroPhaseSeconds because the
; introduction page can be displayed multiple times.
IntOp $IntroPhaseSeconds $IntroPhaseSeconds + $1
SetShellVarContext all ; Set SHCTX to All Users
; If the user doesn't have write access to the installation directory set
; the installation directory to a subdirectory of the All Users application
@ -522,11 +768,28 @@ Function leaveIntro
FunctionEnd
Function createOptions
; Skip the options page unless the Options button was clicked
${If} "$WasOptionsButtonClicked" != "true"
; Check whether the requirements to install are satisfied the first time the
; options page is displayed for metrics.
${If} "$InitialInstallRequirementsCode" == ""
${If} "$CanWriteToInstallDir" != "true"
${AndIf} "$HasRequiredSpaceAvailable" != "true"
StrCpy $InitialInstallRequirementsCode "1"
${ElseIf} "$CanWriteToInstallDir" != "true"
StrCpy $InitialInstallRequirementsCode "2"
${ElseIf} "$HasRequiredSpaceAvailable" != "true"
StrCpy $InitialInstallRequirementsCode "3"
${Else}
StrCpy $InitialInstallRequirementsCode "0"
${EndIf}
${EndIf}
; Skip the options page unless the Options button was clicked as long as the
; installation directory can be written to and there is the minimum required
; space available.
${If} "$WasOptionsButtonClicked" != "1"
${If} "$CanWriteToInstallDir" == "true"
${AndIf} "$HasRequiredSpaceAvailable" == "true"
Abort
Abort ; Skip the options page
${EndIf}
${EndIf}
@ -615,20 +878,20 @@ Function createOptions
${GetTextExtent} "$(SPACE_REQUIRED)" $FontItalic $0 $1
${GetTextExtent} "$(SPACE_AVAILABLE)" $FontItalic $2 $3
${If} $1 > $3
StrCpy $HEIGHT_PX "$1"
StrCpy $ControlHeightPX "$1"
${Else}
StrCpy $HEIGHT_PX "$3"
StrCpy $ControlHeightPX "$3"
${EndIf}
IntOp $0 $0 + 8 ; Add padding to the control's width
; Make both controls the same width as the widest control
${NSD_CreateLabelCenter} ${OPTIONS_SUBITEM_EDGE_DU} 134u $0 $HEIGHT_PX "$(SPACE_REQUIRED)"
${NSD_CreateLabelCenter} ${OPTIONS_SUBITEM_EDGE_DU} 134u $0 $ControlHeightPX "$(SPACE_REQUIRED)"
Pop $5
SetCtlColors $5 ${OPTIONS_TEXT_COLOR_FADED} ${OPTIONS_BKGRD_COLOR}
SendMessage $5 ${WM_SETFONT} $FontItalic 0
IntOp $2 $2 + 8 ; Add padding to the control's width
${NSD_CreateLabelCenter} ${OPTIONS_SUBITEM_EDGE_DU} 145u $2 $HEIGHT_PX "$(SPACE_AVAILABLE)"
${NSD_CreateLabelCenter} ${OPTIONS_SUBITEM_EDGE_DU} 145u $2 $ControlHeightPX "$(SPACE_AVAILABLE)"
Pop $6
SetCtlColors $6 ${OPTIONS_TEXT_COLOR_FADED} ${OPTIONS_BKGRD_COLOR}
SendMessage $6 ${WM_SETFONT} $FontItalic 0
@ -638,11 +901,11 @@ Function createOptions
StrCpy $6 "$5"
${EndIf}
FindWindow $1 "#32770" "" $HWNDPARENT
${GetDlgItemEndPX} $6 $CTL_RIGHT_PX
${GetDlgItemEndPX} $6 $ControlRightPX
IntOp $CTL_RIGHT_PX $CTL_RIGHT_PX + 6
IntOp $ControlRightPX $ControlRightPX + 6
${NSD_CreateLabel} $CTL_RIGHT_PX 134u 100% $HEIGHT_PX \
${NSD_CreateLabel} $ControlRightPX 134u 100% $ControlHeightPX \
"${APPROXIMATE_REQUIRED_SPACE_MB} $(MEGA)$(BYTE)"
Pop $7
SetCtlColors $7 ${OPTIONS_TEXT_COLOR_NORMAL} ${OPTIONS_BKGRD_COLOR}
@ -650,7 +913,7 @@ Function createOptions
; Create the free space label with an empty string and update it by calling
; UpdateFreeSpaceLabel
${NSD_CreateLabel} $CTL_RIGHT_PX 145u 100% $HEIGHT_PX " "
${NSD_CreateLabel} $ControlRightPX 145u 100% $ControlHeightPX " "
Pop $LabelFreeSpace
SetCtlColors $LabelFreeSpace ${OPTIONS_TEXT_COLOR_NORMAL} ${OPTIONS_BKGRD_COLOR}
SendMessage $LabelFreeSpace ${WM_SETFONT} $FontNormal 0
@ -705,7 +968,9 @@ Function createOptions
GetDlgItem $0 $HWNDPARENT 3 ; Back and Options button
SendMessage $0 ${WM_SETTEXT} 0 "STR:$(BACK_BUTTON)"
${If} "$WasOptionsButtonClicked" != "true"
; If the option button was not clicked display the reason for what needs to be
; resolved to continue the installation.
${If} "$WasOptionsButtonClicked" != "1"
${If} "$CanWriteToInstallDir" == "false"
MessageBox MB_OK|MB_ICONEXCLAMATION "$(WARN_WRITE_ACCESS)"
${ElseIf} "$HasRequiredSpaceAvailable" == "false"
@ -713,12 +978,18 @@ Function createOptions
${EndIf}
${EndIf}
IntOp $OptionsPageShownCount $OptionsPageShownCount + 1
System::Call "kernel32::GetTickCount()l .s"
Pop $StartOptionsPhaseTickCount
LockWindow off
nsDialogs::Show
FunctionEnd
Function leaveOptions
LockWindow on
${GetRoot} "$INSTDIR" $0
${GetLongPath} "$INSTDIR" $INSTDIR
${GetLongPath} "$0" $0
@ -742,6 +1013,13 @@ Function leaveOptions
Abort ; Stay on the page
${EndIf}
System::Call "kernel32::GetTickCount()l .s"
Pop $0
${GetSecondsElapsed} "$StartOptionsPhaseTickCount" "$0" $1
; This is added to the previous value of $OptionsPhaseSeconds because the
; options page can be displayed multiple times.
IntOp $OptionsPhaseSeconds $OptionsPhaseSeconds + $1
${NSD_GetState} $CheckboxShortcutOnBar $CheckboxShortcutOnBar
${NSD_GetState} $CheckboxShortcutInStartMenu $CheckboxShortcutInStartMenu
${NSD_GetState} $CheckboxShortcutOnDesktop $CheckboxShortcutOnDesktop
@ -849,7 +1127,8 @@ Function createInstall
${NSD_CreateProgressBar} 103u 166u 157u 9u ""
Pop $ProgressbarDownload
${NSD_AddStyle} $ProgressbarDownload ${PBS_MARQUEE}
SendMessage $ProgressbarDownload ${PBM_SETMARQUEE} 1 10 ; start=1|stop=0 interval(ms)=+N
SendMessage $ProgressbarDownload ${PBM_SETMARQUEE} 1 \
${ProgressbarMarqueeIntervalMS} ; start=1|stop=0 interval(ms)=+N
${NSD_CreateProgressBar} 260u 166u 84u 9u ""
Pop $ProgressbarInstall
@ -881,7 +1160,7 @@ Function createInstall
SendMessage $0 ${WM_KILLFOCUS} 0 0
; Set as default is not supported in the installer for Win8 and above
${If} $CanSetAsDefault == "true"
${If} "$CanSetAsDefault" == "true"
GetDlgItem $0 $HWNDPARENT 10 ; Default browser checkbox
SendMessage $0 ${BM_GETCHECK} 0 0 $CheckboxSetAsDefault
EnableWindow $0 0
@ -894,13 +1173,25 @@ Function createInstall
SetCtlColors $0 ${FOOTER_CONTROL_TEXT_COLOR_FADED} ${FOOTER_BKGRD_COLOR}
ShowWindow $0 ${SW_SHOW}
; Set $DownloadReset to true so the first download tick count is measured.
StrCpy $DownloadReset "true"
StrCpy $IsDownloadFinished "false"
StrCpy $DownloadReset "false"
StrCpy $ExitCode "${ERR_CANCEL_DOWNLOAD}"
${If} ${FileExists} "$INSTDIR\${FileMainEXE}"
StrCpy $ExistingInstall "1"
${Else}
StrCpy $ExistingInstall "0"
StrCpy $DownloadRetryCount "0"
StrCpy $StartLastDownloadTickCount "0"
StrCpy $DownloadFirstTransferSeconds ""
StrCpy $ExitCode "${ERR_DOWNLOAD_CANCEL}"
StrCpy $OpenedDownloadPage "0"
ClearErrors
ReadINIStr $ExistingVersion "$INSTDIR\application.ini" "App" "Version"
${If} ${Errors}
StrCpy $ExistingVersion "0"
${EndIf}
ClearErrors
ReadINIStr $ExistingBuildID "$INSTDIR\application.ini" "App" "BuildID"
${If} ${Errors}
StrCpy $ExistingBuildID "0"
${EndIf}
${If} ${FileExists} "$LOCALAPPDATA\Mozilla\Firefox"
@ -909,8 +1200,10 @@ Function createInstall
StrCpy $ExistingProfile "0"
${EndIf}
StrCpy $DownloadServerIP ""
System::Call "kernel32::GetTickCount()l .s"
Pop $StartTickCount
Pop $StartDownloadPhaseTickCount
${NSD_CreateTimer} StartDownload ${DownloadIntervalMS}
@ -924,14 +1217,10 @@ Function createInstall
${NSD_FreeImage} $HWndBitmapBlurb3
FunctionEnd
Function leaveInstall
# Need a ping?
FunctionEnd
Function StartDownload
${NSD_KillTimer} StartDownload
InetBgDL::Get "${URLStubDownload}" "$PLUGINSDIR\download.exe" \
/RANGEREQUEST /CONNECTTIMEOUT 120 /RECEIVETIMEOUT 120 /END
/CONNECTTIMEOUT 120 /RECEIVETIMEOUT 120 /END
StrCpy $4 ""
${NSD_CreateTimer} OnDownload ${DownloadIntervalMS}
${If} ${FileExists} "$INSTDIR\${TO_BE_DELETED}"
@ -948,37 +1237,90 @@ Function OnDownload
# $4 = Size of current file (Empty string if the size is unknown)
# /RESET must be used if status $0 > 299 (e.g. failure)
# When status is $0 =< 299 it is handled by InetBgDL
StrCpy $DownloadServerIP "$5"
${If} $0 > 299
${NSD_KillTimer} OnDownload
IntOp $DownloadRetryCount $DownloadRetryCount + 1
${If} "$DownloadReset" != "true"
StrCpy $DownloadedAmount "0"
StrCpy $DownloadedBytes "0"
${NSD_AddStyle} $ProgressbarDownload ${PBS_MARQUEE}
SendMessage $ProgressbarDownload ${PBM_SETMARQUEE} 1 10 ; start=1|stop=0 interval(ms)=+N
SendMessage $ProgressbarDownload ${PBM_SETMARQUEE} 1 \
${ProgressbarMarqueeIntervalMS} ; start=1|stop=0 interval(ms)=+N
${EndIf}
InetBgDL::Get /RESET /END
${NSD_CreateTimer} StartDownload ${DownloadIntervalMS}
StrCpy $DownloadSizeBytes ""
StrCpy $DownloadReset "true"
StrCpy $DownloadSize ""
${If} $DownloadRetryCount >= ${DownloadMaxRetries}
StrCpy $ExitCode "${ERR_DOWNLOAD_TOO_MANY_RETRIES}"
; Use a timer so the UI has a chance to update
${NSD_CreateTimer} DisplayDownloadError ${InstallIntervalMS}
${Else}
${NSD_CreateTimer} StartDownload ${DownloadRetryIntervalMS}
${EndIf}
Return
${EndIf}
${If} "$DownloadReset" == "true"
System::Call "kernel32::GetTickCount()l .s"
Pop $StartLastDownloadTickCount
StrCpy $DownloadReset "false"
; The seconds elapsed from the start of the download phase until the first
; bytes are received are only recorded for the first request so it is
; possible to determine connection issues for the first request.
${If} "$DownloadFirstTransferSeconds" == ""
; Get the seconds elapsed from the start of the download phase until the
; first bytes are received.
${GetSecondsElapsed} "$StartDownloadPhaseTickCount" "$StartLastDownloadTickCount" $DownloadFirstTransferSeconds
${EndIf}
${EndIf}
${If} $DownloadSize == ""
${AndIf} $4 != ""
StrCpy $DownloadSize "$4"
${If} "$DownloadSizeBytes" == ""
${AndIf} "$4" != ""
; Handle the case where the size of the file to be downloaded is less than
; the minimum expected size or greater than the maximum expected size at the
; beginning of the download.
${If} $4 < ${DownloadMinSizeBytes}
${OrIf} $4 > ${DownloadMaxSizeBytes}
${NSD_KillTimer} OnDownload
InetBgDL::Get /RESET /END
StrCpy $DownloadReset "true"
${If} $DownloadRetryCount >= ${DownloadMaxRetries}
; Use a timer so the UI has a chance to update
${NSD_CreateTimer} DisplayDownloadError ${InstallIntervalMS}
${Else}
${NSD_CreateTimer} StartDownload ${DownloadIntervalMS}
${EndIf}
Return
${EndIf}
StrCpy $DownloadSizeBytes "$4"
System::Int64Op $4 / 2
Pop $HalfOfDownload
SendMessage $ProgressbarDownload ${PBM_SETMARQUEE} 0 0 ; start=1|stop=0 interval(ms)=+N
${RemoveStyle} $ProgressbarDownload ${PBS_MARQUEE}
SendMessage $ProgressbarDownload ${PBM_SETRANGE32} 0 $DownloadSize
SendMessage $ProgressbarDownload ${PBM_SETRANGE32} 0 $DownloadSizeBytes
${EndIf}
; Don't update the status until after the download starts
${If} $2 != 0
${AndIf} $4 == ""
${AndIf} "$4" == ""
Return
${EndIf}
; Handle the case where the downloaded size is greater than the maximum
; expected size during the download.
${If} $DownloadedBytes > ${DownloadMaxSizeBytes}
InetBgDL::Get /RESET /END
StrCpy $DownloadReset "true"
${If} $DownloadRetryCount >= ${DownloadMaxRetries}
; Use a timer so the UI has a chance to update
${NSD_CreateTimer} DisplayDownloadError ${InstallIntervalMS}
${Else}
${NSD_CreateTimer} StartDownload ${DownloadIntervalMS}
${EndIf}
Return
${EndIf}
@ -991,12 +1333,31 @@ Function OnDownload
; feedback.
StrCpy $InstallCounterStep "${InstallProgressFirstStep}"
System::Call "kernel32::GetTickCount()l .s"
Pop $DownloadTickCount
StrCpy $DownloadedAmount "$DownloadSize"
Pop $EndDownloadPhaseTickCount
StrCpy $DownloadedBytes "$DownloadSizeBytes"
; When a download has finished handle the case where the downloaded size
; is less than the minimum expected size or greater than the maximum
; expected size during the download.
${If} $DownloadedBytes < ${DownloadMinSizeBytes}
${OrIf} $DownloadedBytes > ${DownloadMaxSizeBytes}
InetBgDL::Get /RESET /END
StrCpy $DownloadReset "true"
${If} $DownloadRetryCount >= ${DownloadMaxRetries}
; Use a timer so the UI has a chance to update
${NSD_CreateTimer} DisplayDownloadError ${InstallIntervalMS}
${Else}
${NSD_CreateTimer} StartDownload ${DownloadIntervalMS}
${EndIf}
Return
${EndIf}
LockWindow on
; Update the progress bars first in the UI change so they take affect
; before other UI changes.
SendMessage $ProgressbarDownload ${PBM_SETPOS} $DownloadSize 0
SendMessage $ProgressbarDownload ${PBM_SETPOS} $DownloadSizeBytes 0
SendMessage $ProgressbarInstall ${PBM_SETPOS} $InstallCounterStep 0
ShowWindow $LabelDownloadingInProgress ${SW_HIDE}
ShowWindow $LabelInstallingToBeDone ${SW_HIDE}
@ -1020,7 +1381,7 @@ Function OnDownload
StrCpy $HandleDownload "$R9"
${If} $HandleDownload == ${INVALID_HANDLE_VALUE}
StrCpy $ExitCode "${ERR_INVALID_HANDLE}"
StrCpy $ExitCode "${ERR_PREINSTALL_INVALID_HANDLE}"
StrCpy $0 "0"
StrCpy $1 "0"
${Else}
@ -1031,14 +1392,17 @@ Function OnDownload
Pop $1
${If} $0 == 0
${AndIf} $1 == 0
StrCpy $ExitCode "${ERR_CERT_UNTRUSTED_AND_ATTRIBUTES}"
StrCpy $ExitCode "${ERR_PREINSTALL_CERT_UNTRUSTED_AND_ATTRIBUTES}"
${ElseIf} $0 == 0
StrCpy $ExitCode "${ERR_CERT_UNTRUSTED}"
StrCpy $ExitCode "${ERR_PREINSTALL_CERT_UNTRUSTED}"
${ElseIf} $1 == 0
StrCpy $ExitCode "${ERR_CERT_ATTRIBUTES}"
StrCpy $ExitCode "${ERR_PREINSTALL_CERT_ATTRIBUTES}"
${EndIf}
${EndIf}
System::Call "kernel32::GetTickCount()l .s"
Pop $EndPreInstallPhaseTickCount
${If} $0 == 0
${OrIf} $1 == 0
; Use a timer so the UI has a chance to update
@ -1107,15 +1471,40 @@ Function OnDownload
ShowWindow $BitmapBlurb2 ${SW_SHOW}
LockWindow off
${EndIf}
StrCpy $DownloadedAmount "$3"
StrCpy $DownloadedBytes "$3"
SendMessage $ProgressbarDownload ${PBM_SETPOS} $3 0
${EndIf}
${EndIf}
FunctionEnd
Function OnPing
InetBgDL::GetStats
# $0 = HTTP status code, 0=Completed
# $1 = Completed files
# $2 = Remaining files
# $3 = Number of downloaded bytes for the current file
# $4 = Size of current file (Empty string if the size is unknown)
# /RESET must be used if status $0 > 299 (e.g. failure)
# When status is $0 =< 299 it is handled by InetBgDL
${If} $2 == 0
${OrIf} $0 > 299
${NSD_KillTimer} OnPing
${If} $0 > 299
InetBgDL::Get /RESET /END
${EndIf}
; The following will exit the installer
SetAutoClose true
StrCpy $R9 "2"
Call RelativeGotoPage
${EndIf}
FunctionEnd
Function StartInstall
${NSD_KillTimer} StartInstall
System::Call "kernel32::GetTickCount()l .s"
Pop $EndPreInstallPhaseTickCount
IntOp $InstallCounterStep $InstallCounterStep + 1
LockWindow on
SendMessage $ProgressbarInstall ${PBM_SETPOS} $InstallCounterStep 0
@ -1127,11 +1516,11 @@ FunctionEnd
Function CheckInstall
IntOp $InstallCounterStep $InstallCounterStep + 1
${If} $InstallCounterStep >= ${InstallProgresSteps}
${If} $InstallCounterStep >= ${InstallProgresSteps}
${NSD_KillTimer} CheckInstall
; Close the handle that prevents modification of the full installer
System::Call 'kernel32::CloseHandle(i $HandleDownload)'
StrCpy $ExitCode "${ERR_CHECK_INSTALL_TIMEOUT}"
StrCpy $ExitCode "${ERR_INSTALL_TIMEOUT}"
; Use a timer so the UI has a chance to update
${NSD_CreateTimer} DisplayDownloadError ${InstallIntervalMS}
Return
@ -1155,7 +1544,7 @@ Function CheckInstall
Delete "$PLUGINSDIR\download.exe"
Delete "$PLUGINSDIR\${CONFIG_INI}"
System::Call "kernel32::GetTickCount()l .s"
Pop $InstallTickCount
Pop $EndInstallPhaseTickCount
${NSD_CreateTimer} FinishInstall ${InstallIntervalMS}
${EndUnless}
${EndIf}
@ -1212,14 +1601,11 @@ Function FinishInstall
Call LaunchApp
; The following will exit the installer
SetAutoClose true
StrCpy $R9 "2"
Call RelativeGotoPage
Call SendPing
FunctionEnd
Function OnBack
StrCpy $WasOptionsButtonClicked "true"
StrCpy $WasOptionsButtonClicked "1"
StrCpy $R9 "1" ; Goto the next page
Call RelativeGotoPage
; The call to Abort prevents NSIS from trying to move to the previous or the
@ -1424,12 +1810,12 @@ FunctionEnd
Function LaunchApp
FindWindow $0 "${WindowClass}"
${If} $0 <> 0 ; integer comparison
StrCpy $FirefoxLaunch "1"
StrCpy $FirefoxLaunchCode "1"
MessageBox MB_OK|MB_ICONQUESTION "$(WARN_MANUALLY_CLOSE_APP_LAUNCH)"
Return
${EndIf}
StrCpy $FirefoxLaunch "2"
StrCpy $FirefoxLaunchCode "2"
; Set the current working directory to the installation directory
SetOutPath "$INSTDIR"
@ -1458,11 +1844,10 @@ FunctionEnd
Function DisplayDownloadError
${NSD_KillTimer} DisplayDownloadError
StrCpy $R9 "false"
MessageBox MB_OKCANCEL|MB_ICONSTOP "$(ERROR_DOWNLOAD)" IDCANCEL +2 IDOK 0
StrCpy $R9 "true"
MessageBox MB_OKCANCEL|MB_ICONSTOP "$(ERROR_DOWNLOAD)" IDCANCEL +2 IDOK +1
StrCpy $OpenedDownloadPage "1" ; Already initialized to 0
${If} "$R9" == "true"
${If} "$OpenedDownloadPage" == "1"
ClearErrors
${GetParameters} $0
${GetOptions} "$0" "/UAC:" $1
@ -1474,9 +1859,7 @@ Function DisplayDownloadError
${EndIf}
${EndIf}
SetAutoClose true
StrCpy $R9 "2"
Call RelativeGotoPage
Call SendPing
FunctionEnd
Function OpenManualDownloadURL

View File

@ -31,7 +31,7 @@ BROWSER_TESTS = \
$(NULL)
BROWSER_TEST_RESOURCES = \
res\image01.png \
res/image01.png \
$(NULL)
libs:: $(BROWSER_TESTS)

View File

@ -13,9 +13,11 @@ Components.utils.import("resource://gre/modules/Services.jsm");
const SNIPPETS_URL_PREF = "browser.aboutHomeSnippets.updateUrl";
// Should be bumped up if the snippets content format changes.
const STARTPAGE_VERSION = 3;
const STARTPAGE_VERSION = 4;
this.AboutHomeUtils = new Object();
this.AboutHomeUtils = {
get snippetsVersion() STARTPAGE_VERSION
};
/**
* Returns an object containing the name and searchURL of the original default

View File

@ -474,6 +474,7 @@ user_pref("app.update.staging.enabled", false);
user_pref("browser.panorama.experienced_first_run", true); // Assume experienced
user_pref("dom.w3c_touch_events.enabled", 1);
user_pref("dom.undo_manager.enabled", true);
user_pref("dom.webcomponents.enabled", true);
// Set a future policy version to avoid the telemetry prompt.
user_pref("toolkit.telemetry.prompted", 999);
user_pref("toolkit.telemetry.notifiedOptOut", 999);

View File

@ -105,6 +105,7 @@ public class FennecNativeActions implements Actions {
private final String mGeckoEvent;
private final Object[] mRegistrationParams;
private boolean mEventReceived;
private boolean mEventEverReceived;
private String mEventData;
private static final int MAX_WAIT_MS = 90000;
@ -140,6 +141,7 @@ public class FennecNativeActions implements Actions {
}
FennecNativeDriver.log(FennecNativeDriver.LogLevel.DEBUG,
"unblocked on expecter for " + mGeckoEvent);
mEventReceived = false;
}
public synchronized void blockUntilClear(long millis) {
@ -189,6 +191,7 @@ public class FennecNativeActions implements Actions {
}
FennecNativeDriver.log(FennecNativeDriver.LogLevel.DEBUG,
"unblocked on expecter for " + mGeckoEvent);
mEventReceived = false;
}
public synchronized String blockForEventData() {
@ -197,7 +200,7 @@ public class FennecNativeActions implements Actions {
}
public synchronized boolean eventReceived() {
return mEventReceived;
return mEventEverReceived;
}
void notifyOfEvent(Object[] args) {
@ -205,6 +208,7 @@ public class FennecNativeActions implements Actions {
"received event " + mGeckoEvent);
synchronized (this) {
mEventReceived = true;
mEventEverReceived = true;
mEventData = args[1].toString();
this.notifyAll();
}

View File

@ -92,6 +92,7 @@ class DocumentFragment;
class DocumentType;
class DOMImplementation;
class Element;
struct ElementRegistrationOptions;
class GlobalObject;
class HTMLBodyElement;
class Link;
@ -1910,6 +1911,10 @@ public:
{
return GetRootElement();
}
virtual JSObject*
Register(JSContext* aCx, const nsAString& aName,
const mozilla::dom::ElementRegistrationOptions& aOptions,
mozilla::ErrorResult& rv) = 0;
already_AddRefed<nsContentList>
GetElementsByTagName(const nsAString& aTagName)
{

View File

@ -1,4 +1,5 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* 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/. */

View File

@ -6335,77 +6335,13 @@ nsContentUtils::FindInternalContentViewer(const char* aType,
}
#ifdef MOZ_MEDIA
#ifdef MOZ_OGG
if (DecoderTraits::IsOggType(nsDependentCString(aType))) {
if (DecoderTraits::IsSupportedInVideoDocument(nsDependentCString(aType))) {
docFactory = do_GetService("@mozilla.org/content/document-loader-factory;1");
if (docFactory && aLoaderType) {
*aLoaderType = TYPE_CONTENT;
}
return docFactory.forget();
}
#endif
#ifdef MOZ_WIDGET_GONK
if (DecoderTraits::IsOmxSupportedType(nsDependentCString(aType))) {
docFactory = do_GetService("@mozilla.org/content/document-loader-factory;1");
if (docFactory && aLoaderType) {
*aLoaderType = TYPE_CONTENT;
}
return docFactory.forget();
}
#endif
#ifdef MOZ_WEBM
if (DecoderTraits::IsWebMType(nsDependentCString(aType))) {
docFactory = do_GetService("@mozilla.org/content/document-loader-factory;1");
if (docFactory && aLoaderType) {
*aLoaderType = TYPE_CONTENT;
}
return docFactory.forget();
}
#endif
#ifdef MOZ_DASH
if (DecoderTraits::IsDASHMPDType(nsDependentCString(aType))) {
docFactory = do_GetService("@mozilla.org/content/document-loader-factory;1");
if (docFactory && aLoaderType) {
*aLoaderType = TYPE_CONTENT;
}
return docFactory.forget();
}
#endif
#ifdef MOZ_GSTREAMER
if (DecoderTraits::IsGStreamerSupportedType(nsDependentCString(aType))) {
docFactory = do_GetService("@mozilla.org/content/document-loader-factory;1");
if (docFactory && aLoaderType) {
*aLoaderType = TYPE_CONTENT;
}
return docFactory.forget();
}
#endif
#ifdef MOZ_MEDIA_PLUGINS
if (mozilla::MediaDecoder::IsMediaPluginsEnabled() &&
DecoderTraits::IsMediaPluginsType(nsDependentCString(aType))) {
docFactory = do_GetService("@mozilla.org/content/document-loader-factory;1");
if (docFactory && aLoaderType) {
*aLoaderType = TYPE_CONTENT;
}
return docFactory.forget();
}
#endif // MOZ_MEDIA_PLUGINS
#ifdef MOZ_WMF
if (DecoderTraits::IsWMFSupportedType(nsDependentCString(aType))) {
docFactory = do_GetService("@mozilla.org/content/document-loader-factory;1");
if (docFactory && aLoaderType) {
*aLoaderType = TYPE_CONTENT;
}
return docFactory.forget();
}
#endif
#endif // MOZ_MEDIA
return NULL;

View File

@ -34,6 +34,7 @@
#include "nsIDocShellTreeItem.h"
#include "nsIScriptRuntime.h"
#include "nsCOMArray.h"
#include "nsDOMClassInfo.h"
#include "nsGUIEvent.h"
#include "nsAsyncDOMEvent.h"
@ -138,10 +139,12 @@
#include "nsIPrompt.h"
#include "nsIPropertyBag2.h"
#include "nsIDOMPageTransitionEvent.h"
#include "nsJSUtils.h"
#include "nsFrameLoader.h"
#include "nsEscape.h"
#include "nsObjectLoadingContent.h"
#include "nsHtml5TreeOpExecutor.h"
#include "nsIDOMElementReplaceEvent.h"
#ifdef MOZ_MEDIA
#include "nsHTMLMediaElement.h"
#endif // MOZ_MEDIA
@ -171,8 +174,10 @@
#include "mozilla/dom/Comment.h"
#include "nsTextNode.h"
#include "mozilla/dom/Link.h"
#include "mozilla/dom/HTMLElementBinding.h"
#include "nsXULAppAPI.h"
#include "nsDOMTouchEvent.h"
#include "DictionaryHelpers.h"
#include "mozilla/Preferences.h"
@ -183,6 +188,7 @@
#include "nsIAppsService.h"
#include "mozilla/dom/BindingUtils.h"
#include "mozilla/dom/DocumentFragment.h"
#include "mozilla/dom/WebComponentsBinding.h"
#include "mozilla/dom/HTMLBodyElement.h"
#include "mozilla/dom/NodeFilterBinding.h"
#include "mozilla/dom/UndoManager.h"
@ -1372,6 +1378,13 @@ nsDocument::~nsDocument()
mInDestructor = true;
mInUnlinkOrDeletion = true;
mCustomPrototypes.Clear();
nsISupports* supports;
QueryInterface(NS_GET_IID(nsCycleCollectionISupports), reinterpret_cast<void**>(&supports));
NS_ASSERTION(supports, "Failed to QI to nsCycleCollectionISupports?!");
nsContentUtils::DropJSObjects(supports);
// Clear mObservers to keep it in sync with the mutationobserver list
mObservers.Clear();
@ -1478,6 +1491,7 @@ NS_INTERFACE_TABLE_HEAD(nsDocument)
NS_INTERFACE_TABLE_ENTRY(nsDocument, nsIDOMDocumentTouch)
NS_INTERFACE_TABLE_ENTRY(nsDocument, nsITouchEventReceiver)
NS_INTERFACE_TABLE_ENTRY(nsDocument, nsIInlineEventHandlers)
NS_INTERFACE_TABLE_ENTRY(nsDocument, nsIDocumentRegister)
NS_INTERFACE_TABLE_ENTRY(nsDocument, nsIObserver)
NS_OFFSET_AND_INTERFACE_TABLE_END
NS_OFFSET_AND_INTERFACE_TABLE_TO_MAP_SEGUE
@ -1716,7 +1730,25 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INTERNAL(nsDocument)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
struct CustomPrototypeTraceArgs {
TraceCallback callback;
void* closure;
};
static PLDHashOperator
CustomPrototypeTrace(const nsAString& aName, JSObject* aObject, void *aArg)
{
CustomPrototypeTraceArgs* traceArgs = static_cast<CustomPrototypeTraceArgs*>(aArg);
MOZ_ASSERT(aObject, "Protocol object value must not be null");
traceArgs->callback(aObject, "mCustomPrototypes entry", traceArgs->closure);
return PL_DHASH_NEXT;
}
NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(nsDocument)
CustomPrototypeTraceArgs customPrototypeArgs = { aCallback, aClosure };
tmp->mCustomPrototypes.EnumerateRead(CustomPrototypeTrace, &customPrototypeArgs);
nsINode::Trace(tmp, aCallback, aClosure);
NS_IMPL_CYCLE_COLLECTION_TRACE_END
@ -1781,6 +1813,8 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsDocument)
tmp->mIdentifierMap.Clear();
tmp->mCustomPrototypes.Clear();
if (tmp->mAnimationController) {
tmp->mAnimationController->Unlink();
}
@ -1805,6 +1839,7 @@ nsDocument::Init()
mIdentifierMap.Init();
mStyledLinks.Init();
mRadioGroups.Init();
mCustomPrototypes.Init();
// Force initialization.
nsINode::nsSlots* slots = Slots();
@ -1841,6 +1876,15 @@ nsDocument::Init()
mImageTracker.Init();
mPlugins.Init();
nsXPCOMCycleCollectionParticipant* participant;
CallQueryInterface(this, &participant);
NS_ASSERTION(participant, "Failed to QI to nsXPCOMCycleCollectionParticipant!");
nsISupports* thisSupports;
QueryInterface(NS_GET_IID(nsCycleCollectionISupports), reinterpret_cast<void**>(&thisSupports));
NS_ASSERTION(thisSupports, "Failed to QI to nsCycleCollectionISupports!");
nsContentUtils::HoldJSObjects(thisSupports, participant);
return NS_OK;
}
@ -1961,6 +2005,8 @@ nsDocument::ResetToURI(nsIURI *aURI, nsILoadGroup *aLoadGroup,
mInUnlinkOrDeletion = oldVal;
mCachedRootElement = nullptr;
mCustomPrototypes.Clear();
// Reset our stylesheets
ResetStylesheetsToURI(aURI);
@ -4845,6 +4891,205 @@ nsIDocument::CreateAttributeNS(const nsAString& aNamespaceURI,
return attribute.forget();
}
static JSBool
CustomElementConstructor(JSContext *aCx, unsigned aArgc, JS::Value* aVp)
{
JS::Value calleeVal = JS_CALLEE(aCx, aVp);
JSObject* global = JS_GetGlobalForObject(aCx, &calleeVal.toObject());
nsCOMPtr<nsPIDOMWindow> window = do_QueryWrapper(aCx, global);
MOZ_ASSERT(window, "Should have a non-null window");
nsIDocument* document = window->GetDoc();
// Function name is the type of the custom element.
JSString* jsFunName = JS_GetFunctionId(JS_ValueToFunction(aCx, calleeVal));
nsDependentJSString elemName;
if (!elemName.init(aCx, jsFunName)) {
return false;
}
nsCOMPtr<nsIContent> newElement;
nsresult rv = document->CreateElem(elemName, nullptr, kNameSpaceID_XHTML,
getter_AddRefs(newElement));
JS::Value v;
rv = nsContentUtils::WrapNative(aCx, global, newElement, newElement, &v);
NS_ENSURE_SUCCESS(rv, false);
JS_SET_RVAL(aCx, aVp, v);
return true;
}
bool
nsDocument::RegisterEnabled()
{
static bool sPrefValue =
Preferences::GetBool("dom.webcomponents.enabled", false);
return sPrefValue;
}
NS_IMETHODIMP
nsDocument::Register(const nsAString& aName, const JS::Value& aOptions,
JSContext* aCx, uint8_t aOptionalArgc,
jsval* aConstructor /* out param */)
{
ElementRegistrationOptions options;
if (aOptionalArgc > 0) {
JSAutoCompartment ac(aCx, GetWrapper());
NS_ENSURE_TRUE(JS_WrapValue(aCx, const_cast<JS::Value*>(&aOptions)),
NS_ERROR_UNEXPECTED);
NS_ENSURE_TRUE(options.Init(aCx, nullptr, aOptions),
NS_ERROR_UNEXPECTED);
}
ErrorResult rv;
JSObject* object = Register(aCx, aName, options, rv);
if (rv.Failed()) {
return rv.ErrorCode();
}
NS_ENSURE_TRUE(object, NS_ERROR_UNEXPECTED);
*aConstructor = OBJECT_TO_JSVAL(object);
return NS_OK;
}
JSObject*
nsDocument::Register(JSContext* aCx, const nsAString& aName,
const ElementRegistrationOptions& aOptions,
ErrorResult& rv)
{
nsAutoString lcName;
nsContentUtils::ASCIIToLower(aName, lcName);
if (!StringBeginsWith(lcName, NS_LITERAL_STRING("x-"))) {
rv.Throw(NS_ERROR_DOM_INVALID_CHARACTER_ERR);
return nullptr;
}
if (NS_FAILED(nsContentUtils::CheckQName(lcName, false))) {
rv.Throw(NS_ERROR_DOM_INVALID_CHARACTER_ERR);
return nullptr;
}
nsIScriptGlobalObject* sgo = GetScopeObject();
if (!sgo) {
rv.Throw(NS_ERROR_UNEXPECTED);
return nullptr;
}
JSObject* global = sgo->GetGlobalJSObject();
JSAutoCompartment ac(aCx, global);
JSObject* htmlProto = HTMLElementBinding::GetProtoObject(aCx, global);
if (!htmlProto) {
rv.Throw(NS_ERROR_OUT_OF_MEMORY);
return nullptr;
}
JSObject* protoObject;
if (!aOptions.mPrototype) {
protoObject = JS_NewObject(aCx, NULL, htmlProto, NULL);
if (!protoObject) {
rv.Throw(NS_ERROR_UNEXPECTED);
return nullptr;
}
} else {
// If a prototype is provided, we must check to ensure that it inherits
// from HTMLElement.
protoObject = aOptions.mPrototype;
if (!JS_WrapObject(aCx, &protoObject)) {
rv.Throw(NS_ERROR_UNEXPECTED);
return nullptr;
}
// Check the proto chain for HTMLElement prototype.
JSObject* protoProto;
if (!JS_GetPrototype(aCx, protoObject, &protoProto)) {
rv.Throw(NS_ERROR_UNEXPECTED);
return nullptr;
}
while (protoProto) {
if (protoProto == htmlProto) {
break;
}
if (!JS_GetPrototype(aCx, protoProto, &protoProto)) {
rv.Throw(NS_ERROR_UNEXPECTED);
return nullptr;
}
}
if (!protoProto) {
rv.Throw(NS_ERROR_DOM_TYPE_MISMATCH_ERR);
return nullptr;
}
}
// Associate the prototype with the custom element.
mCustomPrototypes.Put(lcName, protoObject);
// Do element upgrade.
nsRefPtr<nsContentList> list = GetElementsByTagName(lcName);
for (int32_t i = 0; i < list->Length(false); i++) {
nsCOMPtr<nsINode> oldNode = list->Item(i, false);
// TODO(wchen): Perform upgrade on Shadow DOM when implemented.
// Bug 806506.
nsCOMPtr<nsINode> newNode;
rv = nsNodeUtils::Clone(oldNode, true, getter_AddRefs(newNode));
if (rv.Failed()) {
return nullptr;
}
nsINode* parentNode = oldNode->GetParentNode();
MOZ_ASSERT(parentNode, "Node obtained by GetElementsByTagName.");
nsCOMPtr<nsIDOMElement> newElement = do_QueryInterface(newNode);
MOZ_ASSERT(newElement, "Cloned of node obtained by GetElementsByTagName.");
parentNode->ReplaceChild(*newNode, *oldNode, rv);
if (rv.Failed()) {
return nullptr;
}
// Dispatch elementreplaced to replaced elements.
nsCOMPtr<nsIDOMEvent> event;
rv = CreateEvent(NS_LITERAL_STRING("elementreplace"), getter_AddRefs(event));
if (rv.Failed()) {
return nullptr;
}
if (aOptions.mLifecycle.mCreated) {
// Don't abort the upgrade algorithm if the callback throws an
// exception.
ErrorResult dummy;
aOptions.mLifecycle.mCreated->Call(newElement, dummy);
}
nsCOMPtr<nsIDOMElementReplaceEvent> ptEvent = do_QueryInterface(event);
MOZ_ASSERT(ptEvent);
rv = ptEvent->InitElementReplaceEvent(NS_LITERAL_STRING("elementreplace"),
false, false, newElement);
if (rv.Failed()) {
return nullptr;
}
event->SetTrusted(true);
event->SetTarget(oldNode);
nsEventDispatcher::DispatchDOMEvent(oldNode, nullptr, event,
nullptr, nullptr);
}
nsContentUtils::DispatchTrustedEvent(this, static_cast<nsIDocument*>(this),
NS_LITERAL_STRING("elementupgrade"),
true, true);
// Create constructor to return. Store the name of the custom element as the
// name of the function.
JSFunction* constructor = JS_NewFunction(aCx, CustomElementConstructor, 0,
JSFUN_CONSTRUCTOR, nullptr,
NS_ConvertUTF16toUTF8(lcName).get());
JSObject* constructorObject = JS_GetFunctionObject(constructor);
return constructorObject;
}
NS_IMETHODIMP
nsDocument::GetElementsByTagName(const nsAString& aTagname,
nsIDOMNodeList** aReturn)
@ -7427,6 +7672,8 @@ nsDocument::Destroy()
// tearing down all those frame trees right now is the right thing to do.
mExternalResourceMap.Shutdown();
mCustomPrototypes.Clear();
// XXX We really should let cycle collection do this, but that currently still
// leaks (see https://bugzilla.mozilla.org/show_bug.cgi?id=406684).
nsContentUtils::ReleaseWrapper(static_cast<nsINode*>(this), this);

View File

@ -62,6 +62,7 @@
#include "nsIProgressEventSink.h"
#include "nsISecurityEventSink.h"
#include "nsIChannelEventSink.h"
#include "nsIDocumentRegister.h"
#include "imgIRequest.h"
#include "mozilla/dom/DOMImplementation.h"
#include "nsIDOMTouchEvent.h"
@ -480,6 +481,7 @@ class nsDocument : public nsIDocument,
public nsStubMutationObserver,
public nsIDOMDocumentTouch,
public nsIInlineEventHandlers,
public nsIDocumentRegister,
public nsIObserver
{
public:
@ -779,6 +781,9 @@ public:
// nsIInlineEventHandlers
NS_DECL_NSIINLINEEVENTHANDLERS
// nsIDocumentRegister
NS_DECL_NSIDOCUMENTREGISTER
// nsIObserver
NS_DECL_NSIOBSERVER
@ -1013,9 +1018,22 @@ public:
virtual nsIDOMNode* AsDOMNode() { return this; }
JSObject* GetCustomPrototype(const nsAString& aElementName)
{
JSObject* prototype = nullptr;
mCustomPrototypes.Get(aElementName, &prototype);
return prototype;
}
static bool RegisterEnabled();
// WebIDL bits
virtual mozilla::dom::DOMImplementation*
GetImplementation(mozilla::ErrorResult& rv);
virtual JSObject*
Register(JSContext* aCx, const nsAString& aName,
const mozilla::dom::ElementRegistrationOptions& aOptions,
mozilla::ErrorResult& rv);
virtual nsIDOMStyleSheetList* StyleSheets();
virtual void SetSelectedStyleSheetSet(const nsAString& aSheetSet);
virtual void GetLastStyleSheetSet(nsString& aSheetSet);
@ -1184,6 +1202,10 @@ protected:
// non-null when this document is in fullscreen mode.
nsWeakPtr mFullscreenRoot;
// Hashtable for custom element prototypes in web components.
// Custom prototypes are in the document's compartment.
nsDataHashtable<nsStringHashKey, JSObject*> mCustomPrototypes;
nsRefPtr<nsEventListenerManager> mListenerManager;
nsCOMPtr<nsIDOMStyleSheetList> mDOMStyleSheets;
nsRefPtr<nsDOMStyleSheetSetList> mStyleSheetSetList;

View File

@ -1,5 +1,5 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=2 sw=2 et tw=79: */
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* 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/. */
@ -2032,7 +2032,7 @@ nsINode::SizeOfExcludingThis(nsMallocSizeOfFun aMallocSizeOf) const
// Measurement of the following members may be added later if DMD finds it is
// worthwhile:
// - mNodeInfo (Nb: allocated in nsNodeInfo.cpp with a nsFixedSizeAllocator)
// - mNodeInfo
// - mSlots
//
// The following members are not measured:

View File

@ -1,4 +1,5 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* 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/. */
@ -24,7 +25,6 @@
#include "nsReadableUtils.h"
#include "nsAutoPtr.h"
#include NEW_H
#include "nsFixedSizeAllocator.h"
#include "prprf.h"
#include "nsIDocument.h"
#include "nsGkAtoms.h"
@ -32,43 +32,6 @@
using namespace mozilla;
static const size_t kNodeInfoPoolSizes[] = {
sizeof(nsNodeInfo)
};
static const int32_t kNodeInfoPoolInitialSize = sizeof(nsNodeInfo) * 64;
// static
nsFixedSizeAllocator* nsNodeInfo::sNodeInfoPool = nullptr;
// static
nsNodeInfo*
nsNodeInfo::Create(nsIAtom *aName, nsIAtom *aPrefix, int32_t aNamespaceID,
uint16_t aNodeType, nsIAtom *aExtraName,
nsNodeInfoManager *aOwnerManager)
{
if (!sNodeInfoPool) {
sNodeInfoPool = new nsFixedSizeAllocator();
if (!sNodeInfoPool)
return nullptr;
nsresult rv = sNodeInfoPool->Init("NodeInfo Pool", kNodeInfoPoolSizes,
1, kNodeInfoPoolInitialSize);
if (NS_FAILED(rv)) {
delete sNodeInfoPool;
sNodeInfoPool = nullptr;
return nullptr;
}
}
// Create a new one
void* place = sNodeInfoPool->Alloc(sizeof(nsNodeInfo));
return place ?
new (place) nsNodeInfo(aName, aPrefix, aNamespaceID, aNodeType, aExtraName,
aOwnerManager) :
nullptr;
}
nsNodeInfo::~nsNodeInfo()
{
mOwnerManager->RemoveNodeInfo(this);
@ -234,28 +197,11 @@ nsNodeInfo::NamespaceEquals(const nsAString& aNamespaceURI) const
return nsINodeInfo::NamespaceEquals(nsid);
}
// static
void
nsNodeInfo::ClearCache()
{
// Clear our cache.
delete sNodeInfoPool;
sNodeInfoPool = nullptr;
}
void
nsNodeInfo::LastRelease()
{
nsRefPtr<nsNodeInfoManager> kungFuDeathGrip = mOwnerManager;
this->~nsNodeInfo();
// The refcount balancing and destructor re-entrancy protection
// code in Release() sets mRefCnt to 1 so we have to set it to 0
// here to prevent leaks
mRefCnt = 0;
NS_ASSERTION(sNodeInfoPool, "No NodeInfoPool when deleting NodeInfo!!!");
sNodeInfoPool->Free(this, sizeof(nsNodeInfo));
delete this;
}
bool

View File

@ -1,4 +1,5 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* 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/. */
@ -20,8 +21,6 @@
#include "nsIDOMNode.h"
#include "nsGkAtoms.h"
class nsFixedSizeAllocator;
class nsNodeInfo : public nsINodeInfo
{
public:
@ -33,39 +32,27 @@ public:
virtual bool NamespaceEquals(const nsAString& aNamespaceURI) const;
// nsNodeInfo
// Create objects with Create
public:
/*
* aName and aOwnerManager may not be null.
*/
static nsNodeInfo *Create(nsIAtom *aName, nsIAtom *aPrefix,
int32_t aNamespaceID, uint16_t aNodeType,
nsIAtom *aExtraName,
nsNodeInfoManager *aOwnerManager);
private:
nsNodeInfo(); // Unimplemented
nsNodeInfo(const nsNodeInfo& aOther); // Unimplemented
nsNodeInfo(nsIAtom *aName, nsIAtom *aPrefix, int32_t aNamespaceID,
uint16_t aNodeType, nsIAtom *aExtraName,
nsNodeInfoManager *aOwnerManager);
private:
nsNodeInfo(); // Unimplemented
nsNodeInfo(const nsNodeInfo& aOther); // Unimplemented
protected:
virtual ~nsNodeInfo();
public:
/**
* Call before shutdown to clear the cache and free memory for this class.
*/
static void ClearCache();
bool CanSkip();
private:
static nsFixedSizeAllocator* sNodeInfoPool;
/**
* This method gets called by Release() when it's time to delete
* this object, instead of always deleting the object we'll put the
* object in the cache unless the cache is already full.
* This method gets called by Release() when it's time to delete
* this object.
*/
void LastRelease();
};

View File

@ -1,4 +1,5 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* 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/. */
@ -220,10 +221,9 @@ nsNodeInfoManager::GetNodeInfo(nsIAtom *aName, nsIAtom *aPrefix,
}
nsRefPtr<nsNodeInfo> newNodeInfo =
nsNodeInfo::Create(aName, aPrefix, aNamespaceID, aNodeType, aExtraName,
this);
new nsNodeInfo(aName, aPrefix, aNamespaceID, aNodeType, aExtraName, this);
NS_ENSURE_TRUE(newNodeInfo, nullptr);
PLHashEntry *he;
he = PL_HashTableAdd(mNodeInfoHash, &newNodeInfo->mInner, newNodeInfo);
NS_ENSURE_TRUE(he, nullptr);
@ -266,13 +266,11 @@ nsNodeInfoManager::GetNodeInfo(const nsAString& aName, nsIAtom *aPrefix,
return NS_OK;
}
nsCOMPtr<nsIAtom> nameAtom = do_GetAtom(aName);
NS_ENSURE_TRUE(nameAtom, NS_ERROR_OUT_OF_MEMORY);
nsRefPtr<nsNodeInfo> newNodeInfo =
nsNodeInfo::Create(nameAtom, aPrefix, aNamespaceID, aNodeType, nullptr,
this);
new nsNodeInfo(nameAtom, aPrefix, aNamespaceID, aNodeType, nullptr, this);
NS_ENSURE_TRUE(newNodeInfo, NS_ERROR_OUT_OF_MEMORY);
PLHashEntry *he;

View File

@ -156,6 +156,16 @@ public:
nullptr, aNodesWithProperties, nullptr, aResult);
}
/**
* Clones aNode, its attributes and, if aDeep is true, its descendant nodes
*/
static nsresult Clone(nsINode *aNode, bool aDeep, nsINode **aResult)
{
nsCOMArray<nsINode> dummyNodeWithProperties;
return CloneAndAdopt(aNode, true, aDeep, nullptr, nullptr, nullptr,
dummyNodeWithProperties, aNode->GetParent(), aResult);
}
/**
* Walks aNode, its attributes and descendant nodes. If aNewNodeInfoManager is
* not null, it is used to create new nodeinfos for the nodes. Also reparents

View File

@ -54,6 +54,7 @@ MOCHITEST_CHROME_FILES = \
test_domparsing.xul \
test_bug814638.xul \
host_bug814638.xul \
test_document_register.xul \
frame_bug814638.xul \
$(NULL)

View File

@ -0,0 +1,37 @@
<?xml version="1.0"?>
<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
<?xml-stylesheet href="chrome://mochikit/content/tests/SimpleTest/test.css"
type="text/css"?>
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=783129
-->
<window title="Mozilla Bug 549682"
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
<script type="application/javascript"
src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
<!-- test results are displayed in the html:body -->
<body xmlns="http://www.w3.org/1999/xhtml">
<a href="https://bugzilla.mozilla.org/show_bug.cgi?id=783129"
target="_blank">Mozilla Bug 783129</a>
<iframe onload="startTests()" id="fooframe" src="http://example.com"></iframe>
</body>
<!-- test code goes here -->
<script type="application/javascript"><![CDATA[
/** Test for Bug 783129 **/
SimpleTest.waitForExplicitFinish();
function startTests() {
var c = $("fooframe").contentDocument.register("x-foo");
var elem = new c();
is(elem.tagName, "X-FOO", "Constructor should create an x-foo element.");
var anotherElem = $("fooframe").contentDocument.createElement("x-foo");
is(anotherElem.tagName, "X-FOO", "createElement should create an x-foo element.");
SimpleTest.finish();
}
]]></script>
</window>

View File

@ -564,7 +564,6 @@ WebGLContext::SetDimensions(int32_t width, int32_t height)
// we'll end up displaying random memory
gl->fBindFramebuffer(LOCAL_GL_FRAMEBUFFER, 0);
gl->fViewport(0, 0, mWidth, mHeight);
gl->fClearColor(0.0f, 0.0f, 0.0f, 0.0f);
gl->fClearDepth(1.0f);
gl->fClearStencil(0);

View File

@ -764,6 +764,9 @@ public:
bool ValidateUniformSetter(const char* name, WebGLUniformLocation *location_object, GLint& location);
void ValidateProgram(WebGLProgram *prog);
bool ValidateUniformLocation(const char* info, WebGLUniformLocation *location_object);
bool ValidateSamplerUniformSetter(const char* info,
WebGLUniformLocation *location,
WebGLint value);
void VertexAttrib1f(WebGLuint index, WebGLfloat x0);
void VertexAttrib2f(WebGLuint index, WebGLfloat x0, WebGLfloat x1);

View File

@ -2850,6 +2850,15 @@ WebGLContext::GetVertexAttrib(JSContext* cx, WebGLuint index, WebGLenum pname,
return JS::Int32Value(mAttribBuffers[index].stride);
case LOCAL_GL_VERTEX_ATTRIB_ARRAY_SIZE:
{
if (!ValidateAttribIndex(index, "enableVertexAttribArray"))
return JS::NullValue();
if (!mAttribBuffers[index].enabled)
return JS::Int32Value(4);
// Don't break; fall through.
}
case LOCAL_GL_VERTEX_ATTRIB_ARRAY_TYPE:
{
GLint i = 0;
@ -3673,12 +3682,17 @@ WebGLContext::SurfaceFromElementResultToImageSurface(nsLayoutUtils::SurfaceFromE
}
void
WebGLContext::Uniform1i(WebGLUniformLocation *location_object, WebGLint a1)
{
GLint location;
if (!ValidateUniformSetter("Uniform1i", location_object, location))
return;
if (!ValidateSamplerUniformSetter("Uniform1i", location_object, a1))
return;
MakeContextCurrent();
gl->fUniform1i(location, a1);
}
@ -3690,6 +3704,13 @@ WebGLContext::Uniform2i(WebGLUniformLocation *location_object, WebGLint a1,
GLint location;
if (!ValidateUniformSetter("Uniform2i", location_object, location))
return;
if (!ValidateSamplerUniformSetter("Uniform2i", location_object, a1) ||
!ValidateSamplerUniformSetter("Uniform2i", location_object, a2))
{
return;
}
MakeContextCurrent();
gl->fUniform2i(location, a1, a2);
}
@ -3701,6 +3722,14 @@ WebGLContext::Uniform3i(WebGLUniformLocation *location_object, WebGLint a1,
GLint location;
if (!ValidateUniformSetter("Uniform3i", location_object, location))
return;
if (!ValidateSamplerUniformSetter("Uniform3i", location_object, a1) ||
!ValidateSamplerUniformSetter("Uniform3i", location_object, a2) ||
!ValidateSamplerUniformSetter("Uniform3i", location_object, a3))
{
return;
}
MakeContextCurrent();
gl->fUniform3i(location, a1, a2, a3);
}
@ -3712,6 +3741,15 @@ WebGLContext::Uniform4i(WebGLUniformLocation *location_object, WebGLint a1,
GLint location;
if (!ValidateUniformSetter("Uniform4i", location_object, location))
return;
if (!ValidateSamplerUniformSetter("Uniform4i", location_object, a1) ||
!ValidateSamplerUniformSetter("Uniform4i", location_object, a2) ||
!ValidateSamplerUniformSetter("Uniform4i", location_object, a3) ||
!ValidateSamplerUniformSetter("Uniform4i", location_object, a4))
{
return;
}
MakeContextCurrent();
gl->fUniform4i(location, a1, a2, a3, a4);
}
@ -3769,6 +3807,10 @@ WebGLContext::Uniform1iv_base(WebGLUniformLocation *location_object,
numElementsToUpload, arrayLength)) {
return;
}
if (!ValidateSamplerUniformSetter("Uniform1iv", location_object, data[0]))
return;
MakeContextCurrent();
gl->fUniform1iv(location, numElementsToUpload, data);
}
@ -3783,6 +3825,13 @@ WebGLContext::Uniform2iv_base(WebGLUniformLocation *location_object,
numElementsToUpload, arrayLength)) {
return;
}
if (!ValidateSamplerUniformSetter("Uniform2iv", location_object, data[0]) ||
!ValidateSamplerUniformSetter("Uniform2iv", location_object, data[1]))
{
return;
}
MakeContextCurrent();
gl->fUniform2iv(location, numElementsToUpload, data);
}
@ -3797,6 +3846,14 @@ WebGLContext::Uniform3iv_base(WebGLUniformLocation *location_object,
numElementsToUpload, arrayLength)) {
return;
}
if (!ValidateSamplerUniformSetter("Uniform3iv", location_object, data[0]) ||
!ValidateSamplerUniformSetter("Uniform3iv", location_object, data[1]) ||
!ValidateSamplerUniformSetter("Uniform3iv", location_object, data[2]))
{
return;
}
MakeContextCurrent();
gl->fUniform3iv(location, numElementsToUpload, data);
}
@ -3811,6 +3868,15 @@ WebGLContext::Uniform4iv_base(WebGLUniformLocation *location_object,
numElementsToUpload, arrayLength)) {
return;
}
if (!ValidateSamplerUniformSetter("Uniform4iv", location_object, data[0]) ||
!ValidateSamplerUniformSetter("Uniform4iv", location_object, data[1]) ||
!ValidateSamplerUniformSetter("Uniform4iv", location_object, data[2]) ||
!ValidateSamplerUniformSetter("Uniform4iv", location_object, data[3]))
{
return;
}
MakeContextCurrent();
gl->fUniform4iv(location, numElementsToUpload, data);
}

View File

@ -688,6 +688,23 @@ WebGLContext::ValidateUniformLocation(const char* info, WebGLUniformLocation *lo
return true;
}
bool
WebGLContext::ValidateSamplerUniformSetter(const char* info, WebGLUniformLocation *location, WebGLint value)
{
if (location->Info().type != SH_SAMPLER_2D &&
location->Info().type != SH_SAMPLER_CUBE)
{
return true;
}
if (value >= 0 && value < mGLMaxTextureUnits)
return true;
ErrorInvalidValue("%s: this uniform location is a sampler, but %d is not a valid texture unit",
info, value);
return false;
}
bool
WebGLContext::ValidateAttribArraySetter(const char* name, uint32_t cnt, uint32_t arrayLength)
{

View File

@ -866,6 +866,8 @@ nsEventDispatcher::CreateEvent(nsPresContext* aPresContext,
if (aEventType.LowerCaseEqualsLiteral("commandevent") ||
aEventType.LowerCaseEqualsLiteral("commandevents"))
return NS_NewDOMCommandEvent(aDOMEvent, aPresContext, nullptr);
if (aEventType.LowerCaseEqualsLiteral("elementreplace"))
return NS_NewDOMElementReplaceEvent(aDOMEvent, aPresContext, nullptr);
if (aEventType.LowerCaseEqualsLiteral("datacontainerevent") ||
aEventType.LowerCaseEqualsLiteral("datacontainerevents"))
return NS_NewDOMDataContainerEvent(aDOMEvent, aPresContext, nullptr);

View File

@ -379,12 +379,6 @@ protected:
*/
already_AddRefed<DOMMediaStream> CaptureStreamInternal(bool aFinishWhenEnded);
/**
* Create a decoder for the given aMIMEType. Returns null if we
* were unable to create the decoder.
*/
already_AddRefed<MediaDecoder> CreateDecoder(const nsACString& aMIMEType);
/**
* Initialize a decoder as a clone of an existing decoder in another
* element.

View File

@ -155,6 +155,11 @@ public:
SetHTMLBoolAttr(nsGkAtoms::nohref, aValue, aError);
}
void Stringify(nsAString& aResult)
{
GetHref(aResult);
}
protected:
virtual JSObject* WrapNode(JSContext* aCx, JSObject* aScope,
bool* aTriedToWrap) MOZ_OVERRIDE;

View File

@ -10,6 +10,7 @@
#include "nsAttrValueInlines.h"
#include "nsRuleData.h"
#include "nsHTMLStyleSheet.h"
#include "nsMappedAttributes.h"
#include "mozilla/dom/BindingUtils.h"
#include "mozilla/dom/HTMLCollectionBinding.h"
#include "mozilla/dom/HTMLTableElementBinding.h"
@ -1211,6 +1212,15 @@ HTMLTableElement::BuildInheritedAttributes()
}
}
void
HTMLTableElement::ReleaseInheritedAttributes()
{
if (mTableInheritedAttributes &&
mTableInheritedAttributes != TABLE_ATTRS_DIRTY)
NS_RELEASE(mTableInheritedAttributes);
mTableInheritedAttributes = TABLE_ATTRS_DIRTY;
}
nsresult
HTMLTableElement::BindToTree(nsIDocument* aDocument, nsIContent* aParent,
nsIContent* aBindingParent,

View File

@ -9,7 +9,6 @@
#include "nsIDOMHTMLTableElement.h"
#include "mozilla/dom/HTMLTableCaptionElement.h"
#include "mozilla/dom/HTMLTableSectionElement.h"
#include "nsMappedAttributes.h"
namespace mozilla {
namespace dom {
@ -224,12 +223,7 @@ protected:
// to be recalculated.
nsMappedAttributes *mTableInheritedAttributes;
void BuildInheritedAttributes();
void ReleaseInheritedAttributes() {
if (mTableInheritedAttributes &&
mTableInheritedAttributes != TABLE_ATTRS_DIRTY)
NS_RELEASE(mTableInheritedAttributes);
mTableInheritedAttributes = TABLE_ATTRS_DIRTY;
}
void ReleaseInheritedAttributes();
};
} // namespace dom

View File

@ -3,6 +3,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/. */
#include "nsDocument.h"
#include "HTMLUnknownElement.h"
#include "mozilla/dom/HTMLElementBinding.h"
@ -18,7 +19,19 @@ JSObject*
HTMLUnknownElement::WrapNode(JSContext *aCx, JSObject *aScope,
bool *aTriedToWrap)
{
return HTMLUnknownElementBinding::Wrap(aCx, aScope, this, aTriedToWrap);
JSObject* obj =
HTMLUnknownElementBinding::Wrap(aCx, aScope, this, aTriedToWrap);
if (obj && Substring(NodeName(), 0, 2).LowerCaseEqualsLiteral("x-")) {
// If we have a registered x-tag then we fix the prototype.
JSAutoCompartment ac(aCx, obj);
nsDocument* document = static_cast<nsDocument*>(OwnerDoc());
JSObject* prototype = document->GetCustomPrototype(LocalName());
if (prototype) {
NS_ENSURE_TRUE(JS_WrapObject(aCx, &prototype), nullptr);
NS_ENSURE_TRUE(JS_SetPrototype(aCx, obj, prototype), nullptr);
}
}
return obj;
}
// QueryInterface implementation for HTMLUnknownElement

View File

@ -1479,8 +1479,8 @@ nsGenericHTMLElement::ParseScrollingValue(const nsAString& aString,
* Handle attributes common to all html elements
*/
void
nsGenericHTMLElement::MapCommonAttributesExceptHiddenInto(const nsMappedAttributes* aAttributes,
nsRuleData* aData)
nsGenericHTMLElement::MapCommonAttributesInto(const nsMappedAttributes* aAttributes,
nsRuleData* aData)
{
if (aData->mSIDs & NS_STYLE_INHERIT_BIT(UserInterface)) {
nsCSSValue* userModify = aData->ValueForUserModify();
@ -1508,13 +1508,6 @@ nsGenericHTMLElement::MapCommonAttributesExceptHiddenInto(const nsMappedAttribut
eCSSUnit_Ident);
}
}
}
void
nsGenericHTMLElement::MapCommonAttributesInto(const nsMappedAttributes* aAttributes,
nsRuleData* aData)
{
nsGenericHTMLElement::MapCommonAttributesExceptHiddenInto(aAttributes, aData);
if (aData->mSIDs & NS_STYLE_INHERIT_BIT(Display)) {
nsCSSValue* display = aData->ValueForDisplay();

View File

@ -517,14 +517,6 @@ public:
static void MapCommonAttributesInto(const nsMappedAttributes* aAttributes,
nsRuleData* aRuleData);
/**
* This method is used by embed elements because they should ignore the hidden
* attribute for the moment.
* TODO: This should be removed when bug 614825 will be fixed.
*/
static void MapCommonAttributesExceptHiddenInto(const nsMappedAttributes* aAttributes,
nsRuleData* aRuleData);
static const MappedAttributeEntry sCommonAttributeMap[];
static const MappedAttributeEntry sImageMarginSizeAttributeMap[];
static const MappedAttributeEntry sImageBorderAttributeMap[];

View File

@ -75,35 +75,6 @@
#include "nsIPowerManagerService.h"
#include <algorithm>
#ifdef MOZ_OGG
#include "OggDecoder.h"
#endif
#ifdef MOZ_WAVE
#include "WaveDecoder.h"
#endif
#ifdef MOZ_WEBM
#include "WebMDecoder.h"
#endif
#ifdef MOZ_RAW
#include "RawDecoder.h"
#endif
#ifdef MOZ_GSTREAMER
#include "GStreamerDecoder.h"
#endif
#ifdef MOZ_MEDIA_PLUGINS
#include "MediaPluginHost.h"
#include "MediaPluginDecoder.h"
#endif
#ifdef MOZ_WIDGET_GONK
#include "MediaOmxDecoder.h"
#endif
#ifdef MOZ_DASH
#include "DASHDecoder.h"
#endif
#ifdef MOZ_WMF
#include "WMFDecoder.h"
#endif
#ifdef PR_LOGGING
static PRLogModuleInfo* gMediaElementLog;
static PRLogModuleInfo* gMediaElementEventsLog;
@ -2194,89 +2165,6 @@ nsHTMLMediaElement::CanPlayType(const nsAString& aType, nsAString& aResult)
return NS_OK;
}
already_AddRefed<MediaDecoder>
nsHTMLMediaElement::CreateDecoder(const nsACString& aType)
{
// If you change this list to add support for new decoders for codecs that
// can be used by <audio>, please consider updating MediaDecodeTask::CreateDecoder
// as well.
#ifdef MOZ_GSTREAMER
if (DecoderTraits::IsGStreamerSupportedType(aType)) {
nsRefPtr<GStreamerDecoder> decoder = new GStreamerDecoder();
if (decoder->Init(this)) {
return decoder.forget();
}
}
#endif
#ifdef MOZ_RAW
if (DecoderTraits::IsRawType(aType)) {
nsRefPtr<RawDecoder> decoder = new RawDecoder();
if (decoder->Init(this)) {
return decoder.forget();
}
}
#endif
#ifdef MOZ_OGG
if (DecoderTraits::IsOggType(aType)) {
nsRefPtr<OggDecoder> decoder = new OggDecoder();
if (decoder->Init(this)) {
return decoder.forget();
}
}
#endif
#ifdef MOZ_WAVE
if (DecoderTraits::IsWaveType(aType)) {
nsRefPtr<WaveDecoder> decoder = new WaveDecoder();
if (decoder->Init(this)) {
return decoder.forget();
}
}
#endif
#ifdef MOZ_WIDGET_GONK
if (DecoderTraits::IsOmxSupportedType(aType)) {
nsRefPtr<MediaOmxDecoder> decoder = new MediaOmxDecoder();
if (decoder->Init(this)) {
return decoder.forget();
}
}
#endif
#ifdef MOZ_MEDIA_PLUGINS
if (MediaDecoder::IsMediaPluginsEnabled() && GetMediaPluginHost()->FindDecoder(aType, NULL)) {
nsRefPtr<MediaPluginDecoder> decoder = new MediaPluginDecoder(aType);
if (decoder->Init(this)) {
return decoder.forget();
}
}
#endif
#ifdef MOZ_WEBM
if (DecoderTraits::IsWebMType(aType)) {
nsRefPtr<WebMDecoder> decoder = new WebMDecoder();
if (decoder->Init(this)) {
return decoder.forget();
}
}
#endif
#ifdef MOZ_DASH
if (DecoderTraits::IsDASHMPDType(aType)) {
nsRefPtr<DASHDecoder> decoder = new DASHDecoder();
if (decoder->Init(this)) {
return decoder.forget();
}
}
#endif
#ifdef MOZ_WMF
if (DecoderTraits::IsWMFSupportedType(aType)) {
nsRefPtr<WMFDecoder> decoder = new WMFDecoder();
if (decoder->Init(this)) {
return decoder.forget();
}
}
#endif
return nullptr;
}
nsresult nsHTMLMediaElement::InitializeDecoderAsClone(MediaDecoder* aOriginal)
{
NS_ASSERTION(mLoadingSrc, "mLoadingSrc must already be set");
@ -2323,7 +2211,7 @@ nsresult nsHTMLMediaElement::InitializeDecoderForChannel(nsIChannel *aChannel,
aChannel->GetContentType(mimeType);
NS_ASSERTION(!mimeType.IsEmpty(), "We should have the Content-Type.");
nsRefPtr<MediaDecoder> decoder = CreateDecoder(mimeType);
nsRefPtr<MediaDecoder> decoder = DecoderTraits::CreateDecoder(mimeType, this);
if (!decoder) {
nsAutoString src;
GetCurrentSrc(src);

View File

@ -419,21 +419,6 @@ MapAttributesIntoRule(const nsMappedAttributes *aAttributes,
nsGenericHTMLElement::MapCommonAttributesInto(aAttributes, aData);
}
static void
EmbedMapAttributesIntoRule(const nsMappedAttributes *aAttributes,
nsRuleData *aData)
{
// NOTE: this should call the exact some methods than MapAttributesIntoRule
// except that MapCommonAttributesExceptHiddenInto is called instead of
// MapCommonAttributesInto.
// TODO: This method should be removed when bug 614825 will be fixed.
nsGenericHTMLElement::MapImageBorderAttributeInto(aAttributes, aData);
nsGenericHTMLElement::MapImageMarginAttributeInto(aAttributes, aData);
nsGenericHTMLElement::MapImageSizeAttributesInto(aAttributes, aData);
nsGenericHTMLElement::MapImageAlignAttributeInto(aAttributes, aData);
nsGenericHTMLElement::MapCommonAttributesExceptHiddenInto(aAttributes, aData);
}
NS_IMETHODIMP_(bool)
nsHTMLSharedObjectElement::IsAttributeMapped(const nsIAtom *aAttribute) const
{
@ -451,10 +436,6 @@ nsHTMLSharedObjectElement::IsAttributeMapped(const nsIAtom *aAttribute) const
nsMapRuleToAttributesFunc
nsHTMLSharedObjectElement::GetAttributeMappingFunction() const
{
if (mNodeInfo->Equals(nsGkAtoms::embed)) {
return &EmbedMapAttributesIntoRule;
}
return &MapAttributesIntoRule;
}

View File

@ -270,6 +270,7 @@ MOCHITEST_FILES = \
test_bug827126.html \
test_bug827426.html \
test_bug838582.html \
test_bug839913.html \
test_bug841466.html \
test_iframe_sandbox_inheritance.html \
file_iframe_sandbox_a_if1.html \

View File

@ -19,16 +19,12 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=613722
/** Test for Bug 613722 **/
/**
* TODO: this test should be removed when bug 614825 will be fixed.
*/
var rect = document.getElementsByTagName('embed')[0].getBoundingClientRect();
var hasFrame = rect.left != 0 || rect.right != 0 || rect.top != 0 ||
rect.bottom != 0;
ok(hasFrame, "embed should have a frame with hidden set");
ok(!hasFrame, "embed should not have a frame with hidden set");
</script>
</pre>

View File

@ -0,0 +1,14 @@
<!DOCTYPE html>
<meta charset=utf-8>
<title>Test for HTMLAreaElement's stringifier</title>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<div id="log"></div>
<script>
test(function() {
var area = document.createElement("area");
area.href = "http://example.org/";
assert_equals(area.href, "http://example.org/");
assert_equals(String(area), "http://example.org/");
}, "Area elements should stringify to the href attribute");
</script>

View File

@ -9,7 +9,6 @@
#include "nsDocument.h"
#include "nsIHTMLDocument.h"
#include "nsIDOMHTMLDocument.h"
#include "nsIDOMHTMLBodyElement.h"
#include "nsIDOMHTMLCollection.h"
#include "nsIScriptElement.h"
#include "jsapi.h"

View File

@ -18,6 +18,97 @@ namespace mozilla {
namespace dom {
// This is an internal helper class and should not be used outside of this header.
struct AudioTimelineEvent {
enum Type MOZ_ENUM_TYPE(uint32_t) {
SetValue,
LinearRamp,
ExponentialRamp,
SetTarget,
SetValueCurve
};
AudioTimelineEvent(Type aType, double aTime, float aValue, double aTimeConstant = 0.0,
float aDuration = 0.0, float* aCurve = nullptr, uint32_t aCurveLength = 0)
: mType(aType)
, mTimeConstant(aTimeConstant)
, mDuration(aDuration)
#ifdef DEBUG
, mTimeIsInTicks(false)
#endif
{
if (aType == AudioTimelineEvent::SetValueCurve) {
mCurve = aCurve;
mCurveLength = aCurveLength;
} else {
mValue = aValue;
mTime = aTime;
}
}
bool IsValid() const
{
return IsValid(mTime) &&
IsValid(mValue) &&
IsValid(mTimeConstant) &&
IsValid(mDuration);
}
template <class TimeType>
TimeType Time() const;
void SetTimeInTicks(int64_t aTimeInTicks)
{
mTimeInTicks = aTimeInTicks;
#ifdef DEBUG
mTimeIsInTicks = true;
#endif
}
Type mType;
union {
float mValue;
uint32_t mCurveLength;
};
union {
// The time for an event can either be in absolute value or in ticks.
// Initially the time of the event is always in absolute value.
// In order to convert it to ticks, call SetTimeInTicks. Once this
// method has been called for an event, the time cannot be converted
// back to absolute value.
union {
double mTime;
int64_t mTimeInTicks;
};
float* mCurve;
};
double mTimeConstant;
double mDuration;
#ifdef DEBUG
bool mTimeIsInTicks;
#endif
private:
static bool IsValid(double value)
{
return MOZ_DOUBLE_IS_FINITE(value);
}
};
template <>
inline double AudioTimelineEvent::Time<double>() const
{
MOZ_ASSERT(!mTimeIsInTicks);
return mTime;
}
template <>
inline int64_t AudioTimelineEvent::Time<int64_t>() const
{
MOZ_ASSERT(mTimeIsInTicks);
return mTimeInTicks;
}
/**
* This class will be instantiated with different template arguments for testing and
* production code.
@ -28,64 +119,31 @@ namespace dom {
template <class ErrorResult>
class AudioEventTimeline
{
private:
struct Event {
enum Type MOZ_ENUM_TYPE(uint32_t) {
SetValue,
LinearRamp,
ExponentialRamp,
SetTarget,
SetValueCurve
};
Event(Type aType, double aTime, float aValue, double aTimeConstant = 0.0,
float aDuration = 0.0, float* aCurve = nullptr, uint32_t aCurveLength = 0)
: mType(aType)
, mTimeConstant(aTimeConstant)
, mDuration(aDuration)
{
if (aType == Event::SetValueCurve) {
mCurve = aCurve;
mCurveLength = aCurveLength;
} else {
mValue = aValue;
mTime = aTime;
}
}
bool IsValid() const
{
return IsValid(mTime) &&
IsValid(mValue) &&
IsValid(mTimeConstant) &&
IsValid(mDuration);
}
Type mType;
union {
float mValue;
uint32_t mCurveLength;
};
union {
double mTime;
float* mCurve;
};
double mTimeConstant;
double mDuration;
private:
static bool IsValid(double value)
{
return MOZ_DOUBLE_IS_FINITE(value);
}
};
public:
// This constructor should only be used for objects which are meant to be
// copied from other properly constructed objects.
AudioEventTimeline()
: mValue(0.f)
{
}
explicit AudioEventTimeline(float aDefaultValue)
: mValue(aDefaultValue)
{
}
bool HasSimpleValue() const
{
return mEvents.IsEmpty();
}
float GetValue() const
{
// This method should only be called if HasSimpleValue() returns true
MOZ_ASSERT(HasSimpleValue());
return mValue;
}
float Value() const
{
// TODO: Return the current value based on the timeline of the AudioContext
@ -108,29 +166,29 @@ public:
void SetValueAtTime(float aValue, double aStartTime, ErrorResult& aRv)
{
InsertEvent(Event(Event::SetValue, aStartTime, aValue), aRv);
InsertEvent(AudioTimelineEvent(AudioTimelineEvent::SetValue, aStartTime, aValue), aRv);
}
void LinearRampToValueAtTime(float aValue, double aEndTime, ErrorResult& aRv)
{
InsertEvent(Event(Event::LinearRamp, aEndTime, aValue), aRv);
InsertEvent(AudioTimelineEvent(AudioTimelineEvent::LinearRamp, aEndTime, aValue), aRv);
}
void ExponentialRampToValueAtTime(float aValue, double aEndTime, ErrorResult& aRv)
{
InsertEvent(Event(Event::ExponentialRamp, aEndTime, aValue), aRv);
InsertEvent(AudioTimelineEvent(AudioTimelineEvent::ExponentialRamp, aEndTime, aValue), aRv);
}
void SetTargetAtTime(float aTarget, double aStartTime, double aTimeConstant, ErrorResult& aRv)
{
InsertEvent(Event(Event::SetTarget, aStartTime, aTarget, aTimeConstant), aRv);
InsertEvent(AudioTimelineEvent(AudioTimelineEvent::SetTarget, aStartTime, aTarget, aTimeConstant), aRv);
}
void SetValueCurveAtTime(const float* aValues, uint32_t aValuesLength, double aStartTime, double aDuration, ErrorResult& aRv)
{
// TODO: implement
// Note that we will need to copy the buffer here.
// InsertEvent(Event(Event::SetValueCurve, aStartTime, 0.0f, 0.0f, aDuration, aValues, aValuesLength), aRv);
// InsertEvent(AudioTimelineEvent(AudioTimelineEvent::SetValueCurve, aStartTime, 0.0f, 0.0f, aDuration, aValues, aValuesLength), aRv);
}
void CancelScheduledValues(double aStartTime)
@ -151,33 +209,34 @@ public:
}
// This method computes the AudioParam value at a given time based on the event timeline
float GetValueAtTime(double aTime) const
template<class TimeType>
float GetValueAtTime(TimeType aTime) const
{
const Event* previous = nullptr;
const Event* next = nullptr;
const AudioTimelineEvent* previous = nullptr;
const AudioTimelineEvent* next = nullptr;
bool bailOut = false;
for (unsigned i = 0; !bailOut && i < mEvents.Length(); ++i) {
switch (mEvents[i].mType) {
case Event::SetValue:
case Event::SetTarget:
case Event::LinearRamp:
case Event::ExponentialRamp:
if (aTime == mEvents[i].mTime) {
case AudioTimelineEvent::SetValue:
case AudioTimelineEvent::SetTarget:
case AudioTimelineEvent::LinearRamp:
case AudioTimelineEvent::ExponentialRamp:
if (aTime == mEvents[i].template Time<TimeType>()) {
// Find the last event with the same time
do {
++i;
} while (i < mEvents.Length() &&
aTime == mEvents[i].mTime);
aTime == mEvents[i].template Time<TimeType>());
return mEvents[i - 1].mValue;
}
previous = next;
next = &mEvents[i];
if (aTime < mEvents[i].mTime) {
if (aTime < mEvents[i].template Time<TimeType>()) {
bailOut = true;
}
break;
case Event::SetValueCurve:
case AudioTimelineEvent::SetValueCurve:
// TODO: implement
break;
default:
@ -198,17 +257,17 @@ public:
// If the requested time is before all of the existing events
if (!previous) {
switch (next->mType) {
case Event::SetValue:
case Event::SetTarget:
case AudioTimelineEvent::SetValue:
case AudioTimelineEvent::SetTarget:
// The requested time is before the first event
return mValue;
case Event::LinearRamp:
case AudioTimelineEvent::LinearRamp:
// Use t=0 as T0 and v=defaultValue as V0
return LinearInterpolate(0.0, mValue, next->mTime, next->mValue, aTime);
case Event::ExponentialRamp:
return LinearInterpolate(0.0, mValue, next->template Time<TimeType>(), next->mValue, aTime);
case AudioTimelineEvent::ExponentialRamp:
// Use t=0 as T0 and v=defaultValue as V0
return ExponentialInterpolate(0.0, mValue, next->mTime, next->mValue, aTime);
case Event::SetValueCurve:
return ExponentialInterpolate(0.0, mValue, next->template Time<TimeType>(), next->mValue, aTime);
case AudioTimelineEvent::SetValueCurve:
// TODO: implement
return 0.0f;
}
@ -216,24 +275,24 @@ public:
}
// SetTarget nodes can be handled no matter what their next node is (if they have one)
if (previous->mType == Event::SetTarget) {
if (previous->mType == AudioTimelineEvent::SetTarget) {
// Follow the curve, without regard to the next node
return ExponentialApproach(previous->mTime, mValue, previous->mValue,
return ExponentialApproach(previous->template Time<TimeType>(), mValue, previous->mValue,
previous->mTimeConstant, aTime);
}
// If the requested time is after all of the existing events
if (!next) {
switch (previous->mType) {
case Event::SetValue:
case Event::LinearRamp:
case Event::ExponentialRamp:
case AudioTimelineEvent::SetValue:
case AudioTimelineEvent::LinearRamp:
case AudioTimelineEvent::ExponentialRamp:
// The value will be constant after the last event
return previous->mValue;
case Event::SetValueCurve:
case AudioTimelineEvent::SetValueCurve:
// TODO: implement
return 0.0f;
case Event::SetTarget:
case AudioTimelineEvent::SetTarget:
MOZ_ASSERT(false, "unreached");
}
MOZ_ASSERT(false, "unreached");
@ -243,28 +302,28 @@ public:
// First, handle the case where our range ends up in a ramp event
switch (next->mType) {
case Event::LinearRamp:
return LinearInterpolate(previous->mTime, previous->mValue, next->mTime, next->mValue, aTime);
case Event::ExponentialRamp:
return ExponentialInterpolate(previous->mTime, previous->mValue, next->mTime, next->mValue, aTime);
case Event::SetValue:
case Event::SetTarget:
case Event::SetValueCurve:
case AudioTimelineEvent::LinearRamp:
return LinearInterpolate(previous->template Time<TimeType>(), previous->mValue, next->template Time<TimeType>(), next->mValue, aTime);
case AudioTimelineEvent::ExponentialRamp:
return ExponentialInterpolate(previous->template Time<TimeType>(), previous->mValue, next->template Time<TimeType>(), next->mValue, aTime);
case AudioTimelineEvent::SetValue:
case AudioTimelineEvent::SetTarget:
case AudioTimelineEvent::SetValueCurve:
break;
}
// Now handle all other cases
switch (previous->mType) {
case Event::SetValue:
case Event::LinearRamp:
case Event::ExponentialRamp:
case AudioTimelineEvent::SetValue:
case AudioTimelineEvent::LinearRamp:
case AudioTimelineEvent::ExponentialRamp:
// If the next event type is neither linear or exponential ramp, the
// value is constant.
return previous->mValue;
case Event::SetValueCurve:
case AudioTimelineEvent::SetValueCurve:
// TODO: implement
return 0.0f;
case Event::SetTarget:
case AudioTimelineEvent::SetTarget:
MOZ_ASSERT(false, "unreached");
}
@ -293,19 +352,26 @@ public:
return v1 + (v0 - v1) * expf(-(t - t0) / timeConstant);
}
private:
const Event* GetPreviousEvent(double aTime) const
void ConvertEventTimesToTicks(int64_t (*aConvertor)(double aTime, void* aClosure), void* aClosure)
{
const Event* previous = nullptr;
const Event* next = nullptr;
for (unsigned i = 0; i < mEvents.Length(); ++i) {
mEvents[i].SetTimeInTicks(aConvertor(mEvents[i].template Time<double>(), aClosure));
}
}
private:
const AudioTimelineEvent* GetPreviousEvent(double aTime) const
{
const AudioTimelineEvent* previous = nullptr;
const AudioTimelineEvent* next = nullptr;
bool bailOut = false;
for (unsigned i = 0; !bailOut && i < mEvents.Length(); ++i) {
switch (mEvents[i].mType) {
case Event::SetValue:
case Event::SetTarget:
case Event::LinearRamp:
case Event::ExponentialRamp:
case AudioTimelineEvent::SetValue:
case AudioTimelineEvent::SetTarget:
case AudioTimelineEvent::LinearRamp:
case AudioTimelineEvent::ExponentialRamp:
if (aTime == mEvents[i].mTime) {
// Find the last event with the same time
do {
@ -320,7 +386,7 @@ private:
bailOut = true;
}
break;
case Event::SetValueCurve:
case AudioTimelineEvent::SetValueCurve:
// TODO: implement
break;
default:
@ -335,7 +401,7 @@ private:
return previous;
}
void InsertEvent(const Event& aEvent, ErrorResult& aRv)
void InsertEvent(const AudioTimelineEvent& aEvent, ErrorResult& aRv)
{
if (!aEvent.IsValid()) {
aRv.Throw(NS_ERROR_DOM_SYNTAX_ERR);
@ -345,7 +411,7 @@ private:
// Make sure that non-curve events don't fall within the duration of a
// curve event.
for (unsigned i = 0; i < mEvents.Length(); ++i) {
if (mEvents[i].mType == Event::SetValueCurve &&
if (mEvents[i].mType == AudioTimelineEvent::SetValueCurve &&
mEvents[i].mTime <= aEvent.mTime &&
(mEvents[i].mTime + mEvents[i].mDuration) >= aEvent.mTime) {
aRv.Throw(NS_ERROR_DOM_SYNTAX_ERR);
@ -355,7 +421,7 @@ private:
// Make sure that curve events don't fall in a range which includes other
// events.
if (aEvent.mType == Event::SetValueCurve) {
if (aEvent.mType == AudioTimelineEvent::SetValueCurve) {
for (unsigned i = 0; i < mEvents.Length(); ++i) {
if (mEvents[i].mTime >= aEvent.mTime &&
mEvents[i].mTime <= (aEvent.mTime + aEvent.mDuration)) {
@ -366,12 +432,12 @@ private:
}
// Make sure that invalid values are not used for exponential curves
if (aEvent.mType == Event::ExponentialRamp) {
if (aEvent.mType == AudioTimelineEvent::ExponentialRamp) {
if (aEvent.mValue <= 0.f) {
aRv.Throw(NS_ERROR_DOM_SYNTAX_ERR);
return;
}
const Event* previousEvent = GetPreviousEvent(aEvent.mTime);
const AudioTimelineEvent* previousEvent = GetPreviousEvent(aEvent.mTime);
if (previousEvent) {
if (previousEvent->mValue <= 0.f) {
aRv.Throw(NS_ERROR_DOM_SYNTAX_ERR);
@ -418,7 +484,7 @@ private:
// and that is the reason why we're using a simple array as the data structure.
// We can optimize this in the future if the performance of the array ends up
// being a bottleneck.
nsTArray<Event> mEvents;
nsTArray<AudioTimelineEvent> mEvents;
float mValue;
};

View File

@ -68,4 +68,14 @@ AudioBlockCopyChannelWithScale(const float aInput[WEBAUDIO_BLOCK_SIZE],
}
}
void
AudioBlockCopyChannelWithScale(const float aInput[WEBAUDIO_BLOCK_SIZE],
const float aScale[WEBAUDIO_BLOCK_SIZE],
float aOutput[WEBAUDIO_BLOCK_SIZE])
{
for (uint32_t i = 0; i < WEBAUDIO_BLOCK_SIZE; ++i) {
aOutput[i] = aInput[i]*aScale[i];
}
}
}

View File

@ -100,6 +100,13 @@ void AudioBlockCopyChannelWithScale(const float aInput[WEBAUDIO_BLOCK_SIZE],
float aScale,
float aOutput[WEBAUDIO_BLOCK_SIZE]);
/**
* Vector copy-scaled operation.
*/
void AudioBlockCopyChannelWithScale(const float aInput[WEBAUDIO_BLOCK_SIZE],
const float aScale[WEBAUDIO_BLOCK_SIZE],
float aOutput[WEBAUDIO_BLOCK_SIZE]);
/**
* All methods of this class and its subclasses are called on the
* MediaStreamGraph thread.

View File

@ -7,14 +7,48 @@
#include "DecoderTraits.h"
#include "MediaDecoder.h"
#include "nsCharSeparatedTokenizer.h"
#ifdef MOZ_MEDIA_PLUGINS
#include "MediaPluginHost.h"
#endif
#ifdef MOZ_OGG
#include "OggDecoder.h"
#include "OggReader.h"
#endif
#ifdef MOZ_WAVE
#include "WaveDecoder.h"
#include "WaveReader.h"
#endif
#ifdef MOZ_WEBM
#include "WebMDecoder.h"
#include "WebMReader.h"
#endif
#ifdef MOZ_RAW
#include "RawDecoder.h"
#include "RawReader.h"
#endif
#ifdef MOZ_GSTREAMER
#include "mozilla/Preferences.h"
#include "GStreamerDecoder.h"
#include "GStreamerReader.h"
#endif
#ifdef MOZ_MEDIA_PLUGINS
#include "MediaPluginHost.h"
#include "MediaPluginDecoder.h"
#include "MediaPluginReader.h"
#include "MediaPluginHost.h"
#endif
#ifdef MOZ_WIDGET_GONK
#include "MediaOmxDecoder.h"
#include "MediaOmxReader.h"
#endif
#ifdef MOZ_DASH
#include "DASHDecoder.h"
#endif
#ifdef MOZ_WMF
#include "WMFDecoder.h"
#include "WMFReader.h"
#endif
namespace mozilla
@ -42,9 +76,8 @@ static const char* gRawCodecs[1] = {
nullptr
};
/* static */
bool
DecoderTraits::IsRawType(const nsACString& aType)
static bool
IsRawType(const nsACString& aType)
{
if (!MediaDecoder::IsRawEnabled()) {
return false;
@ -77,8 +110,8 @@ static char const *const gOggCodecsWithOpus[4] = {
nullptr
};
bool
DecoderTraits::IsOggType(const nsACString& aType)
static bool
IsOggType(const nsACString& aType)
{
if (!MediaDecoder::IsOggEnabled()) {
return false;
@ -105,8 +138,8 @@ static char const *const gWaveCodecs[2] = {
nullptr
};
bool
DecoderTraits::IsWaveType(const nsACString& aType)
static bool
IsWaveType(const nsACString& aType)
{
if (!MediaDecoder::IsWaveEnabled()) {
return false;
@ -130,8 +163,8 @@ static char const *const gWebMCodecs[4] = {
nullptr
};
bool
DecoderTraits::IsWebMType(const nsACString& aType)
static bool
IsWebMType(const nsACString& aType)
{
if (!MediaDecoder::IsWebMEnabled()) {
return false;
@ -149,8 +182,8 @@ static const char* const gH264Types[4] = {
nullptr
};
bool
DecoderTraits::IsGStreamerSupportedType(const nsACString& aMimeType)
static bool
IsGStreamerSupportedType(const nsACString& aMimeType)
{
if (!MediaDecoder::IsGStreamerEnabled())
return false;
@ -169,8 +202,8 @@ DecoderTraits::IsGStreamerSupportedType(const nsACString& aMimeType)
return false;
}
bool
DecoderTraits::IsH264Type(const nsACString& aType)
static bool
IsH264Type(const nsACString& aType)
{
return CodecListContains(gH264Types, aType);
}
@ -186,8 +219,8 @@ static const char* const gOmxTypes[6] = {
nullptr
};
bool
DecoderTraits::IsOmxSupportedType(const nsACString& aType)
static bool
IsOmxSupportedType(const nsACString& aType)
{
if (!MediaDecoder::IsOmxEnabled()) {
return false;
@ -212,8 +245,8 @@ static char const *const gH264Codecs[9] = {
#endif
#ifdef MOZ_MEDIA_PLUGINS
bool
DecoderTraits::IsMediaPluginsType(const nsACString& aType)
static bool
IsMediaPluginsType(const nsACString& aType)
{
if (!MediaDecoder::IsMediaPluginsEnabled()) {
return false;
@ -233,9 +266,8 @@ static const char* const gDASHMPDTypes[2] = {
nullptr
};
/* static */
bool
DecoderTraits::IsDASHMPDType(const nsACString& aType)
static bool
IsDASHMPDType(const nsACString& aType)
{
if (!MediaDecoder::IsDASHEnabled()) {
return false;
@ -246,7 +278,8 @@ DecoderTraits::IsDASHMPDType(const nsACString& aType)
#endif
#ifdef MOZ_WMF
bool DecoderTraits::IsWMFSupportedType(const nsACString& aType)
static bool
IsWMFSupportedType(const nsACString& aType)
{
return WMFDecoder::GetSupportedCodecs(aType, nullptr);
}
@ -353,5 +386,144 @@ DecoderTraits::CanHandleMediaType(const char* aMIMEType,
return CANPLAY_YES;
}
/* static */
already_AddRefed<MediaDecoder>
DecoderTraits::CreateDecoder(const nsACString& aType, MediaDecoderOwner* aOwner)
{
nsRefPtr<MediaDecoder> decoder;
#ifdef MOZ_GSTREAMER
if (IsGStreamerSupportedType(aType)) {
decoder = new GStreamerDecoder();
}
#endif
#ifdef MOZ_RAW
if (IsRawType(aType)) {
decoder = new RawDecoder();
}
#endif
#ifdef MOZ_OGG
if (IsOggType(aType)) {
decoder = new OggDecoder();
}
#endif
#ifdef MOZ_WAVE
if (IsWaveType(aType)) {
decoder = new WaveDecoder();
}
#endif
#ifdef MOZ_WIDGET_GONK
if (IsOmxSupportedType(aType)) {
decoder = new MediaOmxDecoder();
}
#endif
#ifdef MOZ_MEDIA_PLUGINS
if (MediaDecoder::IsMediaPluginsEnabled() && GetMediaPluginHost()->FindDecoder(aType, NULL)) {
decoder = new MediaPluginDecoder(aType);
}
#endif
#ifdef MOZ_WEBM
if (IsWebMType(aType)) {
decoder = new WebMDecoder();
}
#endif
#ifdef MOZ_DASH
if (IsDASHMPDType(aType)) {
decoder = new DASHDecoder();
}
#endif
#ifdef MOZ_WMF
if (IsWMFSupportedType(aType)) {
decoder = new WMFDecoder();
}
#endif
NS_ENSURE_TRUE(decoder != nullptr, nullptr);
NS_ENSURE_TRUE(decoder->Init(aOwner), nullptr);
return decoder.forget();
}
/* static */
MediaDecoderReader* DecoderTraits::CreateReader(const nsACString& aType, AbstractMediaDecoder* aDecoder)
{
MediaDecoderReader* decoderReader = nullptr;
#ifdef MOZ_GSTREAMER
if (IsGStreamerSupportedType(aType)) {
decoderReader = new GStreamerReader(aDecoder);
} else
#endif
#ifdef MOZ_RAW
if (IsRawType(aType)) {
decoderReader = new RawReader(aDecoder);
} else
#endif
#ifdef MOZ_OGG
if (IsOggType(aType)) {
decoderReader = new OggReader(aDecoder);
} else
#endif
#ifdef MOZ_WAVE
if (IsWaveType(aType)) {
decoderReader = new WaveReader(aDecoder);
} else
#endif
#ifdef MOZ_WIDGET_GONK
if (IsOmxSupportedType(aType)) {
decoderReader = new MediaOmxReader(aDecoder);
} else
#endif
#ifdef MOZ_MEDIA_PLUGINS
if (MediaDecoder::IsMediaPluginsEnabled() &&
GetMediaPluginHost()->FindDecoder(aType, nullptr)) {
decoderReader = new MediaPluginReader(aDecoder, aType);
} else
#endif
#ifdef MOZ_WEBM
if (IsWebMType(aType)) {
decoderReader = new WebMReader(aDecoder);
} else
#endif
#ifdef MOZ_WMF
if (IsWMFSupportedType(aType)) {
decoderReader = new WMFReader(aDecoder);
} else
#endif
#ifdef MOZ_DASH
// The DASH decoder is not supported.
#endif
if (false) {} // dummy if to take care of the dangling else
return decoderReader;
}
/* static */
bool DecoderTraits::IsSupportedInVideoDocument(const nsACString& aType)
{
return
#ifdef MOZ_OGG
IsOggType(aType) ||
#endif
#ifdef MOZ_WIDGET_GONK
IsOmxSupportedType(aType) ||
#endif
#ifdef MOZ_WEBM
IsWebMType(aType) ||
#endif
#ifdef MOZ_DASH
IsDASHMPDType(aType) ||
#endif
#ifdef MOZ_GSTREAMER
IsGStreamerSupportedType(aType) ||
#endif
#ifdef MOZ_MEDIA_PLUGINS
(MediaDecoder::IsMediaPluginsEnabled() && IsMediaPluginsType(aType)) ||
#endif
#ifdef MOZ_WMF
IsWMFSupportedType(aType) ||
#endif
false;
}
}

View File

@ -7,10 +7,15 @@
#ifndef DecoderTraits_h_
#define DecoderTraits_h_
#include "nsCOMPtr.h"
#include "nsAString.h"
namespace mozilla
{
namespace mozilla {
class AbstractMediaDecoder;
class MediaDecoder;
class MediaDecoderOwner;
class MediaDecoderReader;
enum CanPlayStatus {
CANPLAY_NO,
@ -36,44 +41,20 @@ public:
// false here even if CanHandleMediaType would return true.
static bool ShouldHandleMediaType(const char* aMIMEType);
#ifdef MOZ_RAW
static bool IsRawType(const nsACString& aType);
#endif
// Create a decoder for the given aType. Returns null if we
// were unable to create the decoder.
static already_AddRefed<MediaDecoder> CreateDecoder(const nsACString& aType,
MediaDecoderOwner* aOwner);
#ifdef MOZ_OGG
static bool IsOggType(const nsACString& aType);
#endif
// Create a reader for thew given MIME type aType. Returns null
// if we were unable to create the reader.
static MediaDecoderReader* CreateReader(const nsACString& aType,
AbstractMediaDecoder* aDecoder);
#ifdef MOZ_WAVE
static bool IsWaveType(const nsACString& aType);
#endif
#ifdef MOZ_WEBM
static bool IsWebMType(const nsACString& aType);
#endif
#ifdef MOZ_GSTREAMER
// When enabled, use GStreamer for H.264, but not for codecs handled by our
// bundled decoders, unless the "media.prefer-gstreamer" pref is set.
static bool IsGStreamerSupportedType(const nsACString& aType);
static bool IsH264Type(const nsACString& aType);
#endif
#ifdef MOZ_WIDGET_GONK
static bool IsOmxSupportedType(const nsACString& aType);
#endif
#ifdef MOZ_MEDIA_PLUGINS
static bool IsMediaPluginsType(const nsACString& aType);
#endif
#ifdef MOZ_DASH
static bool IsDASHMPDType(const nsACString& aType);
#endif
#ifdef MOZ_WMF
static bool IsWMFSupportedType(const nsACString& aType);
#endif
// Returns true if MIME type aType is supported in video documents,
// or false otherwise. Not all platforms support all MIME types, and
// vice versa.
static bool IsSupportedInVideoDocument(const nsACString& aType);
};
}

View File

@ -6,6 +6,9 @@
#include "GainNode.h"
#include "mozilla/dom/GainNodeBinding.h"
#include "AudioNodeEngine.h"
#include "AudioNodeStream.h"
#include "AudioDestinationNode.h"
namespace mozilla {
namespace dom {
@ -19,10 +22,107 @@ NS_INTERFACE_MAP_END_INHERITING(AudioNode)
NS_IMPL_ADDREF_INHERITED(GainNode, AudioNode)
NS_IMPL_RELEASE_INHERITED(GainNode, AudioNode)
struct ConvertTimeToTickHelper
{
AudioNodeStream* mSourceStream;
AudioNodeStream* mDestinationStream;
static int64_t Convert(double aTime, void* aClosure)
{
TrackRate sampleRate = IdealAudioRate();
ConvertTimeToTickHelper* This = static_cast<ConvertTimeToTickHelper*> (aClosure);
TrackTicks tick = This->mSourceStream->GetCurrentPosition();
StreamTime streamTime = TicksToTimeRoundDown(sampleRate, tick);
GraphTime graphTime = This->mSourceStream->StreamTimeToGraphTime(streamTime);
StreamTime destinationStreamTime = This->mDestinationStream->GraphTimeToStreamTime(graphTime);
return TimeToTicksRoundDown(sampleRate, destinationStreamTime + SecondsToMediaTime(aTime));
}
};
class GainNodeEngine : public AudioNodeEngine
{
public:
explicit GainNodeEngine(AudioDestinationNode* aDestination)
: mSource(nullptr)
, mDestination(static_cast<AudioNodeStream*> (aDestination->Stream()))
{
}
void SetSourceStream(AudioNodeStream* aSource)
{
mSource = aSource;
}
enum Parameters {
GAIN
};
void SetTimelineParameter(uint32_t aIndex, const AudioParamTimeline& aValue) MOZ_OVERRIDE
{
switch (aIndex) {
case GAIN:
MOZ_ASSERT(mSource && mDestination);
mGain = aValue;
ConvertTimeToTickHelper ctth;
ctth.mSourceStream = mSource;
ctth.mDestinationStream = mDestination;
mGain.ConvertEventTimesToTicks(ConvertTimeToTickHelper::Convert, &ctth);
break;
default:
NS_ERROR("Bad GainNodeEngine TimelineParameter");
}
}
virtual void ProduceAudioBlock(AudioNodeStream* aStream,
const AudioChunk& aInput,
AudioChunk* aOutput,
bool* aFinished)
{
MOZ_ASSERT(mSource == aStream, "Invalid source stream");
*aOutput = aInput;
if (mGain.HasSimpleValue()) {
// Optimize the case where we only have a single value set as the volume
aOutput->mVolume *= mGain.GetValue();
} else {
// First, compute a vector of gains for each track tick based on the
// timeline at hand, and then for each channel, multiply the values
// in the buffer with the gain vector.
// Compute the gain values for the duration of the input AudioChunk
// XXX we need to add a method to AudioEventTimeline to compute this buffer directly.
float computedGain[WEBAUDIO_BLOCK_SIZE];
for (size_t counter = 0; counter < WEBAUDIO_BLOCK_SIZE; ++counter) {
TrackTicks tick = aStream->GetCurrentPosition() + counter;
computedGain[counter] = mGain.GetValueAtTime<TrackTicks>(tick);
}
// Apply the gain to the output buffer
for (size_t channel = 0; channel < aOutput->mChannelData.Length(); ++channel) {
float* buffer = static_cast<float*> (const_cast<void*>
(aOutput->mChannelData[channel]));
AudioBlockCopyChannelWithScale(buffer, computedGain, buffer);
}
}
}
AudioNodeStream* mSource;
AudioNodeStream* mDestination;
AudioParamTimeline mGain;
};
GainNode::GainNode(AudioContext* aContext)
: AudioNode(aContext)
, mGain(new AudioParam(this, Callback, 1.0f, 0.0f, 1.0f))
, mGain(new AudioParam(this, SendGainToStream, 1.0f, 0.0f, 1.0f))
{
GainNodeEngine* engine = new GainNodeEngine(aContext->Destination());
mStream = aContext->Graph()->CreateAudioNodeStream(engine);
engine->SetSourceStream(static_cast<AudioNodeStream*> (mStream.get()));
}
GainNode::~GainNode()
{
DestroyMediaStream();
}
JSObject*
@ -31,6 +131,14 @@ GainNode::WrapObject(JSContext* aCx, JSObject* aScope)
return GainNodeBinding::Wrap(aCx, aScope, this);
}
void
GainNode::SendGainToStream(AudioNode* aNode)
{
GainNode* This = static_cast<GainNode*>(aNode);
AudioNodeStream* ns = static_cast<AudioNodeStream*>(This->mStream.get());
ns->SetTimelineParameter(GainNodeEngine::GAIN, *This->mGain);
}
}
}

View File

@ -19,6 +19,7 @@ class GainNode : public AudioNode
{
public:
explicit GainNode(AudioContext* aContext);
virtual ~GainNode();
NS_DECL_ISUPPORTS_INHERITED
NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(GainNode, AudioNode)
@ -30,6 +31,14 @@ public:
return mGain;
}
virtual bool SupportsMediaStreams() const MOZ_OVERRIDE
{
return true;
}
private:
static void SendGainToStream(AudioNode* aNode);
private:
nsRefPtr<AudioParam> mGain;
};

View File

@ -59,6 +59,3 @@ EXPORTS := \
FORCE_STATIC_LIB := 1
include $(topsrcdir)/config/rules.mk
CFLAGS += $(GSTREAMER_CFLAGS)
CXXFLAGS += $(GSTREAMER_CFLAGS)

View File

@ -22,34 +22,6 @@
#include "nsIScriptError.h"
#include "nsMimeTypes.h"
#ifdef MOZ_GSTREAMER
#include "GStreamerReader.h"
#endif
#ifdef MOZ_RAW
#include "RawReader.h"
#endif
#ifdef MOZ_OGG
#include "OggReader.h"
#endif
#ifdef MOZ_WAVE
#include "WaveReader.h"
#endif
#ifdef MOZ_WIDGET_GONK
#include "MediaOmxReader.h"
#endif
#ifdef MOZ_MEDIA_PLUGINS
#include "MediaDecoder.h"
#include "MediaPluginDecoder.h"
#include "MediaPluginReader.h"
#include "MediaPluginHost.h"
#endif
#ifdef MOZ_WEBM
#include "WebMReader.h"
#endif
#ifdef MOZ_WMF
#include "WMFReader.h"
#endif
namespace mozilla {
using namespace dom;
@ -427,51 +399,7 @@ MediaDecodeTask::CreateReader()
// If you change this list to add support for new decoders, please consider
// updating nsHTMLMediaElement::CreateDecoder as well.
#ifdef MOZ_GSTREAMER
if (DecoderTraits::IsGStreamerSupportedType(mContentType)) {
mDecoderReader = new GStreamerReader(mBufferDecoder);
} else
#endif
#ifdef MOZ_RAW
if (DecoderTraits::IsRawType(mContentType)) {
mDecoderReader = new RawReader(mBufferDecoder);
} else
#endif
#ifdef MOZ_OGG
if (DecoderTraits::IsOggType(mContentType)) {
mDecoderReader = new OggReader(mBufferDecoder);
} else
#endif
#ifdef MOZ_WAVE
if (DecoderTraits::IsWaveType(mContentType)) {
mDecoderReader = new WaveReader(mBufferDecoder);
} else
#endif
#ifdef MOZ_WIDGET_GONK
if (DecoderTraits::IsOmxSupportedType(mContentType)) {
mDecoderReader = new MediaOmxReader(mBufferDecoder);
} else
#endif
#ifdef MOZ_MEDIA_PLUGINS
if (MediaDecoder::IsMediaPluginsEnabled() &&
GetMediaPluginHost()->FindDecoder(mContentType, nullptr)) {
mDecoderReader = new MediaPluginReader(mBufferDecoder, mContentType);
} else
#endif
#ifdef MOZ_WEBM
if (DecoderTraits::IsWebMType(mContentType)) {
mDecoderReader = new WebMReader(mBufferDecoder);
} else
#endif
#ifdef MOZ_WMF
if (DecoderTraits::IsWMFSupportedType(mContentType)) {
mDecoderReader = new WMFReader(mBufferDecoder);
} else
#endif
#ifdef MOZ_DASH
// The DASH decoder is not supported.
#endif
if (false) {} // dummy if to take care of the dangling else
mDecoderReader = DecoderTraits::CreateReader(mContentType, mBufferDecoder);
if (!mDecoderReader) {
return false;
@ -610,11 +538,11 @@ MediaDecodeTask::CopyBuffer()
uint32_t outSamples = expectedOutSamples;
#ifdef MOZ_SAMPLE_TYPE_S16
speex_resampler_process_int(resampler, i, bufferData, &inSamples,
speex_resampler_process_int(resampler, i, &bufferData[i * audioData->mFrames], &inSamples,
&resampledBuffer[i * expectedOutSamples],
&outSamples);
#else
speex_resampler_process_float(resampler, i, bufferData, &inSamples,
speex_resampler_process_float(resampler, i, &bufferData[i * audioData->mFrames], &inSamples,
&resampledBuffer[i * expectedOutSamples],
&outSamples);
#endif
@ -868,8 +796,10 @@ WebAudioDecodeJob::OnFailure(ErrorCode aErrorCode)
// Ignore errors in calling the callback, since there is not much that we can
// do about it here.
ErrorResult rv;
mFailureCallback->Call(rv);
if (mFailureCallback) {
ErrorResult rv;
mFailureCallback->Call(rv);
}
mContext->RemoveFromDecodeQueue(this);
}

View File

@ -91,14 +91,14 @@ void TestSpecExample()
ErrorResultMock rv;
// This test is copied from the example in the Web Audio spec
const float t0 = 0.0,
t1 = 0.1,
t2 = 0.2,
t3 = 0.3,
t4 = 0.4,
t5 = 0.6,
t6 = 0.7/*,
t7 = 1.0*/;
const double t0 = 0.0,
t1 = 0.1,
t2 = 0.2,
t3 = 0.3,
t4 = 0.4,
t5 = 0.6,
t6 = 0.7/*,
t7 = 1.0*/;
timeline.SetValueAtTime(0.2f, t0, rv);
is(rv, NS_OK, "SetValueAtTime succeeded");
timeline.SetValueAtTime(0.3f, t1, rv);
@ -115,22 +115,22 @@ void TestSpecExample()
is(rv, NS_OK, "ExponentialRampToValueAtTime succeeded");
// TODO: Add the SetValueCurveAtTime test
is(timeline.GetValueAtTime(0.0f), 0.2f, "Correct value");
is(timeline.GetValueAtTime(0.05f), 0.2f, "Correct value");
is(timeline.GetValueAtTime(0.1f), 0.3f, "Correct value");
is(timeline.GetValueAtTime(0.15f), 0.3f, "Correct value");
is(timeline.GetValueAtTime(0.2f), 0.4f, "Correct value");
is(timeline.GetValueAtTime(0.25f), (0.4f + 1.0f) / 2, "Correct value");
is(timeline.GetValueAtTime(0.3f), 1.0f, "Correct value");
is(timeline.GetValueAtTime(0.35f), (1.0f + 0.15f) / 2, "Correct value");
is(timeline.GetValueAtTime(0.4f), 0.15f, "Correct value");
is(timeline.GetValueAtTime(0.45f), (0.15f * powf(0.75f / 0.15f, 0.05f / 0.2f)), "Correct value");
is(timeline.GetValueAtTime(0.5f), (0.15f * powf(0.75f / 0.15f, 0.5f)), "Correct value");
is(timeline.GetValueAtTime(0.55f), (0.15f * powf(0.75f / 0.15f, 0.15f / 0.2f)), "Correct value");
is(timeline.GetValueAtTime(0.6f), 0.75f, "Correct value");
is(timeline.GetValueAtTime(0.65f), (0.75f * powf(0.05 / 0.75f, 0.5f)), "Correct value");
is(timeline.GetValueAtTime(0.7f), 0.05f, "Correct value");
is(timeline.GetValueAtTime(1.0f), 0.05f, "Correct value");
is(timeline.GetValueAtTime(0.0), 0.2f, "Correct value");
is(timeline.GetValueAtTime(0.05), 0.2f, "Correct value");
is(timeline.GetValueAtTime(0.1), 0.3f, "Correct value");
is(timeline.GetValueAtTime(0.15), 0.3f, "Correct value");
is(timeline.GetValueAtTime(0.2), 0.4f, "Correct value");
is(timeline.GetValueAtTime(0.25), (0.4f + 1.0f) / 2, "Correct value");
is(timeline.GetValueAtTime(0.3), 1.0f, "Correct value");
is(timeline.GetValueAtTime(0.35), (1.0f + 0.15f) / 2, "Correct value");
is(timeline.GetValueAtTime(0.4), 0.15f, "Correct value");
is(timeline.GetValueAtTime(0.45), (0.15f * powf(0.75f / 0.15f, 0.05f / 0.2f)), "Correct value");
is(timeline.GetValueAtTime(0.5), (0.15f * powf(0.75f / 0.15f, 0.5f)), "Correct value");
is(timeline.GetValueAtTime(0.55), (0.15f * powf(0.75f / 0.15f, 0.15f / 0.2f)), "Correct value");
is(timeline.GetValueAtTime(0.6), 0.75f, "Correct value");
is(timeline.GetValueAtTime(0.65), (0.75f * powf(0.05 / 0.75f, 0.5f)), "Correct value");
is(timeline.GetValueAtTime(0.7), 0.05f, "Correct value");
is(timeline.GetValueAtTime(1.0), 0.05f, "Correct value");
}
void TestInvalidEvents()
@ -189,11 +189,11 @@ void TestEventReplacement()
timeline.SetValueAtTime(20.0f, 0.1, rv);
is(rv, NS_OK, "Event scheduling should be successful");
is(timeline.GetEventCount(), 1u, "Event should be replaced");
is(timeline.GetValueAtTime(0.1f), 20.0f, "The first event should be overwritten");
is(timeline.GetValueAtTime(0.1), 20.0f, "The first event should be overwritten");
timeline.LinearRampToValueAtTime(30.0f, 0.1, rv);
is(rv, NS_OK, "Event scheduling should be successful");
is(timeline.GetEventCount(), 2u, "Different event type should be appended");
is(timeline.GetValueAtTime(0.1f), 30.0f, "The first event should be overwritten");
is(timeline.GetValueAtTime(0.1), 30.0f, "The first event should be overwritten");
}
void TestEventRemoval()
@ -222,7 +222,7 @@ void TestBeforeFirstEvent()
ErrorResultMock rv;
timeline.SetValueAtTime(20.0f, 1.0, rv);
is(timeline.GetValueAtTime(0.5f), 10.0f, "Retrun the default value before the first event");
is(timeline.GetValueAtTime(0.5), 10.0f, "Retrun the default value before the first event");
}
void TestAfterLastValueEvent()
@ -232,7 +232,7 @@ void TestAfterLastValueEvent()
ErrorResultMock rv;
timeline.SetValueAtTime(20.0f, 1.0, rv);
is(timeline.GetValueAtTime(1.5f), 20.0f, "Return the last value after the last SetValue event");
is(timeline.GetValueAtTime(1.5), 20.0f, "Return the last value after the last SetValue event");
}
void TestAfterLastTargetValueEvent()
@ -242,7 +242,7 @@ void TestAfterLastTargetValueEvent()
ErrorResultMock rv;
timeline.SetTargetAtTime(20.0f, 1.0, 5.0, rv);
is(timeline.GetValueAtTime(10.f), (20.f + (10.f - 20.f) * expf(-9.0f / 5.0f)), "Return the value after the last SetTarget event based on the curve");
is(timeline.GetValueAtTime(10.), (20.f + (10.f - 20.f) * expf(-9.0f / 5.0f)), "Return the value after the last SetTarget event based on the curve");
}
void TestAfterLastTargetValueEventWithValueSet()
@ -253,7 +253,7 @@ void TestAfterLastTargetValueEventWithValueSet()
timeline.SetValue(50.f);
timeline.SetTargetAtTime(20.0f, 1.0, 5.0, rv);
is(timeline.GetValueAtTime(10.f), (20.f + (50.f - 20.f) * expf(-9.0f / 5.0f)), "Return the value after SetValue and the last SetTarget event based on the curve");
is(timeline.GetValueAtTime(10.), (20.f + (50.f - 20.f) * expf(-9.0f / 5.0f)), "Return the value after SetValue and the last SetTarget event based on the curve");
}
void TestValue()
@ -279,7 +279,7 @@ void TestLinearRampAtZero()
ErrorResultMock rv;
timeline.LinearRampToValueAtTime(20.0f, 0.0, rv);
is(timeline.GetValueAtTime(0.0f), 20.0f, "Should get the correct value when t0 == t1 == 0");
is(timeline.GetValueAtTime(0.0), 20.0f, "Should get the correct value when t0 == t1 == 0");
}
void TestExponentialRampAtZero()
@ -289,7 +289,7 @@ void TestExponentialRampAtZero()
ErrorResultMock rv;
timeline.ExponentialRampToValueAtTime(20.0f, 0.0, rv);
is(timeline.GetValueAtTime(0.0f), 20.0f, "Should get the correct value when t0 == t1 == 0");
is(timeline.GetValueAtTime(0.0), 20.0f, "Should get the correct value when t0 == t1 == 0");
}
void TestLinearRampAtSameTime()
@ -300,7 +300,7 @@ void TestLinearRampAtSameTime()
timeline.SetValueAtTime(5.0f, 1.0, rv);
timeline.LinearRampToValueAtTime(20.0f, 1.0, rv);
is(timeline.GetValueAtTime(1.0f), 20.0f, "Should get the correct value when t0 == t1");
is(timeline.GetValueAtTime(1.0), 20.0f, "Should get the correct value when t0 == t1");
}
void TestExponentialRampAtSameTime()
@ -311,7 +311,7 @@ void TestExponentialRampAtSameTime()
timeline.SetValueAtTime(5.0f, 1.0, rv);
timeline.ExponentialRampToValueAtTime(20.0f, 1.0, rv);
is(timeline.GetValueAtTime(1.0f), 20.0f, "Should get the correct value when t0 == t1");
is(timeline.GetValueAtTime(1.0), 20.0f, "Should get the correct value when t0 == t1");
}
void TestSetTargetZeroTimeConstant()
@ -321,7 +321,7 @@ void TestSetTargetZeroTimeConstant()
ErrorResultMock rv;
timeline.SetTargetAtTime(20.0f, 1.0, 0.0, rv);
is(timeline.GetValueAtTime(10.f), 20.f, "Should get the correct value with timeConstant == 0");
is(timeline.GetValueAtTime(10.), 20.f, "Should get the correct value with timeConstant == 0");
}
void TestExponentialInvalidPreviousZeroValue()

View File

@ -15,6 +15,7 @@ MOCHITEST_FILES := \
test_bug808374.html \
test_bug827541.html \
test_bug839753.html \
test_bug845960.html \
test_AudioBuffer.html \
test_AudioContext.html \
test_AudioListener.html \
@ -28,6 +29,10 @@ MOCHITEST_FILES := \
test_singleSourceDest.html \
ting.ogg \
ting-expected.wav \
ting-dualchannel44.1.ogg \
ting-dualchannel44.1-expected.wav \
ting-dualchannel48.ogg \
ting-dualchannel48-expected.wav \
small-shot.ogg \
small-shot-expected.wav \
invalid.txt \

View File

@ -0,0 +1,20 @@
<!DOCTYPE HTML>
<html>
<head>
<title>Crashtest for bug 845960</title>
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
</head>
<body>
<pre id="test">
<script class="testbody" type="text/javascript">
SpecialPowers.setBoolPref("media.webaudio.enabled", true);
(new AudioContext()).decodeAudioData(new ArrayBuffer(0), function() {});
ok(true, "Should not crash when the optional failure callback is not specified");
SpecialPowers.clearUserPref("media.webaudio.enabled");
</script>
</pre>
</body>
</html>

View File

@ -123,6 +123,28 @@ var tests = [
fuzzTolerance: 12,
fuzzToleranceMobile: 15826
},
// An ogg file with two different channels, 44.1khz
{
url: "ting-dualchannel44.1.ogg",
valid: true,
expected: "ting-dualchannel44.1-expected.wav",
numberOfChannels: 2,
duration: 0.6936,
length: 33297,
fuzzTolerance: 16,
fuzzToleranceMobile: 16713
},
// An ogg file with two different channels, 48khz
{
url: "ting-dualchannel48.ogg",
valid: true,
expected: "ting-dualchannel48-expected.wav",
numberOfChannels: 2,
duration: 0.6373,
length: 30592,
fuzzTolerance: 9,
fuzzToleranceMobile: 2703
},
// An ogg file which needs to be resampled
{
url: "small-shot.ogg",
@ -148,8 +170,8 @@ var tests = [
numberOfChannels: 2,
duration: 1.0811,
length: 51896,
fuzzTolerance: 132,
fuzzToleranceMobile: 56580
fuzzTolerance: 91427,
fuzzToleranceMobile: 119684
},
// Make sure decoding a wave file results in the same buffer
{

Binary file not shown.

Binary file not shown.

View File

@ -106,9 +106,6 @@ private:
bool mDefer;
};
MOZ_STATIC_ASSERT(sizeof(SVGPreserveAspectRatio) <= 4,
"The compiler didn't pack SVGPreserveAspectRatio well");
namespace dom {
class DOMSVGPreserveAspectRatio MOZ_FINAL : public nsISupports,

View File

@ -0,0 +1,13 @@
#
# 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/.
DEPTH = @DEPTH@
topsrcdir = @top_srcdir@
srcdir = @srcdir@
VPATH = @srcdir@
include $(DEPTH)/config/autoconf.mk
include $(topsrcdir)/config/rules.mk

View File

@ -0,0 +1,6 @@
# 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/.
toolkit.jar:
* content/global/platformHTMLBindings.xml (platformHTMLBindings.xml)

View File

@ -0,0 +1,5 @@
# vim: set filetype=python:
# 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/.

View File

@ -0,0 +1,170 @@
<?xml version="1.0"?>
<!-- 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/. -->
<bindings id="htmlBindings"
xmlns="http://www.mozilla.org/xbl"
xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
<binding id="inputFields">
<handlers>
#include ../input-fields-base.inc
<handler event="keypress" key="a" modifiers="accel" command="cmd_selectAll"/>
<handler event="keypress" keycode="VK_LEFT" modifiers="control" command="cmd_wordPrevious"/>
<handler event="keypress" keycode="VK_RIGHT" modifiers="control" command="cmd_wordNext"/>
<handler event="keypress" keycode="VK_LEFT" modifiers="shift,control" command="cmd_selectWordPrevious"/>
<handler event="keypress" keycode="VK_RIGHT" modifiers="shift,control" command="cmd_selectWordNext"/>
<handler event="keypress" keycode="VK_LEFT" modifiers="alt" command="cmd_beginLine"/>
<handler event="keypress" keycode="VK_RIGHT" modifiers="alt" command="cmd_endLine"/>
<handler event="keypress" keycode="VK_LEFT" modifiers="shift,alt" command="cmd_selectBeginLine"/>
<handler event="keypress" keycode="VK_RIGHT" modifiers="shift,alt" command="cmd_selectEndLine"/>
<handler event="keypress" keycode="VK_HOME" command="cmd_beginLine"/>
<handler event="keypress" keycode="VK_END" command="cmd_endLine"/>
<handler event="keypress" keycode="VK_HOME" modifiers="shift" command="cmd_selectBeginLine" />
<handler event="keypress" keycode="VK_END" modifiers="shift" command="cmd_selectEndLine" />
<handler event="keypress" keycode="VK_BACK" modifiers="shift" command="cmd_deleteCharForward"/>
<handler event="keypress" keycode="VK_BACK" modifiers="shift,alt" command="cmd_deleteToEndOfLine"/>
<handler event="keypress" keycode="VK_BACK" modifiers="alt" command="cmd_deleteToBeginningOfLine"/>
<handler event="keypress" keycode="VK_DELETE" modifiers="alt" command="cmd_deleteToEndOfLine"/>
</handlers>
</binding>
<binding id="textAreas">
<handlers>
#include ../textareas-base.inc
<handler event="keypress" key="a" modifiers="accel" command="cmd_selectAll"/>
<handler event="keypress" keycode="VK_LEFT" modifiers="control" command="cmd_wordPrevious"/>
<handler event="keypress" keycode="VK_RIGHT" modifiers="control" command="cmd_wordNext"/>
<handler event="keypress" keycode="VK_LEFT" modifiers="shift,control" command="cmd_selectWordPrevious"/>
<handler event="keypress" keycode="VK_RIGHT" modifiers="shift,control" command="cmd_selectWordNext"/>
<handler event="keypress" keycode="VK_LEFT" modifiers="alt" command="cmd_beginLine"/>
<handler event="keypress" keycode="VK_RIGHT" modifiers="alt" command="cmd_endLine"/>
<handler event="keypress" keycode="VK_LEFT" modifiers="shift,alt" command="cmd_selectBeginLine"/>
<handler event="keypress" keycode="VK_RIGHT" modifiers="shift,alt" command="cmd_selectEndLine"/>
<handler event="keypress" keycode="VK_UP" modifiers="alt" command="cmd_moveTop"/>
<handler event="keypress" keycode="VK_DOWN" modifiers="alt" command="cmd_moveBottom"/>
<handler event="keypress" keycode="VK_UP" modifiers="shift,alt" command="cmd_selectTop"/>
<handler event="keypress" keycode="VK_DOWN" modifiers="shift,alt" command="cmd_selectBottom"/>
<handler event="keypress" keycode="VK_PAGE_UP" command="cmd_movePageUp"/>
<handler event="keypress" keycode="VK_PAGE_DOWN" command="cmd_movePageDown"/>
<handler event="keypress" keycode="VK_PAGE_UP" modifiers="shift" command="cmd_selectPageUp"/>
<handler event="keypress" keycode="VK_PAGE_DOWN" modifiers="shift" command="cmd_selectPageDown"/>
<handler event="keypress" keycode="VK_PAGE_UP" modifiers="alt" command="cmd_moveTop"/>
<handler event="keypress" keycode="VK_PAGE_DOWN" modifiers="alt" command="cmd_moveBottom"/>
<handler event="keypress" keycode="VK_PAGE_UP" modifiers="shift,alt" command="cmd_selectTop"/>
<handler event="keypress" keycode="VK_PAGE_DOWN" modifiers="shift,alt" command="cmd_selectBottom"/>
<handler event="keypress" keycode="VK_HOME" command="cmd_beginLine"/>
<handler event="keypress" keycode="VK_END" command="cmd_endLine"/>
<handler event="keypress" keycode="VK_HOME" modifiers="shift" command="cmd_selectBeginLine" />
<handler event="keypress" keycode="VK_END" modifiers="shift" command="cmd_selectEndLine" />
<handler event="keypress" keycode="VK_HOME" modifiers="control" command="cmd_moveTop"/>
<handler event="keypress" keycode="VK_END" modifiers="control" command="cmd_moveBottom"/>
<handler event="keypress" keycode="VK_HOME" modifiers="shift,control" command="cmd_selectTop" />
<handler event="keypress" keycode="VK_END" modifiers="shift,control" command="cmd_selectBottom" />
<handler event="keypress" keycode="VK_BACK" modifiers="shift" command="cmd_deleteCharForward"/>
<handler event="keypress" keycode="VK_BACK" modifiers="shift,alt" command="cmd_deleteToEndOfLine"/>
<handler event="keypress" keycode="VK_BACK" modifiers="alt" command="cmd_deleteToBeginningOfLine"/>
<handler event="keypress" keycode="VK_DELETE" modifiers="alt" command="cmd_deleteToEndOfLine"/>
</handlers>
</binding>
<binding id="browser">
<handlers>
#include ../browser-base.inc
<handler event="keypress" keycode="VK_LEFT" modifiers="shift" command="cmd_selectCharPrevious" />
<handler event="keypress" keycode="VK_RIGHT" modifiers="shift" command="cmd_selectCharNext" />
<handler event="keypress" keycode="VK_LEFT" modifiers="control" command="cmd_wordPrevious" />
<handler event="keypress" keycode="VK_RIGHT" modifiers="control" command="cmd_wordNext" />
<handler event="keypress" keycode="VK_LEFT" modifiers="control,shift" command="cmd_selectWordPrevious" />
<handler event="keypress" keycode="VK_RIGHT" modifiers="control,shift" command="cmd_selectWordNext" />
<handler event="keypress" keycode="VK_LEFT" modifiers="alt" command="cmd_beginLine"/>
<handler event="keypress" keycode="VK_RIGHT" modifiers="alt" command="cmd_endLine"/>
<handler event="keypress" keycode="VK_LEFT" modifiers="shift,alt" command="cmd_selectBeginLine"/>
<handler event="keypress" keycode="VK_RIGHT" modifiers="shift,alt" command="cmd_selectEndLine"/>
<handler event="keypress" keycode="VK_UP" modifiers="shift" command="cmd_selectLinePrevious" />
<handler event="keypress" keycode="VK_DOWN" modifiers="shift" command="cmd_selectLineNext" />
<handler event="keypress" keycode="VK_UP" modifiers="alt" command="cmd_moveTop"/>
<handler event="keypress" keycode="VK_DOWN" modifiers="alt" command="cmd_moveBottom"/>
<handler event="keypress" keycode="VK_UP" modifiers="shift,alt" command="cmd_selectTop"/>
<handler event="keypress" keycode="VK_DOWN" modifiers="shift,alt" command="cmd_selectBottom"/>
<handler event="keypress" keycode="VK_PAGE_UP" command="cmd_movePageUp"/>
<handler event="keypress" keycode="VK_PAGE_DOWN" command="cmd_movePageDown"/>
<handler event="keypress" keycode="VK_PAGE_UP" modifiers="shift" command="cmd_selectPageUp"/>
<handler event="keypress" keycode="VK_PAGE_DOWN" modifiers="shift" command="cmd_selectPageDown"/>
<handler event="keypress" keycode="VK_PAGE_UP" modifiers="alt" command="cmd_moveTop"/>
<handler event="keypress" keycode="VK_PAGE_DOWN" modifiers="alt" command="cmd_moveBottom"/>
<handler event="keypress" keycode="VK_PAGE_UP" modifiers="shift,alt" command="cmd_selectTop"/>
<handler event="keypress" keycode="VK_PAGE_DOWN" modifiers="shift,alt" command="cmd_selectBottom"/>
<handler event="keypress" keycode="VK_HOME" command="cmd_beginLine"/>
<handler event="keypress" keycode="VK_END" command="cmd_endLine"/>
<handler event="keypress" keycode="VK_HOME" modifiers="shift" command="cmd_selectBeginLine" />
<handler event="keypress" keycode="VK_END" modifiers="shift" command="cmd_selectEndLine" />
<handler event="keypress" keycode="VK_HOME" modifiers="control" command="cmd_moveTop"/>
<handler event="keypress" keycode="VK_END" modifiers="control" command="cmd_moveBottom"/>
<handler event="keypress" keycode="VK_HOME" modifiers="shift,control" command="cmd_selectTop" />
<handler event="keypress" keycode="VK_END" modifiers="shift,control" command="cmd_selectBottom" />
<handler event="keypress" keycode="VK_BACK" modifiers="shift" command="cmd_deleteCharForward"/>
<handler event="keypress" keycode="VK_BACK" modifiers="shift,alt" command="cmd_deleteToEndOfLine"/>
<handler event="keypress" keycode="VK_BACK" modifiers="alt" command="cmd_deleteToBeginningOfLine"/>
<handler event="keypress" keycode="VK_DELETE" modifiers="alt" command="cmd_deleteToEndOfLine"/>
</handlers>
</binding>
<binding id="editor">
<handlers>
#include ../editor-base.inc
<handler event="keypress" key="a" modifiers="accel" command="cmd_selectAll"/>
<handler event="keypress" keycode="VK_LEFT" modifiers="control" command="cmd_wordPrevious"/>
<handler event="keypress" keycode="VK_RIGHT" modifiers="control" command="cmd_wordNext"/>
<handler event="keypress" keycode="VK_LEFT" modifiers="shift,control" command="cmd_selectWordPrevious"/>
<handler event="keypress" keycode="VK_RIGHT" modifiers="shift,control" command="cmd_selectWordNext"/>
<handler event="keypress" keycode="VK_LEFT" modifiers="alt" command="cmd_beginLine"/>
<handler event="keypress" keycode="VK_RIGHT" modifiers="alt" command="cmd_endLine"/>
<handler event="keypress" keycode="VK_LEFT" modifiers="shift,alt" command="cmd_selectBeginLine"/>
<handler event="keypress" keycode="VK_RIGHT" modifiers="shift,alt" command="cmd_selectEndLine"/>
<handler event="keypress" keycode="VK_UP" modifiers="alt" command="cmd_moveTop"/>
<handler event="keypress" keycode="VK_DOWN" modifiers="alt" command="cmd_moveBottom"/>
<handler event="keypress" keycode="VK_UP" modifiers="shift,alt" command="cmd_selectTop"/>
<handler event="keypress" keycode="VK_DOWN" modifiers="shift,alt" command="cmd_selectBottom"/>
<handler event="keypress" keycode="VK_PAGE_UP" command="cmd_movePageUp"/>
<handler event="keypress" keycode="VK_PAGE_DOWN" command="cmd_movePageDown"/>
<handler event="keypress" keycode="VK_PAGE_UP" modifiers="shift" command="cmd_selectPageUp"/>
<handler event="keypress" keycode="VK_PAGE_DOWN" modifiers="shift" command="cmd_selectPageDown"/>
<handler event="keypress" keycode="VK_PAGE_UP" modifiers="alt" command="cmd_moveTop"/>
<handler event="keypress" keycode="VK_PAGE_DOWN" modifiers="alt" command="cmd_moveBottom"/>
<handler event="keypress" keycode="VK_PAGE_UP" modifiers="shift,alt" command="cmd_selectTop"/>
<handler event="keypress" keycode="VK_PAGE_DOWN" modifiers="shift,alt" command="cmd_selectBottom"/>
<handler event="keypress" keycode="VK_HOME" command="cmd_beginLine"/>
<handler event="keypress" keycode="VK_END" command="cmd_endLine"/>
<handler event="keypress" keycode="VK_HOME" modifiers="shift" command="cmd_selectBeginLine" />
<handler event="keypress" keycode="VK_END" modifiers="shift" command="cmd_selectEndLine" />
<handler event="keypress" keycode="VK_HOME" modifiers="control" command="cmd_moveTop"/>
<handler event="keypress" keycode="VK_END" modifiers="control" command="cmd_moveBottom"/>
<handler event="keypress" keycode="VK_HOME" modifiers="shift,control" command="cmd_selectTop" />
<handler event="keypress" keycode="VK_END" modifiers="shift,control" command="cmd_selectBottom" />
<handler event="keypress" keycode="VK_BACK" modifiers="shift" command="cmd_deleteCharForward"/>
<handler event="keypress" keycode="VK_BACK" modifiers="shift,alt" command="cmd_deleteToEndOfLine"/>
<handler event="keypress" keycode="VK_BACK" modifiers="alt" command="cmd_deleteToBeginningOfLine"/>
<handler event="keypress" keycode="VK_DELETE" modifiers="alt" command="cmd_deleteToEndOfLine"/>
</handlers>
</binding>
</bindings>

View File

@ -7,6 +7,8 @@ if CONFIG['OS_ARCH'] in ('OS2', 'WINNT'):
DIRS += ['win']
elif CONFIG['MOZ_WIDGET_TOOLKIT'] == 'cocoa':
DIRS += ['mac']
elif CONFIG['MOZ_WIDGET_TOOLKIT'] == 'android':
DIRS += ['android']
elif CONFIG['MOZ_WIDGET_TOOLKIT'] in ('qt', 'gtk2'):
DIRS += ['unix']
else:

View File

@ -7,7 +7,6 @@
#define nsContentSupportMap_h__
#include "pldhash.h"
#include "nsFixedSizeAllocator.h"
#include "nsTemplateMatch.h"
/**

View File

@ -8,7 +8,6 @@
#include "nscore.h"
#include "nsRuleNetwork.h"
#include "nsFixedSizeAllocator.h"
#include "nsIAtom.h"
#include "nsIDOMDocument.h"

View File

@ -7,7 +7,6 @@
#define nsRDFConInstanceTestNode_h__
#include "nscore.h"
#include "nsFixedSizeAllocator.h"
#include "nsRDFTestNode.h"
#include "nsIRDFResource.h"
#include "nsIRDFDataSource.h"

View File

@ -18,7 +18,6 @@
#include "nsICollation.h"
#include "nsCollationCID.h"
#include "nsFixedSizeAllocator.h"
#include "nsResourceSet.h"
#include "nsRuleNetwork.h"
#include "nsRDFQuery.h"

View File

@ -6,7 +6,6 @@
#ifndef nsXULTemplateResultSetRDF_h__
#define nsXULTemplateResultSetRDF_h__
#include "nsFixedSizeAllocator.h"
#include "nsISimpleEnumerator.h"
#include "nsRuleNetwork.h"
#include "nsRDFQuery.h"

View File

@ -2044,6 +2044,8 @@ nsDOMClassInfo::Init()
DOM_CLASSINFO_MAP_BEGIN(HTMLDocument, nsIDOMHTMLDocument)
DOM_CLASSINFO_MAP_ENTRY(nsIDOMHTMLDocument)
DOM_CLASSINFO_MAP_CONDITIONAL_ENTRY(nsIDocumentRegister,
nsDocument::RegisterEnabled())
DOM_CLASSINFO_DOCUMENT_MAP_ENTRIES
DOM_CLASSINFO_MAP_END

View File

@ -696,6 +696,15 @@ GetWrapperCache(void* p)
return NULL;
}
// Helper template for smart pointers to resolve ambiguity between
// GetWrappeCache(void*) and GetWrapperCache(const ParentObject&).
template <template <typename> class SmartPtr, typename T>
inline nsWrapperCache*
GetWrapperCache(const SmartPtr<T>& aObject)
{
return GetWrapperCache(aObject.get());
}
/**
* A method to handle new-binding wrap failure, by possibly falling back to
* wrapping as a non-new-binding object.

View File

@ -214,7 +214,6 @@ MOCHITEST_FILES += \
test_browserElement_oop_Reload.html \
test_browserElement_oop_Stop.html \
test_browserElement_oop_ContextmenuEvents.html \
test_browserElement_oop_SendEvent.html \
test_browserElement_oop_ScrollEvent.html \
test_browserElement_oop_Auth.html \
test_browserElement_oop_RemoveBrowserElement.html \
@ -227,16 +226,18 @@ MOCHITEST_FILES += \
test_browserElement_oop_DocumentFirstPaint.html \
$(NULL)
# Disabled on Linux temporarily due to bug 779753
# test_browserElement_oop_SendEvent.html
# test_browserElement_oop_SetVisible.html
# test_browserElement_oop_SetVisibleFrames.html
# test_browserElement_oop_SetVisibleFrames2.html
ifneq ($(MOZ_WIDGET_TOOLKIT),gtk2)
MOCHITEST_FILES += \
test_browserElement_oop_SendEvent.html \
test_browserElement_oop_SetVisible.html \
test_browserElement_oop_SetVisibleFrames.html \
test_browserElement_oop_SetVisibleFrames2.html \
$(NULL)
else
$(filter disabled-temporarily--bug-779753, test_browserElement_oop_SetVisible.html)
$(filter disabled-temporarily--bug-779753, test_browserElement_oop_SetVisibleFrames.html)
$(filter disabled-temporarily--bug-779753, test_browserElement_oop_SetVisibleFrames2.html)
endif
endif #}

View File

@ -59,8 +59,8 @@ public:
// Overrides:
NS_IMETHOD GetInternalStream(nsIInputStream**);
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(ArchiveZipFile, nsIDOMFile)
NS_DECL_ISUPPORTS_INHERITED
NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(ArchiveZipFile, nsDOMFileCC)
protected:
virtual already_AddRefed<nsIDOMBlob> CreateSlice(uint64_t aStart,

View File

@ -418,6 +418,11 @@ IndexedDatabaseManager::GetOrCreate()
nsCOMPtr<nsIObserverService> obs = GetObserverService();
NS_ENSURE_TRUE(obs, nullptr);
// Must initialize the storage service on the main thread.
nsCOMPtr<mozIStorageService> ss =
do_GetService(MOZ_STORAGE_SERVICE_CONTRACTID);
NS_ENSURE_TRUE(ss, nullptr);
// We need this callback to know when to shut down all our threads.
rv = obs->AddObserver(instance, PROFILE_BEFORE_CHANGE_OBSERVER_ID, false);
NS_ENSURE_SUCCESS(rv, nullptr);

View File

@ -29,6 +29,7 @@ SDK_XPIDLSRCS = \
nsIDOMNodeList.idl \
nsIDOMProcessingInstruction.idl \
nsIDOMText.idl \
nsIDocumentRegister.idl \
$(NULL)
XPIDLSRCS = \
nsIDOMDOMStringList.idl \

View File

@ -0,0 +1,16 @@
/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* 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/. */
#include "nsISupports.idl"
[scriptable, uuid(e35935bd-ebae-4e0d-93bf-efa93ab14c05)]
interface nsIDocumentRegister : nsISupports
{
[optional_argc,
implicit_jscontext] jsval register(in DOMString name,
[optional] in jsval options)
raises(DOMException);
};

View File

@ -48,6 +48,7 @@ XPIDLSRCS = \
nsIDOMUserProximityEvent.idl \
nsIDOMDeviceOrientationEvent.idl \
nsIDOMDeviceMotionEvent.idl \
nsIDOMElementReplaceEvent.idl \
nsIDOMScrollAreaEvent.idl \
nsIDOMTransitionEvent.idl \
nsIDOMAnimationEvent.idl \

View File

@ -0,0 +1,24 @@
/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* 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/. */
#include "nsIDOMEvent.idl"
interface nsIDOMElement;
[scriptable, builtinclass, uuid(19a31767-54bf-4044-8769-cd172e37eca2)]
interface nsIDOMElementReplaceEvent : nsIDOMEvent
{
readonly attribute nsIDOMElement upgrade;
void initElementReplaceEvent(in DOMString typeArg,
in boolean canBubbleArg,
in boolean canCancelArg,
in nsIDOMElement upgrade);
};
dictionary ElementReplaceEventInit : EventInit
{
nsIDOMElement upgrade;
};

View File

@ -868,8 +868,12 @@ let CaptivePortalDetectionHelper = (function() {
capService.abort(_ongoingInterface);
_ongoingInterface = null;
}
capService.checkCaptivePortal(interfaceName, capCallback);
_ongoingInterface = interfaceName;
try {
capService.checkCaptivePortal(interfaceName, capCallback);
_ongoingInterface = interfaceName;
} catch (e) {
debug('Fail to detect captive portal due to: ' + e.message);
}
};
let _abort = function (interfaceName) {

View File

@ -10315,7 +10315,7 @@ let ICCRecordHelper = {
* @param onerror Callback to be called when error.
*/
readEmail: function readEmail(fileId, fileType, recordNumber, onsuccess, onerror) {
function callback(optoins) {
function callback(options) {
let strLen = Buf.readUint32();
let octetLen = strLen / 2;
let email = null;
@ -10362,7 +10362,7 @@ let ICCRecordHelper = {
* @param onerror Callback to be called when error.
*/
readANR: function readANR(fileId, fileType, recordNumber, onsuccess, onerror) {
function callback(optoins) {
function callback(options) {
let strLen = Buf.readUint32();
let octetLen = strLen / 2;
let number = null;

View File

@ -64,6 +64,7 @@ var interfaceNamesInGlobalScope =
"HTMLOptionElement",
"Pkcs11",
"NotifyAudioAvailableEvent",
"ElementReplaceEvent",
"Array",
"SVGZoomAndPan",
"XULPopupElement",

View File

@ -21,6 +21,7 @@ DIRS += [
'storageevent',
'pointerlock',
'webapps',
'webcomponents',
]
#needs IPC support, also tests do not run successfully in Firefox for now

View File

@ -0,0 +1,18 @@
# 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/.
DEPTH = @DEPTH@
topsrcdir = @top_srcdir@
srcdir = @srcdir@
VPATH = @srcdir@
relativesrcdir = @relativesrcdir@
include $(DEPTH)/config/autoconf.mk
MOCHITEST_FILES = \
test_document_register.html \
test_document_register_lifecycle.html \
$(NULL)
include $(topsrcdir)/config/rules.mk

View File

@ -0,0 +1,5 @@
# vim: set filetype=python:
# 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/.

View File

@ -0,0 +1,90 @@
<!DOCTYPE HTML>
<html>
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=783129
-->
<head>
<title>Test for document.register using custom prototype</title>
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
<script>
var gElementUpgraded = false;
var gElementReplaced = false;
function elementUpgrade() {
gElementUpgraded = true;
// Check for prototype on upgraded element.
var documentElement = document.getElementById("grabme");
ok(documentElement.hello, "Upgraded element should inherit 'hello' method from prototype.");
documentElement.hello();
var customChild = document.getElementById("kid");
ok(customChild, "Upgrade should preserve children.");
ok(customChild.parentNode == documentElement, "Parent should be updated to new custom element.");
// Try creating new element and checking for prototype.
var constructedElement = document.createElement("x-hello");
ok(constructedElement.hello, "Created element should inherit 'hello' method from prototype.");
constructedElement.hello();
}
function elementReplace(e) {
gElementReplaced = true;
ok(e.upgrade != e.target, "Upgraded element should be different from the target.");
ok(e.upgrade.firstElementChild.id == "kid", "Upgrade element should have a child.");
ok(e.target.firstElementChild.id == "kid", "Replacement element should have a child.");
}
function startTest() {
// Create a prototype that inheits from HTMLElement.
var customProto = {};
customProto.__proto__ = HTMLElement.prototype;
customProto.hello = function() {
ok(true, "Custom element should use provided prototype.");
};
var oldElem = document.getElementById("grabme");
oldElem.addEventListener("elementreplace", elementReplace);
document.addEventListener("elementupgrade", elementUpgrade);
var elementConstructor = document.register("x-hello", { prototype: customProto });
// Try creating new element and checking for prototype.
var constructedElement = new elementConstructor();
ok(constructedElement.hello, "Created element should inherit 'hello' method from prototype.");
constructedElement.hello();
ok(!oldElem.hello, "Element obtained prior to registration should not have inherited prototype.");
ok(gElementUpgraded && gElementReplaced, "Upgrade and replace events should have been fired.");
// Check that custom elements registered without a prototype inherit from HTMLElement.
document.register("x-bye");
var byeElement = document.createElement("x-bye");
ok(byeElement.__proto__.__proto__, HTMLElement.prototype, "Element registered without prototype should inherit from HTMLElement.");
// Check that element registration with a prototype that does not inherit from HTMLElement results in exception.
try {
document.register("x-foo", { "prototype": {} });
ok(false, "Prototype that does not inherit from HTMLElement should throw exception");
} catch (ex) {
ok(true, "Prototype that does not inherit from HTMLElement should throw exception");
}
SimpleTest.finish();
}
SimpleTest.waitForExplicitFinish();
</script>
</head>
<body onload="startTest()">
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=783129">Bug 783129</a>
<x-hello id="grabme">
<div id="kid"></div>
</x-hello>
</body>
</html>

View File

@ -0,0 +1,49 @@
<!DOCTYPE HTML>
<html>
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=783129
-->
<head>
<title>Test for document.register lifecycle callback</title>
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
<script>
var gLifecycleCallbackCalled = false;
var lifecycleCallbacks = {
created: function() {
is(this.getAttribute("id"), "grabme", "|this| value should be the upgrade element");
gLifecycleCallbackCalled = true;
}
};
function startTest() {
var HtmlProto = function() {};
HtmlProto.prototype = HTMLElement.prototype;
// Create a prototype that inheits from HTMLElement.
var customProto = new HtmlProto();
customProto.hello = function() {
ok(true, "Custom element should use provided prototype.");
};
var elementConstructor = document.register("x-hello", { prototype: customProto, lifecycle: lifecycleCallbacks });
ok(gLifecycleCallbackCalled, "Lifecycle callback should be called.");
SimpleTest.finish();
}
SimpleTest.waitForExplicitFinish();
</script>
</head>
<body onload="startTest()">
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=783129">Bug 783129</a>
<x-hello id="grabme">
<div id="kid"></div>
</x-hello>
</body>
</html>

View File

@ -228,6 +228,12 @@ partial interface Document {
void mozExitPointerLock ();
};
//http://dvcs.w3.org/hg/webcomponents/raw-file/tip/spec/custom/index.html#dfn-document-register
partial interface Document {
[Throws, Pref="dom.webcomponents.enabled"]
object register(DOMString name, optional ElementRegistrationOptions options);
};
// http://dvcs.w3.org/hg/webperf/raw-file/tip/specs/PageVisibility/Overview.html#sec-document-interface
partial interface Document {
readonly attribute boolean hidden;

View File

@ -20,8 +20,12 @@ interface HTMLAreaElement : HTMLElement {
attribute DOMString coords;
[SetterThrows]
attribute DOMString shape;
// No support for stringifier attributes yet
//[SetterThrows]
//stringifier attribute DOMString href;
stringifier;
[SetterThrows]
stringifier attribute DOMString href;
attribute DOMString href;
[SetterThrows]
attribute DOMString target;
[SetterThrows]

View File

@ -0,0 +1,24 @@
/* 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/.
*
* The origin of this IDL file is
* http://dvcs.w3.org/hg/webcomponents/raw-file/tip/spec/custom/index.html
*
* Copyright © 2012 W3C® (MIT, ERCIM, Keio), All Rights Reserved. W3C
* liability, trademark and document use rules apply.
*/
interface DocumentFragment;
callback LifecycleCreatedCallback = void();
dictionary LifecycleCallbacks {
LifecycleCreatedCallback? created = null;
};
dictionary ElementRegistrationOptions {
object? prototype = null;
LifecycleCallbacks lifecycle;
};

Some files were not shown because too many files have changed in this diff Show More