diff --git a/accessible/public/ia2/Makefile.in b/accessible/public/ia2/Makefile.in
index 7454229bcfd7..b6f3d15fa670 100644
--- a/accessible/public/ia2/Makefile.in
+++ b/accessible/public/ia2/Makefile.in
@@ -20,8 +20,6 @@ GARBAGE += $(MIDL_GENERATED_FILES)
FORCE_SHARED_LIB = 1
-SRCS_IN_OBJDIR = 1
-
# Please keep this list in sync with the moz.build file until the rest of this
# Makefile is ported over.
MIDL_INTERFACES = \
diff --git a/accessible/public/msaa/Makefile.in b/accessible/public/msaa/Makefile.in
index c03fa5b873cf..9a1d37338bf5 100644
--- a/accessible/public/msaa/Makefile.in
+++ b/accessible/public/msaa/Makefile.in
@@ -18,8 +18,6 @@ GARBAGE += $(MIDL_GENERATED_FILES) done_gen dlldata.c
FORCE_SHARED_LIB = 1
-SRCS_IN_OBJDIR = 1
-
CSRCS = \
dlldata.c \
ISimpleDOMNode_p.c \
diff --git a/browser/base/content/browser.js b/browser/base/content/browser.js
index c01e2cb685ba..e9b7bf2c76ba 100644
--- a/browser/base/content/browser.js
+++ b/browser/base/content/browser.js
@@ -3612,6 +3612,7 @@ function mimeTypeIsTextBased(aMimeType)
aMimeType.endsWith("+xml") ||
aMimeType == "application/x-javascript" ||
aMimeType == "application/javascript" ||
+ aMimeType == "application/json" ||
aMimeType == "application/xml" ||
aMimeType == "mozilla.application/cached-xul";
}
diff --git a/browser/metro/base/content/bindings/autocomplete.xml b/browser/metro/base/content/bindings/autocomplete.xml
index e25f8feae126..f9a888b95d13 100644
--- a/browser/metro/base/content/bindings/autocomplete.xml
+++ b/browser/metro/base/content/bindings/autocomplete.xml
@@ -22,6 +22,7 @@
this.popup._input = this;
]]>
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/browser/metro/base/content/browser-ui.js b/browser/metro/base/content/browser-ui.js
index 9c890d452946..1d21706378fe 100644
--- a/browser/metro/base/content/browser-ui.js
+++ b/browser/metro/base/content/browser-ui.js
@@ -97,7 +97,11 @@ var BrowserUI = {
window.addEventListener("MozImprecisePointer", this, true);
Services.prefs.addObserver("browser.cache.disk_cache_ssl", this, false);
+ Services.prefs.addObserver("browser.urlbar.formatting.enabled", this, false);
+ Services.prefs.addObserver("browser.urlbar.trimURLs", this, false);
Services.obs.addObserver(this, "metro_viewstate_changed", false);
+
+ this._edit.inputField.controllers.insertControllerAt(0, this._copyCutURIController);
// Init core UI modules
ContextUI.init();
@@ -239,11 +243,20 @@ var BrowserUI = {
getDisplayURI: function(browser) {
let uri = browser.currentURI;
+ let spec = uri.spec;
+
try {
- uri = gURIFixup.createExposableURI(uri);
+ spec = gURIFixup.createExposableURI(uri).spec;
} catch (ex) {}
- return uri.spec;
+ try {
+ let charset = browser.characterSet;
+ let textToSubURI = Cc["@mozilla.org/intl/texttosuburi;1"].
+ getService(Ci.nsITextToSubURI);
+ spec = textToSubURI.unEscapeNonAsciiURI(charset, spec);
+ } catch (ex) {}
+
+ return spec;
},
/**
@@ -560,6 +573,12 @@ var BrowserUI = {
case "browser.cache.disk_cache_ssl":
this._sslDiskCacheEnabled = Services.prefs.getBoolPref(aData);
break;
+ case "browser.urlbar.formatting.enabled":
+ this._formattingEnabled = Services.prefs.getBookPref(aData);
+ break;
+ case "browser.urlbar.trimURLs":
+ this._mayTrimURLs = Services.prefs.getBoolPref(aData);
+ break;
}
break;
case "metro_viewstate_changed":
@@ -650,11 +669,120 @@ var BrowserUI = {
Elements.urlbarState.setAttribute("mode", "view");
},
+ _trimURL: function _trimURL(aURL) {
+ // This function must not modify the given URL such that calling
+ // nsIURIFixup::createFixupURI with the result will produce a different URI.
+ return aURL /* remove single trailing slash for http/https/ftp URLs */
+ .replace(/^((?:http|https|ftp):\/\/[^/]+)\/$/, "$1")
+ /* remove http:// unless the host starts with "ftp\d*\." or contains "@" */
+ .replace(/^http:\/\/((?!ftp\d*\.)[^\/@]+(?:\/|$))/, "$1");
+ },
+
+ trimURL: function trimURL(aURL) {
+ return this.mayTrimURLs ? this._trimURL(aURL) : aURL;
+ },
+
_setURI: function _setURI(aURL) {
this._edit.value = aURL;
this.lastKnownGoodURL = aURL;
},
+ _getSelectedURIForClipboard: function _getSelectedURIForClipboard() {
+ // Grab the actual input field's value, not our value, which could include moz-action:
+ let inputVal = this._edit.inputField.value;
+ let selectedVal = inputVal.substring(this._edit.selectionStart, this._edit.electionEnd);
+
+ // If the selection doesn't start at the beginning or doesn't span the full domain or
+ // the URL bar is modified, nothing else to do here.
+ if (this._edit.selectionStart > 0 || this._edit.valueIsTyped)
+ return selectedVal;
+ // The selection doesn't span the full domain if it doesn't contain a slash and is
+ // followed by some character other than a slash.
+ if (!selectedVal.contains("/")) {
+ let remainder = inputVal.replace(selectedVal, "");
+ if (remainder != "" && remainder[0] != "/")
+ return selectedVal;
+ }
+
+ let uriFixup = Cc["@mozilla.org/docshell/urifixup;1"].getService(Ci.nsIURIFixup);
+
+ let uri;
+ try {
+ uri = uriFixup.createFixupURI(inputVal, Ci.nsIURIFixup.FIXUP_FLAG_USE_UTF8);
+ } catch (e) {}
+ if (!uri)
+ return selectedVal;
+
+ // Only copy exposable URIs
+ try {
+ uri = uriFixup.createExposableURI(uri);
+ } catch (ex) {}
+
+ // If the entire URL is selected, just use the actual loaded URI.
+ if (inputVal == selectedVal) {
+ // ... but only if isn't a javascript: or data: URI, since those
+ // are hard to read when encoded
+ if (!uri.schemeIs("javascript") && !uri.schemeIs("data")) {
+ // Parentheses are known to confuse third-party applications (bug 458565).
+ selectedVal = uri.spec.replace(/[()]/g, function (c) escape(c));
+ }
+
+ return selectedVal;
+ }
+
+ // Just the beginning of the URL is selected, check for a trimmed value
+ let spec = uri.spec;
+ let trimmedSpec = this.trimURL(spec);
+ if (spec != trimmedSpec) {
+ // Prepend the portion that trimURL removed from the beginning.
+ // This assumes trimURL will only truncate the URL at
+ // the beginning or end (or both).
+ let trimmedSegments = spec.split(trimmedSpec);
+ selectedVal = trimmedSegments[0] + selectedVal;
+ }
+
+ return selectedVal;
+ },
+
+ _copyCutURIController: {
+ doCommand: function(aCommand) {
+ let urlbar = BrowserUI._edit;
+ let val = BrowserUI._getSelectedURIForClipboard();
+ if (!val)
+ return;
+
+ if (aCommand == "cmd_cut" && this.isCommandEnabled(aCommand)) {
+ let start = urlbar.selectionStart;
+ let end = urlbar.selectionEnd;
+ urlbar.inputField.value = urlbar.inputField.value.substring(0, start) +
+ urlbar.inputField.value.substring(end);
+ urlbar.selectionStart = urlbar.selectionEnd = start;
+ }
+
+ Cc["@mozilla.org/widget/clipboardhelper;1"]
+ .getService(Ci.nsIClipboardHelper)
+ .copyString(val, document);
+ },
+
+ supportsCommand: function(aCommand) {
+ switch (aCommand) {
+ case "cmd_copy":
+ case "cmd_cut":
+ return true;
+ }
+ return false;
+ },
+
+ isCommandEnabled: function(aCommand) {
+ let urlbar = BrowserUI._edit;
+ return this.supportsCommand(aCommand) &&
+ (aCommand != "cmd_cut" || !urlbar.readOnly) &&
+ urlbar.selectionStart < urlbar.selectionEnd;
+ },
+
+ onEvent: function(aEventName) {}
+ },
+
_urlbarClicked: function _urlbarClicked() {
// If the urlbar is not already focused, focus it and select the contents.
if (Elements.urlbarState.getAttribute("mode") != "edit")
@@ -662,6 +790,7 @@ var BrowserUI = {
},
_editURI: function _editURI(aShouldDismiss) {
+ this._clearURIFormatting();
this._edit.focus();
this._edit.select();
@@ -671,11 +800,77 @@ var BrowserUI = {
ContextUI.dismissTabs();
},
+ formatURI: function formatURI() {
+ if (!this.formattingEnabled ||
+ Elements.urlbarState.getAttribute("mode") == "edit")
+ return;
+
+ let controller = this._edit.editor.selectionController;
+ let selection = controller.getSelection(controller.SELECTION_URLSECONDARY);
+ selection.removeAllRanges();
+
+ let textNode = this._edit.editor.rootElement.firstChild;
+ let value = textNode.textContent;
+
+ let protocol = value.match(/^[a-z\d.+\-]+:(?=[^\d])/);
+ if (protocol &&
+ ["http:", "https:", "ftp:"].indexOf(protocol[0]) == -1)
+ return;
+ let matchedURL = value.match(/^((?:[a-z]+:\/\/)?(?:[^\/]+@)?)(.+?)(?::\d+)?(?:\/|$)/);
+ if (!matchedURL)
+ return;
+
+ let [, preDomain, domain] = matchedURL;
+ let baseDomain = domain;
+ let subDomain = "";
+ // getBaseDomainFromHost doesn't recognize IPv6 literals in brackets as IPs (bug 667159)
+ if (domain[0] != "[") {
+ try {
+ baseDomain = Services.eTLD.getBaseDomainFromHost(domain);
+ if (!domain.endsWith(baseDomain)) {
+ // getBaseDomainFromHost converts its resultant to ACE.
+ let IDNService = Cc["@mozilla.org/network/idn-service;1"]
+ .getService(Ci.nsIIDNService);
+ baseDomain = IDNService.convertACEtoUTF8(baseDomain);
+ }
+ } catch (e) {}
+ }
+ if (baseDomain != domain) {
+ subDomain = domain.slice(0, -baseDomain.length);
+ }
+
+ let rangeLength = preDomain.length + subDomain.length;
+ if (rangeLength) {
+ let range = document.createRange();
+ range.setStart(textNode, 0);
+ range.setEnd(textNode, rangeLength);
+ selection.addRange(range);
+ }
+
+ let startRest = preDomain.length + domain.length;
+ if (startRest < value.length) {
+ let range = document.createRange();
+ range.setStart(textNode, startRest);
+ range.setEnd(textNode, value.length);
+ selection.addRange(range);
+ }
+ },
+
+ _clearURIFormatting: function _clearURIFormatting() {
+ if (!this.formattingEnabled)
+ return;
+
+ let controller = this._edit.editor.selectionController;
+ let selection = controller.getSelection(controller.SELECTION_URLSECONDARY);
+ selection.removeAllRanges();
+ },
+
_urlbarBlurred: function _urlbarBlurred() {
let state = Elements.urlbarState;
if (state.getAttribute("mode") == "edit")
state.removeAttribute("mode");
this._updateToolbar();
+ this.formatURI();
},
_closeOrQuit: function _closeOrQuit() {
@@ -959,6 +1154,24 @@ var BrowserUI = {
return this._sslDiskCacheEnabled;
},
+ _formattingEnabled: null,
+
+ get formattingEnabled() {
+ if (this._formattingEnabled === null) {
+ this._formattingEnabled = Services.prefs.getBoolPref("browser.urlbar.formatting.enabled");
+ }
+ return this._formattingEnabled;
+ },
+
+ _mayTrimURLs: null,
+
+ get mayTrimURLs() {
+ if (this._mayTrimURLs === null) {
+ this._mayTrimURLs = Services.prefs.getBoolPref("browser.urlbar.trimURLs");
+ }
+ return this._mayTrimURLs;
+ },
+
supportsCommand : function(cmd) {
var isSupported = false;
switch (cmd) {
diff --git a/browser/metro/profile/metro.js b/browser/metro/profile/metro.js
index b6a523ef8125..821487976a04 100644
--- a/browser/metro/profile/metro.js
+++ b/browser/metro/profile/metro.js
@@ -261,6 +261,8 @@ pref("places.favicons.optimizeToDimension", 25);
// various and sundry awesomebar prefs (should remove/re-evaluate
// these once bug 447900 is fixed)
+pref("browser.urlbar.trimURLs", true);
+pref("browser.urlbar.formatting.enabled", true);
pref("browser.urlbar.clickSelectsAll", true);
pref("browser.urlbar.doubleClickSelectsAll", true);
pref("browser.urlbar.autoFill", false);
diff --git a/browser/metro/theme/browser.css b/browser/metro/theme/browser.css
index fe61d5cecb62..dea48f0a4763 100644
--- a/browser/metro/theme/browser.css
+++ b/browser/metro/theme/browser.css
@@ -308,6 +308,12 @@ documenttab[selected] .documenttab-selection {
padding: 0 !important;
}
+#urlbar-edit > hbox > .textbox-input-box > .textbox-input:invalid {
+ /* Hide error glow around the address bar that shows by default
+ * when URLs are made invalid by trmming. */
+ box-shadow: none !important;
+}
+
/* Combined stop-reload button */
#tool-reload {
list-style-image: url("chrome://browser/skin/images/reload.png");
diff --git a/browser/metro/theme/cssthrobber.css b/browser/metro/theme/cssthrobber.css
index fb0fd9c63dee..63b699b207aa 100644
--- a/browser/metro/theme/cssthrobber.css
+++ b/browser/metro/theme/cssthrobber.css
@@ -47,15 +47,15 @@
border-radius: 5px;
position: absolute;
background: #0095dd;
- left:0px;
- top:0px;
+ left: 0;
+ top: 0;
}
@keyframes orbit {
0% {
opacity: 1;
- z-index:99;
+ z-index: 99;
transform: rotate(180deg);
animation-timing-function: ease-out;
}
@@ -64,39 +64,34 @@
opacity: 1;
transform: rotate(300deg);
animation-timing-function: linear;
- origin:0%;
}
30% {
opacity: 1;
- transform:rotate(410deg);
+ transform: rotate(410deg);
animation-timing-function: ease-in-out;
- origin:7%;
}
39% {
opacity: 1;
transform: rotate(645deg);
animation-timing-function: linear;
- origin:30%;
}
70% {
opacity: 1;
transform: rotate(770deg);
animation-timing-function: ease-out;
- origin:39%;
}
75% {
opacity: 1;
transform: rotate(900deg);
animation-timing-function: ease-out;
- origin:70%;
}
76%, 100% {
opacity: 0;
- transform:rotate(900deg);
+ transform: rotate(900deg);
}
}
diff --git a/browser/modules/webrtcUI.jsm b/browser/modules/webrtcUI.jsm
index a059dee2b0f9..ad7b01dba469 100644
--- a/browser/modules/webrtcUI.jsm
+++ b/browser/modules/webrtcUI.jsm
@@ -120,7 +120,7 @@ function prompt(aWindowID, aCallID, aAudioRequested, aVideoRequested, aDevices)
}
let contentWindow = Services.wm.getOuterWindowWithId(aWindowID);
- let host = contentWindow.document.documentURIObject.asciiHost;
+ let host = contentWindow.document.documentURIObject.host;
let browser = getBrowserForWindow(contentWindow);
let chromeDoc = browser.ownerDocument;
let chromeWin = chromeDoc.defaultView;
diff --git a/caps/tests/mochitest/test_app_principal_equality.html b/caps/tests/mochitest/test_app_principal_equality.html
index 2dddc55c0999..927bbce62b5d 100644
--- a/caps/tests/mochitest/test_app_principal_equality.html
+++ b/caps/tests/mochitest/test_app_principal_equality.html
@@ -17,18 +17,6 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=777467
SpecialPowers.addPermission("browser", true, document);
SpecialPowers.addPermission("embed-apps", true, document);
- var previousPrefs = {
- mozBrowserFramesEnabled: undefined,
- oop_by_default: undefined,
- };
- try {
- previousPrefs.mozBrowserFramesEnabled = SpecialPowers.getBoolPref('dom.mozBrowserFramesEnabled');
- } catch(e) {}
-
- try {
- previousPrefs.oop_by_default = SpecialPowers.getBoolPref('dom.ipc.browser_frames.oop_by_default');
- } catch(e) {}
-
SpecialPowers.setBoolPref('dom.mozBrowserFramesEnabled', true);
SpecialPowers.setBoolPref("dom.ipc.browser_frames.oop_by_default", false);
@@ -66,13 +54,8 @@ addLoadEvent(function() {
}
// Cleanup.
- if (previousPrefs.mozBrowserFramesEnabled !== undefined) {
- SpecialPowers.setBoolPref('dom.mozBrowserFramesEnabled', previousPrefs.mozBrowserFramesEnabled);
- }
- if (previousPrefs.oop_by_default !== undefined) {
- SpecialPowers.setBoolPref("dom.ipc.browser_frames.oop_by_default", previousPrefs.oop_by_default);
- }
-
+ SpecialPowers.clearUserPref('dom.mozBrowserFramesEnabled');
+ SpecialPowers.clearUserPref('dom.ipc.browser_frames.oop_by_default');
SpecialPowers.removePermission("browser", window.document);
SpecialPowers.removePermission("embed-apps", window.document);
diff --git a/content/base/src/nsFrameMessageManager.cpp b/content/base/src/nsFrameMessageManager.cpp
index 2dadfdb345e6..595a58d60477 100644
--- a/content/base/src/nsFrameMessageManager.cpp
+++ b/content/base/src/nsFrameMessageManager.cpp
@@ -44,19 +44,6 @@ using namespace mozilla;
using namespace mozilla::dom;
using namespace mozilla::dom::ipc;
-
-static bool
-IsChromeProcess()
-{
- nsCOMPtr rt = do_GetService("@mozilla.org/xre/runtime;1");
- if (!rt)
- return true;
-
- uint32_t type;
- rt->GetProcessType(&type);
- return type == nsIXULRuntime::PROCESS_TYPE_DEFAULT;
-}
-
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsFrameMessageManager)
uint32_t count = tmp->mListeners.Length();
for (uint32_t i = 0; i < count; i++) {
@@ -836,7 +823,8 @@ nsFrameMessageManager::Disconnect(bool aRemoveFromParent)
nsresult
NS_NewGlobalMessageManager(nsIMessageBroadcaster** aResult)
{
- NS_ENSURE_TRUE(IsChromeProcess(), NS_ERROR_NOT_AVAILABLE);
+ NS_ENSURE_TRUE(XRE_GetProcessType() == GeckoProcessType_Default,
+ NS_ERROR_NOT_AVAILABLE);
nsFrameMessageManager* mm = new nsFrameMessageManager(nullptr,
nullptr,
nullptr,
@@ -1387,7 +1375,8 @@ NS_NewParentProcessMessageManager(nsIMessageBroadcaster** aResult)
{
NS_ASSERTION(!nsFrameMessageManager::sParentProcessManager,
"Re-creating sParentProcessManager");
- NS_ENSURE_TRUE(IsChromeProcess(), NS_ERROR_NOT_AVAILABLE);
+ NS_ENSURE_TRUE(XRE_GetProcessType() == GeckoProcessType_Default,
+ NS_ERROR_NOT_AVAILABLE);
nsRefPtr mm = new nsFrameMessageManager(nullptr,
nullptr,
nullptr,
@@ -1432,7 +1421,7 @@ NS_NewChildProcessMessageManager(nsISyncMessageSender** aResult)
"Re-creating sChildProcessManager");
MessageManagerCallback* cb;
- if (IsChromeProcess()) {
+ if (XRE_GetProcessType() == GeckoProcessType_Default) {
cb = new SameChildProcessMessageManagerCallback();
} else {
cb = new ChildProcessMessageManagerCallback();
diff --git a/content/base/test/test_bug450160.html b/content/base/test/test_bug450160.html
index d5fb7f86929d..dd28623b1ab4 100644
--- a/content/base/test/test_bug450160.html
+++ b/content/base/test/test_bug450160.html
@@ -32,9 +32,9 @@ function testHTMLDocuments(ids, isXHTML) {
is(docType1.ownerDocument, doc1, "docType should have ownerDocument!");
ok(!doc1.documentElement, "Document shouldn't have document element!");
is(doc1.body, null, "Shouldn't have .body!");
- ok(doc1 instanceof SpecialPowers.Ci.nsIDOMHTMLDocument,
+ ok(doc1 instanceof HTMLDocument,
"Document should be an HTML document!");
- ok(!(doc1 instanceof SpecialPowers.Ci.nsIDOMSVGDocument),
+ ok(!(doc1 instanceof SVGDocument),
"Document shouldn't be an SVG document!");
var docType2 =
@@ -68,9 +68,9 @@ function testSVGDocument() {
var doc1 = document.implementation.createDocument(null, null, docType1);
is(docType1.ownerDocument, doc1, "docType should have ownerDocument!");
ok(!doc1.documentElement, "Document shouldn't have document element!");
- ok(!(doc1 instanceof SpecialPowers.Ci.nsIDOMHTMLDocument),
+ ok(!(doc1 instanceof HTMLDocument),
"Document shouldn't be an HTML document!");
- ok(doc1 instanceof SpecialPowers.Ci.nsIDOMSVGDocument,
+ ok(doc1 instanceof SVGDocument,
"Document should be an SVG document!");
// SVG documents have .rootElement.
@@ -95,9 +95,9 @@ function testFooBarDocument() {
var doc1 = document.implementation.createDocument(null, null, docType1);
is(docType1.ownerDocument, doc1, "docType should have ownerDocument!");
ok(!doc1.documentElement, "Document shouldn't have document element!");
- ok(!(doc1 instanceof SpecialPowers.Ci.nsIDOMHTMLDocument),
+ ok(!(doc1 instanceof HTMLDocument),
"Document shouldn't be an HTML document!");
- ok(!(doc1 instanceof SpecialPowers.Ci.nsIDOMSVGDocument),
+ ok(!(doc1 instanceof SVGDocument),
"Document shouldn't be an SVG document!");
var docType2 =
@@ -112,9 +112,9 @@ function testFooBarDocument() {
function testNullDocTypeDocument() {
var doc1 = document.implementation.createDocument(null, null, null);
ok(!doc1.documentElement, "Document shouldn't have document element!");
- ok(!(doc1 instanceof SpecialPowers.Ci.nsIDOMHTMLDocument),
+ ok(!(doc1 instanceof HTMLDocument),
"Document shouldn't be an HTML document!");
- ok(!(doc1 instanceof SpecialPowers.Ci.nsIDOMSVGDocument),
+ ok(!(doc1 instanceof SVGDocument),
"Document shouldn't be an SVG document!");
var doc2 = document.implementation.createDocument("FooBarNS",
diff --git a/content/base/test/test_websocket.html b/content/base/test/test_websocket.html
index d05156107e50..2e15e7c17a8a 100644
--- a/content/base/test/test_websocket.html
+++ b/content/base/test/test_websocket.html
@@ -777,8 +777,6 @@ function test22()
waitTest22 = true;
const pref_open = "network.websocket.timeout.open";
- var oldpref_open_value = 20;
- oldpref_open_value = SpecialPowers.getIntPref(pref_open);
SpecialPowers.setIntPref(pref_open, 5);
var ws = CreateTestWS("ws://sub2.test2.example.org/tests/content/base/test/file_websocket", "test-22");
@@ -791,7 +789,7 @@ function test22()
maybeFinished();
};
- SpecialPowers.setIntPref(pref_open, oldpref_open_value);
+ SpecialPowers.clearUserPref(pref_open);
doTest(23);
}
diff --git a/content/html/content/src/HTMLIFrameElement.cpp b/content/html/content/src/HTMLIFrameElement.cpp
index 4f679cde433a..346b19a8c2db 100644
--- a/content/html/content/src/HTMLIFrameElement.cpp
+++ b/content/html/content/src/HTMLIFrameElement.cpp
@@ -7,7 +7,6 @@
#include "mozilla/dom/HTMLIFrameElement.h"
#include "mozilla/dom/HTMLIFrameElementBinding.h"
-#include "nsIDOMSVGDocument.h"
#include "nsMappedAttributes.h"
#include "nsAttrValueInlines.h"
#include "nsError.h"
diff --git a/content/html/content/src/HTMLLabelElement.cpp b/content/html/content/src/HTMLLabelElement.cpp
index e3c7ddab6391..d25bfb0bb38f 100644
--- a/content/html/content/src/HTMLLabelElement.cpp
+++ b/content/html/content/src/HTMLLabelElement.cpp
@@ -28,7 +28,7 @@ HTMLLabelElement::WrapNode(JSContext *aCx, JS::Handle aScope)
return HTMLLabelElementBinding::Wrap(aCx, aScope, this);
}
-// nsISupports
+// nsISupports
NS_IMPL_ADDREF_INHERITED(HTMLLabelElement, Element)
@@ -171,27 +171,26 @@ HTMLLabelElement::PostHandleEvent(nsEventChainPostVisitor& aVisitor)
dragDistance.y > CLICK_DISTANCE ||
dragDistance.y < -CLICK_DISTANCE;
}
-
// Don't click the for-content if we did drag-select text or if we
- // have a kbd modifier (which adjusts a selection), or if it's a
- // double click (we already forwarded the first click event).
- if (dragSelect || event->clickCount > 1 ||
- event->IsShift() || event->IsControl() || event->IsAlt() ||
- event->IsMeta()) {
+ // have a kbd modifier (which adjusts a selection).
+ if (dragSelect || event->IsShift() || event->IsControl() ||
+ event->IsAlt() || event->IsMeta()) {
break;
}
-
- nsIFocusManager* fm = nsFocusManager::GetFocusManager();
- if (fm) {
- // Use FLAG_BYMOVEFOCUS here so that the label is scrolled to.
- // Also, within HTMLInputElement::PostHandleEvent, inputs will
- // be selected only when focused via a key or when the navigation
- // flag is used and we want to select the text on label clicks as
- // well.
- nsCOMPtr elem = do_QueryInterface(content);
- fm->SetFocus(elem, nsIFocusManager::FLAG_BYMOVEFOCUS);
+ // Only set focus on the first click of multiple clicks to prevent
+ // to prevent immediate de-focus.
+ if (event->clickCount <= 1) {
+ nsIFocusManager* fm = nsFocusManager::GetFocusManager();
+ if (fm) {
+ // Use FLAG_BYMOVEFOCUS here so that the label is scrolled to.
+ // Also, within HTMLInputElement::PostHandleEvent, inputs will
+ // be selected only when focused via a key or when the navigation
+ // flag is used and we want to select the text on label clicks as
+ // well.
+ nsCOMPtr elem = do_QueryInterface(content);
+ fm->SetFocus(elem, nsIFocusManager::FLAG_BYMOVEFOCUS);
+ }
}
-
// Dispatch a new click event to |content|
// (For compatibility with IE, we do only left click. If
// we wanted to interpret the HTML spec very narrowly, we
diff --git a/content/html/content/src/HTMLSharedObjectElement.cpp b/content/html/content/src/HTMLSharedObjectElement.cpp
index dff85b6298fd..5a2c862f381c 100644
--- a/content/html/content/src/HTMLSharedObjectElement.cpp
+++ b/content/html/content/src/HTMLSharedObjectElement.cpp
@@ -13,7 +13,6 @@
#include "nsIPluginDocument.h"
#include "nsIDOMDocument.h"
#include "nsThreadUtils.h"
-#include "nsIDOMSVGDocument.h"
#include "nsIScriptError.h"
#include "nsIWidget.h"
#include "nsContentUtils.h"
diff --git a/content/media/AudioNodeStream.cpp b/content/media/AudioNodeStream.cpp
index f77e692a582e..368707d57fc6 100644
--- a/content/media/AudioNodeStream.cpp
+++ b/content/media/AudioNodeStream.cpp
@@ -19,6 +19,7 @@ namespace mozilla {
* for regular audio contexts, and the rate requested by the web content
* for offline audio contexts.
* Each chunk in the track is a single block of WEBAUDIO_BLOCK_SIZE samples.
+ * Note: This must be a different value than MEDIA_STREAM_DEST_TRACK_ID
*/
static const int AUDIO_NODE_STREAM_TRACK_ID = 1;
@@ -235,23 +236,6 @@ AudioNodeStream::SetChannelMixingParametersImpl(uint32_t aNumberOfChannels,
mChannelInterpretation = aChannelInterpretation;
}
-StreamBuffer::Track*
-AudioNodeStream::EnsureTrack()
-{
- StreamBuffer::Track* track = mBuffer.FindTrack(AUDIO_NODE_STREAM_TRACK_ID);
- if (!track) {
- nsAutoPtr segment(new AudioSegment());
- for (uint32_t j = 0; j < mListeners.Length(); ++j) {
- MediaStreamListener* l = mListeners[j];
- l->NotifyQueuedTrackChanges(Graph(), AUDIO_NODE_STREAM_TRACK_ID, mSampleRate, 0,
- MediaStreamListener::TRACK_EVENT_CREATED,
- *segment);
- }
- track = &mBuffer.AddTrack(AUDIO_NODE_STREAM_TRACK_ID, mSampleRate, 0, segment.forget());
- }
- return track;
-}
-
bool
AudioNodeStream::AllInputsFinished() const
{
@@ -399,7 +383,7 @@ AudioNodeStream::ProduceOutput(GraphTime aFrom, GraphTime aTo)
FinishOutput();
}
- StreamBuffer::Track* track = EnsureTrack();
+ StreamBuffer::Track* track = EnsureTrack(AUDIO_NODE_STREAM_TRACK_ID, mSampleRate);
AudioSegment* segment = track->Get();
@@ -460,7 +444,7 @@ AudioNodeStream::ProduceOutput(GraphTime aFrom, GraphTime aTo)
TrackTicks
AudioNodeStream::GetCurrentPosition()
{
- return EnsureTrack()->Get()->GetDuration();
+ return EnsureTrack(AUDIO_NODE_STREAM_TRACK_ID, mSampleRate)->Get()->GetDuration();
}
void
@@ -470,7 +454,7 @@ AudioNodeStream::FinishOutput()
return;
}
- StreamBuffer::Track* track = EnsureTrack();
+ StreamBuffer::Track* track = EnsureTrack(AUDIO_NODE_STREAM_TRACK_ID, mSampleRate);
track->SetEnded();
FinishOnGraphThread();
diff --git a/content/media/AudioNodeStream.h b/content/media/AudioNodeStream.h
index 4beedc7b0e89..5fd5fafc4df5 100644
--- a/content/media/AudioNodeStream.h
+++ b/content/media/AudioNodeStream.h
@@ -116,7 +116,6 @@ public:
protected:
void FinishOutput();
- StreamBuffer::Track* EnsureTrack();
void ObtainInputBlock(AudioChunk& aTmpChunk, uint32_t aPortIndex);
// The engine that will generate output for this node.
diff --git a/content/media/DOMMediaStream.cpp b/content/media/DOMMediaStream.cpp
index dff6dd1c96c3..8cd9a8a89e5e 100644
--- a/content/media/DOMMediaStream.cpp
+++ b/content/media/DOMMediaStream.cpp
@@ -8,6 +8,7 @@
#include "nsContentUtils.h"
#include "mozilla/dom/MediaStreamBinding.h"
#include "mozilla/dom/LocalMediaStreamBinding.h"
+#include "mozilla/dom/AudioNode.h"
#include "MediaStreamGraph.h"
#include "AudioStreamTrack.h"
#include "VideoStreamTrack.h"
@@ -39,6 +40,15 @@ NS_IMPL_CYCLE_COLLECTION_TRACE_WRAPPERCACHE(DOMMediaStream)
NS_IMPL_ISUPPORTS_INHERITED1(DOMLocalMediaStream, DOMMediaStream,
nsIDOMLocalMediaStream)
+NS_IMPL_CYCLE_COLLECTION_INHERITED_1(DOMAudioNodeMediaStream, DOMMediaStream,
+ mStreamNode)
+
+NS_IMPL_ADDREF_INHERITED(DOMAudioNodeMediaStream, DOMMediaStream)
+NS_IMPL_RELEASE_INHERITED(DOMAudioNodeMediaStream, DOMMediaStream)
+
+NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(DOMAudioNodeMediaStream)
+NS_INTERFACE_MAP_END_INHERITING(DOMMediaStream)
+
class DOMMediaStream::StreamListener : public MediaStreamListener {
public:
StreamListener(DOMMediaStream* aStream)
@@ -346,3 +356,18 @@ DOMLocalMediaStream::CreateTrackUnionStream(nsIDOMWindow* aWindow,
stream->InitTrackUnionStream(aWindow, aHintContents);
return stream.forget();
}
+
+DOMAudioNodeMediaStream::DOMAudioNodeMediaStream(AudioNode* aNode)
+: mStreamNode(aNode)
+{
+}
+
+already_AddRefed
+DOMAudioNodeMediaStream::CreateTrackUnionStream(nsIDOMWindow* aWindow,
+ AudioNode* aNode,
+ TrackTypeHints aHintContents)
+{
+ nsRefPtr stream = new DOMAudioNodeMediaStream(aNode);
+ stream->InitTrackUnionStream(aWindow, aHintContents);
+ return stream.forget();
+}
diff --git a/content/media/DOMMediaStream.h b/content/media/DOMMediaStream.h
index afb06285b756..7a08d0465340 100644
--- a/content/media/DOMMediaStream.h
+++ b/content/media/DOMMediaStream.h
@@ -33,6 +33,7 @@ namespace mozilla {
class MediaStream;
namespace dom {
+class AudioNode;
class MediaStreamTrack;
class AudioStreamTrack;
class VideoStreamTrack;
@@ -206,6 +207,29 @@ public:
CreateTrackUnionStream(nsIDOMWindow* aWindow, TrackTypeHints aHintContents = 0);
};
+class DOMAudioNodeMediaStream : public DOMMediaStream
+{
+ typedef dom::AudioNode AudioNode;
+public:
+ DOMAudioNodeMediaStream(AudioNode* aNode);
+
+ NS_DECL_ISUPPORTS_INHERITED
+ NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(DOMAudioNodeMediaStream, DOMMediaStream)
+
+ /**
+ * Create a DOMAudioNodeMediaStream whose underlying stream is a TrackUnionStream.
+ */
+ static already_AddRefed
+ CreateTrackUnionStream(nsIDOMWindow* aWindow,
+ AudioNode* aNode,
+ TrackTypeHints aHintContents = 0);
+
+private:
+ // If this object wraps a stream owned by an AudioNode, we need to ensure that
+ // the node isn't cycle-collected too early.
+ nsRefPtr mStreamNode;
+};
+
}
#endif /* NSDOMMEDIASTREAM_H_ */
diff --git a/content/media/MediaStreamGraph.cpp b/content/media/MediaStreamGraph.cpp
index a046059aa9d3..7108b690df5a 100644
--- a/content/media/MediaStreamGraph.cpp
+++ b/content/media/MediaStreamGraph.cpp
@@ -1525,6 +1525,23 @@ MediaStream::FinishOnGraphThread()
GraphImpl()->FinishStream(this);
}
+StreamBuffer::Track*
+MediaStream::EnsureTrack(TrackID aTrackId, TrackRate aSampleRate)
+{
+ StreamBuffer::Track* track = mBuffer.FindTrack(aTrackId);
+ if (!track) {
+ nsAutoPtr segment(new AudioSegment());
+ for (uint32_t j = 0; j < mListeners.Length(); ++j) {
+ MediaStreamListener* l = mListeners[j];
+ l->NotifyQueuedTrackChanges(Graph(), aTrackId, aSampleRate, 0,
+ MediaStreamListener::TRACK_EVENT_CREATED,
+ *segment);
+ }
+ track = &mBuffer.AddTrack(aTrackId, aSampleRate, 0, segment.forget());
+ }
+ return track;
+}
+
void
MediaStream::RemoveAllListenersImpl()
{
diff --git a/content/media/MediaStreamGraph.h b/content/media/MediaStreamGraph.h
index 345078762b71..d12658067e0b 100644
--- a/content/media/MediaStreamGraph.h
+++ b/content/media/MediaStreamGraph.h
@@ -277,9 +277,11 @@ public:
, mMainThreadDestroyed(false)
, mGraph(nullptr)
{
+ MOZ_COUNT_CTOR(MediaStream);
}
virtual ~MediaStream()
{
+ MOZ_COUNT_DTOR(MediaStream);
NS_ASSERTION(mMainThreadDestroyed, "Should have been destroyed already");
NS_ASSERTION(mMainThreadListeners.IsEmpty(),
"All main thread listeners should have been removed");
@@ -431,6 +433,8 @@ public:
bool HasCurrentData() { return mHasCurrentData; }
+ StreamBuffer::Track* EnsureTrack(TrackID aTrack, TrackRate aSampleRate);
+
void ApplyTrackDisabling(TrackID aTrackID, MediaSegment* aSegment);
DOMMediaStream* GetWrapper()
diff --git a/content/media/TrackUnionStream.h b/content/media/TrackUnionStream.h
index 2601c4197d8b..10066e1e28f7 100644
--- a/content/media/TrackUnionStream.h
+++ b/content/media/TrackUnionStream.h
@@ -26,6 +26,7 @@ class TrackUnionStream : public ProcessedMediaStream {
public:
TrackUnionStream(DOMMediaStream* aWrapper) :
ProcessedMediaStream(aWrapper),
+ mFilterCallback(nullptr),
mMaxTrackID(0) {}
virtual void RemoveInput(MediaInputPort* aPort)
@@ -75,7 +76,7 @@ public:
break;
}
}
- if (!found) {
+ if (!found && (!mFilterCallback || mFilterCallback(tracks.get()))) {
bool trackFinished = false;
uint32_t mapIndex = AddTrack(mInputs[i], tracks.get(), aFrom);
CopyTrackData(tracks.get(), mapIndex, aFrom, aTo, &trackFinished);
@@ -107,7 +108,16 @@ public:
}
}
+ // Consumers may specify a filtering callback to apply to every input track.
+ // Returns true to allow the track to act as an input; false to reject it entirely.
+ typedef bool (*TrackIDFilterCallback)(StreamBuffer::Track*);
+ void SetTrackIDFilter(TrackIDFilterCallback aCallback) {
+ mFilterCallback = aCallback;
+ }
+
protected:
+ TrackIDFilterCallback mFilterCallback;
+
// Only non-ended tracks are allowed to persist in this map.
struct TrackMapEntry {
MediaInputPort* mInputPort;
diff --git a/content/media/moz.build b/content/media/moz.build
index 8bc287a6210a..8e1c32d1f162 100644
--- a/content/media/moz.build
+++ b/content/media/moz.build
@@ -71,6 +71,7 @@ EXPORTS += [
'SharedBuffer.h',
'StreamBuffer.h',
'TimeVarying.h',
+ 'TrackUnionStream.h',
'VideoFrameContainer.h',
'VideoSegment.h',
'VideoUtils.h',
diff --git a/content/media/omx/MediaOmxReader.cpp b/content/media/omx/MediaOmxReader.cpp
index 0e3c81ea97af..8dc632818a35 100644
--- a/content/media/omx/MediaOmxReader.cpp
+++ b/content/media/omx/MediaOmxReader.cpp
@@ -17,6 +17,8 @@
#include "MPAPI.h"
#define MAX_DROPPED_FRAMES 25
+// Try not to spend more than this much time in a single call to DecodeVideoFrame.
+#define MAX_VIDEO_DECODE_SECONDS 3.0
using namespace android;
@@ -156,8 +158,10 @@ bool MediaOmxReader::DecodeVideoFrame(bool &aKeyframeSkip,
aTimeThreshold = mVideoSeekTimeUs;
}
- // Read next frame
- while (true) {
+ TimeStamp start = TimeStamp::Now();
+
+ // Read next frame. Don't let this loop run for too long.
+ while ((TimeStamp::Now() - start) < TimeDuration::FromSeconds(MAX_VIDEO_DECODE_SECONDS)) {
MPAPI::VideoFrame frame;
frame.mGraphicBuffer = nullptr;
frame.mShouldSkip = false;
@@ -165,22 +169,23 @@ bool MediaOmxReader::DecodeVideoFrame(bool &aKeyframeSkip,
mVideoQueue.Finish();
return false;
}
+ doSeek = false;
// Ignore empty buffer which stagefright media read will sporadically return
if (frame.mSize == 0 && !frame.mGraphicBuffer) {
- return true;
+ continue;
}
parsed++;
if (frame.mShouldSkip && mSkipCount < MAX_DROPPED_FRAMES) {
mSkipCount++;
- return true;
+ continue;
}
mSkipCount = 0;
mVideoSeekTimeUs = -1;
- doSeek = aKeyframeSkip = false;
+ aKeyframeSkip = false;
nsIntRect picture = mPicture;
if (frame.Y.mWidth != mInitialFrame.width ||
diff --git a/content/media/test/Makefile.in b/content/media/test/Makefile.in
index eb30daa7aabb..8d1ed24e31ea 100644
--- a/content/media/test/Makefile.in
+++ b/content/media/test/Makefile.in
@@ -117,7 +117,6 @@ MOCHITEST_FILES = \
test_too_many_elements.html \
test_volume.html \
test_video_to_canvas.html \
- use_large_cache.js \
test_audiowrite.html \
test_mozHasAudio.html \
test_source_media.html \
diff --git a/content/media/test/test_buffered.html b/content/media/test/test_buffered.html
index 2c2ee0f1d5da..98ea36c9983f 100644
--- a/content/media/test/test_buffered.html
+++ b/content/media/test/test_buffered.html
@@ -8,7 +8,6 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=462957
-
Mozilla Bug 462957
@@ -85,8 +84,11 @@ function startTest(test, token) {
document.body.appendChild(v);
}
-manager.runTests(gSeekTests, startTest);
-
+SimpleTest.waitForExplicitFinish();
+SpecialPowers.pushPrefEnv({"set": [["media.cache_size", 40000]]}, beginTest);
+function beginTest() {
+ manager.runTests(gSeekTests, startTest);
+}
diff --git a/content/media/test/test_bug493187.html b/content/media/test/test_bug493187.html
index 25c27161f074..db9ce8ee8e80 100644
--- a/content/media/test/test_bug493187.html
+++ b/content/media/test/test_bug493187.html
@@ -8,7 +8,6 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=493187
Bug 493187 - enter HAVE_FUTURE_DATA when seeking within buffered data even if new data isn't arriving
-
@@ -62,8 +61,11 @@ function startTest(test, token) {
document.body.appendChild(v);
}
-manager.runTests(gSeekTests, startTest);
-
+SimpleTest.waitForExplicitFinish();
+SpecialPowers.pushPrefEnv({"set": [["media.cache_size", 40000]]}, beginTest);
+function beginTest() {
+ manager.runTests(gSeekTests, startTest);
+}
diff --git a/content/media/test/test_can_play_type_mpeg.html b/content/media/test/test_can_play_type_mpeg.html
index 1b310013519d..cd113704fc98 100644
--- a/content/media/test/test_can_play_type_mpeg.html
+++ b/content/media/test/test_can_play_type_mpeg.html
@@ -33,24 +33,17 @@ function IsWindows7() {
}
function getMediaPref(name) {
- // Can't use SpecialPowers.getBoolPref because it throws when pref isn't
- // present, and for example on non-Windows systems the WMF prefs won't be
- // present.
var pref = false;
- var prefService = SpecialPowers.wrap(SpecialPowers.Components)
- .classes["@mozilla.org/preferences-service;1"]
- .getService(SpecialPowers.Ci.nsIPrefService);
- var branch = prefService.getBranch("media.");
try {
- pref = branch.getBoolPref(name);
+ pref = SpecialPowers.getBoolPref(name);
} catch(ex) { }
return pref;
}
-var haveMp4 = (getMediaPref("windows-media-foundation.enabled") && IsWindowsVistaOrLater()) ||
- getMediaPref("omx.enabled") ||
- getMediaPref("gstreamer.enabled");
-// TODO: Add "getMediaPref("plugins.enabled")" once MP4 works on Gingerbread.
+var haveMp4 = (getMediaPref("media.windows-media-foundation.enabled") && IsWindowsVistaOrLater()) ||
+ getMediaPref("media.omx.enabled") ||
+ getMediaPref("media.gstreamer.enabled");
+// TODO: Add "getMediaPref("media.plugins.enabled")" once MP4 works on Gingerbread.
check_mp4(document.getElementById('v'), haveMp4);
diff --git a/content/media/test/test_closing_connections.html b/content/media/test/test_closing_connections.html
index 89d483ed5e7e..796f7ef6b685 100644
--- a/content/media/test/test_closing_connections.html
+++ b/content/media/test/test_closing_connections.html
@@ -1,4 +1,4 @@
-
+hg diff