Merge m-c to b2g-inbound

This commit is contained in:
Carsten "Tomcat" Book 2014-09-08 15:34:29 +02:00
commit efa9474eef
268 changed files with 4106 additions and 3897 deletions

View File

@ -154,6 +154,12 @@ SelectionManager::ProcessTextSelChangeEvent(AccEvent* aEvent)
return;
Selection* selection = caretCntr->DOMSelection();
// XXX Sometimes we can't get a selection for caretCntr, in that case assume
// event->mSel is correct.
if (!selection)
selection = event->mSel;
mCaretOffset = caretCntr->DOMPointToOffset(selection->GetFocusNode(),
selection->FocusOffset());
mAccWithCaret = caretCntr;
@ -179,8 +185,7 @@ SelectionManager::NotifySelectionChanged(nsIDOMDocument* aDOMDocument,
logging::SelChange(aSelection, document, aReason);
#endif
// Don't fire events until document is loaded.
if (document && document->IsContentLoaded()) {
if (document) {
// Selection manager has longer lifetime than any document accessible,
// so that we are guaranteed that the notification is processed before
// the selection manager is destroyed.

View File

@ -12,36 +12,17 @@
#include "mozilla/dom/ChildIterator.h"
#include "mozilla/dom/Element.h"
using namespace mozilla;
using namespace mozilla::a11y;
////////////////////////////////////////////////////////////////////////////////
// WalkState
////////////////////////////////////////////////////////////////////////////////
namespace mozilla {
namespace a11y {
struct WalkState
{
WalkState(nsIContent *aContent, uint32_t aFilter) :
content(aContent), prevState(nullptr), iter(aContent, aFilter) {}
nsCOMPtr<nsIContent> content;
WalkState *prevState;
dom::AllChildrenIterator iter;
};
} // namespace a11y
} // namespace mozilla
////////////////////////////////////////////////////////////////////////////////
// TreeWalker
////////////////////////////////////////////////////////////////////////////////
TreeWalker::
TreeWalker(Accessible* aContext, nsIContent* aContent, uint32_t aFlags) :
mDoc(aContext->Document()), mContext(aContext),
mFlags(aFlags), mState(nullptr)
mDoc(aContext->Document()), mContext(aContext), mAnchorNode(aContent),
mFlags(aFlags)
{
NS_ASSERTION(aContent, "No node for the accessible tree walker!");
@ -50,17 +31,13 @@ TreeWalker::
mChildFilter |= nsIContent::eSkipPlaceholderContent;
if (aContent)
mState = new WalkState(aContent, mChildFilter);
PushState(aContent);
MOZ_COUNT_CTOR(TreeWalker);
}
TreeWalker::~TreeWalker()
{
// Clear state stack from memory
while (mState)
PopState();
MOZ_COUNT_DTOR(TreeWalker);
}
@ -68,74 +45,66 @@ TreeWalker::~TreeWalker()
// TreeWalker: private
Accessible*
TreeWalker::NextChildInternal(bool aNoWalkUp)
TreeWalker::NextChild()
{
if (!mState || !mState->content)
if (mStateStack.IsEmpty())
return nullptr;
while (nsIContent* childNode = mState->iter.GetNextChild()) {
bool isSubtreeHidden = false;
Accessible* accessible = mFlags & eWalkCache ?
mDoc->GetAccessible(childNode) :
GetAccService()->GetOrCreateAccessible(childNode, mContext,
&isSubtreeHidden);
dom::AllChildrenIterator* top = &mStateStack[mStateStack.Length() - 1];
while (top) {
while (nsIContent* childNode = top->GetNextChild()) {
bool isSubtreeHidden = false;
Accessible* accessible = mFlags & eWalkCache ?
mDoc->GetAccessible(childNode) :
GetAccService()->GetOrCreateAccessible(childNode, mContext,
&isSubtreeHidden);
if (accessible)
return accessible;
// Walk down into subtree to find accessibles.
if (!isSubtreeHidden && childNode->IsElement()) {
PushState(childNode);
accessible = NextChildInternal(true);
if (accessible)
return accessible;
// Walk down into subtree to find accessibles.
if (!isSubtreeHidden && childNode->IsElement())
top = PushState(childNode);
}
top = PopState();
}
// No more children, get back to the parent.
nsIContent* anchorNode = mState->content;
PopState();
if (aNoWalkUp)
return nullptr;
if (mState)
return NextChildInternal(false);
// If we traversed the whole subtree of the anchor node. Move to next node
// relative anchor node within the context subtree if possible.
if (mFlags != eWalkContextTree)
return nullptr;
while (anchorNode != mContext->GetNode()) {
nsINode* parentNode = anchorNode->GetFlattenedTreeParent();
nsINode* contextNode = mContext->GetNode();
while (mAnchorNode != contextNode) {
nsINode* parentNode = mAnchorNode->GetFlattenedTreeParent();
if (!parentNode || !parentNode->IsElement())
return nullptr;
PushState(parentNode->AsElement());
while (nsIContent* childNode = mState->iter.GetNextChild()) {
if (childNode == anchorNode)
return NextChildInternal(false);
nsIContent* parent = parentNode->AsElement();
top = mStateStack.AppendElement(dom::AllChildrenIterator(parent,
mChildFilter));
while (nsIContent* childNode = top->GetNextChild()) {
if (childNode == mAnchorNode) {
mAnchorNode = parent;
return NextChild();
}
}
PopState();
anchorNode = parentNode->AsElement();
// XXX We really should never get here, it means we're trying to find an
// accessible for a dom node where iterating over its parent's children
// doesn't return it. However this sometimes happens when we're asked for
// the nearest accessible to place holder content which we ignore.
mAnchorNode = parent;
}
return nullptr;
}
void
dom::AllChildrenIterator*
TreeWalker::PopState()
{
WalkState* prevToLastState = mState->prevState;
delete mState;
mState = prevToLastState;
}
void
TreeWalker::PushState(nsIContent* aContent)
{
WalkState* nextToLastState = new WalkState(aContent, mChildFilter);
nextToLastState->prevState = mState;
mState = nextToLastState;
size_t length = mStateStack.Length();
mStateStack.RemoveElementAt(length - 1);
return mStateStack.IsEmpty() ? nullptr : &mStateStack[mStateStack.Length() - 1];
}

View File

@ -8,6 +8,8 @@
#include "mozilla/Attributes.h"
#include <stdint.h>
#include "mozilla/dom/ChildIterator.h"
#include "nsCOMPtr.h"
class nsIContent;
@ -17,8 +19,6 @@ namespace a11y {
class Accessible;
class DocAccessible;
struct WalkState;
/**
* This class is used to walk the DOM tree to create accessible tree.
*/
@ -50,43 +50,36 @@ public:
* rejected during tree creation then the caller should be unbind it
* from the document.
*/
Accessible* NextChild()
{
return NextChildInternal(false);
}
Accessible* NextChild();
private:
TreeWalker();
TreeWalker(const TreeWalker&);
TreeWalker& operator =(const TreeWalker&);
/**
* Return the next child accessible.
*
* @param aNoWalkUp [in] specifies the walk direction, true means we
* shouldn't go up through the tree if we failed find
* accessible children.
*/
Accessible* NextChildInternal(bool aNoWalkUp);
/**
* Create new state for the given node and push it on top of stack.
*
* @note State stack is used to navigate up/down the DOM subtree during
* accessible children search.
*/
void PushState(nsIContent* aNode);
dom::AllChildrenIterator* PushState(nsIContent* aContent)
{
return mStateStack.AppendElement(dom::AllChildrenIterator(aContent,
mChildFilter));
}
/**
* Pop state from stack.
*/
void PopState();
dom::AllChildrenIterator* PopState();
DocAccessible* mDoc;
Accessible* mContext;
nsIContent* mAnchorNode;
nsAutoTArray<dom::AllChildrenIterator, 20> mStateStack;
int32_t mChildFilter;
uint32_t mFlags;
WalkState* mState;
};
} // namespace a11y

View File

@ -1743,10 +1743,11 @@ function textChangeChecker(aID, aStart, aEnd, aTextOrFunc, aIsInserted, aFromUse
/**
* Caret move events checker.
*/
function caretMoveChecker(aCaretOffset, aTargetOrFunc, aTargetFuncArg)
function caretMoveChecker(aCaretOffset, aTargetOrFunc, aTargetFuncArg,
aIsAsync)
{
this.__proto__ = new invokerChecker(EVENT_TEXT_CARET_MOVED,
aTargetOrFunc, aTargetFuncArg);
aTargetOrFunc, aTargetFuncArg, aIsAsync);
this.check = function caretMoveChecker_check(aEvent)
{
@ -1756,6 +1757,12 @@ function caretMoveChecker(aCaretOffset, aTargetOrFunc, aTargetFuncArg)
}
}
function asyncCaretMoveChecker(aCaretOffset, aTargetOrFunc, aTargetFuncArg)
{
this.__proto__ = new caretMoveChecker(aCaretOffset, aTargetOrFunc,
aTargetFuncArg, true);
}
/**
* Text selection change checker.
*/

View File

@ -46,6 +46,7 @@ skip-if = os == 'win' || os == 'linux'
[test_namechange.xul]
[test_namechange.html]
[test_scroll.xul]
[test_scroll_caret.xul]
[test_selection.html]
skip-if = buildapp == 'mulet'
[test_selection.xul]

View File

@ -119,5 +119,63 @@
text text text text text text text text text text text text text text <br>
text text text text text text text text text text text text text text <br>
</p>
<h1 id="heading_1">heading 1</h1>
<p style="color: blue">
text text text text text text text text text text text text text text <br>
text text text text text text text text text text text text text text <br>
text text text text text text text text text text text text text text <br>
text text text text text text text text text text text text text text <br>
text text text text text text text text text text text text text text <br>
text text text text text text text text text text text text text text <br>
text text text text text text text text text text text text text text <br>
text text text text text text text text text text text text text text <br>
text text text text text text text text text text text text text text <br>
text text text text text text text text text text text text text text <br>
text text text text text text text text text text text text text text <br>
text text text text text text text text text text text text text text <br>
text text text text text text text text text text text text text text <br>
text text text text text text text text text text text text text text <br>
text text text text text text text text text text text text text text <br>
text text text text text text text text text text text text text text <br>
text text text text text text text text text text text text text text <br>
text text text text text text text text text text text text text text <br>
text text text text text text text text text text text text text text <br>
text text text text text text text text text text text text text text <br>
text text text text text text text text text text text text text text <br>
text text text text text text text text text text text text text text <br>
text text text text text text text text text text text text text text <br>
text text text text text text text text text text text text text text <br>
text text text text text text text text text text text text text text <br>
text text text text text text text text text text text text text text <br>
text text text text text text text text text text text text text text <br>
text text text text text text text text text text text text text text <br>
text text text text text text text text text text text text text text <br>
text text text text text text text text text text text text text text <br>
text text text text text text text text text text text text text text <br>
text text text text text text text text text text text text text text <br>
text text text text text text text text text text text text text text <br>
text text text text text text text text text text text text text text <br>
text text text text text text text text text text text text text text <br>
text text text text text text text text text text text text text text <br>
text text text text text text text text text text text text text text <br>
text text text text text text text text text text text text text text <br>
text text text text text text text text text text text text text text <br>
text text text text text text text text text text text text text text <br>
text text text text text text text text text text text text text text <br>
text text text text text text text text text text text text text text <br>
text text text text text text text text text text text text text text <br>
text text text text text text text text text text text text text text <br>
text text text text text text text text text text text text text text <br>
text text text text text text text text text text text text text text <br>
text text text text text text text text text text text text text text <br>
text text text text text text text text text text text text text text <br>
text text text text text text text text text text text text text text <br>
text text text text text text text text text text text text text text <br>
text text text text text text text text text text text text text text <br>
text text text text text text text text text text text text text text <br>
text text text text text text text text text text text text text text <br>
text text text text text text text text text text text text text text <br>
</p>
</body>
<html>

View File

@ -0,0 +1,91 @@
<?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"?>
<window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
<script type="application/javascript"
src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js" />
<script type="application/javascript"
src="chrome://mochikit/content/chrome-harness.js"/>
<script type="application/javascript"
src="../common.js" />
<script type="application/javascript"
src="../role.js" />
<script type="application/javascript"
src="../states.js" />
<script type="application/javascript"
src="../events.js" />
<script type="application/javascript"
src="../browser.js"></script>
<script type="application/javascript">
<![CDATA[
////////////////////////////////////////////////////////////////////////////
// Tests
function getAnchorJumpInTabDocument(aTabIdx)
{
var tabDoc = aTabIdx ? tabDocumentAt(aTabIdx) : currentTabDocument();
return tabDoc.querySelector("h1[id='heading_1']");
}
function loadTab(aURL)
{
this.eventSeq = [
new asyncInvokerChecker(EVENT_DOCUMENT_LOAD_COMPLETE, currentTabDocument),
new asyncCaretMoveChecker(0, getAnchorJumpInTabDocument)
];
this.invoke = function loadTab_invoke()
{
tabBrowser().loadURI(aURL);
}
this.getID = function loadTab_getID()
{
return "load tab: " + aURL;
}
}
//gA11yEventDumpToConsole = true; // debug stuff
var gQueue = null;
function doTest()
{
gQueue = new eventQueue();
var url = "http://mochi.test:8888/a11y/accessible/tests/mochitest/events/scroll.html#heading_1";
gQueue.push(new loadTab(url));
gQueue.onFinish = function() { closeBrowserWindow(); }
gQueue.invoke(); // Will call SimpleTest.finish();
}
SimpleTest.waitForExplicitFinish();
openBrowserWindow(doTest);
]]>
</script>
<vbox flex="1" style="overflow: auto;">
<body xmlns="http://www.w3.org/1999/xhtml">
<a target="_blank"
href="https://bugzilla.mozilla.org/show_bug.cgi?id=1056459"
title="Make sure caret move event is fired when document receive focus">
Mozilla Bug 1056459
</a>
<p id="display"></p>
<div id="content" style="display: none">
</div>
<pre id="test">
</pre>
</body>
<vbox id="eventdump"></vbox>
</vbox>
</window>

View File

@ -92,6 +92,8 @@
testWordAt("div17", 3, "you", kOk);
testWordAt("div17", 4, "here", kTodo);
testWords("input_1", ["foo", "bar"]);
SimpleTest.finish();
}
@ -125,5 +127,7 @@
<div id="div16">3+4*5=23</div>
<div id="div17">Hello. Friend, are you here?!</div>
</pre>
<input id="input_1" type="text" value="foo bar" placeholder="something or other">
</body>
</html>

View File

@ -1,6 +1,3 @@
# 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/.
DIST_SUBDIR = 'browser'
export('DIST_SUBDIR')

View File

@ -70,12 +70,16 @@ ToolSidebar.prototype = {
let tab = this._tabbox.tabs.appendItem();
tab.setAttribute("label", ""); // Avoid showing "undefined" while the tab is loading
tab.setAttribute("id", "sidebar-tab-" + id);
let onIFrameLoaded = (event) => {
let doc = event.target;
let win = doc.defaultView;
tab.setAttribute("label", doc.title);
let onIFrameLoaded = () => {
tab.setAttribute("label", iframe.contentDocument.title);
iframe.removeEventListener("load", onIFrameLoaded, true);
if ("setPanel" in iframe.contentWindow) {
iframe.contentWindow.setPanel(this._toolPanel, iframe);
if ("setPanel" in win) {
win.setPanel(this._toolPanel, iframe);
}
this.emit(id + "-ready");
};
@ -109,6 +113,27 @@ ToolSidebar.prototype = {
this.emit("new-tab-registered", id);
},
/**
* Remove an existing tab.
*/
removeTab: function(id) {
let tab = this._tabbox.tabs.querySelector("tab#sidebar-tab-" + id);
if (!tab) {
return;
}
tab.remove();
let panel = this.getTab(id);
if (panel) {
panel.remove();
}
this._tabs.delete(id);
this.emit("tab-unregistered", id);
},
/**
* Select a specific tab.
*/

View File

@ -108,6 +108,7 @@ function test() {
for (let tab of tabs) {
is(tab.getAttribute("label"), label++, "Tab has the right title");
}
is(label, 4, "Found the right amount of tabs.");
is(panel.sidebar._tabbox.selectedPanel, panels[0], "First tab is selected");
ok(panel.sidebar.getCurrentTabID(), "tab1", "getCurrentTabID() is correct");
@ -119,13 +120,32 @@ function test() {
panel.sidebar.hide();
is(panel.sidebar._tabbox.getAttribute("hidden"), "true", "Sidebar hidden");
is(panel.sidebar.getWindowForTab("tab1").location.href, tab1URL, "Window is accessible");
testWidth(panel);
testRemoval(panel);
});
});
panel.sidebar.select("tab2");
}
function testRemoval(panel) {
panel.sidebar.once("tab-unregistered", function(event, id) {
info(event);
registeredTabs[id] = false;
is(id, "tab3", "The right tab must be removed");
let tabs = panel.sidebar._tabbox.querySelectorAll("tab");
let panels = panel.sidebar._tabbox.querySelectorAll("tabpanel");
is(tabs.length, 2, "There is the right number of tabs");
is(panels.length, 2, "There is the right number of panels");
testWidth(panel);
});
panel.sidebar.removeTab("tab3");
}
function testWidth(panel) {
let tabbox = panel.panelDoc.getElementById("sidebar");
tabbox.width = 420;

View File

@ -736,6 +736,19 @@ InspectorPanel.prototype = {
}
},
/**
* Show DOM properties
*/
showDOMProperties: function InspectorPanel_showDOMProperties() {
this._toolbox.openSplitConsole().then(() => {
let panel = this._toolbox.getPanel("webconsole");
let jsterm = panel.hud.jsterm;
jsterm.execute("inspect($0)");
jsterm.focusInput();
});
},
/**
* Clear any pseudo-class locks applied to the current hierarchy.
*/

View File

@ -55,6 +55,9 @@
<menuitem id="node-menu-copyimagedatauri"
label="&inspectorCopyImageDataUri.label;"
oncommand="inspector.copyImageDataUri()"/>
<menuitem id="node-menu-showdomproperties"
label="&inspectorShowDOMProperties.label;"
oncommand="inspector.showDOMProperties()"/>
<menuseparator/>
<menuitem id="node-menu-pasteouterhtml"
label="&inspectorHTMLPasteOuter.label;"

View File

@ -80,11 +80,12 @@ registerCleanupFunction(() => {
});
let test = asyncTest(function* () {
let { inspector } = yield openInspectorForURL(TEST_URL);
let { inspector, toolbox } = yield openInspectorForURL(TEST_URL);
yield testMenuItemSensitivity();
yield testPasteOuterHTMLMenuItemSensitivity();
yield testCopyMenuItems();
yield testShowDOMProperties();
yield testPasteOuterHTMLMenu();
yield testDeleteNode();
yield testDeleteRootNode();
@ -154,6 +155,27 @@ let test = asyncTest(function* () {
}
}
function* testShowDOMProperties() {
info("Testing 'Show DOM Properties' menu item.");
let showDOMPropertiesNode = inspector.panelDoc.getElementById("node-menu-showdomproperties");
ok(showDOMPropertiesNode, "the popup menu has a show dom properties item");
let consoleOpened = toolbox.once("webconsole-ready");
info("Triggering 'Show DOM Properties' and waiting for inspector open");
dispatchCommandEvent(showDOMPropertiesNode);
yield consoleOpened;
let webconsoleUI = toolbox.getPanel("webconsole").hud.ui;
let messagesAdded = webconsoleUI.once("messages-added");
yield messagesAdded;
info("Checking if 'inspect($0)' was evaluated");
ok(webconsoleUI.jsterm.history[0] === 'inspect($0)');
yield toolbox.toggleSplitConsole();
}
function* testPasteOuterHTMLMenu() {
info("Testing that 'Paste Outer HTML' menu item works.");
clipboard.set("this was pasted");

View File

@ -36,6 +36,9 @@
.html-editor-inner {
border: solid .1px;
flex: 1 1 main-size;
/* Keep the editor away from the markup view floating scrollbars */
-moz-margin-end: 12px;
}
.html-editor iframe {

View File

@ -22,3 +22,5 @@
<!ENTITY inspectorSearchHTML.key "F">
<!ENTITY inspectorCopyImageDataUri.label "Copy Image Data-URL">
<!ENTITY inspectorShowDOMProperties.label "Show DOM Properties">

View File

@ -413,6 +413,16 @@ case "$target" in
;;
esac
MOZ_ARG_ENABLE_BOOL(android-resource-constrained,
[ --enable-android-resource-constrained
exclude hi-res images and similar from the final APK],
MOZ_ANDROID_RESOURCE_CONSTRAINED=1)
if test -n "$MOZ_ANDROID_RESOURCE_CONSTRAINED"; then
AC_DEFINE(MOZ_ANDROID_RESOURCE_CONSTRAINED, $MOZ_ANDROID_RESOURCE_CONSTRAINED)
AC_SUBST(MOZ_ANDROID_RESOURCE_CONSTRAINED)
fi
MOZ_ARG_WITH_STRING(android-min-sdk,
[ --with-android-min-sdk=[VER] Impose a minimum Firefox for Android SDK version],
[ MOZ_ANDROID_MIN_SDK_VERSION=$withval ])
@ -433,10 +443,12 @@ if test -n "$MOZ_ANDROID_MIN_SDK_VERSION"; then
fi
AC_DEFINE_UNQUOTED(MOZ_ANDROID_MIN_SDK_VERSION, $MOZ_ANDROID_MIN_SDK_VERSION)
AC_SUBST(MOZ_ANDROID_MIN_SDK_VERSION)
fi
if test -n "$MOZ_ANDROID_MAX_SDK_VERSION"; then
AC_DEFINE_UNQUOTED(MOZ_ANDROID_MAX_SDK_VERSION, $MOZ_ANDROID_MAX_SDK_VERSION)
AC_SUBST(MOZ_ANDROID_MAX_SDK_VERSION)
fi
])

View File

@ -684,7 +684,7 @@ class Automation(object):
import fix_stack_using_bpsyms as stackFixerModule
stackFixerFunction = lambda line: stackFixerModule.fixSymbols(line, symbolsPath)
del sys.path[0]
elif self.IS_DEBUG_BUILD and self.IS_MAC and False:
elif self.IS_DEBUG_BUILD and self.IS_MAC:
# Run each line through a function in fix_macosx_stack.py (uses atos)
sys.path.insert(0, utilityPath)
import fix_macosx_stack as stackFixerModule

View File

@ -1426,7 +1426,15 @@ nsScriptSecurityManager::AddSitesToFileURIWhitelist(const nsCString& aSiteList)
{
// Grab the current site.
bound = SkipUntil<IsWhitespace>(aSiteList, base);
auto site = Substring(aSiteList, base, bound - base);
nsAutoCString site(Substring(aSiteList, base, bound - base));
// Check if the URI is schemeless. If so, add both http and https.
nsAutoCString unused;
if (NS_FAILED(sIOService->ExtractScheme(site, unused))) {
AddSitesToFileURIWhitelist(NS_LITERAL_CSTRING("http://") + site);
AddSitesToFileURIWhitelist(NS_LITERAL_CSTRING("https://") + site);
return;
}
// Convert it to a URI and add it to our list.
nsCOMPtr<nsIURI> uri;

View File

@ -82,11 +82,13 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=995943
pushPrefs.bind(null, [['capability.policy.policynames', ',somepolicy, someotherpolicy, '],
['capability.policy.somepolicy.checkloaduri.enabled', 'allaccess'],
['capability.policy.someotherpolicy.checkloaduri.enabled', 'nope'],
['capability.policy.somepolicy.sites', ' http://example.org https://example.com'],
['capability.policy.somepolicy.sites', ' http://example.org https://example.com test1.example.com'],
['capability.policy.someotherpolicy.sites', 'http://example.net ']]))
.then(checkLoadFileURI.bind(null, 'http://example.org', true))
.then(checkLoadFileURI.bind(null, 'http://example.com', false))
.then(checkLoadFileURI.bind(null, 'http://example.net', false))
.then(checkLoadFileURI.bind(null, 'http://test1.example.com', true))
.then(checkLoadFileURI.bind(null, 'https://test1.example.com', true))
.then(pushPrefs.bind(null, [['capability.policy.someotherpolicy.checkloaduri.enabled', 'allAccess']]))
.then(checkLoadFileURI.bind(null, 'http://example.net', true))
.then(popPrefs)

View File

@ -574,6 +574,10 @@ def tarjan(V, E):
def main():
# Suppress the build time check if MOZ_NO_BUILD_TIME_SM_CHECKS is set.
if "MOZ_NO_BUILD_TIME_SM_CHECKS" in os.environ:
sys.exit(0)
ok = check_style()
if ok:

View File

@ -983,6 +983,62 @@ public:
*/
nsresult SetBoolAttr(nsIAtom* aAttr, bool aValue);
/**
* Helper method for NS_IMPL_ENUM_ATTR_DEFAULT_VALUE.
* Gets the enum value string of an attribute and using a default value if
* the attribute is missing or the string is an invalid enum value.
*
* @param aType the name of the attribute.
* @param aDefault the default value if the attribute is missing or invalid.
* @param aResult string corresponding to the value [out].
*/
void GetEnumAttr(nsIAtom* aAttr,
const char* aDefault,
nsAString& aResult) const;
/**
* Helper method for NS_IMPL_ENUM_ATTR_DEFAULT_MISSING_INVALID_VALUES.
* Gets the enum value string of an attribute and using the default missing
* value if the attribute is missing or the default invalid value if the
* string is an invalid enum value.
*
* @param aType the name of the attribute.
* @param aDefaultMissing the default value if the attribute is missing. If
null and the attribute is missing, aResult will be
set to the null DOMString; this only matters for
cases in which we're reflecting a nullable string.
* @param aDefaultInvalid the default value if the attribute is invalid.
* @param aResult string corresponding to the value [out].
*/
void GetEnumAttr(nsIAtom* aAttr,
const char* aDefaultMissing,
const char* aDefaultInvalid,
nsAString& aResult) const;
/**
* Unset an attribute.
*/
void UnsetAttr(nsIAtom* aAttr, ErrorResult& aError)
{
aError = UnsetAttr(kNameSpaceID_None, aAttr, true);
}
/**
* Set an attribute in the simplest way possible.
*/
void SetAttr(nsIAtom* aAttr, const nsAString& aValue, ErrorResult& aError)
{
aError = SetAttr(kNameSpaceID_None, aAttr, aValue, true);
}
/**
* Set a content attribute via a reflecting nullable string IDL
* attribute (e.g. a CORS attribute). If DOMStringIsNull(aValue),
* this will actually remove the content attribute.
*/
void SetOrRemoveNullableStringAttr(nsIAtom* aName, const nsAString& aValue,
ErrorResult& aError);
/**
* Retrieve the ratio of font-size-inflated text font size to computed font
* size for this element. This will query the element for its primary frame,

View File

@ -2349,8 +2349,6 @@ public:
virtual nsHTMLDocument* AsHTMLDocument() { return nullptr; }
virtual mozilla::dom::SVGDocument* AsSVGDocument() { return nullptr; }
virtual JSObject* WrapObject(JSContext *aCx) MOZ_OVERRIDE;
// Each import tree has exactly one master document which is
// the root of the tree, and owns the browser context.
virtual already_AddRefed<nsIDocument> MasterDocument() = 0;

View File

@ -3107,6 +3107,50 @@ Element::SetBoolAttr(nsIAtom* aAttr, bool aValue)
return UnsetAttr(kNameSpaceID_None, aAttr, true);
}
void
Element::GetEnumAttr(nsIAtom* aAttr,
const char* aDefault,
nsAString& aResult) const
{
GetEnumAttr(aAttr, aDefault, aDefault, aResult);
}
void
Element::GetEnumAttr(nsIAtom* aAttr,
const char* aDefaultMissing,
const char* aDefaultInvalid,
nsAString& aResult) const
{
const nsAttrValue* attrVal = mAttrsAndChildren.GetAttr(aAttr);
aResult.Truncate();
if (!attrVal) {
if (aDefaultMissing) {
AppendASCIItoUTF16(nsDependentCString(aDefaultMissing), aResult);
} else {
SetDOMStringToNull(aResult);
}
} else {
if (attrVal->Type() == nsAttrValue::eEnum) {
attrVal->GetEnumString(aResult, true);
} else if (aDefaultInvalid) {
AppendASCIItoUTF16(nsDependentCString(aDefaultInvalid), aResult);
}
}
}
void
Element::SetOrRemoveNullableStringAttr(nsIAtom* aName, const nsAString& aValue,
ErrorResult& aError)
{
if (DOMStringIsNull(aValue)) {
UnsetAttr(aName, aError);
} else {
SetAttr(aName, aValue, aError);
}
}
Directionality
Element::GetComputedDirectionality() const
{

View File

@ -150,6 +150,9 @@
#include "nsHtml5TreeOpExecutor.h"
#include "mozilla/dom/HTMLLinkElement.h"
#include "mozilla/dom/HTMLMediaElement.h"
#ifdef MOZ_MEDIA_NAVIGATOR
#include "mozilla/MediaManager.h"
#endif // MOZ_MEDIA_NAVIGATOR
#ifdef MOZ_WEBRTC
#include "IPeerConnection.h"
#endif // MOZ_WEBRTC
@ -8503,6 +8506,14 @@ nsDocument::CanSavePresentation(nsIRequest *aNewRequest)
return false;
}
#ifdef MOZ_MEDIA_NAVIGATOR
// Check if we have active GetUserMedia use
if (MediaManager::Exists() && win &&
MediaManager::Get()->IsWindowStillActive(win->WindowID())) {
return false;
}
#endif // MOZ_MEDIA_NAVIGATOR
#ifdef MOZ_WEBRTC
// Check if we have active PeerConnections
nsCOMPtr<IPeerConnectionManager> pcManager =
@ -12258,54 +12269,6 @@ nsDocument::Evaluate(const nsAString& aExpression, nsIDOMNode* aContextNode,
aInResult, aResult);
}
// This is just a hack around the fact that window.document is not
// [Unforgeable] yet.
JSObject*
nsIDocument::WrapObject(JSContext *aCx)
{
MOZ_ASSERT(IsDOMBinding());
JS::Rooted<JSObject*> obj(aCx, nsINode::WrapObject(aCx));
if (!obj) {
return nullptr;
}
nsCOMPtr<nsPIDOMWindow> win = do_QueryInterface(GetInnerWindow());
if (!win ||
static_cast<nsGlobalWindow*>(win.get())->IsDOMBinding()) {
// No window or window on new DOM binding, nothing else to do here.
return obj;
}
if (this != win->GetExtantDoc()) {
// We're not the current document; we're also done here
return obj;
}
JSAutoCompartment ac(aCx, obj);
JS::Rooted<JS::Value> winVal(aCx);
nsresult rv = nsContentUtils::WrapNative(aCx, win, &NS_GET_IID(nsIDOMWindow),
&winVal,
false);
if (NS_FAILED(rv)) {
Throw(aCx, rv);
return nullptr;
}
NS_NAMED_LITERAL_STRING(doc_str, "document");
JS::Rooted<JSObject*> winObj(aCx, &winVal.toObject());
if (!JS_DefineUCProperty(aCx, winObj, doc_str.get(),
doc_str.Length(), obj,
JSPROP_READONLY | JSPROP_ENUMERATE,
JS_PropertyStub, JS_StrictPropertyStub)) {
return nullptr;
}
return obj;
}
XPathEvaluator*
nsIDocument::XPathEvaluator()
{

View File

@ -64,7 +64,6 @@
#include "mozilla/MemoryReporting.h"
#include "mozilla/dom/DOMImplementation.h"
#include "mozilla/dom/StyleSheetList.h"
#include "nsIDOMTouchEvent.h"
#include "nsDataHashtable.h"
#include "mozilla/TimeStamp.h"
#include "mozilla/Attributes.h"

View File

@ -363,10 +363,16 @@ public:
// XPCOM GetCurrentSrc() is OK
// XPCOM GetCrossorigin() is OK
void SetCrossOrigin(const nsAString& aValue, ErrorResult& aRv)
void GetCrossOrigin(nsAString& aResult)
{
SetHTMLAttr(nsGkAtoms::crossorigin, aValue, aRv);
// Null for both missing and invalid defaults is ok, since we
// always parse to an enum value, so we don't need an invalid
// default, and we _want_ the missing default to be null.
GetEnumAttr(nsGkAtoms::crossorigin, nullptr, aResult);
}
void SetCrossOrigin(const nsAString& aCrossOrigin, ErrorResult& aError)
{
SetOrRemoveNullableStringAttr(nsGkAtoms::crossorigin, aCrossOrigin, aError);
}
uint16_t NetworkState() const

View File

@ -151,11 +151,6 @@ HTMLImageElement::SetItemValueText(const nsAString& aValue)
SetSrc(aValue);
}
// crossorigin is not "limited to only known values" per spec, so it's
// just a string attr purposes of the DOM crossOrigin property.
// TODO: It is now (bug 880997).
NS_IMPL_STRING_ATTR(HTMLImageElement, CrossOrigin, crossorigin)
bool
HTMLImageElement::Draggable() const
{

View File

@ -142,9 +142,16 @@ public:
{
SetHTMLAttr(nsGkAtoms::srcset, aSrcset, aError);
}
void GetCrossOrigin(nsAString& aResult)
{
// Null for both missing and invalid defaults is ok, since we
// always parse to an enum value, so we don't need an invalid
// default, and we _want_ the missing default to be null.
GetEnumAttr(nsGkAtoms::crossorigin, nullptr, aResult);
}
void SetCrossOrigin(const nsAString& aCrossOrigin, ErrorResult& aError)
{
SetHTMLAttr(nsGkAtoms::crossorigin, aCrossOrigin, aError);
SetOrRemoveNullableStringAttr(nsGkAtoms::crossorigin, aCrossOrigin, aError);
}
void SetUseMap(const nsAString& aUseMap, ErrorResult& aError)
{

View File

@ -117,7 +117,6 @@ NS_IMPL_STRING_ATTR(HTMLLinkElement, Rel, rel)
NS_IMPL_STRING_ATTR(HTMLLinkElement, Rev, rev)
NS_IMPL_STRING_ATTR(HTMLLinkElement, Target, target)
NS_IMPL_STRING_ATTR(HTMLLinkElement, Type, type)
NS_IMPL_STRING_ATTR(HTMLLinkElement, CrossOrigin, crossorigin)
void
HTMLLinkElement::GetItemValueText(nsAString& aValue)

View File

@ -90,10 +90,16 @@ public:
{
SetHTMLAttr(nsGkAtoms::href, aHref, aRv);
}
// XPCOM GetCrossOrigin is fine.
void SetCrossOrigin(const nsAString& aCrossOrigin, ErrorResult& aRv)
void GetCrossOrigin(nsAString& aResult)
{
SetHTMLAttr(nsGkAtoms::crossorigin, aCrossOrigin, aRv);
// Null for both missing and invalid defaults is ok, since we
// always parse to an enum value, so we don't need an invalid
// default, and we _want_ the missing default to be null.
GetEnumAttr(nsGkAtoms::crossorigin, nullptr, aResult);
}
void SetCrossOrigin(const nsAString& aCrossOrigin, ErrorResult& aError)
{
SetOrRemoveNullableStringAttr(nsGkAtoms::crossorigin, aCrossOrigin, aError);
}
// XPCOM GetRel is fine.
void SetRel(const nsAString& aRel, ErrorResult& aRv)

View File

@ -470,7 +470,6 @@ NS_INTERFACE_MAP_END_INHERITING(nsGenericHTMLElement)
// nsIDOMHTMLMediaElement
NS_IMPL_URI_ATTR(HTMLMediaElement, Src, src)
NS_IMPL_STRING_ATTR(HTMLMediaElement, CrossOrigin, crossorigin)
NS_IMPL_BOOL_ATTR(HTMLMediaElement, Controls, controls)
NS_IMPL_BOOL_ATTR(HTMLMediaElement, Autoplay, autoplay)
NS_IMPL_BOOL_ATTR(HTMLMediaElement, Loop, loop)

View File

@ -137,7 +137,6 @@ NS_IMPL_URI_ATTR(HTMLScriptElement, Src, src)
NS_IMPL_STRING_ATTR(HTMLScriptElement, Type, type)
NS_IMPL_STRING_ATTR(HTMLScriptElement, HtmlFor, _for)
NS_IMPL_STRING_ATTR(HTMLScriptElement, Event, event)
NS_IMPL_STRING_ATTR(HTMLScriptElement, CrossOrigin, crossorigin)
void
HTMLScriptElement::SetCharset(const nsAString& aCharset, ErrorResult& rv)
@ -181,12 +180,6 @@ HTMLScriptElement::SetEvent(const nsAString& aEvent, ErrorResult& rv)
SetHTMLAttr(nsGkAtoms::event, aEvent, rv);
}
void
HTMLScriptElement::SetCrossOrigin(const nsAString& aCrossOrigin, ErrorResult& rv)
{
SetHTMLAttr(nsGkAtoms::crossorigin, aCrossOrigin, rv);
}
nsresult
HTMLScriptElement::GetAsync(bool* aValue)
{

View File

@ -68,7 +68,17 @@ public:
void SetType(const nsAString& aType, ErrorResult& rv);
void SetHtmlFor(const nsAString& aHtmlFor, ErrorResult& rv);
void SetEvent(const nsAString& aEvent, ErrorResult& rv);
void SetCrossOrigin(const nsAString& aCrossOrigin, ErrorResult& rv);
void GetCrossOrigin(nsAString& aResult)
{
// Null for both missing and invalid defaults is ok, since we
// always parse to an enum value, so we don't need an invalid
// default, and we _want_ the missing default to be null.
GetEnumAttr(nsGkAtoms::crossorigin, nullptr, aResult);
}
void SetCrossOrigin(const nsAString& aCrossOrigin, ErrorResult& aError)
{
SetOrRemoveNullableStringAttr(nsGkAtoms::crossorigin, aCrossOrigin, aError);
}
bool Async();
void SetAsync(bool aValue, ErrorResult& rv);

View File

@ -347,7 +347,7 @@ nsGenericHTMLElement::GetOffsetRect(CSSIntRect& aRect)
}
nsIContent* offsetParent = nullptr;
Element* docElement = GetCurrentDoc()->GetRootElement();
Element* docElement = GetComposedDoc()->GetRootElement();
nsIContent* content = frame->GetContent();
if (content && (content->IsHTML(nsGkAtoms::body) || content == docElement)) {
@ -398,7 +398,7 @@ nsGenericHTMLElement::GetOffsetRect(CSSIntRect& aRect)
// parent chain. We want the offset parent in this case to be
// the body, so we just get the body element from the document.
nsCOMPtr<nsIDOMHTMLDocument> html_doc(do_QueryInterface(GetCurrentDoc()));
nsCOMPtr<nsIDOMHTMLDocument> html_doc(do_QueryInterface(GetComposedDoc()));
if (html_doc) {
offsetParent = static_cast<nsHTMLDocument*>(html_doc.get())->GetBody();
@ -1766,37 +1766,6 @@ nsGenericHTMLElement::GetURIListAttr(nsIAtom* aAttr, nsAString& aResult)
return NS_OK;
}
void
nsGenericHTMLElement::GetEnumAttr(nsIAtom* aAttr,
const char* aDefault,
nsAString& aResult) const
{
GetEnumAttr(aAttr, aDefault, aDefault, aResult);
}
void
nsGenericHTMLElement::GetEnumAttr(nsIAtom* aAttr,
const char* aDefaultMissing,
const char* aDefaultInvalid,
nsAString& aResult) const
{
const nsAttrValue* attrVal = mAttrsAndChildren.GetAttr(aAttr);
aResult.Truncate();
if (!attrVal) {
if (aDefaultMissing) {
AppendASCIItoUTF16(nsDependentCString(aDefaultMissing), aResult);
}
} else {
if (attrVal->Type() == nsAttrValue::eEnum) {
attrVal->GetEnumString(aResult, true);
} else if (aDefaultInvalid) {
AppendASCIItoUTF16(nsDependentCString(aDefaultInvalid), aResult);
}
}
}
HTMLMenuElement*
nsGenericHTMLElement::GetContextMenu() const
{

View File

@ -1011,11 +1011,11 @@ protected:
}
void SetHTMLAttr(nsIAtom* aName, const nsAString& aValue, mozilla::ErrorResult& aError)
{
aError = SetAttr(kNameSpaceID_None, aName, aValue, true);
mozilla::dom::Element::SetAttr(aName, aValue, aError);
}
void UnsetHTMLAttr(nsIAtom* aName, mozilla::ErrorResult& aError)
{
aError = UnsetAttr(kNameSpaceID_None, aName, true);
mozilla::dom::Element::UnsetAttr(aName, aError);
}
void SetHTMLBoolAttr(nsIAtom* aName, bool aValue, mozilla::ErrorResult& aError)
{
@ -1122,35 +1122,6 @@ protected:
*/
nsresult GetURIListAttr(nsIAtom* aAttr, nsAString& aResult);
/**
* Helper method for NS_IMPL_ENUM_ATTR_DEFAULT_VALUE.
* Gets the enum value string of an attribute and using a default value if
* the attribute is missing or the string is an invalid enum value.
*
* @param aType the name of the attribute.
* @param aDefault the default value if the attribute is missing or invalid.
* @param aResult string corresponding to the value [out].
*/
void GetEnumAttr(nsIAtom* aAttr,
const char* aDefault,
nsAString& aResult) const;
/**
* Helper method for NS_IMPL_ENUM_ATTR_DEFAULT_MISSING_INVALID_VALUES.
* Gets the enum value string of an attribute and using the default missing
* value if the attribute is missing or the default invalid value if the
* string is an invalid enum value.
*
* @param aType the name of the attribute.
* @param aDefaultMissing the default value if the attribute is missing.
* @param aDefaultInvalid the default value if the attribute is invalid.
* @param aResult string corresponding to the value [out].
*/
void GetEnumAttr(nsIAtom* aAttr,
const char* aDefaultMissing,
const char* aDefaultInvalid,
nsAString& aResult) const;
/**
* Locates the nsIEditor associated with this node. In general this is
* equivalent to GetEditorInternal(), but for designmode or contenteditable,

View File

@ -248,6 +248,7 @@ function reflectUnsignedInt(aParameters)
* OR
* defaultValue Object [optional] object containing two attributes, 'invalid' and 'missing'
* - unsupportedValues Array [optional] valid values we do not support
* - nullable boolean [optional] whether the attribute is nullable
*/
function reflectLimitedEnumerated(aParameters)
{
@ -266,60 +267,73 @@ function reflectLimitedEnumerated(aParameters)
? aParameters.defaultValue : aParameters.defaultValue.missing
var unsupportedValues = aParameters.unsupportedValues !== undefined
? aParameters.unsupportedValues : [];
var nullable = aParameters.nullable;
ok(idlAttr in element, idlAttr + " should be an IDL attribute of this element");
is(typeof element[idlAttr], "string", "'" + idlAttr + "' IDL attribute should be a string");
if (nullable) {
// The missing value default is null, which is typeof == "object"
is(typeof element[idlAttr], "object", "'" + idlAttr + "' IDL attribute should be null, which has typeof == object");
ise(element[idlAttr], null, "'" + idlAttr + "' IDL attribute should be null");
} else {
is(typeof element[idlAttr], "string", "'" + idlAttr + "' IDL attribute should be a string");
}
if (nullable) {
element.setAttribute(contentAttr, "something");
// Now it will be a string
is(typeof element[idlAttr], "string", "'" + idlAttr + "' IDL attribute should be a string");
}
// Explicitly check the default value.
element.removeAttribute(contentAttr);
is(element[idlAttr], defaultValueMissing,
"When no attribute is set, the value should be the default value.");
ise(element[idlAttr], defaultValueMissing,
"When no attribute is set, the value should be the default value.");
// Check valid values.
validValues.forEach(function (v) {
element.setAttribute(contentAttr, v);
is(element[idlAttr], v,
v + " should be accepted as a valid value for " + idlAttr);
is(element.getAttribute(contentAttr), v,
"Content attribute should return the value it has been set to.");
ise(element[idlAttr], v,
"'" + v + "' should be accepted as a valid value for " + idlAttr);
ise(element.getAttribute(contentAttr), v,
"Content attribute should return the value it has been set to.");
element.removeAttribute(contentAttr);
element.setAttribute(contentAttr, v.toUpperCase());
is(element[idlAttr], v,
"Enumerated attributes should be case-insensitive.");
is(element.getAttribute(contentAttr), v.toUpperCase(),
"Content attribute should not be lower-cased.");
ise(element[idlAttr], v,
"Enumerated attributes should be case-insensitive.");
ise(element.getAttribute(contentAttr), v.toUpperCase(),
"Content attribute should not be lower-cased.");
element.removeAttribute(contentAttr);
element[idlAttr] = v;
is(element[idlAttr], v,
v + " should be accepted as a valid value for " + idlAttr);
is(element.getAttribute(contentAttr), v,
"Content attribute should return the value it has been set to.");
ise(element[idlAttr], v,
"'" + v + "' should be accepted as a valid value for " + idlAttr);
ise(element.getAttribute(contentAttr), v,
"Content attribute should return the value it has been set to.");
element.removeAttribute(contentAttr);
element[idlAttr] = v.toUpperCase();
is(element[idlAttr], v,
"Enumerated attributes should be case-insensitive.");
is(element.getAttribute(contentAttr), v.toUpperCase(),
"Content attribute should not be lower-cased.");
ise(element[idlAttr], v,
"Enumerated attributes should be case-insensitive.");
ise(element.getAttribute(contentAttr), v.toUpperCase(),
"Content attribute should not be lower-cased.");
element.removeAttribute(contentAttr);
});
// Check invalid values.
invalidValues.forEach(function (v) {
element.setAttribute(contentAttr, v);
is(element[idlAttr], defaultValueInvalid,
"When the content attribute is set to an invalid value, the default value should be returned.");
is(element.getAttribute(contentAttr), v,
"Content attribute should not have been changed.");
ise(element[idlAttr], defaultValueInvalid,
"When the content attribute is set to an invalid value, the default value should be returned.");
ise(element.getAttribute(contentAttr), v,
"Content attribute should not have been changed.");
element.removeAttribute(contentAttr);
element[idlAttr] = v;
is(element[idlAttr], defaultValueInvalid,
"When the value is set to an invalid value, the default value should be returned.");
is(element.getAttribute(contentAttr), v,
"Content attribute should not have been changed.");
ise(element[idlAttr], defaultValueInvalid,
"When the value is set to an invalid value, the default value should be returned.");
ise(element.getAttribute(contentAttr), v,
"Content attribute should not have been changed.");
element.removeAttribute(contentAttr);
});
@ -328,7 +342,7 @@ function reflectLimitedEnumerated(aParameters)
unsupportedValues.forEach(function (v) {
element.setAttribute(contentAttr, v);
todo_is(element[idlAttr], v,
v + " should be accepted as a valid value for " + idlAttr);
"'" + v + "' should be accepted as a valid value for " + idlAttr);
is(element.getAttribute(contentAttr), v,
"Content attribute should return the value it has been set to.");
element.removeAttribute(contentAttr);
@ -342,7 +356,7 @@ function reflectLimitedEnumerated(aParameters)
element[idlAttr] = v;
todo_is(element[idlAttr], v,
v + " should be accepted as a valid value for " + idlAttr);
"'" + v + "' should be accepted as a valid value for " + idlAttr);
is(element.getAttribute(contentAttr), v,
"Content attribute should return the value it has been set to.");
element.removeAttribute(contentAttr);
@ -354,6 +368,18 @@ function reflectLimitedEnumerated(aParameters)
"Content attribute should not be lower-cased.");
element.removeAttribute(contentAttr);
});
if (nullable) {
ise(defaultValueMissing, null,
"Missing default value should be null for nullable attributes");
ok(validValues.length > 0, "We better have at least one valid value");
element.setAttribute(contentAttr, validValues[0]);
ok(element.hasAttribute(contentAttr),
"Should have content attribute: we just set it");
element[idlAttr] = null;
ok(!element.hasAttribute(contentAttr),
"Should have removed content attribute");
}
}
/**

View File

@ -24,10 +24,17 @@ var els = [ document.createElement("script"),
document.createElementNS("http://www.w3.org/2000/svg", "script") ]
for (var i = 0; i < els.length; ++i) {
reflectString({
reflectLimitedEnumerated({
element: els[i],
attribute: { content: "crossorigin", idl: "crossOrigin" },
otherValues: [ "anonymous", "use-credentials" ]
// "" is a valid value per spec, but gets mapped to the "anonymous" state,
// just like invalid values, so just list it under invalidValues
validValues: [ "anonymous", "use-credentials" ],
invalidValues: [
"", " aNOnYmous ", " UsE-CreDEntIALS ", "foobar", "FOOBAR", " fOoBaR "
],
defaultValue: { invalid: "anonymous", missing: null },
nullable: true,
})
}

View File

@ -26,15 +26,17 @@ reflectURL({
todo("srcset" in document.createElement("img"), "Should implement srcset")
// TODO: Bug 880997 - Make crossOrigin a limited enumerated attribute.
reflectString({
reflectLimitedEnumerated({
element: document.createElement("img"),
attribute: "crossOrigin",
otherValues: [
"", "anonymous", "ANONYMOUS", " aNOnYmous ",
"use-credentials", "USE-CREDENTIALS", " UsE-CreDEntIALS ",
"foobar", "FOOBAR", " fOoBaR "
]
// "" is a valid value per spec, but gets mapped to the "anonymous" state,
// just like invalid values, so just list it under invalidValues
validValues: [ "anonymous", "use-credentials" ],
invalidValues: [
"", " aNOnYmous ", " UsE-CreDEntIALS ", "foobar", "FOOBAR", " fOoBaR "
],
defaultValue: { invalid: "anonymous", missing: null },
nullable: true,
})
reflectString({

View File

@ -21,12 +21,19 @@ reflectURL({
attribute: "href",
});
// .crossOrigin (String)
reflectString({
// .crossOrigin (String or null)
reflectLimitedEnumerated({
element: document.createElement("link"),
attribute: "crossOrigin",
otherValues: ["anonymous", "use-credentials"],
});
// "" is a valid value per spec, but gets mapped to the "anonymous" state,
// just like invalid values, so just list it under invalidValues
validValues: [ "anonymous", "use-credentials" ],
invalidValues: [
"", " aNOnYmous ", " UsE-CreDEntIALS ", "foobar", "FOOBAR", " fOoBaR "
],
defaultValue: { invalid: "anonymous", missing: null },
nullable: true,
})
// .rel (String)
reflectString({

View File

@ -168,9 +168,10 @@ static const int32_t MAX_VIDEO_HEIGHT = 3000;
void ScaleDisplayByAspectRatio(nsIntSize& aDisplay, float aAspectRatio);
// The amount of virtual memory reserved for thread stacks.
#if (defined(XP_WIN) || defined(XP_MACOSX) || defined(LINUX)) && \
!defined(MOZ_ASAN)
#if (defined(XP_WIN) || defined(LINUX)) && !defined(MOZ_ASAN)
#define MEDIA_THREAD_STACK_SIZE (128 * 1024)
#elif defined(XP_MACOSX) && !defined(MOZ_ASAN)
#define MEDIA_THREAD_STACK_SIZE (256 * 1024)
#else
// All other platforms use their system defaults.
#define MEDIA_THREAD_STACK_SIZE nsIThreadManager::DEFAULT_STACK_SIZE

View File

@ -64,7 +64,10 @@ public:
{
return &mRef;
}
private:
// Copy operator isn't supported and is not implemented.
AutoCFRelease<T>& operator=(const AutoCFRelease<T>&);
T mRef;
};

View File

@ -6,17 +6,19 @@
#include <CoreFoundation/CFString.h>
#include "AppleCMLinker.h"
#include "AppleUtils.h"
#include "AppleVTDecoder.h"
#include "AppleVTLinker.h"
#include "mp4_demuxer/DecoderData.h"
#include "MP4Reader.h"
#include "MP4Decoder.h"
#include "MediaData.h"
#include "MacIOSurfaceImage.h"
#include "mozilla/ArrayUtils.h"
#include "nsAutoPtr.h"
#include "nsThreadUtils.h"
#include "AppleCMLinker.h"
#include "AppleVTDecoder.h"
#include "AppleVTLinker.h"
#include "prlog.h"
#include "MediaData.h"
#include "VideoUtils.h"
#ifdef PR_LOGGING
@ -238,81 +240,34 @@ nsresult
AppleVTDecoder::OutputFrame(CVPixelBufferRef aImage,
nsAutoPtr<FrameRef> aFrameRef)
{
size_t width = CVPixelBufferGetWidth(aImage);
size_t height = CVPixelBufferGetHeight(aImage);
LOG(" got decoded frame data... %ux%u %s", width, height,
CVPixelBufferIsPlanar(aImage) ? "planar" : "chunked");
#ifdef DEBUG
size_t planes = CVPixelBufferGetPlaneCount(aImage);
for (size_t i = 0; i < planes; ++i) {
size_t stride = CVPixelBufferGetBytesPerRowOfPlane(aImage, i);
LOG(" plane %u %ux%u rowbytes %u",
(unsigned)i,
CVPixelBufferGetWidthOfPlane(aImage, i),
CVPixelBufferGetHeightOfPlane(aImage, i),
(unsigned)stride);
}
MOZ_ASSERT(planes == 2);
#endif // DEBUG
VideoData::YCbCrBuffer buffer;
// Lock the returned image data.
CVReturn rv = CVPixelBufferLockBaseAddress(aImage, kCVPixelBufferLock_ReadOnly);
if (rv != kCVReturnSuccess) {
NS_ERROR("error locking pixel data");
mCallback->Error();
return NS_ERROR_FAILURE;
}
// Y plane.
buffer.mPlanes[0].mData =
static_cast<uint8_t*>(CVPixelBufferGetBaseAddressOfPlane(aImage, 0));
buffer.mPlanes[0].mStride = CVPixelBufferGetBytesPerRowOfPlane(aImage, 0);
buffer.mPlanes[0].mWidth = width;
buffer.mPlanes[0].mHeight = height;
buffer.mPlanes[0].mOffset = 0;
buffer.mPlanes[0].mSkip = 0;
// Cb plane.
buffer.mPlanes[1].mData =
static_cast<uint8_t*>(CVPixelBufferGetBaseAddressOfPlane(aImage, 1));
buffer.mPlanes[1].mStride = CVPixelBufferGetBytesPerRowOfPlane(aImage, 1);
buffer.mPlanes[1].mWidth = (width+1) / 2;
buffer.mPlanes[1].mHeight = (height+1) / 2;
buffer.mPlanes[1].mOffset = 0;
buffer.mPlanes[1].mSkip = 1;
// Cr plane.
buffer.mPlanes[2].mData =
static_cast<uint8_t*>(CVPixelBufferGetBaseAddressOfPlane(aImage, 1));
buffer.mPlanes[2].mStride = CVPixelBufferGetBytesPerRowOfPlane(aImage, 1);
buffer.mPlanes[2].mWidth = (width+1) / 2;
buffer.mPlanes[2].mHeight = (height+1) / 2;
buffer.mPlanes[2].mOffset = 1;
buffer.mPlanes[2].mSkip = 1;
IOSurfacePtr surface = MacIOSurfaceLib::CVPixelBufferGetIOSurface(aImage);
MOZ_ASSERT(surface, "VideoToolbox didn't return an IOSurface backed buffer");
nsRefPtr<MacIOSurface> macSurface = new MacIOSurface(surface);
// Bounds.
VideoInfo info;
info.mDisplay = nsIntSize(width, height);
info.mDisplay = nsIntSize(macSurface->GetWidth(), macSurface->GetHeight());
info.mHasVideo = true;
gfx::IntRect visible = gfx::IntRect(0,
0,
mConfig.display_width,
mConfig.display_height);
// Copy the image data into our own format.
nsRefPtr<layers::Image> image =
mImageContainer->CreateImage(ImageFormat::MAC_IOSURFACE);
layers::MacIOSurfaceImage* videoImage =
static_cast<layers::MacIOSurfaceImage*>(image.get());
videoImage->SetSurface(macSurface);
nsAutoPtr<VideoData> data;
data =
VideoData::Create(info,
mImageContainer,
nullptr,
aFrameRef->byte_offset,
aFrameRef->composition_timestamp,
aFrameRef->duration,
buffer,
aFrameRef->is_sync_point,
aFrameRef->decode_timestamp,
visible);
// Unlock the returned image data.
CVPixelBufferUnlockBaseAddress(aImage, kCVPixelBufferLock_ReadOnly);
data = VideoData::CreateFromImage(info,
mImageContainer,
aFrameRef->byte_offset,
aFrameRef->composition_timestamp,
aFrameRef->duration, image.forget(),
aFrameRef->is_sync_point,
aFrameRef->decode_timestamp,
visible);
if (!data) {
NS_ERROR("Couldn't create VideoData for frame");
@ -445,31 +400,43 @@ AppleVTDecoder::InitializeSession()
}
// Contruct video decoder selection spec.
AutoCFRelease<CFMutableDictionaryRef> spec =
CFDictionaryCreateMutable(NULL, 0,
&kCFTypeDictionaryKeyCallBacks,
&kCFTypeDictionaryValueCallBacks);
// FIXME: Enabling hardware acceleration causes crashes in
// VTDecompressionSessionCreate() with multiple videos. Bug 1055694
#if 0
// This key is supported (or ignored) but not declared prior to OSX 10.9.
AutoCFRelease<CFStringRef>
kVTVideoDecoderSpecification_EnableHardwareAcceleratedVideoDecoder =
CFStringCreateWithCString(NULL, "EnableHardwareAcceleratedVideoDecoder",
kCFStringEncodingUTF8);
AutoCFRelease<CFDictionaryRef> spec = CreateDecoderSpecification();
CFDictionarySetValue(spec,
kVTVideoDecoderSpecification_EnableHardwareAcceleratedVideoDecoder,
kCFBooleanTrue);
#endif
// Contruct output configuration.
AutoCFRelease<CFDictionaryRef> IOSurfaceProperties =
CFDictionaryCreate(NULL,
NULL,
NULL,
0,
&kCFTypeDictionaryKeyCallBacks,
&kCFTypeDictionaryValueCallBacks);
SInt32 PixelFormatTypeValue = kCVPixelFormatType_32BGRA;
AutoCFRelease<CFNumberRef> PixelFormatTypeNumber =
CFNumberCreate(NULL, kCFNumberSInt32Type, &PixelFormatTypeValue);
const void* outputKeys[] = { kCVPixelBufferIOSurfacePropertiesKey,
kCVPixelBufferPixelFormatTypeKey,
kCVPixelBufferOpenGLCompatibilityKey };
const void* outputValues[] = { IOSurfaceProperties,
PixelFormatTypeNumber,
kCFBooleanTrue };
AutoCFRelease<CFDictionaryRef> outputConfiguration =
CFDictionaryCreate(NULL,
outputKeys,
outputValues,
ArrayLength(outputKeys),
&kCFTypeDictionaryKeyCallBacks,
&kCFTypeDictionaryValueCallBacks);
VTDecompressionOutputCallbackRecord cb = { PlatformCallback, this };
rv = VTDecompressionSessionCreate(NULL, // Allocator.
mFormat,
spec, // Video decoder selection.
NULL, // Output video format.
outputConfiguration, // Output video format.
&cb,
&mSession);
if (rv != noErr) {
NS_ERROR("Couldn't create decompression session!");
return NS_ERROR_FAILURE;
@ -478,4 +445,21 @@ AppleVTDecoder::InitializeSession()
return NS_OK;
}
CFDictionaryRef
AppleVTDecoder::CreateDecoderSpecification()
{
if (!AppleVTLinker::GetPropHWAccel()) {
return nullptr;
}
const void* specKeys[] = { AppleVTLinker::GetPropHWAccel() };
const void* specValues[] = { kCFBooleanTrue };
return CFDictionaryCreate(NULL,
specKeys,
specValues,
ArrayLength(specKeys),
&kCFTypeDictionaryKeyCallBacks,
&kCFTypeDictionaryValueCallBacks);
}
} // namespace mozilla

View File

@ -55,6 +55,8 @@ private:
nsresult WaitForAsynchronousFrames();
void DrainReorderedFrames();
void ClearReorderedFrames();
CFDictionaryRef CreateDecoderSpecification();
};
} // namespace mozilla

View File

@ -24,6 +24,7 @@ AppleVTLinker::sLinkStatus = LinkStatus_INIT;
void* AppleVTLinker::sLink = nullptr;
nsrefcnt AppleVTLinker::sRefCount = 0;
CFStringRef AppleVTLinker::skPropHWAccel = nullptr;
#define LINK_FUNC(func) typeof(func) func;
#include "AppleVTFunctions.h"
@ -58,6 +59,10 @@ AppleVTLinker::Link()
#include "AppleVTFunctions.h"
#undef LINK_FUNC
// Will only resolve in 10.9 and later.
skPropHWAccel =
GetIOConst("kVTVideoDecoderSpecification_EnableHardwareAcceleratedVideoDecoder");
LOG("Loaded VideoToolbox framework.");
sLinkStatus = LinkStatus_SUCCEEDED;
return true;
@ -83,7 +88,25 @@ AppleVTLinker::Unlink()
LOG("Unlinking VideoToolbox framework.");
dlclose(sLink);
sLink = nullptr;
skPropHWAccel = nullptr;
}
}
/* static */ CFStringRef
AppleVTLinker::GetIOConst(const char* symbol)
{
CFStringRef* address = (CFStringRef*)dlsym(sLink, symbol);
if (!address) {
return nullptr;
}
return *address;
}
/* static */ CFStringRef
AppleVTLinker::GetPropHWAccel()
{
return skPropHWAccel;
}
} // namespace mozilla

View File

@ -22,16 +22,20 @@ class AppleVTLinker
public:
static bool Link();
static void Unlink();
static CFStringRef GetPropHWAccel();
private:
static void* sLink;
static nsrefcnt sRefCount;
static CFStringRef skPropHWAccel;
static enum LinkStatus {
LinkStatus_INIT = 0,
LinkStatus_FAILED,
LinkStatus_SUCCEEDED
} sLinkStatus;
static CFStringRef GetIOConst(const char* symbol);
};
#define LINK_FUNC(func) extern typeof(func)* func;

View File

@ -209,28 +209,28 @@ void
MediaSourceReader::Shutdown()
{
MediaDecoderReader::Shutdown();
for (uint32_t i = 0; i < mTrackBuffers.Length(); ++i) {
mTrackBuffers[i]->Shutdown();
}
mTrackBuffers.Clear();
mAudioTrack = nullptr;
mAudioReader = nullptr;
mVideoTrack = nullptr;
mVideoReader = nullptr;
for (uint32_t i = 0; i < mTrackBuffers.Length(); ++i) {
mTrackBuffers[i]->Shutdown();
}
mTrackBuffers.Clear();
}
void
MediaSourceReader::BreakCycles()
{
MediaDecoderReader::BreakCycles();
for (uint32_t i = 0; i < mTrackBuffers.Length(); ++i) {
mTrackBuffers[i]->BreakCycles();
}
mTrackBuffers.Clear();
mAudioTrack = nullptr;
mAudioReader = nullptr;
mVideoTrack = nullptr;
mVideoReader = nullptr;
for (uint32_t i = 0; i < mTrackBuffers.Length(); ++i) {
mTrackBuffers[i]->BreakCycles();
}
mTrackBuffers.Clear();
}
bool

View File

@ -0,0 +1,17 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<script>
function boom()
{
var v = document.createElement('video');
v.src = URL.createObjectURL(new MediaSource());
v.play();
}
</script>
</head>
<body onload="boom();"></body>
</html>

View File

@ -1,3 +1,4 @@
test-pref(media.mediasource.enabled,true) load 926665.html
test-pref(media.mediasource.enabled,true) load 931388.html
test-pref(media.mediasource.enabled,true) load 1005366.html
test-pref(media.mediasource.enabled,true) load 1059035.html

View File

@ -0,0 +1,22 @@
// Helpers for Media Source Extensions tests
function runWithMSE(testFunction) {
addLoadEvent(() => SpecialPowers.pushPrefEnv({"set": [[ "media.mediasource.enabled", true ]]}, testFunction));
}
function fetchWithXHR(uri, onLoadFunction) {
var xhr = new XMLHttpRequest();
xhr.open("GET", uri, true);
xhr.responseType = "blob";
xhr.addEventListener("load", function (e) {
if (xhr.status != 200) {
return;
}
var rdr = new FileReader();
rdr.addEventListener("load", function (e) {
onLoadFunction(e.target.result);
});
rdr.readAsArrayBuffer(e.target.response);
});
xhr.send();
};

View File

@ -1,6 +1,6 @@
[DEFAULT]
skip-if = e10s
support-files = seek.webm seek.webm^headers^
support-files = mediasource.js seek.webm seek.webm^headers^
[test_MediaSource.html]
skip-if = buildapp == 'b2g' # b2g( ReferenceError: MediaSource is not defined)

View File

@ -3,6 +3,7 @@
<head>
<title>MSE: seeking in buffered range</title>
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<script type="text/javascript" src="mediasource.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
</head>
<body>
@ -11,84 +12,49 @@
SimpleTest.waitForExplicitFinish();
addLoadEvent(function() {
ok(!window.MediaSource, "MediaSource should be hidden behind a pref");
var accessThrows = false;
try {
new MediaSource();
} catch (e) {
accessThrows = true;
}
ok(accessThrows, "MediaSource should be hidden behind a pref");
SpecialPowers.pushPrefEnv({"set": [[ "media.mediasource.enabled", true ]]},
function () {
SpecialPowers.setBoolPref("media.mediasource.enabled", true);
var ms = new MediaSource();
ok(ms, "Create a MediaSource object");
ok(ms instanceof EventTarget, "MediaSource must be an EventTarget");
is(ms.readyState, "closed", "New MediaSource must be in closed state");
// Force wrapper creation, tests for leaks.
ms.foo = null;
var o = URL.createObjectURL(ms);
ok(o, "Create an objectURL from the MediaSource");
var v = document.createElement("video");
v.preload = "auto";
document.body.appendChild(v);
v.src = o;
ms.addEventListener("sourceopen", function () {
ok(true, "Receive a sourceopen event");
is(ms.readyState, "open", "MediaSource must be in open state after sourceopen");
var sb = ms.addSourceBuffer("video/webm");
ok(sb, "Create a SourceBuffer");
is(ms.sourceBuffers.length, 1, "MediaSource.sourceBuffers is expected length");
is(ms.sourceBuffers[0], sb, "SourceBuffer in list matches our SourceBuffer");
fetch("seek.webm", function (blob) {
var r = new FileReader();
r.addEventListener("load", function (e) {
sb.appendBuffer(new Uint8Array(e.target.result));
ms.endOfStream();
var target = 2;
v.addEventListener("loadedmetadata", function () {
if (v.buffered.length && v.currentTime != target &&
target >= v.buffered.start(0) &&
target < v.buffered.end(0)) {
v.currentTime = target;
}
});
var wasSeeking = false;
v.addEventListener("seeking", function () {
wasSeeking = true;
is(v.currentTime, target, "Video currentTime not at target");
});
v.addEventListener("seeked", function () {
ok(wasSeeking, "Received expected seeking and seeked events");
is(v.currentTime, target, "Video currentTime not at target");
v.parentNode.removeChild(v);
SimpleTest.finish();
});
});
r.readAsArrayBuffer(blob);
});
runWithMSE(function () {
var ms = new MediaSource();
var v = document.createElement("video");
v.preload = "auto";
v.src = URL.createObjectURL(ms);
document.body.appendChild(v);
ms.addEventListener("sourceopen", function () {
var sb = ms.addSourceBuffer("video/webm");
fetchWithXHR("seek.webm", function (arrayBuffer) {
sb.appendBuffer(new Uint8Array(arrayBuffer));
ms.endOfStream();
});
ms.addEventListener("sourceended", function () {
ok(true, "Receive a sourceended event");
is(ms.readyState, "ended", "MediaSource must be in ended state after sourceended");
var target = 2;
v.addEventListener("loadedmetadata", function () {
if (v.currentTime != target &&
v.buffered.length &&
target >= v.buffered.start(0) &&
target < v.buffered.end(0)) {
v.currentTime = target;
}
});
var wasSeeking = false;
v.addEventListener("seeking", function () {
wasSeeking = true;
is(v.currentTime, target, "Video currentTime not at target");
});
v.addEventListener("seeked", function () {
ok(wasSeeking, "Received expected seeking and seeked events");
is(v.currentTime, target, "Video currentTime not at target");
v.parentNode.removeChild(v);
SimpleTest.finish();
});
});
});
function fetch(src, cb) {
var xhr = new XMLHttpRequest();
xhr.open("GET", src, true);
xhr.responseType = "blob";
xhr.addEventListener("load", function (e) {
if (xhr.status != 200) {
return false;
}
cb(xhr.response);
});
xhr.send();
};
</script>
</pre>
</body>

View File

@ -3,6 +3,7 @@
<head>
<title>MSE: basic functionality</title>
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<script type="text/javascript" src="mediasource.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
</head>
<body>
@ -11,71 +12,64 @@
SimpleTest.waitForExplicitFinish();
addLoadEvent(function() {
ok(!window.MediaSource, "MediaSource should be hidden behind a pref");
var accessThrows = false;
try {
new MediaSource();
} catch (e) {
accessThrows = true;
}
ok(accessThrows, "MediaSource should be hidden behind a pref");
SpecialPowers.pushPrefEnv({"set": [[ "media.mediasource.enabled", true ]]},
function () {
SpecialPowers.setBoolPref("media.mediasource.enabled", true);
var ms = new MediaSource();
ok(ms, "Create a MediaSource object");
ok(ms instanceof EventTarget, "MediaSource must be an EventTarget");
is(ms.readyState, "closed", "New MediaSource must be in closed state");
// Force wrapper creation, tests for leaks.
ms.foo = null;
var o = URL.createObjectURL(ms);
ok(o, "Create an objectURL from the MediaSource");
var v = document.createElement("video");
v.preload = "auto";
document.body.appendChild(v);
v.src = o;
ms.addEventListener("sourceopen", function () {
ok(true, "Receive a sourceopen event");
is(ms.readyState, "open", "MediaSource must be in open state after sourceopen");
var sb = ms.addSourceBuffer("video/webm");
ok(sb, "Create a SourceBuffer");
is(ms.sourceBuffers.length, 1, "MediaSource.sourceBuffers is expected length");
is(ms.sourceBuffers[0], sb, "SourceBuffer in list matches our SourceBuffer");
fetch("seek.webm", function (blob) {
var r = new FileReader();
r.addEventListener("load", function (e) {
sb.appendBuffer(new Uint8Array(e.target.result));
ms.endOfStream();
v.play();
});
r.readAsArrayBuffer(blob);
});
});
ms.addEventListener("sourceended", function () {
ok(true, "Receive a sourceended event");
is(ms.readyState, "ended", "MediaSource must be in ended state after sourceended");
});
v.addEventListener("ended", function () {
is(v.duration, 4, "Video has correct duration");
v.parentNode.removeChild(v);
SimpleTest.finish();
addLoadEvent(function () {
ok(!window.MediaSource && !window.SourceBuffer && !window.SourceBufferList,
"MediaSource should be hidden behind a pref");
SimpleTest.doesThrow(() => new MediaSource, "MediaSource should be hidden behind a pref");
});
runWithMSE(function () {
SimpleTest.doesThrow(() => new SourceBuffer, "new SourceBuffer should fail");
SimpleTest.doesThrow(() => new SourceBufferList, "new SourceBufferList direct should fail");
var ms = new MediaSource();
ok(ms, "Create a MediaSource object");
ok(ms instanceof EventTarget, "MediaSource must be an EventTarget");
is(ms.readyState, "closed", "New MediaSource must be in closed state");
// Wrapper creation, tests for leaks.
SpecialPowers.wrap(ms);
// Set an expando to force wrapper creation, tests for leaks.
ms.foo = null;
var o = URL.createObjectURL(ms);
ok(o, "Create an objectURL from the MediaSource");
var v = document.createElement("video");
v.preload = "auto";
v.src = o;
document.body.appendChild(v);
ms.addEventListener("sourceopen", function () {
ok(true, "Receive a sourceopen event");
is(ms.readyState, "open", "MediaSource must be in open state after sourceopen");
var sb = ms.addSourceBuffer("video/webm");
ok(sb, "Create a SourceBuffer");
is(ms.sourceBuffers.length, 1, "MediaSource.sourceBuffers is expected length");
is(ms.sourceBuffers[0], sb, "SourceBuffer in list matches our SourceBuffer");
is(ms.activeSourceBuffers[0], sb, "SourceBuffer in active list matches our SourceBuffer");
fetchWithXHR("seek.webm", function (arrayBuffer) {
sb.appendBuffer(new Uint8Array(arrayBuffer));
ms.endOfStream();
v.play();
});
});
ms.addEventListener("sourceended", function () {
ok(true, "Receive a sourceended event");
is(ms.readyState, "ended", "MediaSource must be in ended state after sourceended");
});
v.addEventListener("ended", function () {
is(v.duration, 4, "Video has correct duration");
is(v.currentTime, 4, "Video has played to end");
v.parentNode.removeChild(v);
SimpleTest.finish();
});
});
function fetch(src, cb) {
var xhr = new XMLHttpRequest();
xhr.open("GET", src, true);
xhr.responseType = "blob";
xhr.addEventListener("load", function (e) {
if (xhr.status != 200) {
return false;
}
cb(xhr.response);
});
xhr.send();
};
</script>
</pre>
</body>

View File

@ -3,6 +3,7 @@
<head>
<title>MSE: append initialization and media segment separately</title>
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<script type="text/javascript" src="mediasource.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
</head>
<body>
@ -11,72 +12,33 @@
SimpleTest.waitForExplicitFinish();
addLoadEvent(function() {
ok(!window.MediaSource, "MediaSource should be hidden behind a pref");
var accessThrows = false;
try {
new MediaSource();
} catch (e) {
accessThrows = true;
}
ok(accessThrows, "MediaSource should be hidden behind a pref");
SpecialPowers.pushPrefEnv({"set": [[ "media.mediasource.enabled", true ]]},
function () {
SpecialPowers.setBoolPref("media.mediasource.enabled", true);
var ms = new MediaSource();
ok(ms, "Create a MediaSource object");
ok(ms instanceof EventTarget, "MediaSource must be an EventTarget");
is(ms.readyState, "closed", "New MediaSource must be in closed state");
// Force wrapper creation, tests for leaks.
ms.foo = null;
var o = URL.createObjectURL(ms);
ok(o, "Create an objectURL from the MediaSource");
var v = document.createElement("video");
v.preload = "auto";
document.body.appendChild(v);
v.src = o;
ms.addEventListener("sourceopen", function () {
ok(true, "Receive a sourceopen event");
is(ms.readyState, "open", "MediaSource must be in open state after sourceopen");
var sb = ms.addSourceBuffer("video/webm");
ok(sb, "Create a SourceBuffer");
is(ms.sourceBuffers.length, 1, "MediaSource.sourceBuffers is expected length");
is(ms.sourceBuffers[0], sb, "SourceBuffer in list matches our SourceBuffer");
fetch("seek.webm", function (blob) {
var r = new FileReader();
r.addEventListener("load", function (e) {
sb.appendBuffer(new Uint8Array(e.target.result, 0, 318));
sb.appendBuffer(new Uint8Array(e.target.result, 318));
ms.endOfStream();
v.play();
});
r.readAsArrayBuffer(blob);
});
});
ms.addEventListener("sourceended", function () {
ok(true, "Receive a sourceended event");
is(ms.readyState, "ended", "MediaSource must be in ended state after sourceended");
});
v.addEventListener("ended", function () {
is(v.duration, 4, "Video has correct duration");
v.parentNode.removeChild(v);
SimpleTest.finish();
runWithMSE(function () {
var ms = new MediaSource();
var v = document.createElement("video");
v.preload = "auto";
v.src = URL.createObjectURL(ms);
document.body.appendChild(v);
ms.addEventListener("sourceopen", function () {
var sb = ms.addSourceBuffer("video/webm");
fetchWithXHR("seek.webm", function (arrayBuffer) {
sb.appendBuffer(new Uint8Array(arrayBuffer, 0, 318));
sb.appendBuffer(new Uint8Array(arrayBuffer, 318));
ms.endOfStream();
v.play();
});
});
v.addEventListener("ended", function () {
is(v.duration, 4, "Video has correct duration");
is(v.currentTime, 4, "Video has played to end");
v.parentNode.removeChild(v);
SimpleTest.finish();
});
});
function fetch(src, cb) {
var xhr = new XMLHttpRequest();
xhr.open("GET", src, true);
xhr.responseType = "blob";
xhr.addEventListener("load", function (e) {
if (xhr.status != 200) {
return false;
}
cb(xhr.response);
});
xhr.send();
};
</script>
</pre>
</body>

View File

@ -3,6 +3,7 @@
<head>
<title>MSE: append segments with delay</title>
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<script type="text/javascript" src="mediasource.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
</head>
<body>
@ -11,74 +12,35 @@
SimpleTest.waitForExplicitFinish();
addLoadEvent(function() {
ok(!window.MediaSource, "MediaSource should be hidden behind a pref");
var accessThrows = false;
try {
new MediaSource();
} catch (e) {
accessThrows = true;
}
ok(accessThrows, "MediaSource should be hidden behind a pref");
SpecialPowers.pushPrefEnv({"set": [[ "media.mediasource.enabled", true ]]},
function () {
SpecialPowers.setBoolPref("media.mediasource.enabled", true);
var ms = new MediaSource();
ok(ms, "Create a MediaSource object");
ok(ms instanceof EventTarget, "MediaSource must be an EventTarget");
is(ms.readyState, "closed", "New MediaSource must be in closed state");
// Force wrapper creation, tests for leaks.
ms.foo = null;
var o = URL.createObjectURL(ms);
ok(o, "Create an objectURL from the MediaSource");
var v = document.createElement("video");
v.preload = "auto";
document.body.appendChild(v);
v.src = o;
ms.addEventListener("sourceopen", function () {
ok(true, "Receive a sourceopen event");
is(ms.readyState, "open", "MediaSource must be in open state after sourceopen");
var sb = ms.addSourceBuffer("video/webm");
ok(sb, "Create a SourceBuffer");
is(ms.sourceBuffers.length, 1, "MediaSource.sourceBuffers is expected length");
is(ms.sourceBuffers[0], sb, "SourceBuffer in list matches our SourceBuffer");
fetch("seek.webm", function (blob) {
var r = new FileReader();
r.addEventListener("load", function (e) {
sb.appendBuffer(new Uint8Array(e.target.result, 0, 318));
window.setTimeout(function () {
sb.appendBuffer(new Uint8Array(e.target.result, 318));
ms.endOfStream();
}, 1000);
v.play();
});
r.readAsArrayBuffer(blob);
});
});
ms.addEventListener("sourceended", function () {
ok(true, "Receive a sourceended event");
is(ms.readyState, "ended", "MediaSource must be in ended state after sourceended");
});
v.addEventListener("ended", function () {
is(v.duration, 4, "Video has correct duration");
v.parentNode.removeChild(v);
SimpleTest.finish();
runWithMSE(function () {
var ms = new MediaSource();
var v = document.createElement("video");
v.preload = "auto";
v.src = URL.createObjectURL(ms);
document.body.appendChild(v);
ms.addEventListener("sourceopen", function () {
var sb = ms.addSourceBuffer("video/webm");
fetchWithXHR("seek.webm", function (arrayBuffer) {
sb.appendBuffer(new Uint8Array(arrayBuffer, 0, 318));
window.setTimeout(function () {
sb.appendBuffer(new Uint8Array(arrayBuffer, 318));
ms.endOfStream();
}, 1000);
v.play();
});
});
v.addEventListener("ended", function () {
is(v.duration, 4, "Video has correct duration");
is(v.currentTime, 4, "Video has played to end");
v.parentNode.removeChild(v);
SimpleTest.finish();
});
});
function fetch(src, cb) {
var xhr = new XMLHttpRequest();
xhr.open("GET", src, true);
xhr.responseType = "blob";
xhr.addEventListener("load", function (e) {
if (xhr.status != 200) {
return false;
}
cb(xhr.response);
});
xhr.send();
};
</script>
</pre>
</body>

View File

@ -91,15 +91,19 @@ SVGScriptElement::SetType(const nsAString & aType, ErrorResult& rv)
}
void
SVGScriptElement::GetCrossOrigin(nsAString & aOrigin)
SVGScriptElement::GetCrossOrigin(nsAString & aCrossOrigin)
{
GetAttr(kNameSpaceID_None, nsGkAtoms::crossorigin, aOrigin);
// Null for both missing and invalid defaults is ok, since we
// always parse to an enum value, so we don't need an invalid
// default, and we _want_ the missing default to be null.
GetEnumAttr(nsGkAtoms::crossorigin, nullptr, aCrossOrigin);
}
void
SVGScriptElement::SetCrossOrigin(const nsAString & aOrigin, ErrorResult& rv)
SVGScriptElement::SetCrossOrigin(const nsAString & aCrossOrigin,
ErrorResult& aError)
{
rv = SetAttr(kNameSpaceID_None, nsGkAtoms::crossorigin, aOrigin, true);
SetOrRemoveNullableStringAttr(nsGkAtoms::crossorigin, aCrossOrigin, aError);
}
already_AddRefed<SVGAnimatedString>

View File

@ -66,8 +66,8 @@ public:
// WebIDL
void GetType(nsAString & aType);
void SetType(const nsAString & aType, ErrorResult& rv);
void GetCrossOrigin(nsAString & aOrigin);
void SetCrossOrigin(const nsAString & aOrigin, ErrorResult& rv);
void GetCrossOrigin(nsAString & aCrossOrigin);
void SetCrossOrigin(const nsAString & aCrossOrigin, ErrorResult& aError);
already_AddRefed<SVGAnimatedString> Href();
protected:

View File

@ -16,6 +16,7 @@ support-files =
getSubStringLength-helper.svg
matrixUtils.js
MutationEventChecker.js
object-delayed-intrinsic-size.sjs
pointer-events.js
scientific-helper.svg
selectSubString-helper.svg
@ -50,6 +51,7 @@ skip-if = true
[test_lengthParsing.html]
[test_nonAnimStrings.xhtml]
[test_non-scaling-stroke.html]
[test_object-delayed-intrinsic-size.html]
[test_onerror.xhtml]
[test_pathAnimInterpolation.xhtml]
[test_pathLength.html]

View File

@ -0,0 +1,24 @@
var timer = null;
function handleRequest(request, response)
{
response.processAsync();
response.setStatusLine(null, 200, "OK");
response.setHeader("Content-Type", "image/svg+xml", false);
// We need some body output or else gecko will not do an initial reflow
// while waiting for the rest of the document to load:
response.bodyOutputStream.write("\n", 1);
timer = Components.classes["@mozilla.org/timer;1"]
.createInstance(Components.interfaces.nsITimer);
timer.initWithCallback(function()
{
var body = "<svg xmlns='http://www.w3.org/2000/svg' width='70' height='0'></svg>";
response.bodyOutputStream.write(body, body.length);
response.finish();
}, 1000 /* milliseconds */, Components.interfaces.nsITimer.TYPE_ONE_SHOT);
}

View File

@ -0,0 +1,40 @@
<!DOCTYPE html>
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=1063073
-->
<html>
<head>
<title>Test that &lt;object&gt; embedding SVG and using its intrinsic
size will resize if the &lt;object&gt; gets a reflow before the
root-&lt;svg&gt; gets its nsSVGOuterSVGFrame
</title>
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
<script>
// This test checks for a race condition. If it fails intermittently then it
// may actually be a full failure.
SimpleTest.waitForExplicitFinish();
function runTest()
{
var object = document.querySelector("object");
var cs = document.defaultView.getComputedStyle(object, "");
var width = cs.getPropertyValue("width");
is(width, "70px", "Check that the &lt;object&gt; size updated");
SimpleTest.finish();
}
</script>
</head>
<body onload="runTest();">
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1063073">Mozilla Bug 1063073</a>
<p id="display"></p>
<div id="content">
<object style="border:1px solid black" type="image/svg+xml"
data="object-delayed-intrinsic-size.sjs"></object>
</div>
</body>
</html>

View File

@ -386,14 +386,35 @@ nsDefaultURIFixup::GetFixupURIInfo(const nsACString& aStringURI, uint32_t aFixup
info->mFixupCreatedAlternateURI = MakeAlternateURI(info->mFixedURI);
}
// If there is no relevent dot in the host, do we require the domain to
// be whitelisted?
if (info->mFixedURI) {
if (aFixupFlags & FIXUP_FLAG_REQUIRE_WHITELISTED_HOST) {
nsAutoCString asciiHost;
if (NS_SUCCEEDED(info->mFixedURI->GetAsciiHost(asciiHost)) &&
!asciiHost.IsEmpty()) {
uint32_t dotLoc = uint32_t(asciiHost.FindChar('.'));
if ((dotLoc == uint32_t(kNotFound) || dotLoc == asciiHost.Length() - 1)) {
if (IsDomainWhitelisted(asciiHost, dotLoc)) {
info->mPreferredURI = info->mFixedURI;
}
} else {
info->mPreferredURI = info->mFixedURI;
}
}
} else {
info->mPreferredURI = info->mFixedURI;
}
return NS_OK;
}
// If we still haven't been able to construct a valid URI, try to force a
// keyword match. This catches search strings with '.' or ':' in them.
if (info->mFixedURI)
{
info->mPreferredURI = info->mFixedURI;
}
else if (sFixupKeywords && (aFixupFlags & FIXUP_FLAG_ALLOW_KEYWORD_LOOKUP))
{
if (sFixupKeywords && (aFixupFlags & FIXUP_FLAG_ALLOW_KEYWORD_LOOKUP)) {
rv = KeywordToURI(aStringURI, aPostData, getter_AddRefs(info->mPreferredURI));
if (NS_SUCCEEDED(rv) && info->mPreferredURI)
{
@ -964,26 +985,17 @@ void nsDefaultURIFixup::KeywordURIFixup(const nsACString & aURIString,
(dotLoc == lastDotLoc && (dotLoc == 0 || dotLoc == aURIString.Length() - 1))) &&
colonLoc == uint32_t(kNotFound) && qMarkLoc == uint32_t(kNotFound))
{
nsAutoCString asciiHost;
if (aFixupInfo->mFixedURI &&
NS_SUCCEEDED(aFixupInfo->mFixedURI->GetAsciiHost(asciiHost)) &&
!asciiHost.IsEmpty())
{
// Check if this domain is whitelisted as an actual
// domain (which will prevent a keyword query)
// NB: any processing of the host here should stay in sync with
// code in the front-end(s) that set the pref.
nsAutoCString pref("browser.fixup.domainwhitelist.");
if (dotLoc == aURIString.Length() - 1) {
pref.Append(Substring(asciiHost, 0, asciiHost.Length() - 1));
} else {
pref.Append(asciiHost);
}
if (Preferences::GetBool(pref.get(), false))
{
!asciiHost.IsEmpty()) {
if (IsDomainWhitelisted(asciiHost, dotLoc)) {
return;
}
}
// If we get here, we don't have a valid URI, or we did but the
// host is not whitelisted, so we do a keyword search *anyway*:
rv = KeywordToURI(aFixupInfo->mOriginalInput, aPostData,
@ -995,6 +1007,25 @@ void nsDefaultURIFixup::KeywordURIFixup(const nsACString & aURIString,
}
}
bool nsDefaultURIFixup::IsDomainWhitelisted(const nsAutoCString aAsciiHost,
const uint32_t aDotLoc)
{
// Check if this domain is whitelisted as an actual
// domain (which will prevent a keyword query)
// NB: any processing of the host here should stay in sync with
// code in the front-end(s) that set the pref.
nsAutoCString pref("browser.fixup.domainwhitelist.");
if (aDotLoc == aAsciiHost.Length() - 1) {
pref.Append(Substring(aAsciiHost, 0, aAsciiHost.Length() - 1));
} else {
pref.Append(aAsciiHost);
}
return Preferences::GetBool(pref.get(), false);
}
nsresult NS_NewURIFixup(nsIURIFixup **aURIFixup)
{

View File

@ -37,6 +37,8 @@ private:
bool PossiblyHostPortUrl(const nsACString& aUrl);
bool MakeAlternateURI(nsIURI *aURI);
bool IsLikelyFTP(const nsCString& aHostSpec);
bool IsDomainWhitelisted(const nsAutoCString aAsciiHost,
const uint32_t aDotLoc);
};
class nsDefaultURIFixupInfo : public nsIURIFixupInfo

View File

@ -9416,14 +9416,7 @@ nsDocShell::InternalLoad(nsIURI * aURI,
aLoadType == LOAD_HISTORY ||
aLoadType == LOAD_LINK) {
nsCOMPtr<nsIURI> currentURI;
if (sURIFixup && mCurrentURI) {
rv = sURIFixup->CreateExposableURI(mCurrentURI,
getter_AddRefs(currentURI));
NS_ENSURE_SUCCESS(rv, rv);
} else {
currentURI = mCurrentURI;
}
nsCOMPtr<nsIURI> currentURI = mCurrentURI;
// Split currentURI and aURI on the '#' character. Make sure we read
// the return values of SplitURIAtHash; if it fails, we don't want to
// allow a short-circuited navigation.
@ -9439,6 +9432,19 @@ nsDocShell::InternalLoad(nsIURI * aURI,
NS_SUCCEEDED(splitRv2) &&
curBeforeHash.Equals(newBeforeHash);
if (!sameExceptHashes && sURIFixup && currentURI &&
NS_SUCCEEDED(splitRv2)) {
// Maybe aURI came from the exposable form of currentURI?
nsCOMPtr<nsIURI> currentExposableURI;
rv = sURIFixup->CreateExposableURI(currentURI,
getter_AddRefs(currentExposableURI));
NS_ENSURE_SUCCESS(rv, rv);
splitRv1 = nsContentUtils::SplitURIAtHash(currentExposableURI,
curBeforeHash, curHash);
sameExceptHashes = NS_SUCCEEDED(splitRv1) &&
curBeforeHash.Equals(newBeforeHash);
}
bool historyNavBetweenSameDoc = false;
if (mOSHE && aSHEntry) {
// We're doing a history load.

View File

@ -63,7 +63,7 @@ interface nsIURIFixupInfo : nsISupports
/**
* Interface implemented by objects capable of fixing up strings into URIs
*/
[scriptable, uuid(80d4932e-bb2e-4afb-98e0-de9cc9ea7d82)]
[scriptable, uuid(49298f2b-3630-4874-aecc-522300a7fead)]
interface nsIURIFixup : nsISupports
{
/** No fixup flags. */
@ -83,12 +83,18 @@ interface nsIURIFixup : nsISupports
const unsigned long FIXUP_FLAGS_MAKE_ALTERNATE_URI = 2;
/**
* For an input that may be just a domain with only 1 level (eg, "mozilla"),
* require that the host be whitelisted.
*
* Overridden by FIXUP_FLAG_ALLOW_KEYWORD_LOOKUP.
*/
const unsigned long FIXUP_FLAG_REQUIRE_WHITELISTED_HOST = 4;
/*
* Fix common scheme typos.
*/
const unsigned long FIXUP_FLAG_FIX_SCHEME_TYPOS = 8;
/* Note that flag 4 is available. */
/**
* Converts an internal URI (e.g. a wyciwyg URI) into one which we can
* expose to the user, for example on the URL bar.

View File

@ -3,7 +3,8 @@ let urifixup = Cc["@mozilla.org/docshell/urifixup;1"].
Components.utils.import("resource://gre/modules/Services.jsm");
let prefList = ["browser.fixup.typo.scheme", "keyword.enabled"];
let prefList = ["browser.fixup.typo.scheme", "keyword.enabled",
"browser.fixup.domainwhitelist.whitelisted"];
for (let pref of prefList) {
Services.prefs.setBoolPref(pref, true);
}
@ -34,7 +35,8 @@ do_register_cleanup(function() {
let flagInputs = [
urifixup.FIXUP_FLAG_ALLOW_KEYWORD_LOOKUP,
urifixup.FIXUP_FLAGS_MAKE_ALTERNATE_URI,
urifixup.FIXUP_FLAG_FIX_SCHEME_TYPOS
urifixup.FIXUP_FLAG_FIX_SCHEME_TYPOS,
urifixup.FIXUP_FLAG_REQUIRE_WHITELISTED_HOST,
];
flagInputs.concat([
@ -44,42 +46,192 @@ flagInputs.concat([
flagInputs[0] | flagInputs[1] | flagInputs[2]
]);
let testcases = [
["http://www.mozilla.org", "http://www.mozilla.org/", null, false, false],
["http://127.0.0.1/", "http://127.0.0.1/", null, false, false],
["file:///foo/bar", "file:///foo/bar", null, false, false],
["://www.mozilla.org", "http://www.mozilla.org/", null, false, true],
["www.mozilla.org", "http://www.mozilla.org/", null, false, true],
["http://mozilla/", "http://mozilla/", "http://www.mozilla.com/", false, false],
["http://test./", "http://test./", "http://www.test./", false, false],
["127.0.0.1", "http://127.0.0.1/", null, false, true],
["1234", "http://1234/", "http://www.1234.com/", true, true],
["host/foo.txt", "http://host/foo.txt", "http://www.host.com/foo.txt", false, true],
["mozilla", "http://mozilla/", "http://www.mozilla.com/", true, true],
["test.", "http://test./", "http://www.test./", true, true],
[".test", "http://.test/", "http://www..test/", true, true],
["mozilla is amazing", null, null, true, true],
["mozilla ", "http://mozilla/", "http://www.mozilla.com/", true, true],
[" mozilla ", "http://mozilla/", "http://www.mozilla.com/", true, true],
["mozilla \\", null, null, true, true],
["mozilla \\ foo.txt", null, null, true, true],
["mozilla \\\r foo.txt", null, null, true, true],
["mozilla\n", "http://mozilla/", "http://www.mozilla.com/", true, true],
["mozilla \r\n", "http://mozilla/", "http://www.mozilla.com/", true, true],
["moz\r\nfirefox\nos\r", "http://mozfirefoxos/", "http://www.mozfirefoxos.com/", true, true],
["moz\r\n firefox\n", null, null, true, true],
["", null, null, true, true],
["[]", null, null, true, true]
];
/*
The following properties are supported for these test cases:
{
input: "", // Input string, required
fixedURI: "", // Expected fixedURI
alternateURI: "", // Expected alternateURI
keywordLookup: false, // Whether a keyword lookup is expected
protocolChange: false, // Whether a protocol change is expected
affectedByWhitelist: false, // Whether the input host is affected by the whitelist
inWhitelist: false, // Whether the input host is in the whitelist
}
*/
let testcases = [ {
input: "http://www.mozilla.org",
fixedURI: "http://www.mozilla.org/",
}, {
input: "http://127.0.0.1/",
fixedURI: "http://127.0.0.1/",
}, {
input: "file:///foo/bar",
fixedURI: "file:///foo/bar",
}, {
input: "://www.mozilla.org",
fixedURI: "http://www.mozilla.org/",
protocolChange: true,
}, {
input: "www.mozilla.org",
fixedURI: "http://www.mozilla.org/",
protocolChange: true,
}, {
input: "http://mozilla/",
fixedURI: "http://mozilla/",
alternateURI: "http://www.mozilla.com/",
}, {
input: "http://test./",
fixedURI: "http://test./",
alternateURI: "http://www.test./",
}, {
input: "127.0.0.1",
fixedURI: "http://127.0.0.1/",
protocolChange: true,
}, {
input: "1234",
fixedURI: "http://1234/",
alternateURI: "http://www.1234.com/",
keywordLookup: true,
protocolChange: true,
affectedByWhitelist: true,
}, {
input: "host/foo.txt",
fixedURI: "http://host/foo.txt",
alternateURI: "http://www.host.com/foo.txt",
protocolChange: true,
affectedByWhitelist: true,
}, {
input: "mozilla",
fixedURI: "http://mozilla/",
alternateURI: "http://www.mozilla.com/",
keywordLookup: true,
protocolChange: true,
affectedByWhitelist: true,
}, {
input: "test.",
fixedURI: "http://test./",
alternateURI: "http://www.test./",
keywordLookup: true,
protocolChange: true,
affectedByWhitelist: true,
}, {
input: ".test",
fixedURI: "http://.test/",
alternateURI: "http://www..test/",
keywordLookup: true,
protocolChange: true,
}, {
input: "mozilla is amazing",
keywordLookup: true,
protocolChange: true,
}, {
input: "mozilla ",
fixedURI: "http://mozilla/",
alternateURI: "http://www.mozilla.com/",
keywordLookup: true,
protocolChange: true,
affectedByWhitelist: true,
}, {
input: " mozilla ",
fixedURI: "http://mozilla/",
alternateURI: "http://www.mozilla.com/",
keywordLookup: true,
protocolChange: true,
affectedByWhitelist: true,
}, {
input: "mozilla \\",
keywordLookup: true,
protocolChange: true,
affectedByWhitelist: true,
}, {
input: "mozilla \\ foo.txt",
keywordLookup: true,
protocolChange: true,
}, {
input: "mozilla \\\r foo.txt",
keywordLookup: true,
protocolChange: true,
}, {
input: "mozilla\n",
fixedURI: "http://mozilla/",
alternateURI: "http://www.mozilla.com/",
keywordLookup: true,
protocolChange: true,
affectedByWhitelist: true,
}, {
input: "mozilla \r\n",
fixedURI: "http://mozilla/",
alternateURI: "http://www.mozilla.com/",
keywordLookup: true,
protocolChange: true,
affectedByWhitelist: true,
}, {
input: "moz\r\nfirefox\nos\r",
fixedURI: "http://mozfirefoxos/",
alternateURI: "http://www.mozfirefoxos.com/",
keywordLookup: true,
protocolChange: true,
affectedByWhitelist: true,
}, {
input: "moz\r\n firefox\n",
keywordLookup: true,
protocolChange: true,
}, {
input: "",
keywordLookup: true,
protocolChange: true,
}, {
input: "[]",
keywordLookup: true,
protocolChange: true,
}, {
input: "http://whitelisted/",
fixedURI: "http://whitelisted/",
alternateURI: "http://www.whitelisted.com/",
affectedByWhitelist: true,
inWhitelist: true,
}];
if (Services.appinfo.OS.toLowerCase().startsWith("win")) {
testcases.push(["C:\\some\\file.txt", "file:///C:/some/file.txt", null, false, true]);
testcases.push(["//mozilla", "http://mozilla/", "http://www.mozilla.com/", false, true]);
testcases.push(["mozilla\\", "http://mozilla/", "http://www.mozilla.com/", true, true]);
testcases.push({
input: "C:\\some\\file.txt",
fixedURI: "file:///C:/some/file.txt",
protocolChange: true,
});
testcases.push({
input: "//mozilla",
fixedURI: "http://mozilla/",
alternateURI: "http://www.mozilla.com/",
protocolChange: true,
affectedByWhitelist: true,
});
testcases.push({
input: "mozilla\\",
fixedURI: "http://mozilla/",
alternateURI: "http://www.mozilla.com/",
keywordLookup: true,
protocolChange: true,
affectedByWhitelist: true,
});
} else {
testcases.push(["/some/file.txt", "file:///some/file.txt", null, false, true]);
testcases.push(["//mozilla", "file:////mozilla", null, false, true]);
testcases.push(["mozilla\\", "http://mozilla\\/", "http://www.mozilla/", true, true]);
testcases.push({
input: "/some/file.txt",
fixedURI: "file:///some/file.txt",
protocolChange: true,
});
testcases.push({
input: "//mozilla",
fixedURI: "file:////mozilla",
protocolChange: true,
});
testcases.push({
input: "mozilla\\",
fixedURI: "http://mozilla\\/",
alternateURI: "http://www.mozilla/",
keywordLookup: true,
protocolChange: true,
affectedByWhitelist: true,
});
}
function sanitize(input) {
@ -87,8 +239,20 @@ function sanitize(input) {
}
function run_test() {
for (let [testInput, expectedFixedURI, alternativeURI,
expectKeywordLookup, expectProtocolChange] of testcases) {
for (let { input: testInput,
fixedURI: expectedFixedURI,
alternateURI: alternativeURI,
keywordLookup: expectKeywordLookup,
protocolChange: expectProtocolChange,
affectedByWhitelist: affectedByWhitelist,
inWhitelist: inWhitelist } of testcases) {
// Explicitly force these into a boolean
expectKeywordLookup = !!expectKeywordLookup;
expectProtocolChange = !!expectProtocolChange;
affectedByWhitelist = !!affectedByWhitelist;
inWhitelist = !!inWhitelist;
for (let flags of flagInputs) {
let info;
let fixupURIOnly = null;
@ -109,10 +273,12 @@ function run_test() {
continue;
}
do_print("Checking " + testInput + " with flags " + flags);
do_print("Checking \"" + testInput + "\" with flags " + flags);
// Both APIs should then also be using the same spec.
do_check_eq(fixupURIOnly.spec, info.preferredURI.spec);
do_check_eq(!!fixupURIOnly, !!info.preferredURI);
if (fixupURIOnly)
do_check_eq(fixupURIOnly.spec, info.preferredURI.spec);
let isFileURL = expectedFixedURI && expectedFixedURI.startsWith("file");
@ -131,10 +297,25 @@ function run_test() {
do_check_eq(info.fixupCreatedAlternateURI, makeAlternativeURI && alternativeURI != null);
// Check the preferred URI
if (couldDoKeywordLookup && expectKeywordLookup) {
let requiresWhitelistedDomain = flags & urifixup.FIXUP_FLAG_REQUIRE_WHITELISTED_HOST
if (couldDoKeywordLookup) {
if (expectKeywordLookup) {
if (!affectedByWhitelist || (affectedByWhitelist && !inWhitelist)) {
let urlparamInput = encodeURIComponent(sanitize(testInput)).replace("%20", "+", "g");
let searchURL = kSearchEngineURL.replace("{searchTerms}", urlparamInput);
do_check_eq(info.preferredURI.spec, searchURL);
} else {
do_check_eq(info.preferredURI, null);
}
} else {
do_check_eq(info.preferredURI.spec, info.fixedURI.spec);
}
} else if (requiresWhitelistedDomain) {
// Not a keyword search, but we want to enforce the host whitelist
if (!affectedByWhitelist || (affectedByWhitelist && inWhitelist))
do_check_eq(info.preferredURI.spec, info.fixedURI.spec);
else
do_check_eq(info.preferredURI, null);
} else {
// In these cases, we should never be doing a keyword lookup and
// the fixed URI should be preferred:

View File

@ -911,9 +911,8 @@ Console::Method(JSContext* aCx, MethodName aMethodName,
nsGlobalWindow *win = static_cast<nsGlobalWindow*>(mWindow.get());
MOZ_ASSERT(win);
ErrorResult rv;
nsRefPtr<nsPerformance> performance = win->GetPerformance(rv);
if (rv.Failed() || !performance) {
nsRefPtr<nsPerformance> performance = win->GetPerformance();
if (!performance) {
return;
}

View File

@ -69,19 +69,6 @@ ShouldExposeChildWindow(nsString& aNameBeingResolved, nsIDOMWindow *aChild)
aNameBeingResolved, eCaseMatters);
}
static nsGlobalWindow*
GetWindowFromGlobal(JSObject* aGlobal)
{
nsGlobalWindow* win;
if (NS_SUCCEEDED(UNWRAP_OBJECT(Window, aGlobal, win))) {
return win;
}
XPCWrappedNative* wrapper = XPCWrappedNative::Get(aGlobal);
nsCOMPtr<nsPIDOMWindow> piWin = do_QueryWrappedNative(wrapper);
MOZ_ASSERT(piWin);
return static_cast<nsGlobalWindow*>(piWin.get());
}
bool
WindowNamedPropertiesHandler::getOwnPropDescriptor(JSContext* aCx,
JS::Handle<JSObject*> aProxy,
@ -106,7 +93,7 @@ WindowNamedPropertiesHandler::getOwnPropDescriptor(JSContext* aCx,
}
// Grab the DOM window.
nsGlobalWindow* win = GetWindowFromGlobal(global);
nsGlobalWindow* win = xpc::WindowOrNull(global);
if (win->Length() > 0) {
nsCOMPtr<nsIDOMWindow> childWin = win->GetChildWindow(str);
if (childWin && ShouldExposeChildWindow(str, childWin)) {
@ -178,7 +165,7 @@ WindowNamedPropertiesHandler::ownPropNames(JSContext* aCx,
JS::AutoIdVector& aProps) const
{
// Grab the DOM window.
nsGlobalWindow* win = GetWindowFromGlobal(JS_GetGlobalForObject(aCx, aProxy));
nsGlobalWindow* win = xpc::WindowOrNull(JS_GetGlobalForObject(aCx, aProxy));
nsTArray<nsString> names;
win->GetSupportedNames(names);
// Filter out the ones we wouldn't expose from getOwnPropertyDescriptor.

View File

@ -35,7 +35,6 @@
#include "nsIXPConnect.h"
#include "xptcall.h"
#include "nsTArray.h"
#include "nsDocument.h" // nsDOMStyleSheetList
#include "nsDOMBlobBuilder.h"
// General helper includes
@ -51,18 +50,12 @@
#include "mozilla/Telemetry.h"
// Window scriptable helper includes
#include "nsIDocShell.h"
#include "nsJSUtils.h"
#include "nsScriptNameSpaceManager.h"
#include "nsIJSNativeInitializer.h"
#include "nsJSEnvironment.h"
// DOM base includes
#include "nsIDOMLocation.h"
#include "nsIDOMWindow.h"
#include "nsPIDOMWindow.h"
#include "nsIDOMJSWindow.h"
#include "nsIDOMChromeWindow.h"
#include "nsIDOMConstructor.h"
// DOM core includes
@ -134,10 +127,7 @@
#include "mozilla/dom/BindingUtils.h"
#include "mozilla/Likely.h"
#include "WindowNamedPropertiesHandler.h"
#include "nsIInterfaceInfoManager.h"
#include "mozilla/dom/EventTargetBinding.h"
#include "mozilla/dom/WindowBinding.h"
#ifdef MOZ_TIME_MANAGER
#include "TimeManager.h"
@ -151,14 +141,6 @@ static NS_DEFINE_CID(kDOMSOF_CID, NS_DOM_SCRIPT_OBJECT_FACTORY_CID);
// NOTE: DEFAULT_SCRIPTABLE_FLAGS and DOM_DEFAULT_SCRIPTABLE_FLAGS
// are defined in nsIDOMClassInfo.h.
#define WINDOW_SCRIPTABLE_FLAGS \
(nsIXPCScriptable::WANT_PRECREATE | \
nsIXPCScriptable::WANT_POSTCREATE | \
nsIXPCScriptable::WANT_ENUMERATE | \
nsIXPCScriptable::DONT_ENUM_QUERY_INTERFACE | \
nsIXPCScriptable::IS_GLOBAL_OBJECT | \
nsIXPCScriptable::WANT_OUTER_OBJECT)
#define ARRAY_SCRIPTABLE_FLAGS \
(DOM_DEFAULT_SCRIPTABLE_FLAGS | \
nsIXPCScriptable::WANT_GETPROPERTY | \
@ -244,17 +226,6 @@ DOMCI_DATA_NO_CLASS(XULPopupElement)
static nsDOMClassInfoData sClassInfoData[] = {
// Base classes
// The Window class lets you QI into interfaces that are not in the
// flattened set (i.e. nsIXPCScriptable::CLASSINFO_INTERFACES_ONLY
// is not set), because of this make sure all scriptable interfaces
// that are implemented by nsGlobalWindow can securely be exposed
// to JS.
NS_DEFINE_CLASSINFO_DATA(Window, nsWindowSH,
DEFAULT_SCRIPTABLE_FLAGS |
WINDOW_SCRIPTABLE_FLAGS)
NS_DEFINE_CLASSINFO_DATA(DOMPrototype, nsDOMConstructorSH,
DOM_BASE_SCRIPTABLE_FLAGS |
nsIXPCScriptable::WANT_PRECREATE |
@ -300,11 +271,6 @@ static nsDOMClassInfoData sClassInfoData[] = {
DEFAULT_SCRIPTABLE_FLAGS)
#endif
// DOM Chrome Window class.
NS_DEFINE_CHROME_XBL_CLASSINFO_DATA(ChromeWindow, nsWindowSH,
DEFAULT_SCRIPTABLE_FLAGS |
WINDOW_SCRIPTABLE_FLAGS)
#ifdef MOZ_XUL
NS_DEFINE_CHROME_XBL_CLASSINFO_DATA(XULTemplateBuilder, nsDOMGenericSH,
DEFAULT_SCRIPTABLE_FLAGS)
@ -335,10 +301,6 @@ static nsDOMClassInfoData sClassInfoData[] = {
NS_DEFINE_CLASSINFO_DATA(File, nsDOMGenericSH,
DOM_DEFAULT_SCRIPTABLE_FLAGS)
NS_DEFINE_CLASSINFO_DATA(ModalContentWindow, nsWindowSH,
DEFAULT_SCRIPTABLE_FLAGS |
WINDOW_SCRIPTABLE_FLAGS)
NS_DEFINE_CLASSINFO_DATA(MozSmsMessage, nsDOMGenericSH,
DOM_DEFAULT_SCRIPTABLE_FLAGS)
@ -424,10 +386,7 @@ nsIXPConnect *nsDOMClassInfo::sXPConnect = nullptr;
bool nsDOMClassInfo::sIsInitialized = false;
jsid nsDOMClassInfo::sLocation_id = JSID_VOID;
jsid nsDOMClassInfo::sConstructor_id = JSID_VOID;
jsid nsDOMClassInfo::sTop_id = JSID_VOID;
jsid nsDOMClassInfo::sDocument_id = JSID_VOID;
jsid nsDOMClassInfo::sWrappedJSObject_id = JSID_VOID;
static const JSClass *sObjectClass = nullptr;
@ -519,10 +478,7 @@ nsDOMClassInfo::DefineStaticJSVals(JSContext *cx)
else \
return NS_ERROR_OUT_OF_MEMORY;
SET_JSID_TO_STRING(sLocation_id, cx, "location");
SET_JSID_TO_STRING(sConstructor_id, cx, "constructor");
SET_JSID_TO_STRING(sTop_id, cx, "top");
SET_JSID_TO_STRING(sDocument_id, cx, "document");
SET_JSID_TO_STRING(sWrappedJSObject_id, cx, "wrappedJSObject");
return NS_OK;
@ -734,29 +690,6 @@ nsDOMClassInfo::RegisterExternalClasses()
d.mInterfaces = interface_list; \
}
#ifdef MOZ_B2G
#define DOM_CLASSINFO_WINDOW_MAP_ENTRIES \
DOM_CLASSINFO_MAP_ENTRY(nsIDOMWindow) \
DOM_CLASSINFO_MAP_ENTRY(nsIDOMWindowB2G) \
DOM_CLASSINFO_MAP_ENTRY(nsIDOMJSWindow) \
DOM_CLASSINFO_MAP_ENTRY(nsIDOMEventTarget) \
DOM_CLASSINFO_MAP_ENTRY(nsIInlineEventHandlers) \
DOM_CLASSINFO_MAP_ENTRY(nsIDOMWindowPerformance) \
DOM_CLASSINFO_MAP_ENTRY(nsIInterfaceRequestor) \
DOM_CLASSINFO_MAP_CONDITIONAL_ENTRY(nsITouchEventReceiver, \
TouchEvent::PrefEnabled())
#else // !MOZ_B2G
#define DOM_CLASSINFO_WINDOW_MAP_ENTRIES \
DOM_CLASSINFO_MAP_ENTRY(nsIDOMWindow) \
DOM_CLASSINFO_MAP_ENTRY(nsIDOMJSWindow) \
DOM_CLASSINFO_MAP_ENTRY(nsIDOMEventTarget) \
DOM_CLASSINFO_MAP_ENTRY(nsIInlineEventHandlers) \
DOM_CLASSINFO_MAP_ENTRY(nsIDOMWindowPerformance) \
DOM_CLASSINFO_MAP_ENTRY(nsIInterfaceRequestor) \
DOM_CLASSINFO_MAP_CONDITIONAL_ENTRY(nsITouchEventReceiver, \
TouchEvent::PrefEnabled())
#endif // MOZ_B2G
nsresult
nsDOMClassInfo::Init()
{
@ -778,13 +711,6 @@ nsDOMClassInfo::Init()
AutoSafeJSContext cx;
DOM_CLASSINFO_MAP_BEGIN(Window, nsIDOMWindow)
DOM_CLASSINFO_WINDOW_MAP_ENTRIES
#ifdef MOZ_WEBSPEECH
DOM_CLASSINFO_MAP_ENTRY(nsISpeechSynthesisGetter)
#endif
DOM_CLASSINFO_MAP_END
DOM_CLASSINFO_MAP_BEGIN_NO_CLASS_IF(DOMPrototype, nsIDOMDOMConstructor)
DOM_CLASSINFO_MAP_ENTRY(nsIDOMDOMConstructor)
DOM_CLASSINFO_MAP_END
@ -838,14 +764,6 @@ nsDOMClassInfo::Init()
DOM_CLASSINFO_MAP_END
#endif
DOM_CLASSINFO_MAP_BEGIN_NO_CLASS_IF(ChromeWindow, nsIDOMWindow)
DOM_CLASSINFO_WINDOW_MAP_ENTRIES
DOM_CLASSINFO_MAP_ENTRY(nsIDOMChromeWindow)
#ifdef MOZ_WEBSPEECH
DOM_CLASSINFO_MAP_ENTRY(nsISpeechSynthesisGetter)
#endif
DOM_CLASSINFO_MAP_END
#ifdef MOZ_XUL
DOM_CLASSINFO_MAP_BEGIN(XULTemplateBuilder, nsIXULTemplateBuilder)
DOM_CLASSINFO_MAP_ENTRY(nsIXULTemplateBuilder)
@ -890,14 +808,6 @@ nsDOMClassInfo::Init()
DOM_CLASSINFO_MAP_ENTRY(nsIDOMFile)
DOM_CLASSINFO_MAP_END
DOM_CLASSINFO_MAP_BEGIN_NO_CLASS_IF(ModalContentWindow, nsIDOMWindow)
DOM_CLASSINFO_WINDOW_MAP_ENTRIES
DOM_CLASSINFO_MAP_ENTRY(nsIDOMModalContentWindow)
#ifdef MOZ_WEBSPEECH
DOM_CLASSINFO_MAP_ENTRY(nsISpeechSynthesisGetter)
#endif
DOM_CLASSINFO_MAP_END
DOM_CLASSINFO_MAP_BEGIN(MozSmsMessage, nsIDOMMozSmsMessage)
DOM_CLASSINFO_MAP_ENTRY(nsIDOMMozSmsMessage)
DOM_CLASSINFO_MAP_END
@ -1555,146 +1465,13 @@ nsDOMClassInfo::ShutDown()
}
}
sLocation_id = JSID_VOID;
sConstructor_id = JSID_VOID;
sTop_id = JSID_VOID;
sDocument_id = JSID_VOID;
sWrappedJSObject_id = JSID_VOID;
NS_IF_RELEASE(sXPConnect);
sIsInitialized = false;
}
// Window helper
NS_IMETHODIMP
nsWindowSH::PreCreate(nsISupports *nativeObj, JSContext *cx,
JSObject *globalObj, JSObject **parentObj)
{
// Normally ::PreCreate() is used to give XPConnect the parent
// object for the object that's being wrapped, this parent object is
// set as the parent of the wrapper and it's also used to find the
// right scope for the object being wrapped. Now, in the case of the
// global object the wrapper shouldn't have a parent but we supply
// one here anyway (the global object itself) and this will be used
// by XPConnect only to find the right scope, once the scope is
// found XPConnect will find the existing wrapper (which always
// exists since it's created on window construction), since an
// existing wrapper is found the parent we supply here is ignored
// after the wrapper is found.
nsCOMPtr<nsIScriptGlobalObject> sgo(do_QueryInterface(nativeObj));
NS_ASSERTION(sgo, "nativeObj not a global object!");
nsGlobalWindow *win = nsGlobalWindow::FromSupports(nativeObj);
NS_ASSERTION(win->IsInnerWindow(), "Should be inner window.");
// We sometimes get a disconnected window during file api test. :-(
if (!win->GetOuterWindowInternal())
return NS_ERROR_FAILURE;
// If we're bootstrapping, we don't have a JS object yet.
if (win->GetOuterWindowInternal()->IsCreatingInnerWindow())
return NS_OK;
return SetParentToWindow(win, parentObj);
}
NS_IMETHODIMP
nsWindowSH::PostCreatePrototype(JSContext* aCx, JSObject* aProto)
{
JS::Rooted<JSObject*> proto(aCx, aProto);
nsresult rv = nsDOMClassInfo::PostCreatePrototype(aCx, proto);
NS_ENSURE_SUCCESS(rv, rv);
// We should probably move this into the CreateInterfaceObjects for Window
// once it is on WebIDL bindings.
WindowNamedPropertiesHandler::Install(aCx, proto);
return NS_OK;
}
NS_IMETHODIMP
nsWindowSH::PostCreate(nsIXPConnectWrappedNative *wrapper,
JSContext *cx, JSObject *obj)
{
JS::Rooted<JSObject*> window(cx, obj);
#ifdef DEBUG
nsCOMPtr<nsIScriptGlobalObject> sgo(do_QueryWrappedNative(wrapper));
NS_ASSERTION(sgo && sgo->GetGlobalJSObject() == obj,
"Multiple wrappers created for global object!");
#endif
const NativeProperties* windowProperties =
WindowBinding::sNativePropertyHooks->mNativeProperties.regular;
const NativeProperties* eventTargetProperties =
EventTargetBinding::sNativePropertyHooks->mNativeProperties.regular;
if (!DefineWebIDLBindingUnforgeablePropertiesOnXPCObject(cx, window, windowProperties) ||
!DefineWebIDLBindingUnforgeablePropertiesOnXPCObject(cx, window, eventTargetProperties)) {
return NS_ERROR_FAILURE;
}
if (!GlobalPropertiesAreOwn()) {
return NS_OK;
}
return DefineWebIDLBindingPropertiesOnXPCObject(cx, window, windowProperties) &&
DefineWebIDLBindingPropertiesOnXPCObject(cx, window, eventTargetProperties) ?
NS_OK : NS_ERROR_FAILURE;
}
struct ResolveGlobalNameClosure
{
JSContext* cx;
JS::Handle<JSObject*> obj;
bool* retval;
};
static PLDHashOperator
ResolveGlobalName(const nsAString& aName,
const nsGlobalNameStruct& aNameStruct,
void* aClosure)
{
ResolveGlobalNameClosure* closure =
static_cast<ResolveGlobalNameClosure*>(aClosure);
JS::Rooted<JS::Value> dummy(closure->cx);
bool ok = JS_LookupUCProperty(closure->cx, closure->obj,
aName.BeginReading(), aName.Length(),
&dummy);
if (!ok) {
*closure->retval = false;
return PL_DHASH_STOP;
}
return PL_DHASH_NEXT;
}
NS_IMETHODIMP
nsWindowSH::Enumerate(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
JSObject *aObj, bool *_retval)
{
JS::Rooted<JSObject*> obj(cx, aObj);
if (!xpc::WrapperFactory::IsXrayWrapper(obj)) {
*_retval = JS_EnumerateStandardClasses(cx, obj);
if (!*_retval) {
return NS_OK;
}
// Now resolve everything from the namespace manager
nsScriptNameSpaceManager *nameSpaceManager = GetNameSpaceManager();
if (!nameSpaceManager) {
NS_ERROR("Can't get namespace manager.");
return NS_ERROR_UNEXPECTED;
}
ResolveGlobalNameClosure closure = { cx, obj, _retval };
nameSpaceManager->EnumerateGlobalNames(ResolveGlobalName, &closure);
}
return NS_OK;
}
static nsDOMConstructorFunc
FindConstructorFunc(const nsDOMClassInfoData *aDOMClassInfoData)
{
@ -2265,23 +2042,6 @@ GetXPCProto(nsIXPConnect *aXPConnect, JSContext *cx, nsGlobalWindow *aWin,
nsDOMClassInfoID ci_id = (nsDOMClassInfoID)id;
ci = NS_GetDOMClassInfoInstance(ci_id);
// In most cases we want to find the wrapped native prototype in
// aWin's scope and use that prototype for
// ClassName.prototype. But in the case where we're setting up
// "Window.prototype" or "ChromeWindow.prototype" we want to do
// the look up in aWin's outer window's scope since the inner
// window's wrapped native prototype comes from the outer
// window's scope.
if (ci_id == eDOMClassInfo_Window_id ||
ci_id == eDOMClassInfo_ModalContentWindow_id ||
ci_id == eDOMClassInfo_ChromeWindow_id) {
nsGlobalWindow *scopeWindow = aWin->GetOuterWindowInternal();
if (scopeWindow) {
aWin = scopeWindow;
}
}
}
else {
ci = nsDOMClassInfo::GetClassInfoInstance(aNameStruct->mData);
@ -2498,6 +2258,7 @@ LookupComponentsShim(JSContext *cx, JS::Handle<JSObject*> global,
nsPIDOMWindow *win,
JS::MutableHandle<JSPropertyDescriptor> desc);
// static
bool
nsWindowSH::NameStructEnabled(JSContext* aCx, nsGlobalWindow *aWin,
const nsAString& aName,
@ -2732,7 +2493,7 @@ nsWindowSH::GlobalResolve(nsGlobalWindow *aWin, JSContext *cx,
// set up the prototype chain. This will go ahead and define things on the
// actual window's global.
nsCOMPtr<nsIXPConnectJSObjectHolder> proto_holder;
rv = GetXPCProto(sXPConnect, cx, aWin, name_struct,
rv = GetXPCProto(nsDOMClassInfo::sXPConnect, cx, aWin, name_struct,
getter_AddRefs(proto_holder));
NS_ENSURE_SUCCESS(rv, rv);
bool isXray = xpc::WrapperFactory::IsXrayWrapper(obj);
@ -2755,7 +2516,8 @@ nsWindowSH::GlobalResolve(nsGlobalWindow *aWin, JSContext *cx,
ci_data = name_struct->mData;
}
return ResolvePrototype(sXPConnect, aWin, cx, obj, class_name, ci_data,
return ResolvePrototype(nsDOMClassInfo::sXPConnect, aWin, cx, obj,
class_name, ci_data,
name_struct, nameSpaceManager, dot_prototype,
desc);
}
@ -2763,7 +2525,8 @@ nsWindowSH::GlobalResolve(nsGlobalWindow *aWin, JSContext *cx,
if (name_struct->mType == nsGlobalNameStruct::eTypeClassProto) {
// We don't have a XPConnect prototype object, let ResolvePrototype create
// one.
return ResolvePrototype(sXPConnect, aWin, cx, obj, class_name, nullptr,
return ResolvePrototype(nsDOMClassInfo::sXPConnect, aWin, cx, obj,
class_name, nullptr,
name_struct, nameSpaceManager, nullptr, desc);
}
@ -2776,7 +2539,7 @@ nsWindowSH::GlobalResolve(nsGlobalWindow *aWin, JSContext *cx,
// constructor is an alias for (for example for Image we need the prototype
// for HTMLImageElement).
nsCOMPtr<nsIXPConnectJSObjectHolder> proto_holder;
rv = GetXPCProto(sXPConnect, cx, aWin, alias_struct,
rv = GetXPCProto(nsDOMClassInfo::sXPConnect, cx, aWin, alias_struct,
getter_AddRefs(proto_holder));
NS_ENSURE_SUCCESS(rv, rv);
@ -2792,7 +2555,8 @@ nsWindowSH::GlobalResolve(nsGlobalWindow *aWin, JSContext *cx,
return NS_ERROR_UNEXPECTED;
}
return ResolvePrototype(sXPConnect, aWin, cx, obj, class_name, ci_data,
return ResolvePrototype(nsDOMClassInfo::sXPConnect, aWin, cx, obj,
class_name, ci_data,
name_struct, nameSpaceManager, nullptr, desc);
}
@ -2860,77 +2624,6 @@ nsWindowSH::GlobalResolve(nsGlobalWindow *aWin, JSContext *cx,
return rv;
}
template<class Interface>
static nsresult
LocationSetterGuts(JSContext *cx, JSObject *obj, JS::MutableHandle<JS::Value> vp)
{
// This function duplicates some of the logic in XPC_WN_HelperSetProperty
obj = js::CheckedUnwrap(obj, /* stopAtOuter = */ false);
if (!IS_WN_REFLECTOR(obj))
return NS_ERROR_XPC_BAD_CONVERT_JS;
XPCWrappedNative *wrapper = XPCWrappedNative::Get(obj);
// The error checks duplicate code in THROW_AND_RETURN_IF_BAD_WRAPPER
NS_ENSURE_TRUE(!wrapper || wrapper->IsValid(), NS_ERROR_XPC_HAS_BEEN_SHUTDOWN);
nsCOMPtr<Interface> xpcomObj = do_QueryWrappedNative(wrapper, obj);
NS_ENSURE_TRUE(xpcomObj, NS_ERROR_UNEXPECTED);
nsCOMPtr<nsIDOMLocation> location;
nsresult rv = xpcomObj->GetLocation(getter_AddRefs(location));
NS_ENSURE_SUCCESS(rv, rv);
// Grab the value we're being set to before we stomp on |vp|
JS::Rooted<JSString*> val(cx, JS::ToString(cx, vp));
NS_ENSURE_TRUE(val, NS_ERROR_UNEXPECTED);
// Make sure |val| stays alive below
JS::Anchor<JSString *> anchor(val);
// We have to wrap location into vp before null-checking location, to
// avoid assigning the wrong thing into the slot.
rv = WrapNative(cx, location, &NS_GET_IID(nsIDOMLocation), true, vp);
NS_ENSURE_SUCCESS(rv, rv);
if (!location) {
// Make this a no-op
return NS_OK;
}
nsAutoJSString str;
NS_ENSURE_TRUE(str.init(cx, val), NS_ERROR_UNEXPECTED);
return location->SetHref(str);
}
template<class Interface>
static bool
LocationSetter(JSContext *cx, JS::Handle<JSObject*> obj, JS::Handle<jsid> id, bool strict,
JS::MutableHandle<JS::Value> vp)
{
nsresult rv = LocationSetterGuts<Interface>(cx, obj, vp);
if (NS_FAILED(rv)) {
xpc::Throw(cx, rv);
return false;
}
return true;
}
static bool
LocationSetterUnwrapper(JSContext *cx, JS::Handle<JSObject*> obj_, JS::Handle<jsid> id,
bool strict, JS::MutableHandle<JS::Value> vp)
{
JS::Rooted<JSObject*> obj(cx, obj_);
JSObject *wrapped = XPCWrapper::UnsafeUnwrapSecurityWrapper(obj);
if (wrapped) {
obj = wrapped;
}
return LocationSetter<nsIDOMWindow>(cx, obj, id, strict, vp);
}
struct InterfaceShimEntry {
const char *geckoName;
const char *domName;
@ -3019,200 +2712,6 @@ LookupComponentsShim(JSContext *cx, JS::Handle<JSObject*> global,
return NS_OK;
}
NS_IMETHODIMP
nsWindowSH::NewResolve(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
JSObject *obj_, jsid id_, JSObject **objp,
bool *_retval)
{
JS::Rooted<JSObject*> obj(cx, obj_);
JS::Rooted<jsid> id(cx, id_);
if (!JSID_IS_STRING(id)) {
return NS_OK;
}
MOZ_ASSERT(*_retval == true); // guaranteed by XPC_WN_Helper_NewResolve
nsGlobalWindow *win = nsGlobalWindow::FromWrapper(wrapper);
MOZ_ASSERT(win->IsInnerWindow());
// Don't resolve standard classes on XrayWrappers, only resolve them if we're
// resolving on the real global object.
bool isXray = xpc::WrapperFactory::IsXrayWrapper(obj);
if (!isXray) {
bool did_resolve = false;
if (!JS_ResolveStandardClass(cx, obj, id, &did_resolve)) {
// Return NS_OK to avoid stomping over the exception that was passed
// down from the ResolveStandardClass call.
*_retval = false;
return NS_OK;
}
if (did_resolve) {
*objp = obj;
return NS_OK;
}
}
// WebIDL quickstubs handle location for us, but Xrays don't see those. So if
// we're an Xray, we have to resolve stuff here to make "window.location =
// someString" work.
if (sLocation_id == id && isXray) {
nsCOMPtr<nsIDOMLocation> location;
nsresult rv = win->GetLocation(getter_AddRefs(location));
NS_ENSURE_SUCCESS(rv, rv);
JS::Rooted<JS::Value> v(cx);
rv = WrapNative(cx, location, &NS_GET_IID(nsIDOMLocation), true, &v);
NS_ENSURE_SUCCESS(rv, rv);
bool ok = JS_DefinePropertyById(cx, obj, id, v,
JSPROP_PERMANENT | JSPROP_ENUMERATE,
JS_PropertyStub, LocationSetterUnwrapper);
if (!ok) {
return NS_ERROR_FAILURE;
}
*objp = obj;
return NS_OK;
}
// WebIDL quickstubs handle "top" for us, but Xrays don't see those. So if
// we're an Xray and we want "top" to be JSPROP_PERMANENT, we need to resolve
// it here.
if (sTop_id == id && isXray) {
nsCOMPtr<nsIDOMWindow> top;
nsresult rv = win->GetScriptableTop(getter_AddRefs(top));
NS_ENSURE_SUCCESS(rv, rv);
JS::Rooted<JS::Value> v(cx);
js::AssertSameCompartment(cx, obj);
rv = WrapNative(cx, top, &NS_GET_IID(nsIDOMWindow), true, &v);
NS_ENSURE_SUCCESS(rv, rv);
// Hold on to the top window object as a global property so we
// don't need to worry about losing expando properties etc.
if (!JS_DefinePropertyById(cx, obj, id, v,
JSPROP_READONLY | JSPROP_PERMANENT |
JSPROP_ENUMERATE,
JS_PropertyStub, JS_StrictPropertyStub)) {
return NS_ERROR_FAILURE;
}
*objp = obj;
return NS_OK;
}
if (isXray) {
// We promise to resolve on the underlying object first. That will create
// the actual interface object if needed and store it in a data structure
// hanging off the global. Then our second call will wrap up in an Xray as
// needed. We do things this way because we use the existence of the
// object in that data structure as a flag that indicates that its name
// (and any relevant named constructor names) has been resolved before;
// this allows us to avoid re-resolving in the Xray case if the property is
// deleted by page script.
JS::Rooted<JSObject*> global(cx,
js::UncheckedUnwrap(obj, /* stopAtOuter = */ false));
JSAutoCompartment ac(cx, global);
JS::Rooted<JSPropertyDescriptor> desc(cx);
if (!win->DoNewResolve(cx, global, id, &desc)) {
return NS_ERROR_FAILURE;
}
// If we have an object here, that means we resolved the property.
// But if the value is undefined, that means that GlobalResolve
// also already defined it, so we don't have to.
if (desc.object() && !desc.value().isUndefined() &&
!JS_DefinePropertyById(cx, global, id, desc.value(),
desc.attributes(),
desc.getter(), desc.setter())) {
return NS_ERROR_FAILURE;
}
}
JS::Rooted<JSPropertyDescriptor> desc(cx);
if (!win->DoNewResolve(cx, obj, id, &desc)) {
return NS_ERROR_FAILURE;
}
if (desc.object()) {
// If we have an object here, that means we resolved the property.
// But if the value is undefined, that means that GlobalResolve
// also already defined it, so we don't have to. Note that in the
// Xray case we should never see undefined.
MOZ_ASSERT_IF(isXray, !desc.value().isUndefined());
if (!desc.value().isUndefined() &&
!JS_DefinePropertyById(cx, obj, id, desc.value(),
desc.attributes(),
desc.getter(), desc.setter())) {
return NS_ERROR_FAILURE;
}
*objp = obj;
return NS_OK;
}
if (sDocument_id == id) {
nsCOMPtr<nsIDocument> document = win->GetDoc();
JS::Rooted<JS::Value> v(cx);
nsresult rv = WrapNative(cx, document, document,
&NS_GET_IID(nsIDOMDocument), &v, false);
NS_ENSURE_SUCCESS(rv, rv);
// nsIDocument::WrapObject will handle defining the property.
*objp = obj;
// NB: We need to do this for any Xray wrapper.
if (xpc::WrapperFactory::IsXrayWrapper(obj)) {
*_retval = JS_WrapValue(cx, &v) &&
JS_DefineProperty(cx, obj, "document", v,
JSPROP_READONLY | JSPROP_ENUMERATE,
JS_PropertyStub, JS_StrictPropertyStub);
if (!*_retval) {
return NS_ERROR_UNEXPECTED;
}
}
return NS_OK;
}
return nsDOMGenericSH::NewResolve(wrapper, cx, obj, id, objp, _retval);
}
NS_IMETHODIMP
nsWindowSH::OuterObject(nsIXPConnectWrappedNative *wrapper, JSContext * cx,
JSObject * obj, JSObject * *_retval)
{
nsGlobalWindow *origWin = nsGlobalWindow::FromWrapper(wrapper);
nsGlobalWindow *win = origWin->GetOuterWindowInternal();
if (!win) {
// If we no longer have an outer window. No code should ever be
// running on a window w/o an outer, which means this hook should
// never be called when we have no outer. But just in case, return
// null to prevent leaking an inner window to code in a different
// window.
*_retval = nullptr;
return NS_ERROR_UNEXPECTED;
}
JS::Rooted<JSObject*> winObj(cx, win->FastGetGlobalJSObject());
MOZ_ASSERT(winObj);
// Note that while |wrapper| is same-compartment with cx, the outer window
// might not be. If we're running script in an inactive scope and evalute
// |this|, the outer window is actually a cross-compartment wrapper. So we
// need to wrap here.
if (!JS_WrapObject(cx, &winObj)) {
*_retval = nullptr;
return NS_ERROR_UNEXPECTED;
}
*_retval = winObj;
return NS_OK;
}
// EventTarget helper
NS_IMETHODIMP

View File

@ -68,10 +68,11 @@ struct nsExternalDOMClassInfoData : public nsDOMClassInfoData
#define MARK_EXTERNAL(_ptr) (nsIClassInfo*)(uintptr_t(_ptr) | 0x1)
#define IS_EXTERNAL(_ptr) (uintptr_t(_ptr) & 0x1)
class nsWindowSH;
class nsDOMClassInfo : public nsXPCClassInfo
{
friend class nsHTMLDocumentSH;
friend class nsWindowSH;
protected:
virtual ~nsDOMClassInfo();
@ -156,10 +157,7 @@ protected:
static bool sIsInitialized;
public:
static jsid sLocation_id;
static jsid sConstructor_id;
static jsid sTop_id;
static jsid sDocument_id;
static jsid sWrappedJSObject_id;
};
@ -230,46 +228,20 @@ public:
}
};
// Window scriptable helper
class nsWindowSH : public nsDOMGenericSH
// A place to hang some static methods that we should really consider
// moving to be nsGlobalWindow member methods. See bug 1062418.
class nsWindowSH
{
protected:
explicit nsWindowSH(nsDOMClassInfoData *aData) : nsDOMGenericSH(aData)
{
}
virtual ~nsWindowSH()
{
}
static nsresult GlobalResolve(nsGlobalWindow *aWin, JSContext *cx,
JS::Handle<JSObject*> obj, JS::Handle<jsid> id,
JS::MutableHandle<JSPropertyDescriptor> desc);
friend class nsGlobalWindow;
public:
NS_IMETHOD PreCreate(nsISupports *nativeObj, JSContext *cx,
JSObject *globalObj, JSObject **parentObj) MOZ_OVERRIDE;
NS_IMETHOD PostCreatePrototype(JSContext * cx, JSObject * proto) MOZ_OVERRIDE;
NS_IMETHOD PostCreate(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
JSObject *obj) MOZ_OVERRIDE;
NS_IMETHOD Enumerate(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
JSObject *obj, bool *_retval) MOZ_OVERRIDE;
NS_IMETHOD NewResolve(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
JSObject *obj, jsid id, JSObject **objp,
bool *_retval) MOZ_OVERRIDE;
NS_IMETHOD OuterObject(nsIXPConnectWrappedNative *wrapper, JSContext * cx,
JSObject * obj, JSObject * *_retval) MOZ_OVERRIDE;
static bool NameStructEnabled(JSContext* aCx, nsGlobalWindow *aWin,
const nsAString& aName,
const nsGlobalNameStruct& aNameStruct);
static nsIClassInfo *doCreate(nsDOMClassInfoData* aData)
{
return new nsWindowSH(aData);
}
};

View File

@ -4,7 +4,6 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
// IWYU pragma: private, include "nsDOMClassInfoID.h"
DOMCI_CLASS(Window)
DOMCI_CLASS(DOMPrototype)
DOMCI_CLASS(DOMConstructor)
@ -26,9 +25,6 @@ DOMCI_CLASS(TreeSelection)
DOMCI_CLASS(TreeContentView)
#endif
// DOM Chrome Window class, almost identical to Window
DOMCI_CLASS(ChromeWindow)
#ifdef MOZ_XUL
DOMCI_CLASS(XULTemplateBuilder)
DOMCI_CLASS(XULTreeBuilder)
@ -50,9 +46,6 @@ DOMCI_CLASS(XPathNSResolver)
DOMCI_CLASS(Blob)
DOMCI_CLASS(File)
// DOM modal content window class, almost identical to Window
DOMCI_CLASS(ModalContentWindow)
DOMCI_CLASS(MozSmsMessage)
DOMCI_CLASS(MozMmsMessage)
DOMCI_CLASS(MozMobileMessageThread)

View File

@ -3612,6 +3612,23 @@ nsDOMWindowUtils::RunBeforeNextEvent(nsIRunnable *runnable)
return appShell->RunBeforeNextEvent(runnable);
}
NS_IMETHODIMP
nsDOMWindowUtils::RequestCompositorProperty(const nsAString& property,
float* aResult)
{
MOZ_RELEASE_ASSERT(nsContentUtils::IsCallerChrome());
if (nsIWidget* widget = GetWidget()) {
mozilla::layers::LayerManager* manager = widget->GetLayerManager();
if (manager) {
*aResult = manager->RequestProperty(property);
return NS_OK;
}
}
return NS_ERROR_NOT_AVAILABLE;
}
NS_IMETHODIMP
nsDOMWindowUtils::GetOMTAStyle(nsIDOMElement* aElement,
const nsAString& aProperty,

View File

@ -1125,10 +1125,7 @@ nsGlobalWindow::nsGlobalWindow(nsGlobalWindow *aOuterWindow)
// Initialize the PRCList (this).
PR_INIT_CLIST(this);
if (Preferences::GetBool("dom.window_experimental_bindings") ||
!aOuterWindow) {
SetIsDOMBinding();
}
SetIsDOMBinding();
if (aOuterWindow) {
// |this| is an inner window, add this inner window to the outer
@ -1640,20 +1637,12 @@ nsGlobalWindow::FreeInnerObjects()
// nsGlobalWindow::nsISupports
//*****************************************************************************
DOMCI_DATA(Window, nsGlobalWindow)
// QueryInterface implementation for nsGlobalWindow
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsGlobalWindow)
NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
// Make sure this matches the cast in nsGlobalWindow::FromWrapper()
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIDOMEventTarget)
NS_INTERFACE_MAP_ENTRY(nsIDOMWindow)
#ifdef MOZ_B2G
NS_INTERFACE_MAP_ENTRY(nsIDOMWindowB2G)
#endif // MOZ_B2G
#ifdef MOZ_WEBSPEECH
NS_INTERFACE_MAP_ENTRY(nsISpeechSynthesisGetter)
#endif // MOZ_B2G
NS_INTERFACE_MAP_ENTRY(nsIDOMJSWindow)
if (aIID.Equals(NS_GET_IID(nsIDOMWindowInternal))) {
foundInterface = static_cast<nsIDOMWindowInternal*>(this);
@ -1673,10 +1662,6 @@ NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsGlobalWindow)
NS_INTERFACE_MAP_ENTRY(nsPIDOMWindow)
NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference)
NS_INTERFACE_MAP_ENTRY(nsIInterfaceRequestor)
NS_INTERFACE_MAP_ENTRY(nsIDOMWindowPerformance)
NS_INTERFACE_MAP_ENTRY(nsITouchEventReceiver)
NS_INTERFACE_MAP_ENTRY(nsIInlineEventHandlers)
NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(Window)
NS_INTERFACE_MAP_END
@ -2285,22 +2270,10 @@ CreateNativeGlobalForInner(JSContext* aCx,
uint32_t flags = needComponents ? 0 : nsIXPConnect::OMIT_COMPONENTS_OBJECT;
flags |= nsIXPConnect::DONT_FIRE_ONNEWGLOBALHOOK;
if (aNewInner->IsDOMBinding()) {
aGlobal.set(WindowBinding::Wrap(aCx, aNewInner, aNewInner, options,
nsJSPrincipals::get(aPrincipal), false));
if (!aGlobal || !xpc::InitGlobalObject(aCx, aGlobal, flags)) {
return NS_ERROR_FAILURE;
}
} else {
nsIXPConnect* xpc = nsContentUtils::XPConnect();
nsCOMPtr<nsIXPConnectJSObjectHolder> holder;
nsresult rv = xpc->InitClassesWithNewWrappedGlobal(
aCx, ToSupports(aNewInner),
aPrincipal, flags, options, getter_AddRefs(holder));
NS_ENSURE_SUCCESS(rv, rv);
aGlobal.set(holder->GetJSObject());
MOZ_ASSERT(aGlobal);
aGlobal.set(WindowBinding::Wrap(aCx, aNewInner, aNewInner, options,
nsJSPrincipals::get(aPrincipal), false));
if (!aGlobal || !xpc::InitGlobalObject(aCx, aGlobal, flags)) {
return NS_ERROR_FAILURE;
}
MOZ_ASSERT(aNewInner->GetWrapperPreserveColor() == aGlobal);
@ -2403,8 +2376,8 @@ nsGlobalWindow::SetNewDocument(nsIDocument* aDocument,
// having to *always* reach into the inner window to find the
// document.
mDoc = aDocument;
if (IsInnerWindow() && IsDOMBinding()) {
WindowBinding::ClearCachedDocumentValue(cx, this);
if (IsInnerWindow()) {
ClearDocumentDependentSlots(cx);
}
// Take this opportunity to clear mSuspendedDoc. Our old inner window is now
@ -2611,21 +2584,10 @@ nsGlobalWindow::SetNewDocument(nsIDocument* aDocument,
// If we created a new inner window above, we need to do the last little bit
// of initialization now that the dust has settled.
if (createdInnerWindow) {
if (newInnerWindow->IsDOMBinding()) {
JS::Rooted<JSObject*> global(cx, newInnerGlobal);
JS::Rooted<JSObject*> proto(cx);
JS_GetPrototype(cx, global, &proto);
WindowNamedPropertiesHandler::Install(cx, proto);
} else {
nsIXPConnect *xpc = nsContentUtils::XPConnect();
nsCOMPtr<nsIXPConnectWrappedNative> wrapper;
nsresult rv = xpc->GetWrappedNativeOfJSObject(cx, newInnerGlobal,
getter_AddRefs(wrapper));
NS_ENSURE_SUCCESS(rv, rv);
NS_ABORT_IF_FALSE(wrapper, "bad wrapper");
rv = wrapper->FinishInitForWrappedGlobal();
NS_ENSURE_SUCCESS(rv, rv);
}
JS::Rooted<JSObject*> global(cx, newInnerGlobal);
JS::Rooted<JSObject*> proto(cx);
JS_GetPrototype(cx, global, &proto);
WindowNamedPropertiesHandler::Install(cx, proto);
}
if (!aState) {
@ -2682,17 +2644,7 @@ nsGlobalWindow::SetNewDocument(nsIDocument* aDocument,
newInnerWindow->mLocalStorage = nullptr;
newInnerWindow->mSessionStorage = nullptr;
if (newInnerWindow->IsDOMBinding()) {
WindowBinding::ClearCachedDocumentValue(cx, newInnerWindow);
} else {
// We're reusing the inner window for a new document. In this
// case we don't clear the inner window's scope, but we must
// make sure the cached document property gets updated.
JS::Rooted<JSObject*> obj(cx,
currentInner->GetWrapperPreserveColor());
::JS_DeleteProperty(cx, obj, "document");
}
newInnerWindow->ClearDocumentDependentSlots(cx);
}
} else {
newInnerWindow->InnerSetNewDocument(cx, aDocument);
@ -2834,9 +2786,7 @@ nsGlobalWindow::InnerSetNewDocument(JSContext* aCx, nsIDocument* aDocument)
#endif
mDoc = aDocument;
if (IsDOMBinding()) {
WindowBinding::ClearCachedDocumentValue(aCx, this);
}
ClearDocumentDependentSlots(aCx);
mFocusedNode = nullptr;
mLocalStorage = nullptr;
mSessionStorage = nullptr;
@ -3644,25 +3594,11 @@ nsGlobalWindow::GetHistory(nsISupports** aHistory)
}
nsPerformance*
nsGlobalWindow::GetPerformance(ErrorResult& aError)
nsGlobalWindow::GetPerformance()
{
FORWARD_TO_INNER_OR_THROW(GetPerformance, (aError), aError, nullptr);
FORWARD_TO_INNER(GetPerformance, (), nullptr);
nsPerformance* p = nsPIDOMWindow::GetPerformance();
if (!p) {
aError.Throw(NS_ERROR_FAILURE);
}
return p;
}
NS_IMETHODIMP
nsGlobalWindow::GetPerformance(nsISupports** aPerformance)
{
ErrorResult rv;
nsCOMPtr<nsISupports> performance = GetPerformance(rv);
performance.forget(aPerformance);
return rv.ErrorCode();
return nsPIDOMWindow::GetPerformance();
}
nsPerformance*
@ -3830,19 +3766,6 @@ nsGlobalWindow::GetSpeechSynthesis(ErrorResult& aError)
return mSpeechSynthesis;
}
NS_IMETHODIMP
nsGlobalWindow::GetSpeechSynthesis(nsISupports** aSpeechSynthesis)
{
ErrorResult rv;
nsCOMPtr<nsISupports> speechSynthesis;
if (Preferences::GetBool("media.webspeech.synth.enabled")) {
speechSynthesis = GetSpeechSynthesis(rv);
}
speechSynthesis.forget(aSpeechSynthesis);
return rv.ErrorCode();
}
#endif
already_AddRefed<nsIDOMWindow>
@ -13409,12 +13332,9 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(nsGlobalChromeWindow,
NS_IMPL_CYCLE_COLLECTION_UNLINK(mGroupMessageManagers)
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
DOMCI_DATA(ChromeWindow, nsGlobalChromeWindow)
// QueryInterface implementation for nsGlobalChromeWindow
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(nsGlobalChromeWindow)
NS_INTERFACE_MAP_ENTRY(nsIDOMChromeWindow)
NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(ChromeWindow)
NS_INTERFACE_MAP_END_INHERITING(nsGlobalWindow)
NS_IMPL_ADDREF_INHERITED(nsGlobalChromeWindow, nsGlobalWindow)
@ -13811,11 +13731,8 @@ nsGlobalWindow::GetGroupMessageManager(const nsAString& aGroup,
// nsGlobalModalWindow implementation
// QueryInterface implementation for nsGlobalModalWindow
DOMCI_DATA(ModalContentWindow, nsGlobalModalWindow)
NS_INTERFACE_MAP_BEGIN(nsGlobalModalWindow)
NS_INTERFACE_MAP_ENTRY(nsIDOMModalContentWindow)
NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(ModalContentWindow)
NS_INTERFACE_MAP_END_INHERITING(nsGlobalWindow)
NS_IMPL_ADDREF_INHERITED(nsGlobalModalWindow, nsGlobalWindow)
@ -13928,7 +13845,6 @@ nsGlobalModalWindow::SetReturnValue(nsIVariant *aRetVal)
bool
nsGlobalWindow::IsModalContentWindow(JSContext* aCx, JSObject* aGlobal)
{
// For now, have to deal with XPConnect objects here.
return xpc::WindowOrNull(aGlobal)->IsModalContentWindow();
}
@ -14027,15 +13943,13 @@ nsGlobalWindow::GetSidebar(OwningExternalOrWindowProxy& aResult,
#endif
}
/* static */
bool
nsGlobalWindow::WindowOnWebIDL(JSContext* aCx, JSObject* aObj)
void
nsGlobalWindow::ClearDocumentDependentSlots(JSContext* aCx)
{
DebugOnly<nsGlobalWindow*> win;
MOZ_ASSERT_IF(IsDOMObject(aObj),
NS_SUCCEEDED(UNWRAP_OBJECT(Window, aObj, win)));
return IsDOMObject(aObj);
MOZ_ASSERT(IsInnerWindow());
MOZ_ASSERT(IsDOMBinding());
WindowBinding::ClearCachedDocumentValue(aCx, this);
WindowBinding::ClearCachedPerformanceValue(aCx, this);
}
#ifdef MOZ_B2G
@ -14108,94 +14022,6 @@ nsGlobalWindow::DisableNetworkEvent(uint32_t aType)
}
#endif // MOZ_B2G
#define EVENT(name_, id_, type_, struct_) \
NS_IMETHODIMP nsGlobalWindow::GetOn##name_(JSContext *cx, \
JS::MutableHandle<JS::Value> vp) { \
EventHandlerNonNull* h = GetOn##name_(); \
vp.setObjectOrNull(h ? h->Callable().get() : nullptr); \
return NS_OK; \
} \
NS_IMETHODIMP nsGlobalWindow::SetOn##name_(JSContext *cx, \
JS::Handle<JS::Value> v) { \
nsRefPtr<EventHandlerNonNull> handler; \
JS::Rooted<JSObject*> callable(cx); \
if (v.isObject() && \
JS_ObjectIsCallable(cx, callable = &v.toObject())) { \
handler = new EventHandlerNonNull(callable, GetIncumbentGlobal()); \
} \
SetOn##name_(handler); \
return NS_OK; \
}
#define ERROR_EVENT(name_, id_, type_, struct_) \
NS_IMETHODIMP nsGlobalWindow::GetOn##name_(JSContext *cx, \
JS::MutableHandle<JS::Value> vp) { \
EventListenerManager *elm = GetExistingListenerManager(); \
if (elm) { \
OnErrorEventHandlerNonNull* h = elm->GetOnErrorEventHandler(); \
if (h) { \
vp.setObject(*h->Callable()); \
return NS_OK; \
} \
} \
vp.setNull(); \
return NS_OK; \
} \
NS_IMETHODIMP nsGlobalWindow::SetOn##name_(JSContext *cx, \
JS::Handle<JS::Value> v) { \
EventListenerManager *elm = GetOrCreateListenerManager(); \
if (!elm) { \
return NS_ERROR_OUT_OF_MEMORY; \
} \
\
nsRefPtr<OnErrorEventHandlerNonNull> handler; \
JS::Rooted<JSObject*> callable(cx); \
if (v.isObject() && \
JS_ObjectIsCallable(cx, callable = &v.toObject())) { \
handler = new OnErrorEventHandlerNonNull(callable, GetIncumbentGlobal()); \
} \
elm->SetEventHandler(handler); \
return NS_OK; \
}
#define BEFOREUNLOAD_EVENT(name_, id_, type_, struct_) \
NS_IMETHODIMP nsGlobalWindow::GetOn##name_(JSContext *cx, \
JS::MutableHandle<JS::Value> vp) { \
EventListenerManager *elm = GetExistingListenerManager(); \
if (elm) { \
OnBeforeUnloadEventHandlerNonNull* h = \
elm->GetOnBeforeUnloadEventHandler(); \
if (h) { \
vp.setObject(*h->Callable()); \
return NS_OK; \
} \
} \
vp.setNull(); \
return NS_OK; \
} \
NS_IMETHODIMP nsGlobalWindow::SetOn##name_(JSContext *cx, \
JS::Handle<JS::Value> v) { \
EventListenerManager *elm = GetOrCreateListenerManager(); \
if (!elm) { \
return NS_ERROR_OUT_OF_MEMORY; \
} \
\
nsRefPtr<OnBeforeUnloadEventHandlerNonNull> handler; \
JS::Rooted<JSObject*> callable(cx); \
if (v.isObject() && \
JS_ObjectIsCallable(cx, callable = &v.toObject())) { \
handler = new OnBeforeUnloadEventHandlerNonNull(callable, GetIncumbentGlobal()); \
} \
elm->SetEventHandler(handler); \
return NS_OK; \
}
#define WINDOW_ONLY_EVENT EVENT
#define TOUCH_EVENT EVENT
#include "mozilla/EventNameList.h"
#undef TOUCH_EVENT
#undef WINDOW_ONLY_EVENT
#undef BEFOREUNLOAD_EVENT
#undef ERROR_EVENT
#undef EVENT
#ifdef _WINDOWS_
#error "Never include windows.h in this file!"
#endif

View File

@ -43,24 +43,14 @@
#include "nsFrameMessageManager.h"
#include "mozilla/LinkedList.h"
#include "mozilla/TimeStamp.h"
#include "nsIInlineEventHandlers.h"
#include "nsWrapperCacheInlines.h"
#include "nsIIdleObserver.h"
#include "nsIDocument.h"
#include "nsIDOMTouchEvent.h"
#include "mozilla/dom/EventTarget.h"
#include "mozilla/dom/WindowBinding.h"
#include "Units.h"
#include "nsComponentManagerUtils.h"
#ifdef MOZ_B2G
#include "nsIDOMWindowB2G.h"
#endif // MOZ_B2G
#ifdef MOZ_WEBSPEECH
#include "nsISpeechSynthesisGetter.h"
#endif // MOZ_WEBSPEECH
#define DEFAULT_HOME_PAGE "www.mozilla.org"
#define PREF_BROWSER_STARTUP_HOMEPAGE "browser.startup.homepage"
@ -329,16 +319,7 @@ class nsGlobalWindow : public mozilla::dom::EventTarget,
public nsIDOMJSWindow,
public nsSupportsWeakReference,
public nsIInterfaceRequestor,
public PRCListStr,
public nsIDOMWindowPerformance,
public nsITouchEventReceiver,
public nsIInlineEventHandlers
#ifdef MOZ_B2G
, public nsIDOMWindowB2G
#endif // MOZ_B2G
#ifdef MOZ_WEBSPEECH
, public nsISpeechSynthesisGetter
#endif // MOZ_WEBSPEECH
public PRCListStr
{
public:
typedef mozilla::TimeStamp TimeStamp;
@ -387,19 +368,6 @@ public:
// nsIDOMWindow
NS_DECL_NSIDOMWINDOW
#ifdef MOZ_B2G
// nsIDOMWindowB2G
NS_DECL_NSIDOMWINDOWB2G
#endif // MOZ_B2G
#ifdef MOZ_WEBSPEECH
// nsISpeechSynthesisGetter
NS_DECL_NSISPEECHSYNTHESISGETTER
#endif // MOZ_WEBSPEECH
// nsIDOMWindowPerformance
NS_DECL_NSIDOMWINDOWPERFORMANCE
// nsIDOMJSWindow
NS_DECL_NSIDOMJSWINDOW
@ -427,12 +395,6 @@ public:
return GetOuterFromCurrentInner(this);
}
// nsITouchEventReceiver
NS_DECL_NSITOUCHEVENTRECEIVER
// nsIInlineEventHandlers
NS_DECL_NSIINLINEEVENTHANDLERS
// nsPIDOMWindow
virtual nsPIDOMWindow* GetPrivateRoot();
@ -823,8 +785,6 @@ public:
return nullptr;
}
static bool WindowOnWebIDL(JSContext* /* unused */, JSObject* aObj);
nsIDOMWindow* GetWindow(mozilla::ErrorResult& aError);
nsIDOMWindow* GetSelf(mozilla::ErrorResult& aError);
nsIDocument* GetDocument()
@ -973,7 +933,7 @@ public:
int32_t RequestAnimationFrame(mozilla::dom::FrameRequestCallback& aCallback,
mozilla::ErrorResult& aError);
void CancelAnimationFrame(int32_t aHandle, mozilla::ErrorResult& aError);
nsPerformance* GetPerformance(mozilla::ErrorResult& aError);
nsPerformance* GetPerformance();
#ifdef MOZ_WEBSPEECH
mozilla::dom::SpeechSynthesis*
GetSpeechSynthesis(mozilla::ErrorResult& aError);
@ -1399,6 +1359,8 @@ protected:
inline int32_t DOMMinTimeoutValue() const;
// Clear the document-dependent slots on our JS wrapper. Inner windows only.
void ClearDocumentDependentSlots(JSContext* aCx);
// Inner windows only.
already_AddRefed<mozilla::dom::StorageEvent>

View File

@ -1596,7 +1596,6 @@ DOMInterfaces = {
'Window': {
'nativeType': 'nsGlobalWindow',
'hasXPConnectImpls': True,
'binaryNames': {
'postMessage': 'postMessageMoz',
},

View File

@ -2956,12 +2956,6 @@ def CreateBindingJSObject(descriptor, properties, parent):
js::SetReservedSlot(obj, DOM_OBJECT_SLOT, PRIVATE_TO_JSVAL(aObject));
""",
parent=parent)
if "Window" in descriptor.interface.identifier.name:
create = dedent("""
MOZ_ASSERT(false,
"Our current reserved slot situation is unsafe for globals. Fix "
"bug 760095!");
""") + create
create = objDecl + create
if descriptor.nativeOwnership == 'refcounted':
@ -5287,7 +5281,7 @@ class CGArgumentConverter(CGThing):
"args.hasDefined(${index})").substitute(replacer)
self.replacementVariables["haveValue"] = haveValueCheck
self.descriptorProvider = descriptorProvider
if self.argument.optional and not self.argument.defaultValue:
if self.argument.canHaveMissingValue():
self.argcAndIndex = replacer
else:
self.argcAndIndex = None
@ -6130,10 +6124,9 @@ class CGCallGenerator(CGThing):
return True
if a.type.isString():
return True
if a.optional and not a.defaultValue:
# If a.defaultValue, then it's not going to use an Optional,
# so doesn't need to be const just due to being optional.
# This also covers variadic arguments.
if a.canHaveMissingValue():
# This will need an Optional or it's a variadic;
# in both cases it should be const.
return True
if a.type.isUnion():
return True
@ -6350,7 +6343,7 @@ def wrapArgIntoCurrentCompartment(arg, value, isMember=True):
As wrapTypeIntoCurrentCompartment but handles things being optional
"""
origValue = value
isOptional = arg.optional and not arg.defaultValue
isOptional = arg.canHaveMissingValue()
if isOptional:
value = value + ".Value()"
wrap = wrapTypeIntoCurrentCompartment(arg.type, value, isMember)
@ -6857,8 +6850,7 @@ class CGMethodCall(CGThing):
# enough that we can examine this argument. But note that we
# still want to claim that optional arguments are optional, in
# case undefined was passed in.
argIsOptional = (distinguishingArgument(signature).optional and
not distinguishingArgument(signature).defaultValue)
argIsOptional = distinguishingArgument(signature).canHaveMissingValue()
testCode = instantiateJSToNativeConversion(
getJSToNativeConversionInfo(type, descriptor,
failureCode=failureCode,
@ -7144,6 +7136,9 @@ class FakeArgument():
def allowTreatNonCallableAsNull(self):
return self._allowTreatNonCallableAsNull
def canHaveMissingValue(self):
return False
class CGSetterCall(CGPerSignatureCall):
"""
@ -7675,9 +7670,7 @@ class CGSpecializedGetter(CGAbstractStaticMethod):
nativeName = CGSpecializedGetter.makeNativeName(self.descriptor,
self.attr)
if self.attr.slotIndex is not None:
if (self.descriptor.hasXPConnectImpls and
(self.descriptor.interface.identifier.name != 'Window' or
self.attr.identifier.name != 'document')):
if self.descriptor.hasXPConnectImpls:
raise TypeError("Interface '%s' has XPConnect impls, so we "
"can't use our slot for property '%s'!" %
(self.descriptor.interface.identifier.name,
@ -11119,10 +11112,9 @@ class CGDictionary(CGThing):
isEnforceRange=member.enforceRange,
isClamp=member.clamp,
isMember="Dictionary",
isOptional=(not member.defaultValue),
isOptional=member.canHaveMissingValue(),
defaultValue=member.defaultValue,
sourceDescription=("'%s' member of %s" %
(member.identifier.name, dictionary.identifier.name))))
sourceDescription=self.getMemberSourceDescription(member)))
for member in dictionary.members]
# If we have a union member containing something in the same
@ -11322,7 +11314,7 @@ class CGDictionary(CGThing):
self.makeClassName(self.dictionary.parent)))
for m, _ in self.memberInfo:
memberName = self.makeMemberName(m.identifier.name)
if not m.defaultValue:
if m.canHaveMissingValue():
memberAssign = CGGeneric(fill(
"""
if (aOther.${name}.WasPassed()) {
@ -11476,6 +11468,19 @@ class CGDictionary(CGThing):
"}\n")
if member.defaultValue:
conversion += "${convert}"
elif not conversionInfo.dealWithOptional:
# We're required, but have no default value. Make sure
# that we throw if we have no value provided.
conversion += dedent(
"""
// Skip the undefined check if we have no cx. In that
// situation the caller is default-constructing us and we'll
// just assume they know what they're doing.
if (cx && (isNull || temp->isUndefined())) {
return ThrowErrorMessage(cx, MSG_MISSING_REQUIRED_DICTIONARY_MEMBER,
"%s");
}
${convert}""" % self.getMemberSourceDescription(member))
else:
conversion += (
"if (!isNull && !temp->isUndefined()) {\n"
@ -11491,7 +11496,7 @@ class CGDictionary(CGThing):
member = memberInfo[0]
declType = memberInfo[1].declType
memberLoc = self.makeMemberName(member.identifier.name)
if member.defaultValue:
if not member.canHaveMissingValue():
memberData = memberLoc
else:
# The data is inside the Optional<>
@ -11547,7 +11552,7 @@ class CGDictionary(CGThing):
pre=("do {\n"
" // block for our 'break' successCode and scope for 'temp' and 'currentValue'\n"),
post="} while(0);\n")
if not member.defaultValue:
if member.canHaveMissingValue():
# Only do the conversion if we have a value
conversion = CGIfWrapper(conversion, "%s.WasPassed()" % memberLoc)
return conversion
@ -11556,7 +11561,7 @@ class CGDictionary(CGThing):
type = member.type
assert typeNeedsRooting(type)
memberLoc = self.makeMemberName(member.identifier.name)
if member.defaultValue:
if not member.canHaveMissingValue():
memberData = memberLoc
else:
# The data is inside the Optional<>
@ -11597,7 +11602,7 @@ class CGDictionary(CGThing):
else:
assert False # unknown type
if not member.defaultValue:
if member.canHaveMissingValue():
trace = CGIfWrapper(trace, "%s.WasPassed()" % memberLoc)
return trace.define()
@ -11609,8 +11614,8 @@ class CGDictionary(CGThing):
value, so they're safe to trace at all times.
"""
member, _ = memberInfo
if not member.defaultValue:
# No default value means no need to set it up front, since it's
if member.canHaveMissingValue():
# Allowed missing value means no need to set it up front, since it's
# inside an Optional and won't get traced until it's actually set
# up.
return None
@ -11621,6 +11626,10 @@ class CGDictionary(CGThing):
return "nullptr"
return None
def getMemberSourceDescription(self, member):
return ("'%s' member of %s" %
(member.identifier.name, self.dictionary.identifier.name))
@staticmethod
def makeIdName(name):
return name.replace("-", "_") + "_id"
@ -12526,8 +12535,7 @@ class CGNativeMember(ClassMethod):
"""
Get the full argument declaration for an argument
"""
decl, ref = self.getArgType(arg.type,
arg.optional and not arg.defaultValue,
decl, ref = self.getArgType(arg.type, arg.canHaveMissingValue(),
"Variadic" if arg.variadic else False)
if ref:
decl = CGWrapper(decl, pre="const ", post="&")
@ -13606,7 +13614,7 @@ class CallbackMember(CGNativeMember):
jsvalIndex = "%d + idx" % i
else:
jsvalIndex = "%d" % i
if arg.optional and not arg.defaultValue:
if arg.canHaveMissingValue():
argval += ".Value()"
if arg.type.isDOMString():
# XPConnect string-to-JS conversion wants to mutate the string. So
@ -13649,7 +13657,7 @@ class CallbackMember(CGNativeMember):
""",
arg=arg.identifier.name,
conversion=conversion)
elif arg.optional and not arg.defaultValue:
elif arg.canHaveMissingValue():
conversion = fill(
"""
if (${argName}.WasPassed()) {
@ -14383,7 +14391,7 @@ class CGEventMethod(CGNativeMember):
def getArg(self, arg):
decl, ref = self.getArgType(arg.type,
arg.optional and not arg.defaultValue,
arg.canHaveMissingValue(),
"Variadic" if arg.variadic else False)
if ref:
decl = CGWrapper(decl, pre="const ", post="&")

View File

@ -59,3 +59,4 @@ MSG_DEF(MSG_INVALID_HEADER_NAME, 1, "{0} is an invalid header name.")
MSG_DEF(MSG_INVALID_HEADER_VALUE, 1, "{0} is an invalid header value.")
MSG_DEF(MSG_INVALID_HEADER_SEQUENCE, 0, "Headers require name/value tuples when being initialized by a sequence.")
MSG_DEF(MSG_PERMISSION_DENIED_TO_PASS_ARG, 1, "Permission denied to pass cross-origin object as {0}.")
MSG_DEF(MSG_MISSING_REQUIRED_DICTIONARY_MEMBER, 1, "Missing required {0}.")

View File

@ -2,11 +2,6 @@
<html>
<head>
<script>
/*
user_pref("dom.window_experimental_bindings", true);
*/
function boom()
{
window.__proto__ = null;

View File

@ -2,11 +2,6 @@
<html>
<head>
<script>
/*
user_pref("dom.window_experimental_bindings", true);
*/
function boom()
{
window.__proto__ = function(){};

View File

@ -3474,6 +3474,9 @@ class IDLArgument(IDLObjectWithIdentifier):
deps.add(self.defaultValue)
return deps
def canHaveMissingValue(self):
return self.optional and not self.defaultValue
class IDLCallbackType(IDLType, IDLObjectWithScope):
def __init__(self, location, parentScope, identifier, returnType, arguments):
assert isinstance(returnType, IDLType)
@ -4141,8 +4144,8 @@ class Tokenizer(object):
"long": "LONG",
"object": "OBJECT",
"octet": "OCTET",
"optional": "OPTIONAL",
"Promise": "PROMISE",
"required": "REQUIRED",
"sequence": "SEQUENCE",
"MozMap": "MOZMAP",
"short": "SHORT",
@ -4427,15 +4430,21 @@ class Parser(Tokenizer):
def p_DictionaryMember(self, p):
"""
DictionaryMember : Type IDENTIFIER Default SEMICOLON
DictionaryMember : Required Type IDENTIFIER Default SEMICOLON
"""
# These quack a lot like optional arguments, so just treat them that way.
t = p[1]
t = p[2]
assert isinstance(t, IDLType)
identifier = IDLUnresolvedIdentifier(self.getLocation(p, 2), p[2])
defaultValue = p[3]
identifier = IDLUnresolvedIdentifier(self.getLocation(p, 3), p[3])
defaultValue = p[4]
optional = not p[1]
p[0] = IDLArgument(self.getLocation(p, 2), identifier, t, optional=True,
if not optional and defaultValue:
raise WebIDLError("Required dictionary members can't have a default value.",
[self.getLocation(p, 4)])
p[0] = IDLArgument(self.getLocation(p, 3), identifier, t,
optional=optional,
defaultValue=defaultValue, variadic=False,
dictionaryMember=True)
@ -4633,7 +4642,7 @@ class Parser(Tokenizer):
def p_AttributeRest(self, p):
"""
AttributeRest : ReadOnly ATTRIBUTE Type IDENTIFIER SEMICOLON
AttributeRest : ReadOnly ATTRIBUTE Type AttributeName SEMICOLON
"""
location = self.getLocation(p, 2)
readonly = p[1]
@ -4962,6 +4971,7 @@ class Parser(Tokenizer):
| INTERFACE
| LEGACYCALLER
| PARTIAL
| REQUIRED
| SERIALIZER
| SETTER
| STATIC
@ -4972,6 +4982,13 @@ class Parser(Tokenizer):
"""
p[0] = p[1]
def p_AttributeName(self, p):
"""
AttributeName : IDENTIFIER
| REQUIRED
"""
p[0] = p[1]
def p_Optional(self, p):
"""
Optional : OPTIONAL
@ -4984,6 +5001,18 @@ class Parser(Tokenizer):
"""
p[0] = False
def p_Required(self, p):
"""
Required : REQUIRED
"""
p[0] = True
def p_RequiredEmpty(self, p):
"""
Required :
"""
p[0] = False
def p_Ellipsis(self, p):
"""
Ellipsis : ELLIPSIS

View File

@ -951,6 +951,9 @@ dictionary Dict : ParentDict {
sequence<long>? seq5 = [];
long dashed-name;
required long requiredLong;
required object requiredObject;
};
dictionary ParentDict : GrandparentDict {

View File

@ -3496,22 +3496,6 @@ CanvasRenderingContext2D::DrawDirectlyToCanvas(
NS_ENSURE_SUCCESS_VOID(rv);
}
static bool
IsStandardCompositeOp(CompositionOp op)
{
return (op == CompositionOp::OP_SOURCE ||
op == CompositionOp::OP_ATOP ||
op == CompositionOp::OP_IN ||
op == CompositionOp::OP_OUT ||
op == CompositionOp::OP_OVER ||
op == CompositionOp::OP_DEST_IN ||
op == CompositionOp::OP_DEST_OUT ||
op == CompositionOp::OP_DEST_OVER ||
op == CompositionOp::OP_DEST_ATOP ||
op == CompositionOp::OP_ADD ||
op == CompositionOp::OP_XOR);
}
void
CanvasRenderingContext2D::SetGlobalCompositeOperation(const nsAString& op,
ErrorResult& error)
@ -3551,10 +3535,6 @@ CanvasRenderingContext2D::SetGlobalCompositeOperation(const nsAString& op,
// XXX ERRMSG we need to report an error to developers here! (bug 329026)
else return;
if (!IsStandardCompositeOp(comp_op)) {
Demote();
}
#undef CANVAS_OP_TO_GFX_OP
CurrentState().op = comp_op;
}
@ -3599,10 +3579,6 @@ CanvasRenderingContext2D::GetGlobalCompositeOperation(nsAString& op,
error.Throw(NS_ERROR_FAILURE);
}
if (!IsStandardCompositeOp(comp_op)) {
Demote();
}
#undef CANVAS_OP_TO_GFX_OP
}

View File

@ -38,15 +38,5 @@ XPIDL_SOURCES += [
'nsITabParent.idl',
]
if CONFIG['MOZ_B2G']:
XPIDL_SOURCES += [
'nsIDOMWindowB2G.idl',
]
if CONFIG['MOZ_WEBSPEECH']:
XPIDL_SOURCES += [
'nsISpeechSynthesisGetter.idl'
]
XPIDL_MODULE = 'dom_base'

View File

@ -23,7 +23,7 @@ interface nsIVariant;
* @see <http://www.whatwg.org/html/#window>
*/
[scriptable, uuid(ed7cc4e4-cf5b-42af-9c2e-8df074a01470)]
[scriptable, uuid(3addc629-754d-4a2a-99a3-449ed1a2e4bd)]
interface nsIDOMWindow : nsISupports
{
// the current browsing context
@ -478,56 +478,12 @@ interface nsIDOMWindow : nsISupports
*/
readonly attribute long long mozAnimationStartTime;
/**
* HTML5 event attributes that only apply to windows and <body>/<frameset>
*/
[implicit_jscontext] attribute jsval onafterprint;
[implicit_jscontext] attribute jsval onbeforeprint;
[implicit_jscontext] attribute jsval onbeforeunload;
[implicit_jscontext] attribute jsval onhashchange;
[implicit_jscontext] attribute jsval onlanguagechange;
[implicit_jscontext] attribute jsval onmessage;
[implicit_jscontext] attribute jsval onoffline;
[implicit_jscontext] attribute jsval ononline;
[implicit_jscontext] attribute jsval onpopstate;
[implicit_jscontext] attribute jsval onpagehide;
[implicit_jscontext] attribute jsval onpageshow;
// Not supported yet
// [implicit_jscontext] attribute jsval onredo;
[implicit_jscontext] attribute jsval onresize;
// Not supported yet
// [implicit_jscontext] attribute jsval onstorage;
// Not supported yet
// [implicit_jscontext] attribute jsval onundo;
[implicit_jscontext] attribute jsval onunload;
/**
* Non-HTML5 window-specific event attributes
*/
[implicit_jscontext] attribute jsval ondevicemotion;
[implicit_jscontext] attribute jsval ondeviceorientation;
[implicit_jscontext] attribute jsval ondeviceproximity;
[implicit_jscontext] attribute jsval onuserproximity;
[implicit_jscontext] attribute jsval ondevicelight;
[implicit_jscontext] attribute jsval onmouseenter;
[implicit_jscontext] attribute jsval onmouseleave;
/**
* Console API
*/
[implicit_jscontext] attribute jsval console;
};
[scriptable, uuid(2146c906-57f7-486c-a1b4-8cdb57ef577f)]
interface nsIDOMWindowPerformance : nsISupports
{
/**
* A namespace to hold performance related data and statistics.
*/
readonly attribute nsISupports performance;
};
/**
* Empty interface for compatibility with older versions.
* @deprecated Use nsIDOMWindow instead

View File

@ -1,14 +0,0 @@
/* -*- 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(96bde2ae-9b74-4f4d-b674-664a67a35b7e)]
interface nsIDOMWindowB2G : nsISupports
{
[implicit_jscontext] attribute jsval onmoztimechange;
[implicit_jscontext] attribute jsval onmoznetworkupload;
[implicit_jscontext] attribute jsval onmoznetworkdownload;
};

View File

@ -51,7 +51,7 @@ interface nsITranslationNodeList;
interface nsIJSRAIIHelper;
interface nsIContentPermissionRequest;
[scriptable, uuid(11911980-607c-4efd-aacc-de3b9005c058)]
[scriptable, uuid(669095d8-1b96-472f-a48d-022adde26cfd)]
interface nsIDOMWindowUtils : nsISupports {
/**
@ -1673,6 +1673,18 @@ interface nsIDOMWindowUtils : nsISupports {
*/
AString getOMTAStyle(in nsIDOMElement aElement, in AString aProperty);
/**
* Special function that gets a property syncronously from the last composite
* that occured.
*
* Supported properties:
* "overdraw": Report a percentage between 0 and 999 indicate how many times
* each pixels on the destination window have been touched.
* "missed_hwc": Report a bool if hardware composer is supported but was
* not used for the last frame.
*/
float requestCompositorProperty(in AString aProperty);
/**
* If aHandlingInput is true, this informs the event state manager that
* we're handling user input. Otherwise, this is a no-op (as by default

View File

@ -1,17 +0,0 @@
/* -*- 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"
/**
* SpeechSynthesisGetter
* http://dvcs.w3.org/hg/speech-api/raw-file/tip/speechapi.html#tts-section
*/
[scriptable, uuid(31e6c818-0279-4948-843c-930043f6bafd)]
interface nsISpeechSynthesisGetter : nsISupports
{
readonly attribute nsISupports speechSynthesis;
};

View File

@ -23,7 +23,6 @@ XPIDL_SOURCES += [
'nsIDOMText.idl',
'nsIDOMUserDataHandler.idl',
'nsIDOMXMLDocument.idl',
'nsIInlineEventHandlers.idl',
]
XPIDL_MODULE = 'dom_core'

View File

@ -1,93 +0,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/. */
#include "domstubs.idl"
%{ C++
#include "jspubtd.h"
%}
[scriptable, uuid(6c1fcf3d-119b-4cf4-9437-b9357508976a)]
interface nsIInlineEventHandlers : nsISupports
{
[implicit_jscontext] attribute jsval onabort;
[implicit_jscontext] attribute jsval onblur;
[implicit_jscontext] attribute jsval oncanplay;
[implicit_jscontext] attribute jsval oncanplaythrough;
[implicit_jscontext] attribute jsval onchange;
[implicit_jscontext] attribute jsval onclick;
[implicit_jscontext] attribute jsval oncontextmenu;
// Not supported yet
// [implicit_jscontext] attribute jsval oncuechange;
[implicit_jscontext] attribute jsval ondblclick;
[implicit_jscontext] attribute jsval ondrag;
[implicit_jscontext] attribute jsval ondragend;
[implicit_jscontext] attribute jsval ondragenter;
[implicit_jscontext] attribute jsval ondragleave;
[implicit_jscontext] attribute jsval ondragover;
[implicit_jscontext] attribute jsval ondragstart;
[implicit_jscontext] attribute jsval ondrop;
[implicit_jscontext] attribute jsval ondurationchange;
[implicit_jscontext] attribute jsval onemptied;
[implicit_jscontext] attribute jsval onended;
[implicit_jscontext] attribute jsval onerror;
[implicit_jscontext] attribute jsval onfocus;
[implicit_jscontext] attribute jsval oninput;
[implicit_jscontext] attribute jsval oninvalid;
[implicit_jscontext] attribute jsval onkeydown;
[implicit_jscontext] attribute jsval onkeypress;
[implicit_jscontext] attribute jsval onkeyup;
[implicit_jscontext] attribute jsval onload;
[implicit_jscontext] attribute jsval onloadeddata;
[implicit_jscontext] attribute jsval onloadedmetadata;
[implicit_jscontext] attribute jsval onloadstart;
[implicit_jscontext] attribute jsval onmousedown;
[implicit_jscontext] attribute jsval onmousemove;
[implicit_jscontext] attribute jsval onmouseout;
[implicit_jscontext] attribute jsval onmouseover;
[implicit_jscontext] attribute jsval onmouseup;
// Not supported yet
// [implicit_jscontext] attribute jsval onmousewheel;
[implicit_jscontext] attribute jsval onmozfullscreenchange;
[implicit_jscontext] attribute jsval onmozfullscreenerror;
[implicit_jscontext] attribute jsval onmozpointerlockchange;
[implicit_jscontext] attribute jsval onmozpointerlockerror;
[implicit_jscontext] attribute jsval onpause;
[implicit_jscontext] attribute jsval onplay;
[implicit_jscontext] attribute jsval onplaying;
[implicit_jscontext] attribute jsval onprogress;
[implicit_jscontext] attribute jsval onratechange;
[implicit_jscontext] attribute jsval onreset;
[implicit_jscontext] attribute jsval onscroll;
[implicit_jscontext] attribute jsval onseeked;
[implicit_jscontext] attribute jsval onseeking;
[implicit_jscontext] attribute jsval onselect;
[implicit_jscontext] attribute jsval onshow;
[implicit_jscontext] attribute jsval onstalled;
[implicit_jscontext] attribute jsval onsubmit;
[implicit_jscontext] attribute jsval onsuspend;
[implicit_jscontext] attribute jsval ontimeupdate;
[implicit_jscontext] attribute jsval onvolumechange;
[implicit_jscontext] attribute jsval onwaiting;
[implicit_jscontext] attribute jsval onwheel;
[implicit_jscontext] attribute jsval onpointerdown;
[implicit_jscontext] attribute jsval onpointermove;
[implicit_jscontext] attribute jsval onpointerout;
[implicit_jscontext] attribute jsval onpointerover;
[implicit_jscontext] attribute jsval onpointerup;
[implicit_jscontext] attribute jsval onpointerenter;
[implicit_jscontext] attribute jsval onpointerleave;
[implicit_jscontext] attribute jsval ongotpointercapture;
[implicit_jscontext] attribute jsval onlostpointercapture;
[implicit_jscontext] attribute jsval onpointercancel;
/**
* Non-HTML5 event attributes
*/
[implicit_jscontext] attribute jsval oncopy;
[implicit_jscontext] attribute jsval oncut;
[implicit_jscontext] attribute jsval onpaste;
[implicit_jscontext] attribute jsval onbeforescriptexecute;
[implicit_jscontext] attribute jsval onafterscriptexecute;
};

View File

@ -28,7 +28,6 @@ XPIDL_SOURCES += [
'nsIDOMPaintRequest.idl',
'nsIDOMScrollAreaEvent.idl',
'nsIDOMSimpleGestureEvent.idl',
'nsIDOMTouchEvent.idl',
'nsIDOMTransitionEvent.idl',
'nsIDOMUIEvent.idl',
'nsIDOMWheelEvent.idl',

View File

@ -1,19 +0,0 @@
/* vim: set shiftwidth=2 tabstop=8 autoindent cindent expandtab: */
/* 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 "nsIDOMUIEvent.idl"
%{C++
#include "nsWeakPtr.h"
#include "nsPoint.h"
%}
interface nsIVariant;
[scriptable, uuid(6d5484f7-92ac-45f8-9388-39b5bad055ce)]
interface nsITouchEventReceiver : nsISupports {
[implicit_jscontext] attribute jsval ontouchstart;
[implicit_jscontext] attribute jsval ontouchend;
[implicit_jscontext] attribute jsval ontouchmove;
[implicit_jscontext] attribute jsval ontouchcancel;
};

View File

@ -16,14 +16,13 @@
* http://www.whatwg.org/specs/web-apps/current-work/
*/
[uuid(e83e726a-0aef-4292-938b-253fec691e2f)]
[uuid(ec18e71c-4f5c-4cc3-aa36-5273168644dc)]
interface nsIDOMHTMLImageElement : nsISupports
{
attribute DOMString alt;
attribute DOMString src;
attribute DOMString srcset;
attribute DOMString sizes;
attribute DOMString crossOrigin;
attribute DOMString useMap;
attribute boolean isMap;
attribute unsigned long width;

View File

@ -16,7 +16,7 @@
* http://www.whatwg.org/specs/web-apps/current-work/
*/
[uuid(95d6ec66-2754-45bd-a068-49ac1fb45004)]
[uuid(ee50b7ab-0015-4fbe-89e0-e3feacd4ffde)]
interface nsIDOMHTMLLinkElement : nsISupports
{
[binaryname(MozDisabled)]
@ -29,5 +29,4 @@ interface nsIDOMHTMLLinkElement : nsISupports
attribute DOMString rev;
attribute DOMString target;
attribute DOMString type;
attribute DOMString crossOrigin;
};

View File

@ -27,7 +27,7 @@ interface nsIDOMMediaStream;
#endif
%}
[uuid(0e14e6ad-2074-48b7-a247-e545a3a15131)]
[uuid(c041d76c-15ce-47ad-b61d-e8755a6db638)]
interface nsIDOMHTMLMediaElement : nsISupports
{
// error state
@ -37,7 +37,6 @@ interface nsIDOMHTMLMediaElement : nsISupports
attribute DOMString src;
attribute nsIDOMMediaStream mozSrcObject;
readonly attribute DOMString currentSrc;
attribute DOMString crossOrigin;
const unsigned short NETWORK_EMPTY = 0;
const unsigned short NETWORK_IDLE = 1;
const unsigned short NETWORK_LOADING = 2;

View File

@ -16,7 +16,7 @@
* http://www.whatwg.org/specs/web-apps/current-work/
*/
[uuid(4627336e-3070-4e73-8f67-3851b54cc0eb)]
[uuid(fe96dc1c-40e4-4974-9354-e3fce663c3d5)]
interface nsIDOMHTMLScriptElement : nsISupports
{
attribute DOMString src;
@ -28,5 +28,4 @@ interface nsIDOMHTMLScriptElement : nsISupports
attribute DOMString htmlFor;
attribute DOMString event;
attribute DOMString crossOrigin;
};

View File

@ -879,11 +879,6 @@ TabChild::Observe(nsISupports *aSubject,
mContentDocumentIsDisplayed = true;
// Reset CSS viewport and zoom to default on new page, then
// calculate them properly using the actual metadata from the
// page.
SetCSSViewport(kDefaultViewportSize);
// In some cases before-first-paint gets called before
// RecvUpdateDimensions is called and therefore before we have an
// mInnerSize value set. In such cases defer initializing the viewport

View File

@ -546,6 +546,11 @@ public:
// from MediaManager thread.
static MediaManager* Get();
static bool Exists()
{
return !!sSingleton;
}
static nsIThread* GetThread() {
return Get()->mMediaThread;
}

View File

@ -679,16 +679,19 @@ RTCPeerConnection.prototype = {
let idpComplete = false;
let setRemoteComplete = false;
let idpError = null;
let isDone = false;
// we can run the IdP validation in parallel with setRemoteDescription this
// complicates much more than would be ideal, but it ensures that the IdP
// doesn't hold things up too much when it's not on the critical path
let allDone = () => {
if (!setRemoteComplete || !idpComplete || !onSuccess) {
if (!setRemoteComplete || !idpComplete || isDone) {
return;
}
// May be null if the user didn't supply success/failure callbacks.
// Violation of spec, but we allow it for now
this.callCB(onSuccess);
onSuccess = null;
isDone = true;
this._executeNext();
};

View File

@ -643,8 +643,6 @@ var interfaceNamesInGlobalScope =
"MimeType",
// IMPORTANT: Do not change this list without review from a DOM peer!
"MimeTypeArray",
// IMPORTANT: Do not change this list without review from a DOM peer!
"ModalContentWindow",
// IMPORTANT: Do not change this list without review from a DOM peer!
"MouseEvent",
// IMPORTANT: Do not change this list without review from a DOM peer!

View File

@ -26,7 +26,7 @@ interface HTMLImageElement : HTMLElement {
[SetterThrows, Pref="dom.image.srcset.enabled"]
attribute DOMString srcset;
[SetterThrows]
attribute DOMString crossOrigin;
attribute DOMString? crossOrigin;
[SetterThrows]
attribute DOMString useMap;
[SetterThrows]

View File

@ -18,7 +18,7 @@ interface HTMLLinkElement : HTMLElement {
[SetterThrows, Pure]
attribute DOMString href;
[SetterThrows, Pure]
attribute DOMString crossOrigin;
attribute DOMString? crossOrigin;
[SetterThrows, Pure]
attribute DOMString rel;
readonly attribute DOMTokenList relList;

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