mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Merge from mozilla-central.
This commit is contained in:
commit
983c973cfe
@ -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)
|
||||
{
|
||||
|
@ -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.
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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();
|
||||
}
|
||||
|
||||
|
@ -59,6 +59,8 @@
|
||||
var gQueue = null;
|
||||
function doTests()
|
||||
{
|
||||
disableLogging(); // from test_takeFocus.html
|
||||
|
||||
// Test focus events.
|
||||
gQueue = new eventQueue();
|
||||
|
||||
|
@ -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.
|
||||
|
@ -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");
|
||||
|
@ -627,4 +627,5 @@ chatbox {
|
||||
chatbar {
|
||||
-moz-binding: url("chrome://browser/content/socialchat.xml#chatbar");
|
||||
height: 0;
|
||||
max-height: 0;
|
||||
}
|
||||
|
@ -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",
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@ -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"
|
||||
|
@ -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) {
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -31,7 +31,7 @@ BROWSER_TESTS = \
|
||||
$(NULL)
|
||||
|
||||
BROWSER_TEST_RESOURCES = \
|
||||
res\image01.png \
|
||||
res/image01.png \
|
||||
$(NULL)
|
||||
|
||||
libs:: $(BROWSER_TESTS)
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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/. */
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
@ -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:
|
||||
|
@ -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
|
||||
|
@ -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();
|
||||
};
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -54,6 +54,7 @@ MOCHITEST_CHROME_FILES = \
|
||||
test_domparsing.xul \
|
||||
test_bug814638.xul \
|
||||
host_bug814638.xul \
|
||||
test_document_register.xul \
|
||||
frame_bug814638.xul \
|
||||
$(NULL)
|
||||
|
||||
|
37
content/base/test/chrome/test_document_register.xul
Normal file
37
content/base/test/chrome/test_document_register.xul
Normal 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>
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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);
|
||||
|
@ -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.
|
||||
|
@ -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;
|
||||
|
@ -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,
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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();
|
||||
|
@ -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[];
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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 \
|
||||
|
@ -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>
|
||||
|
14
content/html/content/test/test_bug839913.html
Normal file
14
content/html/content/test/test_bug839913.html
Normal 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>
|
@ -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"
|
||||
|
@ -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;
|
||||
};
|
||||
|
||||
|
@ -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];
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -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.
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -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);
|
||||
};
|
||||
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
};
|
||||
|
@ -59,6 +59,3 @@ EXPORTS := \
|
||||
FORCE_STATIC_LIB := 1
|
||||
|
||||
include $(topsrcdir)/config/rules.mk
|
||||
|
||||
CFLAGS += $(GSTREAMER_CFLAGS)
|
||||
CXXFLAGS += $(GSTREAMER_CFLAGS)
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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()
|
||||
|
@ -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 \
|
||||
|
20
content/media/webaudio/test/test_bug845960.html
Normal file
20
content/media/webaudio/test/test_bug845960.html
Normal 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>
|
@ -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
|
||||
{
|
||||
|
BIN
content/media/webaudio/test/ting-dualchannel44.1-expected.wav
Normal file
BIN
content/media/webaudio/test/ting-dualchannel44.1-expected.wav
Normal file
Binary file not shown.
BIN
content/media/webaudio/test/ting-dualchannel44.1.ogg
Normal file
BIN
content/media/webaudio/test/ting-dualchannel44.1.ogg
Normal file
Binary file not shown.
BIN
content/media/webaudio/test/ting-dualchannel48-expected.wav
Normal file
BIN
content/media/webaudio/test/ting-dualchannel48-expected.wav
Normal file
Binary file not shown.
BIN
content/media/webaudio/test/ting-dualchannel48.ogg
Normal file
BIN
content/media/webaudio/test/ting-dualchannel48.ogg
Normal file
Binary file not shown.
@ -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,
|
||||
|
13
content/xbl/builtin/android/Makefile.in
Normal file
13
content/xbl/builtin/android/Makefile.in
Normal 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
|
6
content/xbl/builtin/android/jar.mn
Normal file
6
content/xbl/builtin/android/jar.mn
Normal 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)
|
5
content/xbl/builtin/android/moz.build
Normal file
5
content/xbl/builtin/android/moz.build
Normal 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/.
|
||||
|
170
content/xbl/builtin/android/platformHTMLBindings.xml
Normal file
170
content/xbl/builtin/android/platformHTMLBindings.xml
Normal 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>
|
@ -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:
|
||||
|
@ -7,7 +7,6 @@
|
||||
#define nsContentSupportMap_h__
|
||||
|
||||
#include "pldhash.h"
|
||||
#include "nsFixedSizeAllocator.h"
|
||||
#include "nsTemplateMatch.h"
|
||||
|
||||
/**
|
||||
|
@ -8,7 +8,6 @@
|
||||
|
||||
#include "nscore.h"
|
||||
#include "nsRuleNetwork.h"
|
||||
#include "nsFixedSizeAllocator.h"
|
||||
#include "nsIAtom.h"
|
||||
#include "nsIDOMDocument.h"
|
||||
|
||||
|
@ -7,7 +7,6 @@
|
||||
#define nsRDFConInstanceTestNode_h__
|
||||
|
||||
#include "nscore.h"
|
||||
#include "nsFixedSizeAllocator.h"
|
||||
#include "nsRDFTestNode.h"
|
||||
#include "nsIRDFResource.h"
|
||||
#include "nsIRDFDataSource.h"
|
||||
|
@ -18,7 +18,6 @@
|
||||
#include "nsICollation.h"
|
||||
#include "nsCollationCID.h"
|
||||
|
||||
#include "nsFixedSizeAllocator.h"
|
||||
#include "nsResourceSet.h"
|
||||
#include "nsRuleNetwork.h"
|
||||
#include "nsRDFQuery.h"
|
||||
|
@ -6,7 +6,6 @@
|
||||
#ifndef nsXULTemplateResultSetRDF_h__
|
||||
#define nsXULTemplateResultSetRDF_h__
|
||||
|
||||
#include "nsFixedSizeAllocator.h"
|
||||
#include "nsISimpleEnumerator.h"
|
||||
#include "nsRuleNetwork.h"
|
||||
#include "nsRDFQuery.h"
|
||||
|
@ -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
|
||||
|
||||
|
@ -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.
|
||||
|
@ -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 #}
|
||||
|
@ -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,
|
||||
|
@ -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);
|
||||
|
@ -29,6 +29,7 @@ SDK_XPIDLSRCS = \
|
||||
nsIDOMNodeList.idl \
|
||||
nsIDOMProcessingInstruction.idl \
|
||||
nsIDOMText.idl \
|
||||
nsIDocumentRegister.idl \
|
||||
$(NULL)
|
||||
XPIDLSRCS = \
|
||||
nsIDOMDOMStringList.idl \
|
||||
|
16
dom/interfaces/core/nsIDocumentRegister.idl
Normal file
16
dom/interfaces/core/nsIDocumentRegister.idl
Normal 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);
|
||||
};
|
||||
|
@ -48,6 +48,7 @@ XPIDLSRCS = \
|
||||
nsIDOMUserProximityEvent.idl \
|
||||
nsIDOMDeviceOrientationEvent.idl \
|
||||
nsIDOMDeviceMotionEvent.idl \
|
||||
nsIDOMElementReplaceEvent.idl \
|
||||
nsIDOMScrollAreaEvent.idl \
|
||||
nsIDOMTransitionEvent.idl \
|
||||
nsIDOMAnimationEvent.idl \
|
||||
|
24
dom/interfaces/events/nsIDOMElementReplaceEvent.idl
Normal file
24
dom/interfaces/events/nsIDOMElementReplaceEvent.idl
Normal 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;
|
||||
};
|
@ -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) {
|
||||
|
@ -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;
|
||||
|
@ -64,6 +64,7 @@ var interfaceNamesInGlobalScope =
|
||||
"HTMLOptionElement",
|
||||
"Pkcs11",
|
||||
"NotifyAudioAvailableEvent",
|
||||
"ElementReplaceEvent",
|
||||
"Array",
|
||||
"SVGZoomAndPan",
|
||||
"XULPopupElement",
|
||||
|
@ -21,6 +21,7 @@ DIRS += [
|
||||
'storageevent',
|
||||
'pointerlock',
|
||||
'webapps',
|
||||
'webcomponents',
|
||||
]
|
||||
|
||||
#needs IPC support, also tests do not run successfully in Firefox for now
|
||||
|
18
dom/tests/mochitest/webcomponents/Makefile.in
Normal file
18
dom/tests/mochitest/webcomponents/Makefile.in
Normal 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
|
5
dom/tests/mochitest/webcomponents/moz.build
Normal file
5
dom/tests/mochitest/webcomponents/moz.build
Normal 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/.
|
||||
|
@ -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>
|
@ -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>
|
@ -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;
|
||||
|
@ -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]
|
||||
|
24
dom/webidl/WebComponents.webidl
Normal file
24
dom/webidl/WebComponents.webidl
Normal 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
Loading…
Reference in New Issue
Block a user