mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
merge mozilla-inbound to mozilla-central a=merge
This commit is contained in:
commit
add1a88604
@ -21,18 +21,38 @@ using namespace mozilla::a11y;
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
TreeWalker::
|
||||
TreeWalker(Accessible* aContext, nsIContent* aContent, uint32_t aFlags) :
|
||||
mDoc(aContext->Document()), mContext(aContext), mAnchorNode(aContent),
|
||||
mFlags(aFlags)
|
||||
TreeWalker(Accessible* aContext) :
|
||||
mDoc(aContext->Document()), mContext(aContext), mAnchorNode(nullptr),
|
||||
mARIAOwnsIdx(0),
|
||||
mChildFilter(nsIContent::eSkipPlaceholderContent), mFlags(0)
|
||||
{
|
||||
NS_ASSERTION(aContent, "No node for the accessible tree walker!");
|
||||
|
||||
mChildFilter = mContext->NoXBLKids() ?
|
||||
mChildFilter |= mContext->NoXBLKids() ?
|
||||
nsIContent::eAllButXBL : nsIContent::eAllChildren;
|
||||
mChildFilter |= nsIContent::eSkipPlaceholderContent;
|
||||
|
||||
if (aContent)
|
||||
PushState(aContent);
|
||||
mAnchorNode = mContext->IsDoc() ?
|
||||
mDoc->DocumentNode()->GetRootElement() : mContext->GetContent();
|
||||
|
||||
if (mAnchorNode) {
|
||||
PushState(mAnchorNode);
|
||||
}
|
||||
|
||||
MOZ_COUNT_CTOR(TreeWalker);
|
||||
}
|
||||
|
||||
TreeWalker::
|
||||
TreeWalker(Accessible* aContext, nsIContent* aAnchorNode, uint32_t aFlags) :
|
||||
mDoc(aContext->Document()), mContext(aContext), mAnchorNode(aAnchorNode),
|
||||
mARIAOwnsIdx(0),
|
||||
mChildFilter(nsIContent::eSkipPlaceholderContent), mFlags(aFlags)
|
||||
{
|
||||
MOZ_ASSERT(aAnchorNode, "No anchor node for the accessible tree walker");
|
||||
MOZ_ASSERT(mDoc->GetAccessibleOrContainer(aAnchorNode) == mContext,
|
||||
"Unexpected anchor node was given");
|
||||
|
||||
mChildFilter |= mContext->NoXBLKids() ?
|
||||
nsIContent::eAllButXBL : nsIContent::eAllChildren;
|
||||
|
||||
PushState(aAnchorNode);
|
||||
|
||||
MOZ_COUNT_CTOR(TreeWalker);
|
||||
}
|
||||
@ -48,29 +68,44 @@ TreeWalker::~TreeWalker()
|
||||
Accessible*
|
||||
TreeWalker::Next()
|
||||
{
|
||||
if (mStateStack.IsEmpty())
|
||||
return nullptr;
|
||||
if (mStateStack.IsEmpty()) {
|
||||
return mDoc->ARIAOwnedAt(mContext, mARIAOwnsIdx++);
|
||||
}
|
||||
|
||||
ChildrenIterator* top = &mStateStack[mStateStack.Length() - 1];
|
||||
dom::AllChildrenIterator* top = &mStateStack[mStateStack.Length() - 1];
|
||||
while (top) {
|
||||
Accessible* child = nullptr;
|
||||
bool skipSubtree = false;
|
||||
while (nsIContent* childNode = Next(top, &child, &skipSubtree)) {
|
||||
if (child)
|
||||
while (nsIContent* childNode = top->GetNextChild()) {
|
||||
bool skipSubtree = false;
|
||||
Accessible* child = nullptr;
|
||||
if (mFlags & eWalkCache) {
|
||||
child = mDoc->GetAccessible(childNode);
|
||||
}
|
||||
else if (mContext->IsAcceptableChild(childNode)) {
|
||||
child = GetAccService()->
|
||||
GetOrCreateAccessible(childNode, mContext, &skipSubtree);
|
||||
}
|
||||
|
||||
// Ignore the accessible and its subtree if it was repositioned by means
|
||||
// of aria-owns.
|
||||
if (child) {
|
||||
if (child->IsRelocated()) {
|
||||
continue;
|
||||
}
|
||||
return child;
|
||||
}
|
||||
|
||||
// Walk down into subtree to find accessibles.
|
||||
if (!skipSubtree && childNode->IsElement())
|
||||
if (!skipSubtree && childNode->IsElement()) {
|
||||
top = PushState(childNode);
|
||||
}
|
||||
}
|
||||
|
||||
top = PopState();
|
||||
}
|
||||
|
||||
// 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;
|
||||
return Next();
|
||||
|
||||
nsINode* contextNode = mContext->GetNode();
|
||||
while (mAnchorNode != contextNode) {
|
||||
@ -80,7 +115,7 @@ TreeWalker::Next()
|
||||
|
||||
nsIContent* parent = parentNode->AsElement();
|
||||
top = PushState(parent);
|
||||
if (top->mDOMIter.Seek(mAnchorNode)) {
|
||||
if (top->Seek(mAnchorNode)) {
|
||||
mAnchorNode = parent;
|
||||
return Next();
|
||||
}
|
||||
@ -92,55 +127,10 @@ TreeWalker::Next()
|
||||
mAnchorNode = parent;
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
return Next();
|
||||
}
|
||||
|
||||
nsIContent*
|
||||
TreeWalker::Next(ChildrenIterator* aIter, Accessible** aAccesible,
|
||||
bool* aSkipSubtree)
|
||||
{
|
||||
nsIContent* childEl = aIter->mDOMIter.GetNextChild();
|
||||
if (!aAccesible)
|
||||
return childEl;
|
||||
|
||||
*aAccesible = nullptr;
|
||||
*aSkipSubtree = false;
|
||||
|
||||
if (childEl) {
|
||||
Accessible* accessible = nullptr;
|
||||
if (mFlags & eWalkCache) {
|
||||
accessible = mDoc->GetAccessible(childEl);
|
||||
}
|
||||
else if (mContext->IsAcceptableChild(childEl)) {
|
||||
accessible = GetAccService()->
|
||||
GetOrCreateAccessible(childEl, mContext, aSkipSubtree);
|
||||
}
|
||||
|
||||
// Ignore the accessible and its subtree if it was repositioned by means of
|
||||
// aria-owns.
|
||||
if (accessible) {
|
||||
if (accessible->IsRelocated()) {
|
||||
*aSkipSubtree = true;
|
||||
} else {
|
||||
*aAccesible = accessible;
|
||||
}
|
||||
}
|
||||
return childEl;
|
||||
}
|
||||
|
||||
// At last iterate over ARIA owned children.
|
||||
Accessible* parent = mDoc->GetAccessible(aIter->mDOMIter.Parent());
|
||||
if (parent) {
|
||||
Accessible* child = mDoc->ARIAOwnedAt(parent, aIter->mARIAOwnsIdx++);
|
||||
if (child) {
|
||||
*aAccesible = child;
|
||||
return child->GetContent();
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
TreeWalker::ChildrenIterator*
|
||||
dom::AllChildrenIterator*
|
||||
TreeWalker::PopState()
|
||||
{
|
||||
size_t length = mStateStack.Length();
|
||||
|
@ -33,14 +33,20 @@ public:
|
||||
};
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
* Used to navigate and create if needed the accessible children.
|
||||
*/
|
||||
explicit TreeWalker(Accessible* aContext);
|
||||
|
||||
/**
|
||||
* Used to navigate the accessible children relative to the anchor.
|
||||
*
|
||||
* @param aContext [in] container accessible for the given node, used to
|
||||
* define accessible context
|
||||
* @param aNode [in] the node the search will be prepared relative to
|
||||
* @param aAnchorNode [in] the node the search will be prepared relative to
|
||||
* @param aFlags [in] flags (see enum above)
|
||||
*/
|
||||
TreeWalker(Accessible* aContext, nsIContent* aNode, uint32_t aFlags = 0);
|
||||
TreeWalker(Accessible* aContext, nsIContent* aAnchorNode, uint32_t aFlags = 0);
|
||||
|
||||
~TreeWalker();
|
||||
|
||||
/**
|
||||
@ -57,37 +63,30 @@ private:
|
||||
TreeWalker(const TreeWalker&);
|
||||
TreeWalker& operator =(const TreeWalker&);
|
||||
|
||||
struct ChildrenIterator {
|
||||
ChildrenIterator(nsIContent* aNode, uint32_t aFilter) :
|
||||
mDOMIter(aNode, aFilter), mARIAOwnsIdx(0) { }
|
||||
|
||||
dom::AllChildrenIterator mDOMIter;
|
||||
uint32_t mARIAOwnsIdx;
|
||||
};
|
||||
|
||||
nsIContent* Next(ChildrenIterator* aIter, Accessible** aAccessible = nullptr,
|
||||
bool* aSkipSubtree = nullptr);
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
ChildrenIterator* PushState(nsIContent* aContent)
|
||||
dom::AllChildrenIterator* PushState(nsIContent* aContent)
|
||||
{
|
||||
return mStateStack.AppendElement(ChildrenIterator(aContent, mChildFilter));
|
||||
return mStateStack.AppendElement(
|
||||
dom::AllChildrenIterator(aContent, mChildFilter));
|
||||
}
|
||||
|
||||
/**
|
||||
* Pop state from stack.
|
||||
*/
|
||||
ChildrenIterator* PopState();
|
||||
dom::AllChildrenIterator* PopState();
|
||||
|
||||
DocAccessible* mDoc;
|
||||
Accessible* mContext;
|
||||
nsIContent* mAnchorNode;
|
||||
AutoTArray<ChildrenIterator, 20> mStateStack;
|
||||
|
||||
AutoTArray<dom::AllChildrenIterator, 20> mStateStack;
|
||||
uint32_t mARIAOwnsIdx;
|
||||
|
||||
int32_t mChildFilter;
|
||||
uint32_t mFlags;
|
||||
};
|
||||
|
@ -2541,10 +2541,9 @@ Accessible::LastRelease()
|
||||
void
|
||||
Accessible::CacheChildren()
|
||||
{
|
||||
DocAccessible* doc = Document();
|
||||
NS_ENSURE_TRUE_VOID(doc);
|
||||
NS_ENSURE_TRUE_VOID(Document());
|
||||
|
||||
TreeWalker walker(this, mContent);
|
||||
TreeWalker walker(this);
|
||||
|
||||
Accessible* child = nullptr;
|
||||
while ((child = walker.Next()) && AppendChild(child));
|
||||
|
@ -1248,6 +1248,12 @@ DocAccessible::GetAccessibleOrContainer(nsINode* aNode) const
|
||||
if (!(currNode = parent)) break;
|
||||
}
|
||||
|
||||
// HTML comboboxes have no-content list accessible as an intermediate
|
||||
// containing all options.
|
||||
if (accessible && accessible->IsHTMLCombobox()) {
|
||||
return accessible->FirstChild();
|
||||
}
|
||||
|
||||
return accessible;
|
||||
}
|
||||
|
||||
@ -1418,25 +1424,6 @@ if (!aNode->IsContent() || !aNode->AsContent()->IsHTMLElement(nsGkAtoms::area))
|
||||
return GetAccessible(aNode);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Accessible protected
|
||||
|
||||
void
|
||||
DocAccessible::CacheChildren()
|
||||
{
|
||||
// Search for accessible children starting from the document element since
|
||||
// some web pages tend to insert elements under it rather than document body.
|
||||
dom::Element* rootElm = mDocumentNode->GetRootElement();
|
||||
if (!rootElm)
|
||||
return;
|
||||
|
||||
TreeWalker walker(this, rootElm);
|
||||
Accessible* child = nullptr;
|
||||
while ((child = walker.Next())) {
|
||||
AppendChild(child);
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Protected members
|
||||
|
||||
@ -1725,11 +1712,6 @@ DocAccessible::ProcessContentInserted(Accessible* aContainer,
|
||||
// there is no HTML body element.
|
||||
}
|
||||
|
||||
// HTML comboboxes have no-content list accessible as an intermidiate
|
||||
// containing all options.
|
||||
if (container->IsHTMLCombobox())
|
||||
container = container->FirstChild();
|
||||
|
||||
// We have a DOM/layout change under the container accessible, and its tree
|
||||
// might need an update. Since DOM/layout change of the element may affect
|
||||
// on the accessibleness of adjacent elements (for example, insertion of
|
||||
|
@ -359,9 +359,6 @@ protected:
|
||||
|
||||
void LastRelease();
|
||||
|
||||
// Accessible
|
||||
virtual void CacheChildren() override;
|
||||
|
||||
// DocAccessible
|
||||
virtual nsresult AddEventListeners();
|
||||
virtual nsresult RemoveEventListeners();
|
||||
|
@ -114,35 +114,12 @@ HTMLSelectListAccessible::SetCurrentItem(Accessible* aItem)
|
||||
true);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// HTMLSelectListAccessible: Accessible protected
|
||||
|
||||
void
|
||||
HTMLSelectListAccessible::CacheChildren()
|
||||
bool
|
||||
HTMLSelectListAccessible::IsAcceptableChild(nsIContent* aEl) const
|
||||
{
|
||||
// Cache accessibles for <optgroup> and <option> DOM decendents as children,
|
||||
// as well as the accessibles for them. Avoid whitespace text nodes. We want
|
||||
// to count all the <optgroup>s and <option>s as children because we want
|
||||
// a flat tree under the Select List.
|
||||
for (nsIContent* childContent = mContent->GetFirstChild(); childContent;
|
||||
childContent = childContent->GetNextSibling()) {
|
||||
if (!childContent->IsHTMLElement()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (childContent->IsAnyOfHTMLElements(nsGkAtoms::option,
|
||||
nsGkAtoms::optgroup)) {
|
||||
|
||||
// Get an accessible for option or optgroup and cache it.
|
||||
RefPtr<Accessible> accessible =
|
||||
GetAccService()->GetOrCreateAccessible(childContent, this);
|
||||
if (accessible)
|
||||
AppendChild(accessible);
|
||||
}
|
||||
}
|
||||
return aEl->IsAnyOfHTMLElements(nsGkAtoms::option, nsGkAtoms::optgroup);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// HTMLSelectOptionAccessible
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -51,10 +51,7 @@ public:
|
||||
virtual Accessible* CurrentItem() override;
|
||||
virtual void SetCurrentItem(Accessible* aItem) override;
|
||||
|
||||
protected:
|
||||
|
||||
// Accessible
|
||||
virtual void CacheChildren() override;
|
||||
virtual bool IsAcceptableChild(nsIContent* aEl) const override;
|
||||
};
|
||||
|
||||
/*
|
||||
|
@ -251,11 +251,13 @@ enum CheckboxValue {
|
||||
{
|
||||
mozAccessible* nativeAcc = nil;
|
||||
if (AccessibleWrap* accWrap = [self getGeckoAccessible]) {
|
||||
Accessible* accTab = accWrap->GetSelectedItem(0);
|
||||
accTab->GetNativeInterface((void**)&nativeAcc);
|
||||
if (Accessible* accTab = accWrap->GetSelectedItem(0)) {
|
||||
accTab->GetNativeInterface((void**)&nativeAcc);
|
||||
}
|
||||
} else if (ProxyAccessible* proxy = [self getProxyAccessible]) {
|
||||
ProxyAccessible* proxyTab = proxy->GetSelectedItem(0);
|
||||
nativeAcc = GetNativeFromProxy(proxyTab);
|
||||
if (ProxyAccessible* proxyTab = proxy->GetSelectedItem(0)) {
|
||||
nativeAcc = GetNativeFromProxy(proxyTab);
|
||||
}
|
||||
}
|
||||
|
||||
return nativeAcc;
|
||||
|
@ -102,7 +102,7 @@
|
||||
}
|
||||
}
|
||||
|
||||
// gA11yEventDumpToConsole = true;
|
||||
//gA11yEventDumpToConsole = true;
|
||||
|
||||
function doTest()
|
||||
{
|
||||
|
@ -42,5 +42,4 @@ skip-if = true
|
||||
[tab-close-on-startup.xpi]
|
||||
[toolkit-require-reload.xpi]
|
||||
[translators.xpi]
|
||||
[unpacked.xpi]
|
||||
[unsafe-content-script.xpi]
|
||||
|
@ -17,7 +17,9 @@ exports.main = function main(options, callbacks) {
|
||||
assert.ok('loadReason' in options, 'loadReason is in options provided by main');
|
||||
assert.equal(typeof callbacks.print, 'function', 'callbacks.print is a function');
|
||||
assert.equal(typeof callbacks.quit, 'function', 'callbacks.quit is a function');
|
||||
assert.equal(options.loadReason, 'install', 'options.loadReason is install');
|
||||
|
||||
// Re-enable when bug 1251664 is fixed
|
||||
//assert.equal(options.loadReason, 'install', 'options.loadReason is install');
|
||||
}
|
||||
|
||||
require('sdk/test/runner').runTestsFromModule({exports: tests});
|
||||
|
@ -1,18 +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/. */
|
||||
"use strict";
|
||||
|
||||
const { packed } = require("sdk/self");
|
||||
const url = require("sdk/url");
|
||||
|
||||
exports["test self.packed"] = function (assert) {
|
||||
assert.ok(!packed, "require('sdk/self').packed is correct");
|
||||
}
|
||||
|
||||
exports["test url.toFilename"] = function (assert) {
|
||||
assert.ok(/.*main\.js$/.test(url.toFilename(module.uri)),
|
||||
"url.toFilename() on resource: URIs should work");
|
||||
}
|
||||
|
||||
require("sdk/test/runner").runTestsFromModule(module);
|
@ -1,6 +0,0 @@
|
||||
{
|
||||
"id": "test-url@jetpack",
|
||||
"unpack": true,
|
||||
"main": "./main.js",
|
||||
"version": "0.0.1"
|
||||
}
|
@ -31,7 +31,7 @@ externalProtocolChkMsg=Remember my choice for all links of this type.
|
||||
externalProtocolLaunchBtn=Launch application
|
||||
malwareBlocked=The site at %S has been reported as an attack site and has been blocked based on your security preferences.
|
||||
unwantedBlocked=The site at %S has been reported as serving unwanted software and has been blocked based on your security preferences.
|
||||
phishingBlocked=The website at %S has been reported as a web forgery designed to trick users into sharing personal or financial information.
|
||||
deceptiveBlocked=This web page at %S has been reported as a deceptive site and has been blocked based on your security preferences.
|
||||
forbiddenBlocked=The site at %S has been blocked by your browser configuration.
|
||||
cspBlocked=This page has a content security policy that prevents it from being loaded in this way.
|
||||
corruptedContentError=The page you are trying to view cannot be shown because an error in the data transmission was detected.
|
||||
|
@ -1201,10 +1201,6 @@ pref("security.sandbox.content.level", 2);
|
||||
pref("security.sandbox.content.level", 0);
|
||||
#endif
|
||||
|
||||
// ID (a UUID when set by gecko) that is used as a per profile suffix to a low
|
||||
// integrity temp directory.
|
||||
pref("security.sandbox.content.tempDirSuffix", "");
|
||||
|
||||
#if defined(MOZ_STACKWALKING)
|
||||
// This controls the depth of stack trace that is logged when Windows sandbox
|
||||
// logging is turned on. This is only currently available for the content
|
||||
@ -1227,6 +1223,15 @@ pref("security.sandbox.windows.log.stackTraceDepth", 0);
|
||||
pref("security.sandbox.content.level", 1);
|
||||
#endif
|
||||
|
||||
#if defined(XP_MACOSX) || defined(XP_WIN)
|
||||
#if defined(MOZ_SANDBOX) && defined(MOZ_CONTENT_SANDBOX)
|
||||
// ID (a UUID when set by gecko) that is used to form the name of a
|
||||
// sandbox-writable temporary directory to be used by content processes
|
||||
// when a temporary writable file is required in a level 1 sandbox.
|
||||
pref("security.sandbox.content.tempDirSuffix", "");
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// This pref governs whether we attempt to work around problems caused by
|
||||
// plugins using OS calls to manipulate the cursor while running out-of-
|
||||
// process. These workarounds all involve intercepting (hooking) certain
|
||||
|
@ -414,9 +414,6 @@
|
||||
<h1 id="et_unsafeContentType">&unsafeContentType.title;</h1>
|
||||
<h1 id="et_nssFailure2">&nssFailure2.title;</h1>
|
||||
<h1 id="et_nssBadCert">&nssBadCert.title;</h1>
|
||||
<h1 id="et_malwareBlocked">&malwareBlocked.title;</h1>
|
||||
<h1 id="et_unwantedBlocked">&unwantedBlocked.title;</h1>
|
||||
<h1 id="et_forbiddenBlocked">&forbiddenBlocked.title;</h1>
|
||||
<h1 id="et_cspBlocked">&cspBlocked.title;</h1>
|
||||
<h1 id="et_remoteXUL">&remoteXUL.title;</h1>
|
||||
<h1 id="et_corruptedContentError">&corruptedContentError.title;</h1>
|
||||
@ -444,9 +441,6 @@
|
||||
<div id="ed_unsafeContentType">&unsafeContentType.longDesc;</div>
|
||||
<div id="ed_nssFailure2">&nssFailure2.longDesc2;</div>
|
||||
<div id="ed_nssBadCert">&nssBadCert.longDesc2;</div>
|
||||
<div id="ed_malwareBlocked">&malwareBlocked.longDesc;</div>
|
||||
<div id="ed_unwantedBlocked">&unwantedBlocked.longDesc;</div>
|
||||
<div id="ed_forbiddenBlocked">&forbiddenBlocked.longDesc;</div>
|
||||
<div id="ed_cspBlocked">&cspBlocked.longDesc;</div>
|
||||
<div id="ed_remoteXUL">&remoteXUL.longDesc;</div>
|
||||
<div id="ed_corruptedContentError">&corruptedContentError.longDesc;</div>
|
||||
|
@ -88,7 +88,7 @@
|
||||
case "malwareBlocked" :
|
||||
error = "malware";
|
||||
break;
|
||||
case "phishingBlocked" :
|
||||
case "deceptiveBlocked" :
|
||||
error = "phishing";
|
||||
break;
|
||||
case "unwantedBlocked" :
|
||||
@ -200,7 +200,7 @@
|
||||
|
||||
<!-- Error Title -->
|
||||
<div id="errorTitle">
|
||||
<h1 id="errorTitleText_phishing">&safeb.blocked.phishingPage.title;</h1>
|
||||
<h1 id="errorTitleText_phishing">&safeb.blocked.phishingPage.title2;</h1>
|
||||
<h1 id="errorTitleText_malware">&safeb.blocked.malwarePage.title;</h1>
|
||||
<h1 id="errorTitleText_unwanted">&safeb.blocked.unwantedPage.title;</h1>
|
||||
<h1 id="errorTitleText_forbidden">&safeb.blocked.forbiddenPage.title2;</h1>
|
||||
@ -210,7 +210,7 @@
|
||||
|
||||
<!-- Short Description -->
|
||||
<div id="errorShortDesc">
|
||||
<p id="errorShortDescText_phishing">&safeb.blocked.phishingPage.shortDesc;</p>
|
||||
<p id="errorShortDescText_phishing">&safeb.blocked.phishingPage.shortDesc2;</p>
|
||||
<p id="errorShortDescText_malware">&safeb.blocked.malwarePage.shortDesc;</p>
|
||||
<p id="errorShortDescText_unwanted">&safeb.blocked.unwantedPage.shortDesc;</p>
|
||||
<p id="errorShortDescText_forbidden">&safeb.blocked.forbiddenPage.shortDesc2;</p>
|
||||
@ -218,7 +218,7 @@
|
||||
|
||||
<!-- Long Description -->
|
||||
<div id="errorLongDesc">
|
||||
<p id="errorLongDescText_phishing">&safeb.blocked.phishingPage.longDesc;</p>
|
||||
<p id="errorLongDescText_phishing">&safeb.blocked.phishingPage.longDesc2;</p>
|
||||
<p id="errorLongDescText_malware">&safeb.blocked.malwarePage.longDesc;</p>
|
||||
<p id="errorLongDescText_unwanted">&safeb.blocked.unwantedPage.longDesc;</p>
|
||||
</div>
|
||||
|
@ -15,7 +15,7 @@ var gSafeBrowsing = {
|
||||
// will point to the internal error page we loaded instead.
|
||||
var docURI = gBrowser.selectedBrowser.documentURI;
|
||||
var isPhishingPage =
|
||||
docURI && docURI.spec.startsWith("about:blocked?e=phishingBlocked");
|
||||
docURI && docURI.spec.startsWith("about:blocked?e=deceptiveBlocked");
|
||||
|
||||
// Show/hide the appropriate menu item.
|
||||
document.getElementById("menu_HelpPopup_reportPhishingtoolmenu")
|
||||
|
@ -2915,10 +2915,10 @@ var BrowserOnClick = {
|
||||
}
|
||||
};
|
||||
} else if (reason === 'phishing') {
|
||||
title = gNavigatorBundle.getString("safebrowsing.reportedWebForgery");
|
||||
title = gNavigatorBundle.getString("safebrowsing.deceptiveSite");
|
||||
buttons[1] = {
|
||||
label: gNavigatorBundle.getString("safebrowsing.notAForgeryButton.label"),
|
||||
accessKey: gNavigatorBundle.getString("safebrowsing.notAForgeryButton.accessKey"),
|
||||
label: gNavigatorBundle.getString("safebrowsing.notADeceptiveSiteButton.label"),
|
||||
accessKey: gNavigatorBundle.getString("safebrowsing.notADeceptiveSiteButton.accessKey"),
|
||||
callback: function() {
|
||||
openUILinkIn(gSafeBrowsing.getReportURL('PhishMistake'), 'tab');
|
||||
}
|
||||
|
@ -18,15 +18,15 @@
|
||||
</broadcasterset>
|
||||
<menupopup id="menu_HelpPopup">
|
||||
<menuitem id="menu_HelpPopup_reportPhishingtoolmenu"
|
||||
label="&reportPhishSiteMenu.title2;"
|
||||
accesskey="&reportPhishSiteMenu.accesskey;"
|
||||
label="&reportDeceptiveSiteMenu.title;"
|
||||
accesskey="&reportDeceptiveSiteMenu.accesskey;"
|
||||
insertbefore="aboutSeparator"
|
||||
observes="reportPhishingBroadcaster"
|
||||
oncommand="openUILink(gSafeBrowsing.getReportURL('Phish'), event);"
|
||||
onclick="checkForMiddleClick(this, event);"/>
|
||||
<menuitem id="menu_HelpPopup_reportPhishingErrortoolmenu"
|
||||
label="&safeb.palm.notforgery.label2;"
|
||||
accesskey="&reportPhishSiteMenu.accesskey;"
|
||||
label="&safeb.palm.notdeceptive.label;"
|
||||
accesskey="&reportDeceptiveSiteMenu.accesskey;"
|
||||
insertbefore="aboutSeparator"
|
||||
observes="reportPhishingErrorBroadcaster"
|
||||
oncommand="openUILinkIn(gSafeBrowsing.getReportURL('PhishMistake'), 'tab');"
|
||||
|
@ -1,11 +1,28 @@
|
||||
"use strict";
|
||||
|
||||
const {PlacesTestUtils} =
|
||||
Cu.import("resource://testing-common/PlacesTestUtils.jsm", {});
|
||||
|
||||
let tab;
|
||||
let notificationURL = "http://example.org/browser/browser/base/content/test/alerts/file_dom_notifications.html";
|
||||
let oldShowFavicons;
|
||||
|
||||
add_task(function* test_notificationClose() {
|
||||
let pm = Services.perms;
|
||||
pm.add(makeURI(notificationURL), "desktop-notification", pm.ALLOW_ACTION);
|
||||
let notificationURI = makeURI(notificationURL);
|
||||
pm.add(notificationURI, "desktop-notification", pm.ALLOW_ACTION);
|
||||
|
||||
oldShowFavicons = Services.prefs.getBoolPref("alerts.showFavicons");
|
||||
Services.prefs.setBoolPref("alerts.showFavicons", true);
|
||||
|
||||
yield PlacesTestUtils.addVisits(notificationURI);
|
||||
let faviconURI = yield new Promise(resolve => {
|
||||
let faviconURI = makeURI("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAIAAACQd1PeAAAADElEQVQI12P4//8/AAX+Av7czFnnAAAAAElFTkSuQmCC");
|
||||
PlacesUtils.favicons.setAndFetchFaviconForPage(notificationURI, faviconURI,
|
||||
true, PlacesUtils.favicons.FAVICON_LOAD_NON_PRIVATE,
|
||||
(faviconURI, iconSize, iconData, mimeType) => resolve(faviconURI),
|
||||
Services.scriptSecurityManager.getSystemPrincipal());
|
||||
});
|
||||
|
||||
yield BrowserTestUtils.withNewTab({
|
||||
gBrowser,
|
||||
@ -26,6 +43,8 @@ add_task(function* test_notificationClose() {
|
||||
is(alertTitleLabel.value, "Test title", "Title text of notification should be present");
|
||||
let alertTextLabel = alertWindow.document.getElementById("alertTextLabel");
|
||||
is(alertTextLabel.textContent, "Test body 2", "Body text of notification should be present");
|
||||
let alertIcon = alertWindow.document.getElementById("alertIcon");
|
||||
is(alertIcon.src, faviconURI.spec, "Icon of notification should be present");
|
||||
|
||||
let alertCloseButton = alertWindow.document.querySelector(".alertCloseButton");
|
||||
is(alertCloseButton.localName, "toolbarbutton", "close button found");
|
||||
@ -47,4 +66,7 @@ add_task(function* test_notificationClose() {
|
||||
|
||||
add_task(function* cleanup() {
|
||||
Services.perms.remove(makeURI(notificationURL), "desktop-notification");
|
||||
if (typeof oldShowFavicons == "boolean") {
|
||||
Services.prefs.setBoolPref("alerts.showFavicons", oldShowFavicons);
|
||||
}
|
||||
});
|
||||
|
@ -177,14 +177,28 @@ var SessionFileInternal = {
|
||||
},
|
||||
}),
|
||||
|
||||
// `true` once `write` has succeeded at last once.
|
||||
// Used for error-reporting.
|
||||
_hasWriteEverSucceeded: false,
|
||||
// Number of attempted calls to `write`.
|
||||
// Note that we may have _attempts > _successes + _failures,
|
||||
// if attempts never complete.
|
||||
// Used for error reporting.
|
||||
_attempts: 0,
|
||||
|
||||
// Number of successful calls to `write`.
|
||||
// Used for error reporting.
|
||||
_successes: 0,
|
||||
|
||||
// Number of failed calls to `write`.
|
||||
// Used for error reporting.
|
||||
_failures: 0,
|
||||
|
||||
// Resolved once initialization is complete.
|
||||
// The promise never rejects.
|
||||
_deferredInitialized: PromiseUtils.defer(),
|
||||
|
||||
// `true` once we have started initialization, i.e. once something
|
||||
// has been scheduled that will eventually resolve `_deferredInitialized`.
|
||||
_initializationStarted: false,
|
||||
|
||||
// The ID of the latest version of Gecko for which we have an upgrade backup
|
||||
// or |undefined| if no upgrade backup was ever written.
|
||||
get latestUpgradeBackupID() {
|
||||
@ -195,7 +209,10 @@ var SessionFileInternal = {
|
||||
}
|
||||
},
|
||||
|
||||
// Find the correct session file, read it and setup the worker.
|
||||
read: Task.async(function* () {
|
||||
this._initializationStarted = true;
|
||||
|
||||
let result;
|
||||
let noFilesFound = true;
|
||||
// Attempt to load by order of priority from the various backups
|
||||
@ -205,6 +222,7 @@ var SessionFileInternal = {
|
||||
try {
|
||||
let path = this.Paths[key];
|
||||
let startMs = Date.now();
|
||||
|
||||
let source = yield OS.File.read(path, { encoding: "utf-8" });
|
||||
let parsed = JSON.parse(source);
|
||||
|
||||
@ -259,19 +277,39 @@ var SessionFileInternal = {
|
||||
|
||||
result.noFilesFound = noFilesFound;
|
||||
|
||||
// Initialize the worker to let it handle backups and also
|
||||
// Initialize the worker (in the background) to let it handle backups and also
|
||||
// as a workaround for bug 964531.
|
||||
let initialized = SessionWorker.post("init", [result.origin, this.Paths, {
|
||||
let promiseInitialized = SessionWorker.post("init", [result.origin, this.Paths, {
|
||||
maxUpgradeBackups: Preferences.get(PREF_MAX_UPGRADE_BACKUPS, 3),
|
||||
maxSerializeBack: Preferences.get(PREF_MAX_SERIALIZE_BACK, 10),
|
||||
maxSerializeForward: Preferences.get(PREF_MAX_SERIALIZE_FWD, -1)
|
||||
}]);
|
||||
|
||||
initialized.catch(Promise.reject).then(() => this._deferredInitialized.resolve());
|
||||
promiseInitialized.catch(err => {
|
||||
// Ensure that we report errors but that they do not stop us.
|
||||
Promise.reject(err);
|
||||
}).then(() => this._deferredInitialized.resolve());
|
||||
|
||||
return result;
|
||||
}),
|
||||
|
||||
// Post a message to the worker, making sure that it has been initialized
|
||||
// first.
|
||||
_postToWorker: Task.async(function*(...args) {
|
||||
if (!this._initializationStarted) {
|
||||
// Initializing the worker is somewhat complex, as proper handling of
|
||||
// backups requires us to first read and check the session. Consequently,
|
||||
// the only way to initialize the worker is to first call `this.read()`.
|
||||
|
||||
// The call to `this.read()` causes background initialization of the worker.
|
||||
// Initialization will be complete once `this._deferredInitialized.promise`
|
||||
// resolves.
|
||||
this.read();
|
||||
}
|
||||
yield this._deferredInitialized.promise;
|
||||
return SessionWorker.post(...args)
|
||||
}),
|
||||
|
||||
write: function (aData) {
|
||||
if (RunState.isClosed) {
|
||||
return Promise.reject(new Error("SessionFile is closed"));
|
||||
@ -288,14 +326,15 @@ var SessionFileInternal = {
|
||||
let performShutdownCleanup = isFinalWrite &&
|
||||
!sessionStartup.isAutomaticRestoreEnabled();
|
||||
|
||||
this._attempts++;
|
||||
let options = {isFinalWrite, performShutdownCleanup};
|
||||
let promise = this._deferredInitialized.promise.then(() => SessionWorker.post("write", [aData, options]));
|
||||
let promise = this._postToWorker("write", [aData, options]);
|
||||
|
||||
// Wait until the write is done.
|
||||
promise = promise.then(msg => {
|
||||
// Record how long the write took.
|
||||
this._recordTelemetry(msg.telemetry);
|
||||
this._hasWriteEverSucceeded = true;
|
||||
this._successes++;
|
||||
if (msg.result.upgradeBackup) {
|
||||
// We have just completed a backup-on-upgrade, store the information
|
||||
// in preferences.
|
||||
@ -305,6 +344,7 @@ var SessionFileInternal = {
|
||||
}, err => {
|
||||
// Catch and report any errors.
|
||||
console.error("Could not write session state file ", err, err.stack);
|
||||
this._failures++;
|
||||
// By not doing anything special here we ensure that |promise| cannot
|
||||
// be rejected anymore. The shutdown/cleanup code at the end of the
|
||||
// function will thus always be executed.
|
||||
@ -318,7 +358,9 @@ var SessionFileInternal = {
|
||||
{
|
||||
fetchState: () => ({
|
||||
options,
|
||||
hasEverSucceeded: this._hasWriteEverSucceeded
|
||||
attempts: this._attempts,
|
||||
successes: this._successes,
|
||||
failures: this._failures,
|
||||
})
|
||||
});
|
||||
|
||||
@ -336,7 +378,7 @@ var SessionFileInternal = {
|
||||
},
|
||||
|
||||
wipe: function () {
|
||||
return this._deferredInitialized.promise.then(() => SessionWorker.post("wipe"));
|
||||
return this._postToWorker("wipe");
|
||||
},
|
||||
|
||||
_recordTelemetry: function(telemetry) {
|
||||
|
@ -151,8 +151,10 @@ var SessionStorageInternal = {
|
||||
try {
|
||||
let storageManager = aDocShell.QueryInterface(Ci.nsIDOMStorageManager);
|
||||
storage = storageManager.getStorage(window, aPrincipal);
|
||||
storage.length; // XXX: Bug 1232955 - storage.length can throw, catch that failure
|
||||
} catch (e) {
|
||||
// sessionStorage might throw if it's turned off, see bug 458954
|
||||
storage = null;
|
||||
}
|
||||
|
||||
if (storage && storage.length) {
|
||||
|
@ -52,6 +52,7 @@ support-files =
|
||||
restore_redirect_http.html^headers^
|
||||
restore_redirect_js.html
|
||||
restore_redirect_target.html
|
||||
browser_1234021_page.html
|
||||
|
||||
#NB: the following are disabled
|
||||
# browser_464620_a.html
|
||||
@ -220,3 +221,4 @@ run-if = e10s
|
||||
[browser_async_window_flushing.js]
|
||||
[browser_forget_async_closings.js]
|
||||
[browser_sessionStoreContainer.js]
|
||||
[browser_1234021.js]
|
||||
|
18
browser/components/sessionstore/test/browser_1234021.js
Normal file
18
browser/components/sessionstore/test/browser_1234021.js
Normal file
@ -0,0 +1,18 @@
|
||||
"use strict";
|
||||
|
||||
const PREF = 'network.cookie.cookieBehavior';
|
||||
const PAGE_URL = 'http://mochi.test:8888/browser/' +
|
||||
'browser/components/sessionstore/test/browser_1234021_page.html';
|
||||
const BEHAVIOR_REJECT = 2;
|
||||
|
||||
add_task(function* test() {
|
||||
yield pushPrefs([PREF, BEHAVIOR_REJECT]);
|
||||
|
||||
yield BrowserTestUtils.withNewTab({
|
||||
gBrowser: gBrowser,
|
||||
url: PAGE_URL
|
||||
}, function* handler(aBrowser) {
|
||||
yield TabStateFlusher.flush(aBrowser);
|
||||
ok(true, "Flush didn't time out");
|
||||
});
|
||||
});
|
@ -0,0 +1,6 @@
|
||||
<!doctype html>
|
||||
<html>
|
||||
<script>
|
||||
sessionStorage
|
||||
</script>
|
||||
</html>
|
@ -403,9 +403,9 @@ pointerLock.autoLock.title3=This site will hide the pointer.
|
||||
# it's okay for them to have the same access key
|
||||
safebrowsing.getMeOutOfHereButton.label=Get me out of here!
|
||||
safebrowsing.getMeOutOfHereButton.accessKey=G
|
||||
safebrowsing.reportedWebForgery=Reported Web Forgery!
|
||||
safebrowsing.notAForgeryButton.label=This isn't a web forgery…
|
||||
safebrowsing.notAForgeryButton.accessKey=F
|
||||
safebrowsing.deceptiveSite=Deceptive Site!
|
||||
safebrowsing.notADeceptiveSiteButton.label=This isn't a deceptive site…
|
||||
safebrowsing.notADeceptiveSiteButton.accessKey=D
|
||||
safebrowsing.reportedAttackSite=Reported Attack Site!
|
||||
safebrowsing.notAnAttackButton.label=This isn't an attack site…
|
||||
safebrowsing.notAnAttackButton.accessKey=A
|
||||
|
@ -4,7 +4,8 @@
|
||||
|
||||
<!ENTITY safeb.palm.accept.label "Get me out of here!">
|
||||
<!ENTITY safeb.palm.decline.label "Ignore this warning">
|
||||
<!ENTITY safeb.palm.notforgery.label2 "This isn't a web forgery…">
|
||||
<!-- Localization note (safeb.palm.notdeceptive.label) - Label of the Help menu item. -->
|
||||
<!ENTITY safeb.palm.notdeceptive.label "This isn't a deceptive site…">
|
||||
<!ENTITY safeb.palm.reportPage.label "Why was this page blocked?">
|
||||
<!ENTITY safeb.palm.whyForbidden.label "Why was this page blocked?">
|
||||
|
||||
@ -18,10 +19,10 @@
|
||||
<!ENTITY safeb.blocked.unwantedPage.shortDesc "This web page at <span id='unwanted_sitename'/> has been reported to contain unwanted software and has been blocked based on your security preferences.">
|
||||
<!ENTITY safeb.blocked.unwantedPage.longDesc "<p>Unwanted software pages try to install software that can be deceptive and affect your system in unexpected ways.</p>">
|
||||
|
||||
<!ENTITY safeb.blocked.phishingPage.title "Reported Web Forgery!">
|
||||
<!-- Localization note (safeb.blocked.phishingPage.shortDesc) - Please don't translate the contents of the <span id="phishing_sitename"/> tag. It will be replaced at runtime with a domain name (e.g. www.badsite.com) -->
|
||||
<!ENTITY safeb.blocked.phishingPage.shortDesc "This web page at <span id='phishing_sitename'/> has been reported as a web forgery and has been blocked based on your security preferences.">
|
||||
<!ENTITY safeb.blocked.phishingPage.longDesc "<p>Web forgeries are designed to trick you into revealing personal or financial information by imitating sources you may trust.</p><p>Entering any information on this web page may result in identity theft or other fraud.</p>">
|
||||
<!ENTITY safeb.blocked.phishingPage.title2 "Deceptive Site!">
|
||||
<!-- Localization note (safeb.blocked.phishingPage.shortDesc2) - Please don't translate the contents of the <span id="phishing_sitename"/> tag. It will be replaced at runtime with a domain name (e.g. www.badsite.com) -->
|
||||
<!ENTITY safeb.blocked.phishingPage.shortDesc2 "This web page at <span id='phishing_sitename'/> has been reported as a deceptive site and has been blocked based on your security preferences.">
|
||||
<!ENTITY safeb.blocked.phishingPage.longDesc2 "<p>Deceptive sites are designed to trick you into doing something dangerous, like installing software, or revealing your personal information, like passwords, phone numbers or credit cards.</p><p>Entering any information on this web page may result in identity theft or other fraud.</p>">
|
||||
|
||||
<!ENTITY safeb.blocked.forbiddenPage.title2 "Blocked Site">
|
||||
<!-- Localization note (safeb.blocked.forbiddenPage.shortDesc2) - Please don't translate the contents of the <span id="forbidden_sitename"/> tag. It will be replaced at runtime with a domain name (e.g. www.badsite.com) -->
|
||||
|
@ -2,5 +2,5 @@
|
||||
- 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/. -->
|
||||
|
||||
<!ENTITY reportPhishSiteMenu.title2 "Report Web Forgery…">
|
||||
<!ENTITY reportPhishSiteMenu.accesskey "F">
|
||||
<!ENTITY reportDeceptiveSiteMenu.title "Report deceptive site…">
|
||||
<!ENTITY reportDeceptiveSiteMenu.accesskey "D">
|
||||
|
@ -31,7 +31,7 @@ externalProtocolChkMsg=Remember my choice for all links of this type.
|
||||
externalProtocolLaunchBtn=Launch application
|
||||
malwareBlocked=The site at %S has been reported as an attack site and has been blocked based on your security preferences.
|
||||
unwantedBlocked=The site at %S has been reported as serving unwanted software and has been blocked based on your security preferences.
|
||||
phishingBlocked=The website at %S has been reported as a web forgery designed to trick users into sharing personal or financial information.
|
||||
deceptiveBlocked=This web page at %S has been reported as a deceptive site and has been blocked based on your security preferences.
|
||||
forbiddenBlocked=The site at %S has been blocked by your browser configuration.
|
||||
cspBlocked=This page has a content security policy that prevents it from being loaded in this way.
|
||||
corruptedContentError=The page you are trying to view cannot be shown because an error in the data transmission was detected.
|
||||
|
@ -160,27 +160,6 @@ be temporary, and you can try again later.</li>
|
||||
</ul>
|
||||
">
|
||||
|
||||
<!ENTITY malwareBlocked.title "Suspected Attack Site!">
|
||||
<!ENTITY malwareBlocked.longDesc "
|
||||
<p>Attack sites try to install programs that steal private information, use your computer to attack others, or damage your system.</p>
|
||||
<p>Website owners who believe their site has been reported as an attack site in error may <a href='http://www.stopbadware.org/home/reviewinfo' >request a review</a>.</p>
|
||||
">
|
||||
|
||||
<!ENTITY unwantedBlocked.title "Suspected Unwanted Software Site!">
|
||||
<!ENTITY unwantedBlocked.longDesc "
|
||||
<p>Unwanted software pages try to install software that can be deceptive and affect your system in unexpected ways.</p>
|
||||
">
|
||||
|
||||
<!ENTITY phishingBlocked.title "Suspected Web Forgery!">
|
||||
<!ENTITY phishingBlocked.longDesc "
|
||||
<p>Entering any personal information on this page may result in identity theft or other fraud.</p>
|
||||
<p>These types of web forgeries are used in scams known as phishing attacks, in which fraudulent web pages and emails are used to imitate sources you may trust.</p>
|
||||
">
|
||||
|
||||
<!ENTITY forbiddenBlocked.title "Forbidden Site">
|
||||
<!ENTITY forbiddenBlocked.longDesc "<p>&brandShortName; prevented this page from loading because it is configured to block it.</p>
|
||||
">
|
||||
|
||||
<!ENTITY cspBlocked.title "Blocked by Content Security Policy">
|
||||
<!ENTITY cspBlocked.longDesc "<p>&brandShortName; prevented this page from loading in this way because the page has a content security policy that disallows it.</p>">
|
||||
|
||||
|
@ -1,12 +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/.
|
||||
|
||||
TEST_EXTENSIONS_DIR = $(DEPTH)/_tests/testing/mochitest/extensions
|
||||
GENERATED_DIRS = $(TEST_EXTENSIONS_DIR)
|
||||
XPI_PKGNAME = mozscreenshots@mozilla.org
|
||||
|
||||
include $(topsrcdir)/config/rules.mk
|
||||
|
||||
libs::
|
||||
(cd $(DIST)/xpi-stage && tar $(TAR_CREATE_FLAGS) - $(XPI_NAME)) | (cd $(TEST_EXTENSIONS_DIR) && tar -xf -)
|
@ -9,7 +9,7 @@
|
||||
|
||||
<Description about="urn:mozilla:install-manifest">
|
||||
<em:id>mozscreenshots@mozilla.org</em:id>
|
||||
#expand <em:version>__MOZILLA_VERSION_U__</em:version>
|
||||
<em:version>0.3.2</em:version>
|
||||
<em:bootstrap>true</em:bootstrap>
|
||||
|
||||
<!-- for running custom screenshot binaries -->
|
||||
|
@ -15,3 +15,7 @@ FINAL_TARGET_PP_FILES += [
|
||||
'bootstrap.js',
|
||||
'install.rdf',
|
||||
]
|
||||
|
||||
TEST_HARNESS_FILES.testing.mochitest.extensions += [
|
||||
'mozscreenshots-signed.xpi',
|
||||
]
|
||||
|
Binary file not shown.
@ -9,13 +9,18 @@ MOZ_ARG_ENABLE_BOOL(clang-plugin,
|
||||
ENABLE_CLANG_PLUGIN=1,
|
||||
ENABLE_CLANG_PLUGIN= )
|
||||
if test -n "$ENABLE_CLANG_PLUGIN"; then
|
||||
if test -z "$CLANG_CC"; then
|
||||
if test -z "${CLANG_CC}${CLANG_CL}"; then
|
||||
AC_MSG_ERROR([Can't use clang plugin without clang.])
|
||||
fi
|
||||
|
||||
AC_MSG_CHECKING([for llvm-config])
|
||||
if test -z "$LLVMCONFIG"; then
|
||||
LLVMCONFIG=`$CXX -print-prog-name=llvm-config`
|
||||
if test -n "$CLANG_CL"; then
|
||||
CXX_COMPILER="$(dirname "$CXX")/clang"
|
||||
else
|
||||
CXX_COMPILER="${CXX}"
|
||||
fi
|
||||
LLVMCONFIG=`$CXX_COMPILER -print-prog-name=llvm-config`
|
||||
fi
|
||||
|
||||
if test -z "$LLVMCONFIG"; then
|
||||
@ -36,18 +41,57 @@ if test -n "$ENABLE_CLANG_PLUGIN"; then
|
||||
dnl The clang package we use on OSX is old, and its llvm-config doesn't
|
||||
dnl recognize --system-libs, so ask for that separately. llvm-config's
|
||||
dnl failure here is benign, so we can ignore it if it happens.
|
||||
LLVM_LDFLAGS=`$LLVMCONFIG --system-libs | xargs`
|
||||
LLVM_LDFLAGS="$LLVM_LDFLAGS `$LLVMCONFIG --ldflags --libs core mc analysis asmparser mcparser bitreader option | xargs`"
|
||||
dnl Use tr instead of xargs in order to avoid problems with path separators on Windows.
|
||||
LLVM_LDFLAGS=`$LLVMCONFIG --system-libs | tr '\n' ' '`
|
||||
LLVM_LDFLAGS="$LLVM_LDFLAGS `$LLVMCONFIG --ldflags --libs core mc analysis asmparser mcparser bitreader option | tr '\n' ' '`"
|
||||
|
||||
if test "${HOST_OS_ARCH}" = "Darwin"; then
|
||||
CLANG_LDFLAGS="-lclangFrontend -lclangDriver -lclangSerialization"
|
||||
CLANG_LDFLAGS="$CLANG_LDFLAGS -lclangParse -lclangSema -lclangAnalysis"
|
||||
CLANG_LDFLAGS="$CLANG_LDFLAGS -lclangEdit -lclangAST -lclangLex"
|
||||
CLANG_LDFLAGS="$CLANG_LDFLAGS -lclangBasic -lclangASTMatchers"
|
||||
elif test "${HOST_OS_ARCH}" = "WINNT"; then
|
||||
CLANG_LDFLAGS="clangFrontend.lib clangDriver.lib clangSerialization.lib"
|
||||
CLANG_LDFLAGS="$CLANG_LDFLAGS clangParse.lib clangSema.lib clangAnalysis.lib"
|
||||
CLANG_LDFLAGS="$CLANG_LDFLAGS clangEdit.lib clangAST.lib clangLex.lib"
|
||||
CLANG_LDFLAGS="$CLANG_LDFLAGS clangBasic.lib clangASTMatchers.lib"
|
||||
else
|
||||
CLANG_LDFLAGS="-lclangASTMatchers"
|
||||
fi
|
||||
|
||||
if test -n "$CLANG_CL"; then
|
||||
dnl The llvm-config coming with clang-cl may give us arguments in the
|
||||
dnl /ARG form, which in msys will be interpreted as a path name. So we
|
||||
dnl need to split the args and convert the leading slashes that we find
|
||||
dnl into a dash.
|
||||
LLVM_REPLACE_CXXFLAGS=''
|
||||
for arg in $LLVM_CXXFLAGS; do
|
||||
dnl The following expression replaces a leading slash with a dash.
|
||||
dnl Also replace any backslashes with forward slash.
|
||||
arg=`echo "$arg"|sed -e 's/^\//-/' -e 's/\\\\/\//g'`
|
||||
LLVM_REPLACE_CXXFLAGS="$LLVM_REPLACE_CXXFLAGS $arg"
|
||||
done
|
||||
LLVM_CXXFLAGS="$LLVM_REPLACE_CXXFLAGS"
|
||||
|
||||
LLVM_REPLACE_LDFLAGS=''
|
||||
for arg in $LLVM_LDFLAGS; do
|
||||
dnl The following expression replaces a leading slash with a dash.
|
||||
dnl Also replace any backslashes with forward slash.
|
||||
arg=`echo "$arg"|sed -e 's/^\//-/' -e 's/\\\\/\//g'`
|
||||
LLVM_REPLACE_LDFLAGS="$LLVM_REPLACE_LDFLAGS $arg"
|
||||
done
|
||||
LLVM_LDFLAGS="$LLVM_REPLACE_LDFLAGS"
|
||||
|
||||
CLANG_REPLACE_LDFLAGS=''
|
||||
for arg in $CLANG_LDFLAGS; do
|
||||
dnl The following expression replaces a leading slash with a dash.
|
||||
dnl Also replace any backslashes with forward slash.
|
||||
arg=`echo "$arg"|sed -e 's/^\//-/' -e 's/\\\\/\//g'`
|
||||
CLANG_REPLACE_LDFLAGS="$CLANG_REPLACE_LDFLAGS $arg"
|
||||
done
|
||||
CLANG_LDFLAGS="$CLANG_REPLACE_LDFLAGS"
|
||||
fi
|
||||
|
||||
dnl Check for the new ASTMatcher API names. Since this happened in the
|
||||
dnl middle of the 3.8 cycle, our CLANG_VERSION_FULL is impossible to use
|
||||
dnl correctly, so we have to detect this at configure time.
|
||||
|
@ -9,10 +9,14 @@ include $(topsrcdir)/config/config.mk
|
||||
|
||||
# In the current moz.build world, we need to override essentially every
|
||||
# variable to limit ourselves to what we need to build the clang plugin.
|
||||
ifeq ($(HOST_OS_ARCH),WINNT)
|
||||
OS_CXXFLAGS := $(LLVM_CXXFLAGS) -GR- -EHsc
|
||||
else
|
||||
OS_CXXFLAGS := $(LLVM_CXXFLAGS) -fno-rtti -fno-exceptions
|
||||
DSO_LDOPTS := -shared
|
||||
endif
|
||||
OS_COMPILE_CXXFLAGS :=
|
||||
OS_LDFLAGS := $(LLVM_LDFLAGS) $(CLANG_LDFLAGS)
|
||||
DSO_LDOPTS := -shared
|
||||
|
||||
ifeq ($(HOST_OS_ARCH)_$(OS_ARCH),Linux_Darwin)
|
||||
# Use the host compiler instead of the target compiler.
|
||||
|
@ -1517,3 +1517,7 @@ public:
|
||||
|
||||
static FrontendPluginRegistry::Add<MozCheckAction> X("moz-check",
|
||||
"check moz action");
|
||||
// Export the registry on Windows.
|
||||
#ifdef LLVM_EXPORT_REGISTRY
|
||||
LLVM_EXPORT_REGISTRY(FrontendPluginRegistry)
|
||||
#endif
|
||||
|
@ -54,16 +54,9 @@ leak:mozilla::plugins::PPluginModuleParent::OnCallReceived
|
||||
leak:sec_asn1e_allocate_item
|
||||
leak:PORT_Strdup_Util
|
||||
|
||||
# Bug 1021302 - Leak of fds allocated in nsSocketTransport::BuildSocket(). m1, m5, dt, oth
|
||||
leak:nsSocketTransport::BuildSocket
|
||||
leak:nsServerSocket::OnSocketReady
|
||||
|
||||
# Bug 1021350 - Small leak under event_base_once. m1, m4, bc3
|
||||
leak:event_base_once
|
||||
|
||||
# Bug 1021854 - nsFileStreamBase::DoOpen() leaking fds. bc1, oth
|
||||
leak:nsLocalFile::OpenNSPRFileDesc
|
||||
|
||||
# Bug 1022010 - Small leak under _render_glyph_outline. bc1
|
||||
leak:_render_glyph_outline
|
||||
|
||||
@ -74,7 +67,7 @@ leak:SECITEM_AllocItem_Util
|
||||
leak:GlobalPrinters::InitializeGlobalPrinters
|
||||
leak:nsPSPrinterList::GetPrinterList
|
||||
|
||||
# Bug 1028456 - More leaks with _PR_Getfd, in nsLocalFile::CopyToNative and do_create. bc1, bc3
|
||||
# Bug 1028456 - Various NSPR fd-related leaks. m1-m5, bc1,bc2,bc5,bc7,dt4,dt5.
|
||||
leak:_PR_Getfd
|
||||
|
||||
# Bug 1028483 - The XML parser sometimes leaks an object. bc3
|
||||
|
@ -495,6 +495,8 @@ nsScriptSecurityManager::ContentSecurityPolicyPermitsJSAction(JSContext *cx)
|
||||
if (const char *file = scriptFilename.get()) {
|
||||
CopyUTF8toUTF16(nsDependentCString(file), fileName);
|
||||
}
|
||||
} else {
|
||||
MOZ_ASSERT(!JS_IsExceptionPending(cx));
|
||||
}
|
||||
csp->LogViolationDetails(nsIContentSecurityPolicy::VIOLATION_TYPE_EVAL,
|
||||
fileName,
|
||||
|
@ -6,7 +6,7 @@
|
||||
# script. Additional scripts may be added by specific subdirectories.
|
||||
|
||||
ifdef ENABLE_CLANG_PLUGIN
|
||||
CLANG_PLUGIN := $(DEPTH)/build/clang-plugin/$(DLL_PREFIX)clang-plugin$(DLL_SUFFIX)
|
||||
CLANG_PLUGIN := $(topobjdir)/build/clang-plugin/$(DLL_PREFIX)clang-plugin$(DLL_SUFFIX)
|
||||
OS_CXXFLAGS += -Xclang -load -Xclang $(CLANG_PLUGIN) -Xclang -add-plugin -Xclang moz-check
|
||||
OS_CFLAGS += -Xclang -load -Xclang $(CLANG_PLUGIN) -Xclang -add-plugin -Xclang moz-check
|
||||
endif
|
||||
|
@ -4969,7 +4969,7 @@ nsDocShell::DisplayLoadError(nsresult aError, nsIURI* aURI,
|
||||
bool sendTelemetry = false;
|
||||
if (NS_ERROR_PHISHING_URI == aError) {
|
||||
sendTelemetry = true;
|
||||
error.AssignLiteral("phishingBlocked");
|
||||
error.AssignLiteral("deceptiveBlocked");
|
||||
bucketId = IsFrame() ? nsISecurityUITelemetry::WARNING_PHISHING_PAGE_FRAME
|
||||
: nsISecurityUITelemetry::WARNING_PHISHING_PAGE_TOP;
|
||||
} else if (NS_ERROR_MALWARE_URI == aError) {
|
||||
|
@ -18,5 +18,32 @@ AnimationEffectTiming::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenPr
|
||||
return AnimationEffectTimingBinding::Wrap(aCx, this, aGivenProto);
|
||||
}
|
||||
|
||||
void
|
||||
AnimationEffectTiming::SetDuration(const UnrestrictedDoubleOrString& aDuration)
|
||||
{
|
||||
if (mTiming.mDuration.IsUnrestrictedDouble() &&
|
||||
aDuration.IsUnrestrictedDouble() &&
|
||||
mTiming.mDuration.GetAsUnrestrictedDouble() ==
|
||||
aDuration.GetAsUnrestrictedDouble()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (mTiming.mDuration.IsString() && aDuration.IsString() &&
|
||||
mTiming.mDuration.GetAsString() == aDuration.GetAsString()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (aDuration.IsUnrestrictedDouble()) {
|
||||
mTiming.mDuration.SetAsUnrestrictedDouble() =
|
||||
aDuration.GetAsUnrestrictedDouble();
|
||||
} else {
|
||||
mTiming.mDuration.SetAsString() = aDuration.GetAsString();
|
||||
}
|
||||
|
||||
if (mEffect) {
|
||||
mEffect->NotifySpecifiedTimingUpdated();
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
@ -8,6 +8,7 @@
|
||||
#define mozilla_dom_AnimationEffectTiming_h
|
||||
|
||||
#include "mozilla/dom/AnimationEffectTimingReadOnly.h"
|
||||
#include "mozilla/Attributes.h" // For MOZ_NON_OWNING_REF
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
@ -15,10 +16,18 @@ namespace dom {
|
||||
class AnimationEffectTiming : public AnimationEffectTimingReadOnly
|
||||
{
|
||||
public:
|
||||
explicit AnimationEffectTiming(const TimingParams& aTiming)
|
||||
: AnimationEffectTimingReadOnly(aTiming) { }
|
||||
AnimationEffectTiming(const TimingParams& aTiming, KeyframeEffect* aEffect)
|
||||
: AnimationEffectTimingReadOnly(aTiming)
|
||||
, mEffect(aEffect) { }
|
||||
|
||||
JSObject* WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) override;
|
||||
|
||||
void Unlink() override { mEffect = nullptr; }
|
||||
|
||||
void SetDuration(const UnrestrictedDoubleOrString& aDuration);
|
||||
|
||||
private:
|
||||
KeyframeEffect* MOZ_NON_OWNING_REF mEffect;
|
||||
};
|
||||
|
||||
} // namespace dom
|
||||
|
@ -97,6 +97,8 @@ public:
|
||||
const TimingParams& AsTimingParams() const { return mTiming; }
|
||||
void SetTimingParams(const TimingParams& aTiming) { mTiming = aTiming; }
|
||||
|
||||
virtual void Unlink() { }
|
||||
|
||||
protected:
|
||||
nsCOMPtr<nsISupports> mParent;
|
||||
TimingParams mTiming;
|
||||
|
@ -19,6 +19,7 @@
|
||||
#include "nsCSSProps.h" // For nsCSSProps::PropHasFlags
|
||||
#include "nsCSSPseudoElements.h"
|
||||
#include "nsCSSValue.h"
|
||||
#include "nsDOMMutationObserver.h" // For nsAutoAnimationMutationBatch
|
||||
#include "nsStyleUtil.h"
|
||||
#include <algorithm> // For std::max
|
||||
|
||||
@ -2142,7 +2143,7 @@ KeyframeEffect::KeyframeEffect(nsIDocument* aDocument,
|
||||
CSSPseudoElementType aPseudoType,
|
||||
const TimingParams& aTiming)
|
||||
: KeyframeEffectReadOnly(aDocument, aTarget, aPseudoType,
|
||||
new AnimationEffectTiming(aTiming))
|
||||
new AnimationEffectTiming(aTiming, this))
|
||||
{
|
||||
}
|
||||
|
||||
@ -2153,5 +2154,39 @@ KeyframeEffect::WrapObject(JSContext* aCx,
|
||||
return KeyframeEffectBinding::Wrap(aCx, this, aGivenProto);
|
||||
}
|
||||
|
||||
void KeyframeEffect::NotifySpecifiedTimingUpdated()
|
||||
{
|
||||
nsIDocument* doc = nullptr;
|
||||
// Bug 1249219:
|
||||
// We don't support animation mutation observers on pseudo-elements yet.
|
||||
if (mTarget &&
|
||||
mPseudoType == CSSPseudoElementType::NotPseudo) {
|
||||
doc = mTarget->OwnerDoc();
|
||||
}
|
||||
|
||||
nsAutoAnimationMutationBatch mb(doc);
|
||||
|
||||
if (mAnimation) {
|
||||
mAnimation->NotifyEffectTimingUpdated();
|
||||
|
||||
if (mAnimation->IsRelevant()) {
|
||||
nsNodeUtils::AnimationChanged(mAnimation);
|
||||
}
|
||||
|
||||
nsPresContext* presContext = GetPresContext();
|
||||
if (presContext) {
|
||||
presContext->EffectCompositor()->
|
||||
RequestRestyle(mTarget, mPseudoType,
|
||||
EffectCompositor::RestyleType::Layer,
|
||||
mAnimation->CascadeLevel());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
KeyframeEffect::~KeyframeEffect()
|
||||
{
|
||||
mTiming->Unlink();
|
||||
}
|
||||
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
@ -19,7 +19,6 @@
|
||||
#include "mozilla/StyleAnimationValue.h"
|
||||
#include "mozilla/TimeStamp.h"
|
||||
#include "mozilla/dom/AnimationEffectReadOnly.h"
|
||||
#include "mozilla/dom/AnimationEffectTiming.h"
|
||||
#include "mozilla/dom/AnimationEffectTimingReadOnly.h" // TimingParams
|
||||
#include "mozilla/dom/Element.h"
|
||||
#include "mozilla/dom/KeyframeBinding.h"
|
||||
@ -428,6 +427,11 @@ public:
|
||||
return ConstructKeyframeEffect<KeyframeEffect>(aGlobal, aTarget, aFrames,
|
||||
aTiming, aRv);
|
||||
}
|
||||
|
||||
void NotifySpecifiedTimingUpdated();
|
||||
|
||||
protected:
|
||||
~KeyframeEffect() override;
|
||||
};
|
||||
|
||||
} // namespace dom
|
||||
|
@ -1470,6 +1470,47 @@ addAsyncAnimTest("tree_ordering", { observe: div, subtree: true }, function*() {
|
||||
childB.remove();
|
||||
});
|
||||
|
||||
|
||||
addAsyncAnimTest("change_duration_and_currenttime",
|
||||
{ observe: div, subtree: true }, function*() {
|
||||
var anim = div.animate({ opacity: [ 0, 1 ] }, 100000);
|
||||
yield await_frame();
|
||||
assert_records([{ added: [anim], changed: [], removed: [] }],
|
||||
"records after animation is added");
|
||||
|
||||
anim.effect.timing.duration = 10000;
|
||||
yield await_frame();
|
||||
|
||||
assert_records([{ added: [], changed: [anim], removed: [] }],
|
||||
"records after duration is changed");
|
||||
|
||||
anim.effect.timing.duration = 10000;
|
||||
yield await_frame();
|
||||
assert_records([], "records after assigning same value");
|
||||
|
||||
anim.currentTime = 50000;
|
||||
yield await_frame();
|
||||
assert_records([{ added: [], changed: [], removed: [anim] }],
|
||||
"records after animation end");
|
||||
|
||||
anim.effect.timing.duration = 100000;
|
||||
yield await_frame();
|
||||
assert_records([{ added: [anim], changed: [], removed: [] }],
|
||||
"records after animation restarted");
|
||||
|
||||
anim.effect.timing.duration = "auto";
|
||||
yield await_frame();
|
||||
assert_records([{ added: [], changed: [], removed: [anim] }],
|
||||
"records after duration set \"auto\"");
|
||||
|
||||
anim.effect.timing.duration = "auto";
|
||||
yield await_frame();
|
||||
assert_records([], "records after assigning same value \"auto\"");
|
||||
|
||||
anim.cancel();
|
||||
yield await_frame();
|
||||
});
|
||||
|
||||
// Run the tests.
|
||||
SimpleTest.requestLongerTimeout(2);
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
@ -346,6 +346,26 @@ waitForAllPaints(function() {
|
||||
yield ensureElementRemoval(div);
|
||||
});
|
||||
|
||||
add_task_if_omta_enabled(function* change_duration_and_currenttime() {
|
||||
var div = addDiv(null);
|
||||
var animation = div.animate({ opacity: [ 0, 1 ] }, 10000);
|
||||
|
||||
yield animation.ready;
|
||||
ok(animation.isRunningOnCompositor);
|
||||
|
||||
animation.currentTime = 50000;
|
||||
|
||||
ok(!animation.isRunningOnCompositor);
|
||||
|
||||
animation.effect.timing.duration = 100000;
|
||||
var markers = yield observeStyling(5);
|
||||
is(markers.length, 1,
|
||||
'Animations running on the compositor should update style' +
|
||||
'when timing.duration is made longer than the current time');
|
||||
|
||||
yield ensureElementRemoval(div);
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
</script>
|
||||
|
@ -285,6 +285,48 @@ promise_test(function(t) {
|
||||
}, 'isRunningOnCompositor is true when a property that would otherwise block ' +
|
||||
'running on the compositor is overridden in the CSS cascade');
|
||||
|
||||
promise_test(function(t) {
|
||||
var div = addDiv(t);
|
||||
var animation = div.animate({ opacity: [ 0, 1 ] }, 100000);
|
||||
|
||||
return animation.ready.then(t.step_func(function() {
|
||||
assert_equals(animation.isRunningOnCompositor, omtaEnabled,
|
||||
'Animation reports that it is running on the compositor');
|
||||
|
||||
animation.currentTime = 50000;
|
||||
animation.effect.timing.duration = 10000;
|
||||
|
||||
assert_equals(animation.isRunningOnCompositor, false,
|
||||
'Animation reports that it is NOT running on the compositor'
|
||||
+ ' when the animation is set a shorter duration than current time');
|
||||
}));
|
||||
}, 'animation is immediately removed from compositor' +
|
||||
'when timing.duration is made shorter than the current time');
|
||||
|
||||
promise_test(function(t) {
|
||||
var div = addDiv(t);
|
||||
var animation = div.animate({ opacity: [ 0, 1 ] }, 10000);
|
||||
|
||||
return animation.ready.then(t.step_func(function() {
|
||||
assert_equals(animation.isRunningOnCompositor, omtaEnabled,
|
||||
'Animation reports that it is running on the compositor');
|
||||
|
||||
animation.currentTime = 50000;
|
||||
|
||||
assert_equals(animation.isRunningOnCompositor, false,
|
||||
'Animation reports that it is NOT running on the compositor'
|
||||
+ ' when finished');
|
||||
|
||||
animation.effect.timing.duration = 100000;
|
||||
return waitForFrame();
|
||||
})).then(t.step_func(function() {
|
||||
assert_equals(animation.isRunningOnCompositor, omtaEnabled,
|
||||
'Animation reports that it is running on the compositor'
|
||||
+ ' when restarted');
|
||||
}));
|
||||
}, 'animation is added to compositor' +
|
||||
' when timing.duration is made longer than the current time');
|
||||
|
||||
</script>
|
||||
</script>
|
||||
</body>
|
||||
|
574
dom/base/BodyUtil.cpp
Normal file
574
dom/base/BodyUtil.cpp
Normal file
@ -0,0 +1,574 @@
|
||||
/* 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 "BodyUtil.h"
|
||||
|
||||
#include "nsError.h"
|
||||
#include "nsString.h"
|
||||
#include "nsIGlobalObject.h"
|
||||
#include "nsIUnicodeDecoder.h"
|
||||
|
||||
#include "nsCharSeparatedTokenizer.h"
|
||||
#include "nsDOMString.h"
|
||||
#include "nsNetUtil.h"
|
||||
#include "nsReadableUtils.h"
|
||||
#include "nsStreamUtils.h"
|
||||
#include "nsStringStream.h"
|
||||
|
||||
#include "mozilla/ErrorResult.h"
|
||||
#include "mozilla/dom/EncodingUtils.h"
|
||||
#include "mozilla/dom/Exceptions.h"
|
||||
#include "mozilla/dom/FetchUtil.h"
|
||||
#include "mozilla/dom/File.h"
|
||||
#include "mozilla/dom/FormData.h"
|
||||
#include "mozilla/dom/Headers.h"
|
||||
#include "mozilla/dom/Promise.h"
|
||||
#include "mozilla/dom/URLSearchParams.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
namespace {
|
||||
|
||||
class StreamDecoder final
|
||||
{
|
||||
nsCOMPtr<nsIUnicodeDecoder> mDecoder;
|
||||
nsString mDecoded;
|
||||
|
||||
public:
|
||||
StreamDecoder()
|
||||
: mDecoder(EncodingUtils::DecoderForEncoding("UTF-8"))
|
||||
{
|
||||
MOZ_ASSERT(mDecoder);
|
||||
}
|
||||
|
||||
nsresult
|
||||
AppendText(const char* aSrcBuffer, uint32_t aSrcBufferLen)
|
||||
{
|
||||
int32_t destBufferLen;
|
||||
nsresult rv =
|
||||
mDecoder->GetMaxLength(aSrcBuffer, aSrcBufferLen, &destBufferLen);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
if (!mDecoded.SetCapacity(mDecoded.Length() + destBufferLen, fallible)) {
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
char16_t* destBuffer = mDecoded.BeginWriting() + mDecoded.Length();
|
||||
int32_t totalChars = mDecoded.Length();
|
||||
|
||||
int32_t srcLen = (int32_t) aSrcBufferLen;
|
||||
int32_t outLen = destBufferLen;
|
||||
rv = mDecoder->Convert(aSrcBuffer, &srcLen, destBuffer, &outLen);
|
||||
MOZ_ASSERT(NS_SUCCEEDED(rv));
|
||||
|
||||
totalChars += outLen;
|
||||
mDecoded.SetLength(totalChars);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsString&
|
||||
GetText()
|
||||
{
|
||||
return mDecoded;
|
||||
}
|
||||
};
|
||||
|
||||
// Reads over a CRLF and positions start after it.
|
||||
static bool
|
||||
PushOverLine(nsACString::const_iterator& aStart)
|
||||
{
|
||||
if (*aStart == nsCRT::CR && (aStart.size_forward() > 1) && *(++aStart) == nsCRT::LF) {
|
||||
++aStart; // advance to after CRLF
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
class MOZ_STACK_CLASS FillFormIterator final
|
||||
: public URLSearchParams::ForEachIterator
|
||||
{
|
||||
public:
|
||||
explicit FillFormIterator(FormData* aFormData)
|
||||
: mFormData(aFormData)
|
||||
{
|
||||
MOZ_ASSERT(aFormData);
|
||||
}
|
||||
|
||||
bool URLParamsIterator(const nsString& aName,
|
||||
const nsString& aValue) override
|
||||
{
|
||||
ErrorResult rv;
|
||||
mFormData->Append(aName, aValue, rv);
|
||||
MOZ_ASSERT(!rv.Failed());
|
||||
return true;
|
||||
}
|
||||
|
||||
private:
|
||||
FormData* mFormData;
|
||||
};
|
||||
|
||||
/**
|
||||
* A simple multipart/form-data parser as defined in RFC 2388 and RFC 2046.
|
||||
* This does not respect any encoding specified per entry, using UTF-8
|
||||
* throughout. This is as the Fetch spec states in the consume body algorithm.
|
||||
* Borrows some things from Necko's nsMultiMixedConv, but is simpler since
|
||||
* unlike Necko we do not have to deal with receiving incomplete chunks of data.
|
||||
*
|
||||
* This parser will fail the entire parse on any invalid entry, so it will
|
||||
* never return a partially filled FormData.
|
||||
* The content-disposition header is used to figure out the name and filename
|
||||
* entries. The inclusion of the filename parameter decides if the entry is
|
||||
* inserted into the FormData as a string or a File.
|
||||
*
|
||||
* File blobs are copies of the underlying data string since we cannot adopt
|
||||
* char* chunks embedded within the larger body without significant effort.
|
||||
* FIXME(nsm): Bug 1127552 - We should add telemetry to calls to formData() and
|
||||
* friends to figure out if Fetch ends up copying big blobs to see if this is
|
||||
* worth optimizing.
|
||||
*/
|
||||
class MOZ_STACK_CLASS FormDataParser
|
||||
{
|
||||
private:
|
||||
RefPtr<FormData> mFormData;
|
||||
nsCString mMimeType;
|
||||
nsCString mData;
|
||||
|
||||
// Entry state, reset in START_PART.
|
||||
nsCString mName;
|
||||
nsCString mFilename;
|
||||
nsCString mContentType;
|
||||
|
||||
enum
|
||||
{
|
||||
START_PART,
|
||||
PARSE_HEADER,
|
||||
PARSE_BODY,
|
||||
} mState;
|
||||
|
||||
nsIGlobalObject* mParentObject;
|
||||
|
||||
// Reads over a boundary and sets start to the position after the end of the
|
||||
// boundary. Returns false if no boundary is found immediately.
|
||||
bool
|
||||
PushOverBoundary(const nsACString& aBoundaryString,
|
||||
nsACString::const_iterator& aStart,
|
||||
nsACString::const_iterator& aEnd)
|
||||
{
|
||||
// We copy the end iterator to keep the original pointing to the real end
|
||||
// of the string.
|
||||
nsACString::const_iterator end(aEnd);
|
||||
const char* beginning = aStart.get();
|
||||
if (FindInReadable(aBoundaryString, aStart, end)) {
|
||||
// We either should find the body immediately, or after 2 chars with the
|
||||
// 2 chars being '-', everything else is failure.
|
||||
if ((aStart.get() - beginning) == 0) {
|
||||
aStart.advance(aBoundaryString.Length());
|
||||
return true;
|
||||
}
|
||||
|
||||
if ((aStart.get() - beginning) == 2) {
|
||||
if (*(--aStart) == '-' && *(--aStart) == '-') {
|
||||
aStart.advance(aBoundaryString.Length() + 2);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
ParseHeader(nsACString::const_iterator& aStart,
|
||||
nsACString::const_iterator& aEnd,
|
||||
bool* aWasEmptyHeader)
|
||||
{
|
||||
nsAutoCString headerName, headerValue;
|
||||
if (!FetchUtil::ExtractHeader(aStart, aEnd,
|
||||
headerName, headerValue,
|
||||
aWasEmptyHeader)) {
|
||||
return false;
|
||||
}
|
||||
if (*aWasEmptyHeader) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (headerName.LowerCaseEqualsLiteral("content-disposition")) {
|
||||
nsCCharSeparatedTokenizer tokenizer(headerValue, ';');
|
||||
bool seenFormData = false;
|
||||
while (tokenizer.hasMoreTokens()) {
|
||||
const nsDependentCSubstring& token = tokenizer.nextToken();
|
||||
if (token.IsEmpty()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (token.EqualsLiteral("form-data")) {
|
||||
seenFormData = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (seenFormData &&
|
||||
StringBeginsWith(token, NS_LITERAL_CSTRING("name="))) {
|
||||
mName = StringTail(token, token.Length() - 5);
|
||||
mName.Trim(" \"");
|
||||
continue;
|
||||
}
|
||||
|
||||
if (seenFormData &&
|
||||
StringBeginsWith(token, NS_LITERAL_CSTRING("filename="))) {
|
||||
mFilename = StringTail(token, token.Length() - 9);
|
||||
mFilename.Trim(" \"");
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (mName.IsVoid()) {
|
||||
// Could not parse a valid entry name.
|
||||
return false;
|
||||
}
|
||||
} else if (headerName.LowerCaseEqualsLiteral("content-type")) {
|
||||
mContentType = headerValue;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// The end of a body is marked by a CRLF followed by the boundary. So the
|
||||
// CRLF is part of the boundary and not the body, but any prior CRLFs are
|
||||
// part of the body. This will position the iterator at the beginning of the
|
||||
// boundary (after the CRLF).
|
||||
bool
|
||||
ParseBody(const nsACString& aBoundaryString,
|
||||
nsACString::const_iterator& aStart,
|
||||
nsACString::const_iterator& aEnd)
|
||||
{
|
||||
const char* beginning = aStart.get();
|
||||
|
||||
// Find the boundary marking the end of the body.
|
||||
nsACString::const_iterator end(aEnd);
|
||||
if (!FindInReadable(aBoundaryString, aStart, end)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// We found a boundary, strip the just prior CRLF, and consider
|
||||
// everything else the body section.
|
||||
if (aStart.get() - beginning < 2) {
|
||||
// Only the first entry can have a boundary right at the beginning. Even
|
||||
// an empty body will have a CRLF before the boundary. So this is
|
||||
// a failure.
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check that there is a CRLF right before the boundary.
|
||||
aStart.advance(-2);
|
||||
|
||||
// Skip optional hyphens.
|
||||
if (*aStart == '-' && *(aStart.get()+1) == '-') {
|
||||
if (aStart.get() - beginning < 2) {
|
||||
return false;
|
||||
}
|
||||
|
||||
aStart.advance(-2);
|
||||
}
|
||||
|
||||
if (*aStart != nsCRT::CR || *(aStart.get()+1) != nsCRT::LF) {
|
||||
return false;
|
||||
}
|
||||
|
||||
nsAutoCString body(beginning, aStart.get() - beginning);
|
||||
|
||||
// Restore iterator to after the \r\n as we promised.
|
||||
// We do not need to handle the extra hyphens case since our boundary
|
||||
// parser in PushOverBoundary()
|
||||
aStart.advance(2);
|
||||
|
||||
if (!mFormData) {
|
||||
mFormData = new FormData();
|
||||
}
|
||||
|
||||
NS_ConvertUTF8toUTF16 name(mName);
|
||||
|
||||
if (mFilename.IsVoid()) {
|
||||
ErrorResult rv;
|
||||
mFormData->Append(name, NS_ConvertUTF8toUTF16(body), rv);
|
||||
MOZ_ASSERT(!rv.Failed());
|
||||
} else {
|
||||
// Unfortunately we've to copy the data first since all our strings are
|
||||
// going to free it. We also need fallible alloc, so we can't just use
|
||||
// ToNewCString().
|
||||
char* copy = static_cast<char*>(moz_xmalloc(body.Length()));
|
||||
if (!copy) {
|
||||
NS_WARNING("Failed to copy File entry body.");
|
||||
return false;
|
||||
}
|
||||
nsCString::const_iterator bodyIter, bodyEnd;
|
||||
body.BeginReading(bodyIter);
|
||||
body.EndReading(bodyEnd);
|
||||
char *p = copy;
|
||||
while (bodyIter != bodyEnd) {
|
||||
*p++ = *bodyIter++;
|
||||
}
|
||||
p = nullptr;
|
||||
|
||||
RefPtr<Blob> file =
|
||||
File::CreateMemoryFile(mParentObject,
|
||||
reinterpret_cast<void *>(copy), body.Length(),
|
||||
NS_ConvertUTF8toUTF16(mFilename),
|
||||
NS_ConvertUTF8toUTF16(mContentType), /* aLastModifiedDate */ 0);
|
||||
Optional<nsAString> dummy;
|
||||
ErrorResult rv;
|
||||
mFormData->Append(name, *file, dummy, rv);
|
||||
if (NS_WARN_IF(rv.Failed())) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public:
|
||||
FormDataParser(const nsACString& aMimeType, const nsACString& aData, nsIGlobalObject* aParent)
|
||||
: mMimeType(aMimeType), mData(aData), mState(START_PART), mParentObject(aParent)
|
||||
{
|
||||
}
|
||||
|
||||
bool
|
||||
Parse()
|
||||
{
|
||||
// Determine boundary from mimetype.
|
||||
const char* boundaryId = nullptr;
|
||||
boundaryId = strstr(mMimeType.BeginWriting(), "boundary");
|
||||
if (!boundaryId) {
|
||||
return false;
|
||||
}
|
||||
|
||||
boundaryId = strchr(boundaryId, '=');
|
||||
if (!boundaryId) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Skip over '='.
|
||||
boundaryId++;
|
||||
|
||||
char *attrib = (char *) strchr(boundaryId, ';');
|
||||
if (attrib) *attrib = '\0';
|
||||
|
||||
nsAutoCString boundaryString(boundaryId);
|
||||
if (attrib) *attrib = ';';
|
||||
|
||||
boundaryString.Trim(" \"");
|
||||
|
||||
if (boundaryString.Length() == 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
nsACString::const_iterator start, end;
|
||||
mData.BeginReading(start);
|
||||
// This should ALWAYS point to the end of data.
|
||||
// Helpers make copies.
|
||||
mData.EndReading(end);
|
||||
|
||||
while (start != end) {
|
||||
switch(mState) {
|
||||
case START_PART:
|
||||
mName.SetIsVoid(true);
|
||||
mFilename.SetIsVoid(true);
|
||||
mContentType = NS_LITERAL_CSTRING("text/plain");
|
||||
|
||||
// MUST start with boundary.
|
||||
if (!PushOverBoundary(boundaryString, start, end)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (start != end && *start == '-') {
|
||||
// End of data.
|
||||
if (!mFormData) {
|
||||
mFormData = new FormData();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!PushOverLine(start)) {
|
||||
return false;
|
||||
}
|
||||
mState = PARSE_HEADER;
|
||||
break;
|
||||
|
||||
case PARSE_HEADER:
|
||||
bool emptyHeader;
|
||||
if (!ParseHeader(start, end, &emptyHeader)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (emptyHeader && !PushOverLine(start)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
mState = emptyHeader ? PARSE_BODY : PARSE_HEADER;
|
||||
break;
|
||||
|
||||
case PARSE_BODY:
|
||||
if (mName.IsVoid()) {
|
||||
NS_WARNING("No content-disposition header with a valid name was "
|
||||
"found. Failing at body parse.");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!ParseBody(boundaryString, start, end)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
mState = START_PART;
|
||||
break;
|
||||
|
||||
default:
|
||||
MOZ_CRASH("Invalid case");
|
||||
}
|
||||
}
|
||||
|
||||
NS_NOTREACHED("Should never reach here.");
|
||||
return false;
|
||||
}
|
||||
|
||||
already_AddRefed<FormData> GetFormData()
|
||||
{
|
||||
return mFormData.forget();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
// static
|
||||
void
|
||||
BodyUtil::ConsumeArrayBuffer(JSContext* aCx,
|
||||
JS::MutableHandle<JSObject*> aValue,
|
||||
uint32_t aInputLength, uint8_t* aInput,
|
||||
ErrorResult& aRv)
|
||||
{
|
||||
JS::Rooted<JSObject*> arrayBuffer(aCx);
|
||||
arrayBuffer = JS_NewArrayBufferWithContents(aCx, aInputLength,
|
||||
reinterpret_cast<void *>(aInput));
|
||||
if (!arrayBuffer) {
|
||||
JS_ClearPendingException(aCx);
|
||||
aRv.Throw(NS_ERROR_OUT_OF_MEMORY);
|
||||
return;
|
||||
}
|
||||
aValue.set(arrayBuffer);
|
||||
}
|
||||
|
||||
// static
|
||||
already_AddRefed<Blob>
|
||||
BodyUtil::ConsumeBlob(nsISupports* aParent, const nsString& aMimeType,
|
||||
uint32_t aInputLength, uint8_t* aInput,
|
||||
ErrorResult& aRv)
|
||||
{
|
||||
RefPtr<Blob> blob =
|
||||
Blob::CreateMemoryBlob(aParent,
|
||||
reinterpret_cast<void *>(aInput), aInputLength,
|
||||
aMimeType);
|
||||
|
||||
if (!blob) {
|
||||
aRv.Throw(NS_ERROR_DOM_UNKNOWN_ERR);
|
||||
return nullptr;
|
||||
}
|
||||
return blob.forget();
|
||||
}
|
||||
|
||||
// static
|
||||
already_AddRefed<FormData>
|
||||
BodyUtil::ConsumeFormData(nsIGlobalObject* aParent, const nsCString& aMimeType,
|
||||
const nsCString& aStr, ErrorResult& aRv)
|
||||
{
|
||||
NS_NAMED_LITERAL_CSTRING(formDataMimeType, "multipart/form-data");
|
||||
|
||||
// Allow semicolon separated boundary/encoding suffix like multipart/form-data; boundary=
|
||||
// but disallow multipart/form-datafoobar.
|
||||
bool isValidFormDataMimeType = StringBeginsWith(aMimeType, formDataMimeType);
|
||||
|
||||
if (isValidFormDataMimeType && aMimeType.Length() > formDataMimeType.Length()) {
|
||||
isValidFormDataMimeType = aMimeType[formDataMimeType.Length()] == ';';
|
||||
}
|
||||
|
||||
if (isValidFormDataMimeType) {
|
||||
FormDataParser parser(aMimeType, aStr, aParent);
|
||||
if (!parser.Parse()) {
|
||||
aRv.ThrowTypeError<MSG_BAD_FORMDATA>();
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
RefPtr<FormData> fd = parser.GetFormData();
|
||||
MOZ_ASSERT(fd);
|
||||
return fd.forget();
|
||||
}
|
||||
|
||||
NS_NAMED_LITERAL_CSTRING(urlDataMimeType, "application/x-www-form-urlencoded");
|
||||
bool isValidUrlEncodedMimeType = StringBeginsWith(aMimeType, urlDataMimeType);
|
||||
|
||||
if (isValidUrlEncodedMimeType && aMimeType.Length() > urlDataMimeType.Length()) {
|
||||
isValidUrlEncodedMimeType = aMimeType[urlDataMimeType.Length()] == ';';
|
||||
}
|
||||
|
||||
if (isValidUrlEncodedMimeType) {
|
||||
URLParams params;
|
||||
params.ParseInput(aStr);
|
||||
|
||||
RefPtr<FormData> fd = new FormData(aParent);
|
||||
FillFormIterator iterator(fd);
|
||||
DebugOnly<bool> status = params.ForEach(iterator);
|
||||
MOZ_ASSERT(status);
|
||||
|
||||
return fd.forget();
|
||||
}
|
||||
|
||||
aRv.ThrowTypeError<MSG_BAD_FORMDATA>();
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// static
|
||||
nsresult
|
||||
BodyUtil::ConsumeText(uint32_t aInputLength, uint8_t* aInput,
|
||||
nsString& aText)
|
||||
{
|
||||
StreamDecoder decoder;
|
||||
nsresult rv = decoder.AppendText(reinterpret_cast<char*>(aInput),
|
||||
aInputLength);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
aText = decoder.GetText();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// static
|
||||
void
|
||||
BodyUtil::ConsumeJson(JSContext* aCx, JS::MutableHandle<JS::Value> aValue,
|
||||
const nsString& aStr, ErrorResult& aRv)
|
||||
{
|
||||
aRv.MightThrowJSException();
|
||||
|
||||
AutoForceSetExceptionOnContext forceExn(aCx);
|
||||
JS::Rooted<JS::Value> json(aCx);
|
||||
if (!JS_ParseJSON(aCx, aStr.get(), aStr.Length(), &json)) {
|
||||
if (!JS_IsExceptionPending(aCx)) {
|
||||
aRv.Throw(NS_ERROR_DOM_UNKNOWN_ERR);
|
||||
return;
|
||||
}
|
||||
|
||||
JS::Rooted<JS::Value> exn(aCx);
|
||||
DebugOnly<bool> gotException = JS_GetPendingException(aCx, &exn);
|
||||
MOZ_ASSERT(gotException);
|
||||
|
||||
JS_ClearPendingException(aCx);
|
||||
aRv.ThrowJSException(aCx, exn);
|
||||
return;
|
||||
}
|
||||
|
||||
aValue.set(json);
|
||||
}
|
||||
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
68
dom/base/BodyUtil.h
Normal file
68
dom/base/BodyUtil.h
Normal file
@ -0,0 +1,68 @@
|
||||
/* 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/. */
|
||||
|
||||
#ifndef mozilla_dom_BodyUtil_h
|
||||
#define mozilla_dom_BodyUtil_h
|
||||
|
||||
#include "nsString.h"
|
||||
#include "nsError.h"
|
||||
|
||||
#include "mozilla/ErrorResult.h"
|
||||
#include "mozilla/dom/File.h"
|
||||
#include "mozilla/dom/FormData.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
class BodyUtil final
|
||||
{
|
||||
private:
|
||||
BodyUtil() = delete;
|
||||
|
||||
public:
|
||||
/**
|
||||
* Creates an array buffer from an array, assigning the result to |aValue|.
|
||||
* The array buffer takes ownership of |aInput|, which must be allocated
|
||||
* by |malloc|.
|
||||
*/
|
||||
static void
|
||||
ConsumeArrayBuffer(JSContext* aCx, JS::MutableHandle<JSObject*> aValue,
|
||||
uint32_t aInputLength, uint8_t* aInput, ErrorResult& aRv);
|
||||
|
||||
/**
|
||||
* Creates an in-memory blob from an array. The blob takes ownership of
|
||||
* |aInput|, which must be allocated by |malloc|.
|
||||
*/
|
||||
static already_AddRefed<Blob>
|
||||
ConsumeBlob(nsISupports* aParent, const nsString& aMimeType,
|
||||
uint32_t aInputLength, uint8_t* aInput, ErrorResult& aRv);
|
||||
|
||||
/**
|
||||
* Creates a form data object from a UTF-8 encoded |aStr|. Returns |nullptr|
|
||||
* and sets |aRv| to MSG_BAD_FORMDATA if |aStr| contains invalid data.
|
||||
*/
|
||||
static already_AddRefed<FormData>
|
||||
ConsumeFormData(nsIGlobalObject* aParent, const nsCString& aMimeType,
|
||||
const nsCString& aStr, ErrorResult& aRv);
|
||||
|
||||
/**
|
||||
* UTF-8 decodes |aInput| into |aText|. The caller may free |aInput|
|
||||
* once this method returns.
|
||||
*/
|
||||
static nsresult
|
||||
ConsumeText(uint32_t aInputLength, uint8_t* aInput, nsString& aText);
|
||||
|
||||
/**
|
||||
* Parses a UTF-8 encoded |aStr| as JSON, assigning the result to |aValue|.
|
||||
* Sets |aRv| to a syntax error if |aStr| contains invalid data.
|
||||
*/
|
||||
static void
|
||||
ConsumeJson(JSContext* aCx, JS::MutableHandle<JS::Value> aValue,
|
||||
const nsString& aStr, ErrorResult& aRv);
|
||||
};
|
||||
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // mozilla_dom_BodyUtil_h
|
@ -371,7 +371,7 @@ private:
|
||||
|
||||
RefPtr<WorkerControlRunnable> runnable =
|
||||
new ConsoleReleaseRunnable(mWorkerPrivate, this);
|
||||
runnable->Dispatch(nullptr);
|
||||
runnable->Dispatch();
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -11,6 +11,9 @@
|
||||
#include "mozilla/dom/Element.h"
|
||||
#include "nsIURL.h"
|
||||
#include "nsISizeOf.h"
|
||||
#include "nsIDocShell.h"
|
||||
#include "nsIPrefetchService.h"
|
||||
#include "nsCPrefetchService.h"
|
||||
|
||||
#include "nsEscape.h"
|
||||
#include "nsGkAtoms.h"
|
||||
@ -72,6 +75,70 @@ Link::CancelDNSPrefetch(nsWrapperCache::FlagsType aDeferredFlag,
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
Link::TryDNSPrefetchPreconnectOrPrefetch()
|
||||
{
|
||||
MOZ_ASSERT(mElement->IsInComposedDoc());
|
||||
if (!ElementHasHref()) {
|
||||
return;
|
||||
}
|
||||
|
||||
nsAutoString rel;
|
||||
if (!mElement->GetAttr(kNameSpaceID_None, nsGkAtoms::rel, rel)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!nsContentUtils::PrefetchEnabled(mElement->OwnerDoc()->GetDocShell())) {
|
||||
return;
|
||||
}
|
||||
|
||||
uint32_t linkTypes = nsStyleLinkElement::ParseLinkTypes(rel,
|
||||
mElement->NodePrincipal());
|
||||
|
||||
if ((linkTypes & nsStyleLinkElement::ePREFETCH) ||
|
||||
(linkTypes & nsStyleLinkElement::eNEXT)){
|
||||
nsCOMPtr<nsIPrefetchService> prefetchService(do_GetService(NS_PREFETCHSERVICE_CONTRACTID));
|
||||
if (prefetchService) {
|
||||
nsCOMPtr<nsIURI> uri(GetURI());
|
||||
if (uri) {
|
||||
nsCOMPtr<nsIDOMNode> domNode = GetAsDOMNode(mElement);
|
||||
prefetchService->PrefetchURI(uri,
|
||||
mElement->OwnerDoc()->GetDocumentURI(),
|
||||
domNode, true);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (linkTypes & nsStyleLinkElement::ePRECONNECT) {
|
||||
nsCOMPtr<nsIURI> uri(GetURI());
|
||||
if (uri && mElement->OwnerDoc()) {
|
||||
mElement->OwnerDoc()->MaybePreconnect(uri,
|
||||
mElement->AttrValueToCORSMode(mElement->GetParsedAttr(nsGkAtoms::crossorigin)));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (linkTypes & nsStyleLinkElement::eDNS_PREFETCH) {
|
||||
if (nsHTMLDNSPrefetch::IsAllowed(mElement->OwnerDoc())) {
|
||||
nsHTMLDNSPrefetch::PrefetchLow(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
Link::CancelPrefetch()
|
||||
{
|
||||
nsCOMPtr<nsIPrefetchService> prefetchService(do_GetService(NS_PREFETCHSERVICE_CONTRACTID));
|
||||
if (prefetchService) {
|
||||
nsCOMPtr<nsIURI> uri(GetURI());
|
||||
if (uri) {
|
||||
nsCOMPtr<nsIDOMNode> domNode = GetAsDOMNode(mElement);
|
||||
prefetchService->CancelPrefetchURI(uri, domNode);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
Link::SetLinkState(nsLinkState aState)
|
||||
{
|
||||
|
@ -111,11 +111,15 @@ public:
|
||||
|
||||
bool ElementHasHref() const;
|
||||
|
||||
// This is called by HTMLAnchorElement.
|
||||
void TryDNSPrefetch();
|
||||
|
||||
void CancelDNSPrefetch(nsWrapperCache::FlagsType aDeferredFlag,
|
||||
nsWrapperCache::FlagsType aRequestedFlag);
|
||||
|
||||
// This is called by HTMLLinkElement.
|
||||
void TryDNSPrefetchPreconnectOrPrefetch();
|
||||
void CancelPrefetch();
|
||||
|
||||
protected:
|
||||
virtual ~Link();
|
||||
|
||||
|
@ -2503,14 +2503,14 @@ public:
|
||||
bool WorkerRun(JSContext* aCx, WorkerPrivate* aWorkerPrivate) override
|
||||
{
|
||||
aWorkerPrivate->AssertIsOnWorkerThread();
|
||||
aWorkerPrivate->ModifyBusyCountFromWorker(aCx, true);
|
||||
aWorkerPrivate->ModifyBusyCountFromWorker(true);
|
||||
return !NS_FAILED(mImpl->CancelInternal());
|
||||
}
|
||||
|
||||
void PostRun(JSContext* aCx, WorkerPrivate* aWorkerPrivate,
|
||||
bool aRunResult) override
|
||||
{
|
||||
aWorkerPrivate->ModifyBusyCountFromWorker(aCx, false);
|
||||
aWorkerPrivate->ModifyBusyCountFromWorker(false);
|
||||
}
|
||||
|
||||
bool
|
||||
@ -2523,8 +2523,7 @@ public:
|
||||
}
|
||||
|
||||
void
|
||||
PostDispatch(JSContext* aCx, WorkerPrivate* aWorkerPrivate,
|
||||
bool aDispatchResult) override
|
||||
PostDispatch(WorkerPrivate* aWorkerPrivate, bool aDispatchResult) override
|
||||
{
|
||||
// We don't call WorkerRunnable::PostDispatch because it would assert the
|
||||
// wrong thing about which thread we're on.
|
||||
@ -2547,7 +2546,7 @@ WebSocketImpl::Cancel(nsresult aStatus)
|
||||
MOZ_ASSERT(mWorkerPrivate);
|
||||
RefPtr<CancelRunnable> runnable =
|
||||
new CancelRunnable(mWorkerPrivate, this);
|
||||
if (!runnable->Dispatch(nullptr)) {
|
||||
if (!runnable->Dispatch()) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
@ -2676,7 +2675,7 @@ public:
|
||||
bool WorkerRun(JSContext* aCx, WorkerPrivate* aWorkerPrivate) override
|
||||
{
|
||||
aWorkerPrivate->AssertIsOnWorkerThread();
|
||||
aWorkerPrivate->ModifyBusyCountFromWorker(aCx, true);
|
||||
aWorkerPrivate->ModifyBusyCountFromWorker(true);
|
||||
|
||||
// No messages when disconnected.
|
||||
if (mWebSocketImpl->mDisconnectingOrDisconnected) {
|
||||
@ -2690,7 +2689,7 @@ public:
|
||||
void PostRun(JSContext* aCx, WorkerPrivate* aWorkerPrivate,
|
||||
bool aRunResult) override
|
||||
{
|
||||
aWorkerPrivate->ModifyBusyCountFromWorker(aCx, false);
|
||||
aWorkerPrivate->ModifyBusyCountFromWorker(false);
|
||||
}
|
||||
|
||||
bool
|
||||
@ -2704,8 +2703,7 @@ public:
|
||||
}
|
||||
|
||||
void
|
||||
PostDispatch(JSContext* aCx, WorkerPrivate* aWorkerPrivate,
|
||||
bool aDispatchResult) override
|
||||
PostDispatch(WorkerPrivate* aWorkerPrivate, bool aDispatchResult) override
|
||||
{
|
||||
// We don't call WorkerRunnable::PreDispatch because it would assert the
|
||||
// wrong thing about which thread we're on. We're on whichever thread the
|
||||
@ -2751,7 +2749,7 @@ WebSocketImpl::Dispatch(already_AddRefed<nsIRunnable>&& aEvent, uint32_t aFlags)
|
||||
RefPtr<WorkerRunnableDispatcher> event =
|
||||
new WorkerRunnableDispatcher(this, mWorkerPrivate, event_ref.forget());
|
||||
|
||||
if (!event->Dispatch(nullptr)) {
|
||||
if (!event->Dispatch()) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
|
@ -93,7 +93,6 @@ EXPORTS += [
|
||||
'nsIDocumentInlines.h',
|
||||
'nsIDocumentObserver.h',
|
||||
'nsIDOMClassInfo.h',
|
||||
'nsIDOMScriptObjectFactory.h',
|
||||
'nsIGlobalObject.h',
|
||||
'nsImageLoadingContent.h',
|
||||
'nsIMutationObserver.h',
|
||||
@ -157,6 +156,7 @@ EXPORTS.mozilla.dom += [
|
||||
'Attr.h',
|
||||
'BarProps.h',
|
||||
'BlobSet.h',
|
||||
'BodyUtil.h',
|
||||
'ChildIterator.h',
|
||||
'ChromeNodeList.h',
|
||||
'ChromeUtils.h',
|
||||
@ -224,6 +224,7 @@ UNIFIED_SOURCES += [
|
||||
'AnonymousContent.cpp',
|
||||
'Attr.cpp',
|
||||
'BarProps.cpp',
|
||||
'BodyUtil.cpp',
|
||||
'ChildIterator.cpp',
|
||||
'ChromeNodeList.cpp',
|
||||
'ChromeUtils.cpp',
|
||||
@ -279,7 +280,6 @@ UNIFIED_SOURCES += [
|
||||
'nsDOMClassInfo.cpp',
|
||||
'nsDOMMutationObserver.cpp',
|
||||
'nsDOMNavigationTiming.cpp',
|
||||
'nsDOMScriptObjectFactory.cpp',
|
||||
'nsDOMSerializer.cpp',
|
||||
'nsDOMTokenList.cpp',
|
||||
'nsDOMWindowList.cpp',
|
||||
|
@ -692,7 +692,11 @@ nsContentSink::ProcessLink(const nsSubstring& aAnchor, const nsSubstring& aHref,
|
||||
if (!LinkContextIsOurDocument(aAnchor)) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
if (!nsContentUtils::PrefetchEnabled(mDocShell)) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
bool hasPrefetch = linkTypes & nsStyleLinkElement::ePREFETCH;
|
||||
// prefetch href if relation is "next" or "prefetch"
|
||||
if (hasPrefetch || (linkTypes & nsStyleLinkElement::eNEXT)) {
|
||||
@ -827,35 +831,6 @@ nsContentSink::PrefetchHref(const nsAString &aHref,
|
||||
nsINode *aSource,
|
||||
bool aExplicit)
|
||||
{
|
||||
//
|
||||
// SECURITY CHECK: disable prefetching from mailnews!
|
||||
//
|
||||
// walk up the docshell tree to see if any containing
|
||||
// docshell are of type MAIL.
|
||||
//
|
||||
if (!mDocShell)
|
||||
return;
|
||||
|
||||
nsCOMPtr<nsIDocShell> docshell = mDocShell;
|
||||
|
||||
nsCOMPtr<nsIDocShellTreeItem> parentItem;
|
||||
do {
|
||||
uint32_t appType = 0;
|
||||
nsresult rv = docshell->GetAppType(&appType);
|
||||
if (NS_FAILED(rv) || appType == nsIDocShell::APP_TYPE_MAIL)
|
||||
return; // do not prefetch from mailnews
|
||||
docshell->GetParent(getter_AddRefs(parentItem));
|
||||
if (parentItem) {
|
||||
docshell = do_QueryInterface(parentItem);
|
||||
if (!docshell) {
|
||||
NS_ERROR("cannot get a docshell from a treeItem!");
|
||||
return;
|
||||
}
|
||||
}
|
||||
} while (parentItem);
|
||||
|
||||
// OK, we passed the security check...
|
||||
|
||||
nsCOMPtr<nsIPrefetchService> prefetchService(do_GetService(NS_PREFETCHSERVICE_CONTRACTID));
|
||||
if (prefetchService) {
|
||||
// construct URI using document charset
|
||||
|
@ -119,7 +119,6 @@
|
||||
#include "nsIDOMHTMLInputElement.h"
|
||||
#include "nsIDOMNode.h"
|
||||
#include "nsIDOMNodeList.h"
|
||||
#include "nsIDOMScriptObjectFactory.h"
|
||||
#include "nsIDOMWindowUtils.h"
|
||||
#include "nsIDOMXULCommandEvent.h"
|
||||
#include "nsIDragService.h"
|
||||
@ -7233,6 +7232,43 @@ nsContentUtils::GenerateUUIDInPlace(nsID& aUUID)
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
bool
|
||||
nsContentUtils::PrefetchEnabled(nsIDocShell* aDocShell)
|
||||
{
|
||||
//
|
||||
// SECURITY CHECK: disable prefetching from mailnews!
|
||||
//
|
||||
// walk up the docshell tree to see if any containing
|
||||
// docshell are of type MAIL.
|
||||
//
|
||||
|
||||
if (!aDocShell) {
|
||||
return false;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIDocShell> docshell = aDocShell;
|
||||
nsCOMPtr<nsIDocShellTreeItem> parentItem;
|
||||
|
||||
do {
|
||||
uint32_t appType = 0;
|
||||
nsresult rv = docshell->GetAppType(&appType);
|
||||
if (NS_FAILED(rv) || appType == nsIDocShell::APP_TYPE_MAIL) {
|
||||
return false; // do not prefetch, preconnect from mailnews
|
||||
}
|
||||
|
||||
docshell->GetParent(getter_AddRefs(parentItem));
|
||||
if (parentItem) {
|
||||
docshell = do_QueryInterface(parentItem);
|
||||
if (!docshell) {
|
||||
NS_ERROR("cannot get a docshell from a treeItem!");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
} while (parentItem);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
uint64_t
|
||||
nsContentUtils::GetInnerWindowID(nsIRequest* aRequest)
|
||||
{
|
||||
|
@ -917,6 +917,7 @@ public:
|
||||
*/
|
||||
static nsresult GenerateUUIDInPlace(nsID& aUUID);
|
||||
|
||||
static bool PrefetchEnabled(nsIDocShell* aDocShell);
|
||||
|
||||
/**
|
||||
* Fill (with the parameters given) the localized string named |aKey| in
|
||||
|
@ -26,6 +26,7 @@
|
||||
|
||||
#include "nscore.h"
|
||||
#include "nsDOMClassInfo.h"
|
||||
#include "nsIDOMClassInfo.h"
|
||||
#include "nsCRT.h"
|
||||
#include "nsCRTGlue.h"
|
||||
#include "nsICategoryManager.h"
|
||||
@ -117,8 +118,6 @@
|
||||
using namespace mozilla;
|
||||
using namespace mozilla::dom;
|
||||
|
||||
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.
|
||||
|
||||
@ -140,7 +139,7 @@ static NS_DEFINE_CID(kDOMSOF_CID, NS_DOM_SCRIPT_OBJECT_FACTORY_CID);
|
||||
_chromeOnly, _allowXBL) \
|
||||
{ #_class, \
|
||||
nullptr, \
|
||||
{ _helper::doCreate }, \
|
||||
_helper::doCreate, \
|
||||
nullptr, \
|
||||
nullptr, \
|
||||
nullptr, \
|
||||
@ -352,15 +351,6 @@ nsDOMClassInfo::nsDOMClassInfo(nsDOMClassInfoData* aData) : mData(aData)
|
||||
{
|
||||
}
|
||||
|
||||
nsDOMClassInfo::~nsDOMClassInfo()
|
||||
{
|
||||
if (IS_EXTERNAL(mData->mCachedClassInfo)) {
|
||||
// Some compilers don't like delete'ing a const nsDOMClassInfo*
|
||||
nsDOMClassInfoData* data = const_cast<nsDOMClassInfoData*>(mData);
|
||||
delete static_cast<nsExternalDOMClassInfoData*>(data);
|
||||
}
|
||||
}
|
||||
|
||||
NS_IMPL_ADDREF(nsDOMClassInfo)
|
||||
NS_IMPL_RELEASE(nsDOMClassInfo)
|
||||
|
||||
@ -448,58 +438,6 @@ nsDOMClassInfo::RegisterClassProtos(int32_t aClassInfoID)
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// static
|
||||
nsresult
|
||||
nsDOMClassInfo::RegisterExternalClasses()
|
||||
{
|
||||
nsScriptNameSpaceManager *nameSpaceManager = GetNameSpaceManager();
|
||||
NS_ENSURE_TRUE(nameSpaceManager, NS_ERROR_NOT_INITIALIZED);
|
||||
|
||||
nsCOMPtr<nsIComponentRegistrar> registrar;
|
||||
nsresult rv = NS_GetComponentRegistrar(getter_AddRefs(registrar));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsCOMPtr<nsICategoryManager> cm =
|
||||
do_GetService(NS_CATEGORYMANAGER_CONTRACTID, &rv);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsCOMPtr<nsISimpleEnumerator> e;
|
||||
rv = cm->EnumerateCategory(JAVASCRIPT_DOM_CLASS, getter_AddRefs(e));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsXPIDLCString contractId;
|
||||
nsAutoCString categoryEntry;
|
||||
nsCOMPtr<nsISupports> entry;
|
||||
|
||||
while (NS_SUCCEEDED(e->GetNext(getter_AddRefs(entry)))) {
|
||||
nsCOMPtr<nsISupportsCString> category(do_QueryInterface(entry));
|
||||
|
||||
if (!category) {
|
||||
NS_WARNING("Category entry not an nsISupportsCString!");
|
||||
continue;
|
||||
}
|
||||
|
||||
rv = category->GetData(categoryEntry);
|
||||
|
||||
cm->GetCategoryEntry(JAVASCRIPT_DOM_CLASS, categoryEntry.get(),
|
||||
getter_Copies(contractId));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsCID *cid;
|
||||
rv = registrar->ContractIDToCID(contractId, &cid);
|
||||
if (NS_FAILED(rv)) {
|
||||
NS_WARNING("Bad contract id registered with the script namespace manager");
|
||||
continue;
|
||||
}
|
||||
|
||||
rv = nameSpaceManager->RegisterExternalClassName(categoryEntry.get(), *cid);
|
||||
free(cid);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
|
||||
return nameSpaceManager->RegisterExternalInterfaces(true);
|
||||
}
|
||||
|
||||
#define _DOM_CLASSINFO_MAP_BEGIN(_class, _ifptr, _has_class_if) \
|
||||
{ \
|
||||
nsDOMClassInfoData &d = sClassInfoData[eDOMClassInfo_##_class##_id]; \
|
||||
@ -710,7 +648,7 @@ nsDOMClassInfo::Init()
|
||||
|
||||
#ifdef DEBUG
|
||||
for (size_t i = 0; i < eDOMClassInfoIDCount; i++) {
|
||||
if (!sClassInfoData[i].u.mConstructorFptr ||
|
||||
if (!sClassInfoData[i].mConstructorFptr ||
|
||||
sClassInfoData[i].mDebugID != i) {
|
||||
MOZ_CRASH("Class info data out of sync, you forgot to update "
|
||||
"nsDOMClassInfo.h and nsDOMClassInfo.cpp! Fix this, "
|
||||
@ -745,8 +683,6 @@ nsDOMClassInfo::Init()
|
||||
RegisterClassProtos(i);
|
||||
}
|
||||
|
||||
RegisterExternalClasses();
|
||||
|
||||
sIsInitialized = true;
|
||||
|
||||
return NS_OK;
|
||||
@ -978,41 +914,6 @@ nsDOMClassInfo::HasInstance(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
|
||||
static nsresult
|
||||
GetExternalClassInfo(nsScriptNameSpaceManager *aNameSpaceManager,
|
||||
const nsAString &aName,
|
||||
const nsGlobalNameStruct *aStruct,
|
||||
const nsGlobalNameStruct **aResult)
|
||||
{
|
||||
NS_ASSERTION(aStruct->mType ==
|
||||
nsGlobalNameStruct::eTypeExternalClassInfoCreator,
|
||||
"Wrong type!");
|
||||
|
||||
nsresult rv;
|
||||
nsCOMPtr<nsIDOMCIExtension> creator(do_CreateInstance(aStruct->mCID, &rv));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsCOMPtr<nsIDOMScriptObjectFactory> sof(do_GetService(kDOMSOF_CID));
|
||||
NS_ENSURE_TRUE(sof, NS_ERROR_FAILURE);
|
||||
|
||||
rv = creator->RegisterDOMCI(NS_ConvertUTF16toUTF8(aName).get(), sof);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
const nsGlobalNameStruct *name_struct = aNameSpaceManager->LookupName(aName);
|
||||
if (name_struct &&
|
||||
name_struct->mType == nsGlobalNameStruct::eTypeExternalClassInfo) {
|
||||
*aResult = name_struct;
|
||||
}
|
||||
else {
|
||||
NS_ERROR("Couldn't get the DOM ClassInfo data.");
|
||||
|
||||
*aResult = nullptr;
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
static nsresult
|
||||
ResolvePrototype(nsIXPConnect *aXPConnect, nsGlobalWindow *aWin, JSContext *cx,
|
||||
JS::Handle<JSObject*> obj, const char16_t *name,
|
||||
@ -1134,48 +1035,20 @@ NS_GetDOMClassInfoInstance(nsDOMClassInfoID aID)
|
||||
if (!sClassInfoData[aID].mCachedClassInfo) {
|
||||
nsDOMClassInfoData& data = sClassInfoData[aID];
|
||||
|
||||
data.mCachedClassInfo = data.u.mConstructorFptr(&data);
|
||||
data.mCachedClassInfo = data.mConstructorFptr(&data);
|
||||
NS_ENSURE_TRUE(data.mCachedClassInfo, nullptr);
|
||||
|
||||
NS_ADDREF(data.mCachedClassInfo);
|
||||
}
|
||||
|
||||
NS_ASSERTION(!IS_EXTERNAL(sClassInfoData[aID].mCachedClassInfo),
|
||||
"This is bad, internal class marked as external!");
|
||||
|
||||
return sClassInfoData[aID].mCachedClassInfo;
|
||||
}
|
||||
|
||||
// static
|
||||
nsIClassInfo *
|
||||
nsDOMClassInfo::GetClassInfoInstance(nsDOMClassInfoData* aData)
|
||||
{
|
||||
NS_ASSERTION(IS_EXTERNAL(aData->mCachedClassInfo)
|
||||
|| !aData->mCachedClassInfo,
|
||||
"This is bad, external class marked as internal!");
|
||||
|
||||
if (!aData->mCachedClassInfo) {
|
||||
if (aData->u.mExternalConstructorFptr) {
|
||||
aData->mCachedClassInfo =
|
||||
aData->u.mExternalConstructorFptr(aData->mName);
|
||||
} else {
|
||||
aData->mCachedClassInfo = nsDOMGenericSH::doCreate(aData);
|
||||
}
|
||||
NS_ENSURE_TRUE(aData->mCachedClassInfo, nullptr);
|
||||
|
||||
NS_ADDREF(aData->mCachedClassInfo);
|
||||
aData->mCachedClassInfo = MARK_EXTERNAL(aData->mCachedClassInfo);
|
||||
}
|
||||
|
||||
return GET_CLEAN_CI_PTR(aData->mCachedClassInfo);
|
||||
}
|
||||
|
||||
|
||||
// static
|
||||
void
|
||||
nsDOMClassInfo::ShutDown()
|
||||
{
|
||||
if (sClassInfoData[0].u.mConstructorFptr) {
|
||||
if (sClassInfoData[0].mConstructorFptr) {
|
||||
uint32_t i;
|
||||
|
||||
for (i = 0; i < eDOMClassInfoIDCount; i++) {
|
||||
@ -1202,12 +1075,10 @@ BaseStubConstructor(nsIWeakReference* aWeakOwner,
|
||||
nsCOMPtr<nsISupports> native;
|
||||
if (name_struct->mType == nsGlobalNameStruct::eTypeClassConstructor) {
|
||||
rv = NS_ERROR_NOT_AVAILABLE;
|
||||
} else if (name_struct->mType == nsGlobalNameStruct::eTypeExternalConstructor) {
|
||||
native = do_CreateInstance(name_struct->mCID, &rv);
|
||||
} else if (name_struct->mType == nsGlobalNameStruct::eTypeExternalConstructorAlias) {
|
||||
native = do_CreateInstance(name_struct->mAlias->mCID, &rv);
|
||||
} else {
|
||||
native = do_CreateInstance(*name_struct->mData->mConstructorCID, &rv);
|
||||
MOZ_ASSERT(name_struct->mType ==
|
||||
nsGlobalNameStruct::eTypeExternalConstructor);
|
||||
native = do_CreateInstance(name_struct->mCID, &rv);
|
||||
}
|
||||
if (NS_FAILED(rv)) {
|
||||
NS_ERROR("Failed to create the object");
|
||||
@ -1279,7 +1150,6 @@ protected:
|
||||
public:
|
||||
|
||||
static nsresult Create(const char16_t* aName,
|
||||
const nsDOMClassInfoData* aData,
|
||||
const nsGlobalNameStruct* aNameStruct,
|
||||
nsPIDOMWindowInner* aOwner,
|
||||
nsDOMConstructor** aResult);
|
||||
@ -1335,25 +1205,9 @@ private:
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
static bool IsConstructable(const nsDOMClassInfoData *aData)
|
||||
{
|
||||
if (IS_EXTERNAL(aData->mCachedClassInfo)) {
|
||||
const nsExternalDOMClassInfoData* data =
|
||||
static_cast<const nsExternalDOMClassInfoData*>(aData);
|
||||
return data->mConstructorCID != nullptr;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
static bool IsConstructable(const nsGlobalNameStruct *aNameStruct)
|
||||
{
|
||||
return
|
||||
(aNameStruct->mType == nsGlobalNameStruct::eTypeClassConstructor &&
|
||||
IsConstructable(&sClassInfoData[aNameStruct->mDOMClassInfoID])) ||
|
||||
(aNameStruct->mType == nsGlobalNameStruct::eTypeExternalClassInfo &&
|
||||
IsConstructable(aNameStruct->mData)) ||
|
||||
aNameStruct->mType == nsGlobalNameStruct::eTypeExternalConstructor ||
|
||||
aNameStruct->mType == nsGlobalNameStruct::eTypeExternalConstructorAlias;
|
||||
return aNameStruct->mType == nsGlobalNameStruct::eTypeExternalConstructor;
|
||||
}
|
||||
|
||||
const char16_t* mClassName;
|
||||
@ -1364,7 +1218,6 @@ private:
|
||||
//static
|
||||
nsresult
|
||||
nsDOMConstructor::Create(const char16_t* aName,
|
||||
const nsDOMClassInfoData* aData,
|
||||
const nsGlobalNameStruct* aNameStruct,
|
||||
nsPIDOMWindowInner* aOwner,
|
||||
nsDOMConstructor** aResult)
|
||||
@ -1385,9 +1238,7 @@ nsDOMConstructor::Create(const char16_t* aName,
|
||||
return NS_ERROR_DOM_SECURITY_ERR;
|
||||
}
|
||||
|
||||
bool constructable = aNameStruct ?
|
||||
IsConstructable(aNameStruct) :
|
||||
IsConstructable(aData);
|
||||
bool constructable = aNameStruct && IsConstructable(aNameStruct);
|
||||
|
||||
*aResult = new nsDOMConstructor(aName, constructable, currentInner);
|
||||
NS_ADDREF(*aResult);
|
||||
@ -1513,9 +1364,7 @@ nsDOMConstructor::HasInstance(nsIXPConnectWrappedNative *wrapper,
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
if (name_struct->mType != nsGlobalNameStruct::eTypeClassConstructor &&
|
||||
name_struct->mType != nsGlobalNameStruct::eTypeExternalClassInfo &&
|
||||
name_struct->mType != nsGlobalNameStruct::eTypeExternalConstructorAlias) {
|
||||
if (name_struct->mType != nsGlobalNameStruct::eTypeClassConstructor) {
|
||||
// Doesn't have DOM interfaces.
|
||||
return NS_OK;
|
||||
}
|
||||
@ -1529,59 +1378,27 @@ nsDOMConstructor::HasInstance(nsIXPConnectWrappedNative *wrapper,
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsScriptNameSpaceManager *nameSpaceManager = GetNameSpaceManager();
|
||||
NS_ASSERTION(nameSpaceManager, "Can't get namespace manager?");
|
||||
|
||||
const nsIID *class_iid;
|
||||
if (class_name_struct->mType == nsGlobalNameStruct::eTypeInterface ||
|
||||
class_name_struct->mType == nsGlobalNameStruct::eTypeClassProto) {
|
||||
if (class_name_struct->mType == nsGlobalNameStruct::eTypeClassProto) {
|
||||
class_iid = &class_name_struct->mIID;
|
||||
} else if (class_name_struct->mType == nsGlobalNameStruct::eTypeClassConstructor) {
|
||||
class_iid =
|
||||
sClassInfoData[class_name_struct->mDOMClassInfoID].mProtoChainInterface;
|
||||
} else if (class_name_struct->mType == nsGlobalNameStruct::eTypeExternalClassInfo) {
|
||||
class_iid = class_name_struct->mData->mProtoChainInterface;
|
||||
} else if (class_name_struct->mType == nsGlobalNameStruct::eTypeExternalConstructorAlias) {
|
||||
const nsGlobalNameStruct* alias_struct =
|
||||
nameSpaceManager->GetConstructorProto(class_name_struct);
|
||||
if (!alias_struct) {
|
||||
NS_ERROR("Couldn't get constructor prototype.");
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
|
||||
if (alias_struct->mType == nsGlobalNameStruct::eTypeClassConstructor) {
|
||||
class_iid =
|
||||
sClassInfoData[alias_struct->mDOMClassInfoID].mProtoChainInterface;
|
||||
} else if (alias_struct->mType == nsGlobalNameStruct::eTypeExternalClassInfo) {
|
||||
class_iid = alias_struct->mData->mProtoChainInterface;
|
||||
} else {
|
||||
NS_ERROR("Expected eTypeClassConstructor or eTypeExternalClassInfo.");
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
} else {
|
||||
*bp = false;
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
if (name_struct->mType == nsGlobalNameStruct::eTypeExternalConstructorAlias) {
|
||||
name_struct = nameSpaceManager->GetConstructorProto(name_struct);
|
||||
if (!name_struct) {
|
||||
NS_ERROR("Couldn't get constructor prototype.");
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
}
|
||||
|
||||
NS_ASSERTION(name_struct->mType == nsGlobalNameStruct::eTypeClassConstructor ||
|
||||
name_struct->mType == nsGlobalNameStruct::eTypeExternalClassInfo,
|
||||
NS_ASSERTION(name_struct->mType == nsGlobalNameStruct::eTypeClassConstructor,
|
||||
"The constructor was set up with a struct of the wrong type.");
|
||||
|
||||
const nsDOMClassInfoData *ci_data = nullptr;
|
||||
const nsDOMClassInfoData *ci_data;
|
||||
if (name_struct->mType == nsGlobalNameStruct::eTypeClassConstructor &&
|
||||
name_struct->mDOMClassInfoID >= 0) {
|
||||
ci_data = &sClassInfoData[name_struct->mDOMClassInfoID];
|
||||
} else if (name_struct->mType == nsGlobalNameStruct::eTypeExternalClassInfo) {
|
||||
ci_data = name_struct->mData;
|
||||
} else {
|
||||
ci_data = nullptr;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIInterfaceInfoManager>
|
||||
@ -1625,14 +1442,11 @@ nsDOMConstructor::ResolveInterfaceConstants(JSContext *cx, JS::Handle<JSObject*>
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
|
||||
const nsIID *class_iid;
|
||||
if (class_name_struct->mType == nsGlobalNameStruct::eTypeInterface ||
|
||||
class_name_struct->mType == nsGlobalNameStruct::eTypeClassProto) {
|
||||
if (class_name_struct->mType == nsGlobalNameStruct::eTypeClassProto) {
|
||||
class_iid = &class_name_struct->mIID;
|
||||
} else if (class_name_struct->mType == nsGlobalNameStruct::eTypeClassConstructor) {
|
||||
class_iid =
|
||||
sClassInfoData[class_name_struct->mDOMClassInfoID].mProtoChainInterface;
|
||||
} else if (class_name_struct->mType == nsGlobalNameStruct::eTypeExternalClassInfo) {
|
||||
class_iid = class_name_struct->mData->mProtoChainInterface;
|
||||
} else {
|
||||
return NS_OK;
|
||||
}
|
||||
@ -1659,23 +1473,15 @@ GetXPCProto(nsIXPConnect *aXPConnect, JSContext *cx, nsGlobalWindow *aWin,
|
||||
const nsGlobalNameStruct *aNameStruct,
|
||||
JS::MutableHandle<JSObject*> aProto)
|
||||
{
|
||||
NS_ASSERTION(aNameStruct->mType ==
|
||||
nsGlobalNameStruct::eTypeClassConstructor ||
|
||||
aNameStruct->mType == nsGlobalNameStruct::eTypeExternalClassInfo,
|
||||
NS_ASSERTION(aNameStruct->mType == nsGlobalNameStruct::eTypeClassConstructor,
|
||||
"Wrong type!");
|
||||
|
||||
nsCOMPtr<nsIClassInfo> ci;
|
||||
if (aNameStruct->mType == nsGlobalNameStruct::eTypeClassConstructor) {
|
||||
int32_t id = aNameStruct->mDOMClassInfoID;
|
||||
MOZ_ASSERT(id >= 0, "Negative DOM classinfo?!?");
|
||||
int32_t id = aNameStruct->mDOMClassInfoID;
|
||||
MOZ_ASSERT(id >= 0, "Negative DOM classinfo?!?");
|
||||
|
||||
nsDOMClassInfoID ci_id = (nsDOMClassInfoID)id;
|
||||
nsDOMClassInfoID ci_id = (nsDOMClassInfoID)id;
|
||||
|
||||
ci = NS_GetDOMClassInfoInstance(ci_id);
|
||||
}
|
||||
else {
|
||||
ci = nsDOMClassInfo::GetClassInfoInstance(aNameStruct->mData);
|
||||
}
|
||||
nsCOMPtr<nsIClassInfo> ci = NS_GetDOMClassInfoInstance(ci_id);
|
||||
NS_ENSURE_TRUE(ci, NS_ERROR_UNEXPECTED);
|
||||
|
||||
nsresult rv =
|
||||
@ -1703,8 +1509,7 @@ ResolvePrototype(nsIXPConnect *aXPConnect, nsGlobalWindow *aWin, JSContext *cx,
|
||||
"Wrong type or missing ci_data!");
|
||||
|
||||
RefPtr<nsDOMConstructor> constructor;
|
||||
nsresult rv = nsDOMConstructor::Create(name, ci_data, name_struct,
|
||||
aWin->AsInner(),
|
||||
nsresult rv = nsDOMConstructor::Create(name, name_struct, aWin->AsInner(),
|
||||
getter_AddRefs(constructor));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
@ -1857,8 +1662,7 @@ OldBindingConstructorEnabled(const nsGlobalNameStruct *aStruct,
|
||||
nsGlobalWindow *aWin, JSContext *cx)
|
||||
{
|
||||
MOZ_ASSERT(aStruct->mType == nsGlobalNameStruct::eTypeProperty ||
|
||||
aStruct->mType == nsGlobalNameStruct::eTypeClassConstructor ||
|
||||
aStruct->mType == nsGlobalNameStruct::eTypeExternalClassInfo);
|
||||
aStruct->mType == nsGlobalNameStruct::eTypeClassConstructor);
|
||||
|
||||
// Don't expose chrome only constructors to content windows.
|
||||
if (aStruct->mChromeOnly) {
|
||||
@ -1889,17 +1693,8 @@ nsWindowSH::NameStructEnabled(JSContext* aCx, nsGlobalWindow *aWin,
|
||||
const nsGlobalNameStruct& aNameStruct)
|
||||
{
|
||||
const nsGlobalNameStruct* nameStruct = &aNameStruct;
|
||||
if (nameStruct->mType == nsGlobalNameStruct::eTypeExternalClassInfoCreator) {
|
||||
nsresult rv = GetExternalClassInfo(GetNameSpaceManager(), aName, nameStruct,
|
||||
&nameStruct);
|
||||
if (NS_FAILED(rv) || !nameStruct) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return (nameStruct->mType != nsGlobalNameStruct::eTypeProperty &&
|
||||
nameStruct->mType != nsGlobalNameStruct::eTypeClassConstructor &&
|
||||
nameStruct->mType != nsGlobalNameStruct::eTypeExternalClassInfo) ||
|
||||
nameStruct->mType != nsGlobalNameStruct::eTypeClassConstructor) ||
|
||||
OldBindingConstructorEnabled(nameStruct, aWin, aCx);
|
||||
}
|
||||
|
||||
@ -1969,16 +1764,7 @@ nsWindowSH::GlobalResolve(nsGlobalWindow *aWin, JSContext *cx,
|
||||
|
||||
nsresult rv = NS_OK;
|
||||
|
||||
if (name_struct->mType == nsGlobalNameStruct::eTypeExternalClassInfoCreator) {
|
||||
rv = GetExternalClassInfo(nameSpaceManager, name, name_struct,
|
||||
&name_struct);
|
||||
if (NS_FAILED(rv) || !name_struct) {
|
||||
return rv;
|
||||
}
|
||||
}
|
||||
|
||||
if (name_struct->mType == nsGlobalNameStruct::eTypeNewDOMBinding ||
|
||||
name_struct->mType == nsGlobalNameStruct::eTypeInterface ||
|
||||
name_struct->mType == nsGlobalNameStruct::eTypeClassProto ||
|
||||
name_struct->mType == nsGlobalNameStruct::eTypeClassConstructor) {
|
||||
// Lookup new DOM bindings.
|
||||
@ -2070,45 +1856,7 @@ nsWindowSH::GlobalResolve(nsGlobalWindow *aWin, JSContext *cx,
|
||||
}
|
||||
}
|
||||
|
||||
if (name_struct->mType == nsGlobalNameStruct::eTypeInterface) {
|
||||
// We're resolving a name of a DOM interface for which there is no
|
||||
// direct DOM class, create a constructor object...
|
||||
RefPtr<nsDOMConstructor> constructor;
|
||||
rv = nsDOMConstructor::Create(class_name,
|
||||
nullptr,
|
||||
name_struct,
|
||||
aWin->AsInner(),
|
||||
getter_AddRefs(constructor));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
JS::Rooted<JS::Value> v(cx);
|
||||
js::AssertSameCompartment(cx, obj);
|
||||
rv = nsContentUtils::WrapNative(cx, constructor,
|
||||
&NS_GET_IID(nsIDOMDOMConstructor), &v,
|
||||
false);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
JS::Rooted<JSObject*> class_obj(cx, &v.toObject());
|
||||
|
||||
// ... and define the constants from the DOM interface on that
|
||||
// constructor object.
|
||||
|
||||
{
|
||||
JSAutoCompartment ac(cx, class_obj);
|
||||
rv = DefineInterfaceConstants(cx, class_obj, &name_struct->mIID);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
|
||||
if (!JS_WrapValue(cx, &v)) {
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
|
||||
FillPropertyDescriptor(desc, obj, 0, v);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
if (name_struct->mType == nsGlobalNameStruct::eTypeClassConstructor ||
|
||||
name_struct->mType == nsGlobalNameStruct::eTypeExternalClassInfo) {
|
||||
if (name_struct->mType == nsGlobalNameStruct::eTypeClassConstructor) {
|
||||
if (!OldBindingConstructorEnabled(name_struct, aWin, cx)) {
|
||||
return NS_OK;
|
||||
}
|
||||
@ -2132,15 +1880,9 @@ nsWindowSH::GlobalResolve(nsGlobalWindow *aWin, JSContext *cx,
|
||||
|
||||
// This is the Xray case. Look up the constructor object for this
|
||||
// prototype.
|
||||
const nsDOMClassInfoData *ci_data;
|
||||
if (name_struct->mType == nsGlobalNameStruct::eTypeClassConstructor) {
|
||||
ci_data = &sClassInfoData[name_struct->mDOMClassInfoID];
|
||||
} else {
|
||||
ci_data = name_struct->mData;
|
||||
}
|
||||
|
||||
return ResolvePrototype(nsDOMClassInfo::sXPConnect, aWin, cx, obj,
|
||||
class_name, ci_data,
|
||||
class_name,
|
||||
&sClassInfoData[name_struct->mDOMClassInfoID],
|
||||
name_struct, nameSpaceManager, dot_prototype,
|
||||
desc);
|
||||
}
|
||||
@ -2153,38 +1895,10 @@ nsWindowSH::GlobalResolve(nsGlobalWindow *aWin, JSContext *cx,
|
||||
name_struct, nameSpaceManager, nullptr, desc);
|
||||
}
|
||||
|
||||
if (name_struct->mType == nsGlobalNameStruct::eTypeExternalConstructorAlias) {
|
||||
const nsGlobalNameStruct *alias_struct =
|
||||
nameSpaceManager->GetConstructorProto(name_struct);
|
||||
NS_ENSURE_TRUE(alias_struct, NS_ERROR_UNEXPECTED);
|
||||
|
||||
// We need to use the XPConnect prototype for the DOM class that this
|
||||
// constructor is an alias for (for example for Image we need the prototype
|
||||
// for HTMLImageElement).
|
||||
JS::Rooted<JSObject*> dot_prototype(cx);
|
||||
rv = GetXPCProto(nsDOMClassInfo::sXPConnect, cx, aWin, alias_struct,
|
||||
&dot_prototype);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
MOZ_ASSERT(dot_prototype);
|
||||
|
||||
const nsDOMClassInfoData *ci_data;
|
||||
if (alias_struct->mType == nsGlobalNameStruct::eTypeClassConstructor) {
|
||||
ci_data = &sClassInfoData[alias_struct->mDOMClassInfoID];
|
||||
} else if (alias_struct->mType == nsGlobalNameStruct::eTypeExternalClassInfo) {
|
||||
ci_data = alias_struct->mData;
|
||||
} else {
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
|
||||
return ResolvePrototype(nsDOMClassInfo::sXPConnect, aWin, cx, obj,
|
||||
class_name, ci_data,
|
||||
name_struct, nameSpaceManager, nullptr, desc);
|
||||
}
|
||||
|
||||
if (name_struct->mType == nsGlobalNameStruct::eTypeExternalConstructor) {
|
||||
RefPtr<nsDOMConstructor> constructor;
|
||||
rv = nsDOMConstructor::Create(class_name, nullptr, name_struct,
|
||||
aWin->AsInner(), getter_AddRefs(constructor));
|
||||
rv = nsDOMConstructor::Create(class_name, name_struct, aWin->AsInner(),
|
||||
getter_AddRefs(constructor));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
JS::Rooted<JS::Value> val(cx);
|
||||
|
@ -8,9 +8,9 @@
|
||||
#define nsDOMClassInfo_h___
|
||||
|
||||
#include "mozilla/Attributes.h"
|
||||
#include "nsDOMClassInfoID.h"
|
||||
#include "nsIXPCScriptable.h"
|
||||
#include "nsIScriptGlobalObject.h"
|
||||
#include "nsIDOMScriptObjectFactory.h"
|
||||
#include "js/Id.h"
|
||||
#include "nsIXPConnect.h"
|
||||
|
||||
@ -32,13 +32,9 @@ struct nsDOMClassInfoData
|
||||
{
|
||||
const char *mName;
|
||||
const char16_t *mNameUTF16;
|
||||
union {
|
||||
nsDOMClassInfoConstructorFnc mConstructorFptr;
|
||||
nsDOMClassInfoExternalConstructorFnc mExternalConstructorFptr;
|
||||
} u;
|
||||
nsDOMClassInfoConstructorFnc mConstructorFptr;
|
||||
|
||||
nsIClassInfo *mCachedClassInfo; // low bit is set to 1 if external,
|
||||
// so be sure to mask if necessary!
|
||||
nsIClassInfo *mCachedClassInfo;
|
||||
const nsIID *mProtoChainInterface;
|
||||
const nsIID **mInterfaces;
|
||||
uint32_t mScriptableFlags : 31; // flags must not use more than 31 bits!
|
||||
@ -51,19 +47,6 @@ struct nsDOMClassInfoData
|
||||
#endif
|
||||
};
|
||||
|
||||
struct nsExternalDOMClassInfoData : public nsDOMClassInfoData
|
||||
{
|
||||
const nsCID *mConstructorCID;
|
||||
};
|
||||
|
||||
|
||||
// To be used with the nsDOMClassInfoData::mCachedClassInfo pointer.
|
||||
// The low bit is set when we created a generic helper for an external
|
||||
// (which holds on to the nsDOMClassInfoData).
|
||||
#define GET_CLEAN_CI_PTR(_ptr) (nsIClassInfo*)(uintptr_t(_ptr) & ~0x1)
|
||||
#define MARK_EXTERNAL(_ptr) (nsIClassInfo*)(uintptr_t(_ptr) | 0x1)
|
||||
#define IS_EXTERNAL(_ptr) (uintptr_t(_ptr) & 0x1)
|
||||
|
||||
class nsWindowSH;
|
||||
|
||||
class nsDOMClassInfo : public nsXPCClassInfo
|
||||
@ -71,7 +54,7 @@ class nsDOMClassInfo : public nsXPCClassInfo
|
||||
friend class nsWindowSH;
|
||||
|
||||
protected:
|
||||
virtual ~nsDOMClassInfo();
|
||||
virtual ~nsDOMClassInfo() {};
|
||||
|
||||
public:
|
||||
explicit nsDOMClassInfo(nsDOMClassInfoData* aData);
|
||||
@ -82,17 +65,6 @@ public:
|
||||
|
||||
NS_DECL_NSICLASSINFO
|
||||
|
||||
// Helper method that returns a *non* refcounted pointer to a
|
||||
// helper. So please note, don't release this pointer, if you do,
|
||||
// you better make sure you've addreffed before release.
|
||||
//
|
||||
// Whaaaaa! I wanted to name this method GetClassInfo, but nooo,
|
||||
// some of Microsoft devstudio's headers #defines GetClassInfo to
|
||||
// GetClassInfoA so I can't, those $%#@^! bastards!!! What gives
|
||||
// them the right to do that?
|
||||
|
||||
static nsIClassInfo* GetClassInfoInstance(nsDOMClassInfoData* aData);
|
||||
|
||||
static nsresult Init();
|
||||
static void ShutDown();
|
||||
|
||||
@ -134,7 +106,6 @@ protected:
|
||||
}
|
||||
|
||||
static nsresult RegisterClassProtos(int32_t aDOMClassInfoID);
|
||||
static nsresult RegisterExternalClasses();
|
||||
|
||||
static nsIXPConnect *sXPConnect;
|
||||
|
||||
|
@ -60,10 +60,6 @@ NS_GetDOMClassInfoInstance(nsDOMClassInfoID aID);
|
||||
} \
|
||||
} else
|
||||
|
||||
#else
|
||||
|
||||
// See nsIDOMClassInfo.h
|
||||
|
||||
#endif // MOZILLA_INTERNAL_API
|
||||
|
||||
#endif // nsDOMClassInfoID_h__
|
||||
|
@ -1,127 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*
|
||||
*
|
||||
* This Original Code has been modified by IBM Corporation.
|
||||
* Modifications made by IBM described herein are
|
||||
* Copyright (c) International Business Machines
|
||||
* Corporation, 2000
|
||||
*
|
||||
* Modifications to Mozilla code or documentation
|
||||
* identified per MPL Section 3.3
|
||||
*
|
||||
* Date Modified by Description of modification
|
||||
* 03/27/2000 IBM Corp. Added PR_CALLBACK for Optlink
|
||||
* use in OS2
|
||||
*/
|
||||
|
||||
#include "nsDOMScriptObjectFactory.h"
|
||||
#include "nsScriptNameSpaceManager.h"
|
||||
#include "nsIObserverService.h"
|
||||
#include "nsJSEnvironment.h"
|
||||
#include "nsGlobalWindow.h"
|
||||
#include "nsCRT.h"
|
||||
#ifdef MOZ_XUL
|
||||
#include "nsXULPrototypeCache.h"
|
||||
#endif
|
||||
#include "nsThreadUtils.h"
|
||||
|
||||
using mozilla::dom::GetNameSpaceManager;
|
||||
|
||||
nsDOMScriptObjectFactory::nsDOMScriptObjectFactory()
|
||||
{
|
||||
nsCOMPtr<nsIObserverService> observerService =
|
||||
mozilla::services::GetObserverService();
|
||||
if (observerService) {
|
||||
observerService->AddObserver(this, NS_XPCOM_SHUTDOWN_OBSERVER_ID, false);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
NS_INTERFACE_MAP_BEGIN(nsDOMScriptObjectFactory)
|
||||
NS_INTERFACE_MAP_ENTRY(nsIDOMScriptObjectFactory)
|
||||
NS_INTERFACE_MAP_ENTRY(nsIObserver)
|
||||
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIDOMScriptObjectFactory)
|
||||
NS_INTERFACE_MAP_END
|
||||
|
||||
|
||||
NS_IMPL_ADDREF(nsDOMScriptObjectFactory)
|
||||
NS_IMPL_RELEASE(nsDOMScriptObjectFactory)
|
||||
|
||||
NS_IMETHODIMP_(nsISupports *)
|
||||
nsDOMScriptObjectFactory::GetClassInfoInstance(nsDOMClassInfoID aID)
|
||||
{
|
||||
return NS_GetDOMClassInfoInstance(aID);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP_(nsISupports *)
|
||||
nsDOMScriptObjectFactory::GetExternalClassInfoInstance(const nsAString& aName)
|
||||
{
|
||||
nsScriptNameSpaceManager *nameSpaceManager = GetNameSpaceManager();
|
||||
NS_ENSURE_TRUE(nameSpaceManager, nullptr);
|
||||
|
||||
const nsGlobalNameStruct *globalStruct = nameSpaceManager->LookupName(aName);
|
||||
if (globalStruct) {
|
||||
if (globalStruct->mType == nsGlobalNameStruct::eTypeExternalClassInfoCreator) {
|
||||
nsresult rv;
|
||||
nsCOMPtr<nsIDOMCIExtension> creator(do_CreateInstance(globalStruct->mCID, &rv));
|
||||
NS_ENSURE_SUCCESS(rv, nullptr);
|
||||
|
||||
rv = creator->RegisterDOMCI(NS_ConvertUTF16toUTF8(aName).get(), this);
|
||||
NS_ENSURE_SUCCESS(rv, nullptr);
|
||||
|
||||
globalStruct = nameSpaceManager->LookupName(aName);
|
||||
NS_ENSURE_TRUE(globalStruct, nullptr);
|
||||
|
||||
NS_ASSERTION(globalStruct->mType == nsGlobalNameStruct::eTypeExternalClassInfo,
|
||||
"The classinfo data for this class didn't get registered.");
|
||||
}
|
||||
if (globalStruct->mType == nsGlobalNameStruct::eTypeExternalClassInfo) {
|
||||
return nsDOMClassInfo::GetClassInfoInstance(globalStruct->mData);
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDOMScriptObjectFactory::Observe(nsISupports *aSubject,
|
||||
const char *aTopic,
|
||||
const char16_t *someData)
|
||||
{
|
||||
if (!nsCRT::strcmp(aTopic, NS_XPCOM_SHUTDOWN_OBSERVER_ID)) {
|
||||
#ifdef MOZ_XUL
|
||||
// Flush the XUL cache since it holds JS roots, and we're about to
|
||||
// start the final GC.
|
||||
nsXULPrototypeCache* cache = nsXULPrototypeCache::GetInstance();
|
||||
|
||||
if (cache)
|
||||
cache->Flush();
|
||||
#endif
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDOMScriptObjectFactory::RegisterDOMClassInfo(const char *aName,
|
||||
nsDOMClassInfoExternalConstructorFnc aConstructorFptr,
|
||||
const nsIID *aProtoChainInterface,
|
||||
const nsIID **aInterfaces,
|
||||
uint32_t aScriptableFlags,
|
||||
bool aHasClassInterface,
|
||||
const nsCID *aConstructorCID)
|
||||
{
|
||||
nsScriptNameSpaceManager *nameSpaceManager = GetNameSpaceManager();
|
||||
NS_ENSURE_TRUE(nameSpaceManager, NS_ERROR_NOT_INITIALIZED);
|
||||
|
||||
return nameSpaceManager->RegisterDOMCIData(aName,
|
||||
aConstructorFptr,
|
||||
aProtoChainInterface,
|
||||
aInterfaces,
|
||||
aScriptableFlags,
|
||||
aHasClassInterface,
|
||||
aConstructorCID);
|
||||
}
|
@ -1,50 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*
|
||||
*
|
||||
* This Original Code has been modified by IBM Corporation.
|
||||
* Modifications made by IBM described herein are
|
||||
* Copyright (c) International Business Machines
|
||||
* Corporation, 2000
|
||||
*
|
||||
* Modifications to Mozilla code or documentation
|
||||
* identified per MPL Section 3.3
|
||||
*
|
||||
* Date Modified by Description of modification
|
||||
* 03/27/2000 IBM Corp. Added PR_CALLBACK for Optlink
|
||||
* use in OS2
|
||||
*/
|
||||
|
||||
#include "nsIDOMScriptObjectFactory.h"
|
||||
#include "nsIObserver.h"
|
||||
#include "mozilla/Attributes.h"
|
||||
|
||||
class nsDOMScriptObjectFactory final : public nsIDOMScriptObjectFactory,
|
||||
public nsIObserver
|
||||
{
|
||||
~nsDOMScriptObjectFactory() {}
|
||||
|
||||
public:
|
||||
nsDOMScriptObjectFactory();
|
||||
|
||||
NS_DECL_ISUPPORTS
|
||||
|
||||
// nsIObserver
|
||||
NS_DECL_NSIOBSERVER
|
||||
|
||||
// nsIDOMScriptObjectFactory
|
||||
NS_IMETHOD_(nsISupports *) GetClassInfoInstance(nsDOMClassInfoID aID) override;
|
||||
NS_IMETHOD_(nsISupports *) GetExternalClassInfoInstance(const nsAString& aName) override;
|
||||
|
||||
NS_IMETHOD RegisterDOMClassInfo(const char *aName,
|
||||
nsDOMClassInfoExternalConstructorFnc aConstructorFptr,
|
||||
const nsIID *aProtoChainInterface,
|
||||
const nsIID **aInterfaces,
|
||||
uint32_t aScriptableFlags,
|
||||
bool aHasClassInterface,
|
||||
const nsCID *aConstructorCID) override;
|
||||
};
|
||||
|
@ -11,6 +11,7 @@
|
||||
#include "AppProcessChecker.h"
|
||||
#include "ContentChild.h"
|
||||
#include "nsContentUtils.h"
|
||||
#include "nsDOMClassInfoID.h"
|
||||
#include "nsError.h"
|
||||
#include "nsIXPConnect.h"
|
||||
#include "jsapi.h"
|
||||
|
@ -7,12 +7,7 @@
|
||||
#ifndef nsIDOMClassInfo_h___
|
||||
#define nsIDOMClassInfo_h___
|
||||
|
||||
#include "nsIClassInfoImpl.h"
|
||||
#include "nsDOMClassInfoID.h"
|
||||
#include "nsIXPCScriptable.h"
|
||||
#include "nsIServiceManager.h"
|
||||
#include "nsIDOMScriptObjectFactory.h"
|
||||
#include "nsDOMCID.h"
|
||||
|
||||
#define DOM_BASE_SCRIPTABLE_FLAGS \
|
||||
(nsIXPCScriptable::USE_JSSTUB_FOR_ADDPROPERTY | \
|
||||
@ -32,153 +27,4 @@
|
||||
nsIXPCScriptable::DONT_ENUM_QUERY_INTERFACE | \
|
||||
nsIXPCScriptable::CLASSINFO_INTERFACES_ONLY)
|
||||
|
||||
|
||||
#ifdef MOZILLA_INTERNAL_API
|
||||
|
||||
// See nsDOMClassInfoID.h
|
||||
|
||||
#else
|
||||
|
||||
#define NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(_class) \
|
||||
if (aIID.Equals(NS_GET_IID(nsIClassInfo)) || \
|
||||
aIID.Equals(NS_GET_IID(nsXPCClassInfo))) { \
|
||||
static NS_DEFINE_CID(kDOMSOF_CID, NS_DOM_SCRIPT_OBJECT_FACTORY_CID); \
|
||||
\
|
||||
nsresult rv; \
|
||||
nsCOMPtr<nsIDOMScriptObjectFactory> sof(do_GetService(kDOMSOF_CID, \
|
||||
&rv)); \
|
||||
if (NS_FAILED(rv)) { \
|
||||
*aInstancePtr = nullptr; \
|
||||
return rv; \
|
||||
} \
|
||||
\
|
||||
foundInterface = \
|
||||
sof->GetClassInfoInstance(eDOMClassInfo_##_class##_id); \
|
||||
} else
|
||||
|
||||
#endif /* MOZILLA_INTERNAL_API */
|
||||
|
||||
// Looks up the nsIClassInfo for a class name registered with the
|
||||
// nsScriptNamespaceManager. Remember to release NS_CLASSINFO_NAME(_class)
|
||||
// (eg. when your module unloads).
|
||||
#define NS_INTERFACE_MAP_ENTRY_EXTERNAL_DOM_CLASSINFO(_class) \
|
||||
if (aIID.Equals(NS_GET_IID(nsIClassInfo)) || \
|
||||
aIID.Equals(NS_GET_IID(nsXPCClassInfo))) { \
|
||||
extern nsISupports *NS_CLASSINFO_NAME(_class); \
|
||||
if (NS_CLASSINFO_NAME(_class)) { \
|
||||
foundInterface = NS_CLASSINFO_NAME(_class); \
|
||||
} else { \
|
||||
static NS_DEFINE_CID(kDOMSOF_CID, NS_DOM_SCRIPT_OBJECT_FACTORY_CID); \
|
||||
\
|
||||
nsresult rv; \
|
||||
nsCOMPtr<nsIDOMScriptObjectFactory> sof(do_GetService(kDOMSOF_CID, \
|
||||
&rv)); \
|
||||
if (NS_FAILED(rv)) { \
|
||||
*aInstancePtr = nullptr; \
|
||||
return rv; \
|
||||
} \
|
||||
\
|
||||
foundInterface = \
|
||||
sof->GetExternalClassInfoInstance(NS_LITERAL_STRING(#_class)); \
|
||||
\
|
||||
if (foundInterface) { \
|
||||
NS_CLASSINFO_NAME(_class) = foundInterface; \
|
||||
NS_CLASSINFO_NAME(_class)->AddRef(); \
|
||||
} \
|
||||
} \
|
||||
} else
|
||||
|
||||
|
||||
#define NS_DECL_DOM_CLASSINFO(_class) \
|
||||
nsISupports *NS_CLASSINFO_NAME(_class) = nullptr;
|
||||
|
||||
// {891a7b01-1b61-11d6-a7f2-f690b638899c}
|
||||
#define NS_IDOMCI_EXTENSION_IID \
|
||||
{ 0x891a7b01, 0x1b61, 0x11d6, \
|
||||
{ 0xa7, 0xf2, 0xf6, 0x90, 0xb6, 0x38, 0x89, 0x9c } }
|
||||
|
||||
class nsIDOMScriptObjectFactory;
|
||||
|
||||
class nsIDOMCIExtension : public nsISupports {
|
||||
public:
|
||||
NS_DECLARE_STATIC_IID_ACCESSOR(NS_IDOMCI_EXTENSION_IID)
|
||||
|
||||
NS_IMETHOD RegisterDOMCI(const char* aName,
|
||||
nsIDOMScriptObjectFactory* aDOMSOFactory) = 0;
|
||||
};
|
||||
|
||||
NS_DEFINE_STATIC_IID_ACCESSOR(nsIDOMCIExtension, NS_IDOMCI_EXTENSION_IID)
|
||||
|
||||
#define NS_DOMCI_EXTENSION_NAME(_module) ns##_module##DOMCIExtension
|
||||
#define NS_DOMCI_EXTENSION_CONSTRUCTOR(_module) \
|
||||
ns##_module##DOMCIExtensionConstructor
|
||||
#define NS_DOMCI_EXTENSION_CONSTRUCTOR_IMP(_extension) \
|
||||
NS_GENERIC_FACTORY_CONSTRUCTOR(_extension)
|
||||
|
||||
#define NS_DOMCI_EXTENSION(_module) \
|
||||
class NS_DOMCI_EXTENSION_NAME(_module) : public nsIDOMCIExtension \
|
||||
{ \
|
||||
public: \
|
||||
NS_DOMCI_EXTENSION_NAME(_module)(); \
|
||||
virtual ~NS_DOMCI_EXTENSION_NAME(_module)(); \
|
||||
\
|
||||
NS_DECL_ISUPPORTS \
|
||||
\
|
||||
NS_IMETHOD RegisterDOMCI(const char* aName, \
|
||||
nsIDOMScriptObjectFactory* aDOMSOFactory); \
|
||||
}; \
|
||||
\
|
||||
NS_DOMCI_EXTENSION_CONSTRUCTOR_IMP(NS_DOMCI_EXTENSION_NAME(_module)) \
|
||||
\
|
||||
NS_DOMCI_EXTENSION_NAME(_module)::NS_DOMCI_EXTENSION_NAME(_module)() \
|
||||
{ \
|
||||
} \
|
||||
\
|
||||
NS_DOMCI_EXTENSION_NAME(_module)::~NS_DOMCI_EXTENSION_NAME(_module)() \
|
||||
{ \
|
||||
} \
|
||||
\
|
||||
NS_IMPL_ISUPPORTS(NS_DOMCI_EXTENSION_NAME(_module), nsIDOMCIExtension) \
|
||||
\
|
||||
NS_IMETHODIMP \
|
||||
NS_DOMCI_EXTENSION_NAME(_module)::RegisterDOMCI(const char* aName, \
|
||||
nsIDOMScriptObjectFactory* aDOMSOFactory) \
|
||||
{
|
||||
|
||||
#define NS_DOMCI_EXTENSION_ENTRY_BEGIN(_class) \
|
||||
if (nsCRT::strcmp(aName, #_class) == 0) { \
|
||||
static const nsIID* interfaces[] = {
|
||||
|
||||
#define NS_DOMCI_EXTENSION_ENTRY_INTERFACE(_interface) \
|
||||
&NS_GET_IID(_interface),
|
||||
|
||||
// Don't forget to register the primary interface (_proto) in the
|
||||
// JAVASCRIPT_DOM_INTERFACE category, or prototypes for this class
|
||||
// won't work (except if the interface name starts with nsIDOM).
|
||||
#define NS_DOMCI_EXTENSION_ENTRY_END_HELPER(_class, _proto, _hasclassif, \
|
||||
_constructorcid) \
|
||||
nullptr \
|
||||
}; \
|
||||
aDOMSOFactory->RegisterDOMClassInfo(#_class, nullptr, _proto, \
|
||||
interfaces, \
|
||||
DOM_DEFAULT_SCRIPTABLE_FLAGS, \
|
||||
_hasclassif, _constructorcid); \
|
||||
return NS_OK; \
|
||||
}
|
||||
|
||||
#define NS_DOMCI_EXTENSION_ENTRY_END(_class, _proto, _hasclassif, \
|
||||
_constructorcid) \
|
||||
NS_DOMCI_EXTENSION_ENTRY_END_HELPER(_class, &NS_GET_IID(_proto), \
|
||||
_hasclassif, _constructorcid)
|
||||
|
||||
#define NS_DOMCI_EXTENSION_ENTRY_END_NO_PRIMARY_IF(_class, _hasclassif, \
|
||||
_constructorcid) \
|
||||
NS_DOMCI_EXTENSION_ENTRY_END_HELPER(_class, nullptr, _hasclassif, \
|
||||
_constructorcid)
|
||||
|
||||
#define NS_DOMCI_EXTENSION_END \
|
||||
return NS_ERROR_FAILURE; \
|
||||
}
|
||||
|
||||
|
||||
#endif /* nsIDOMClassInfo_h___ */
|
||||
|
@ -1,45 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef nsIDOMScriptObjectFactory_h__
|
||||
#define nsIDOMScriptObjectFactory_h__
|
||||
|
||||
#include "nsISupports.h"
|
||||
#include "nsIDOMClassInfo.h"
|
||||
#include "nsString.h"
|
||||
|
||||
#define NS_IDOM_SCRIPT_OBJECT_FACTORY_IID \
|
||||
{ 0x2a50e17c, 0x46ff, 0x4150, \
|
||||
{ 0xbb, 0x46, 0xd8, 0x07, 0xb3, 0x36, 0xde, 0xab } }
|
||||
|
||||
typedef nsXPCClassInfo* (*nsDOMClassInfoExternalConstructorFnc)
|
||||
(const char* aName);
|
||||
|
||||
class nsIDOMScriptObjectFactory : public nsISupports {
|
||||
public:
|
||||
NS_DECLARE_STATIC_IID_ACCESSOR(NS_IDOM_SCRIPT_OBJECT_FACTORY_IID)
|
||||
|
||||
NS_IMETHOD_(nsISupports *) GetClassInfoInstance(nsDOMClassInfoID aID) = 0;
|
||||
NS_IMETHOD_(nsISupports *) GetExternalClassInfoInstance(const nsAString& aName) = 0;
|
||||
|
||||
// Register the info for an external class. aName must be static
|
||||
// data, it will not be deleted by the DOM code. aProtoChainInterface
|
||||
// must be registered in the JAVASCRIPT_DOM_INTERFACE category, or
|
||||
// prototypes for this class won't work (except if the interface
|
||||
// name starts with nsIDOM).
|
||||
NS_IMETHOD RegisterDOMClassInfo(const char *aName,
|
||||
nsDOMClassInfoExternalConstructorFnc aConstructorFptr,
|
||||
const nsIID *aProtoChainInterface,
|
||||
const nsIID **aInterfaces,
|
||||
uint32_t aScriptableFlags,
|
||||
bool aHasClassInterface,
|
||||
const nsCID *aConstructorCID) = 0;
|
||||
};
|
||||
|
||||
NS_DEFINE_STATIC_IID_ACCESSOR(nsIDOMScriptObjectFactory,
|
||||
NS_IDOM_SCRIPT_OBJECT_FACTORY_IID)
|
||||
|
||||
#endif /* nsIDOMScriptObjectFactory_h__ */
|
@ -10,9 +10,6 @@
|
||||
#define JAVASCRIPT_GLOBAL_CONSTRUCTOR_CATEGORY \
|
||||
"JavaScript-global-constructor"
|
||||
|
||||
#define JAVASCRIPT_GLOBAL_CONSTRUCTOR_PROTO_ALIAS_CATEGORY \
|
||||
"JavaScript-global-constructor-prototype-alias"
|
||||
|
||||
#define JAVASCRIPT_GLOBAL_PROPERTY_CATEGORY \
|
||||
"JavaScript-global-property"
|
||||
|
||||
@ -23,10 +20,4 @@
|
||||
#define JAVASCRIPT_NAVIGATOR_PROPERTY_CATEGORY \
|
||||
"JavaScript-navigator-property"
|
||||
|
||||
#define JAVASCRIPT_DOM_CLASS \
|
||||
"JavaScript-DOM-class"
|
||||
|
||||
#define JAVASCRIPT_DOM_INTERFACE \
|
||||
"JavaScript-DOM-interface"
|
||||
|
||||
#endif /* nsIScriptNameSpaceManager_h__ */
|
||||
|
@ -2562,8 +2562,6 @@ AsmJSCacheOpenEntryForWrite(JS::Handle<JSObject*> aGlobal,
|
||||
aSize, aMemory, aHandle);
|
||||
}
|
||||
|
||||
static NS_DEFINE_CID(kDOMScriptObjectFactoryCID, NS_DOM_SCRIPT_OBJECT_FACTORY_CID);
|
||||
|
||||
void
|
||||
nsJSContext::EnsureStatics()
|
||||
{
|
||||
@ -2695,15 +2693,6 @@ nsJSContext::EnsureStatics()
|
||||
obs->AddObserver(observer, "quit-application", false);
|
||||
obs->AddObserver(observer, NS_XPCOM_SHUTDOWN_OBSERVER_ID, false);
|
||||
|
||||
// Bug 907848 - We need to explicitly get the nsIDOMScriptObjectFactory
|
||||
// service in order to force its constructor to run, which registers a
|
||||
// shutdown observer. It would be nice to make this more explicit and less
|
||||
// side-effect-y.
|
||||
nsCOMPtr<nsIDOMScriptObjectFactory> factory = do_GetService(kDOMScriptObjectFactoryCID);
|
||||
if (!factory) {
|
||||
MOZ_CRASH();
|
||||
}
|
||||
|
||||
sIsInitialized = true;
|
||||
}
|
||||
|
||||
|
@ -61,21 +61,6 @@ GlobalNameHashClearEntry(PLDHashTable *table, PLDHashEntryHdr *entry)
|
||||
// An entry is being cleared, let the key (nsString) do its own
|
||||
// cleanup.
|
||||
e->mKey.~nsString();
|
||||
if (e->mGlobalName.mType == nsGlobalNameStruct::eTypeExternalClassInfo) {
|
||||
nsIClassInfo* ci = GET_CLEAN_CI_PTR(e->mGlobalName.mData->mCachedClassInfo);
|
||||
|
||||
// If we constructed an internal helper, we'll let the helper delete
|
||||
// the nsDOMClassInfoData structure, if not we do it here.
|
||||
if (!ci || e->mGlobalName.mData->u.mExternalConstructorFptr) {
|
||||
delete e->mGlobalName.mData;
|
||||
}
|
||||
|
||||
// Release our pointer to the helper.
|
||||
NS_IF_RELEASE(ci);
|
||||
}
|
||||
else if (e->mGlobalName.mType == nsGlobalNameStruct::eTypeExternalConstructorAlias) {
|
||||
delete e->mGlobalName.mAlias;
|
||||
}
|
||||
|
||||
// This will set e->mGlobalName.mType to
|
||||
// nsGlobalNameStruct::eTypeNotInitialized
|
||||
@ -151,21 +136,6 @@ nsScriptNameSpaceManager::RemoveFromHash(PLDHashTable *aTable,
|
||||
aTable->Remove(aKey);
|
||||
}
|
||||
|
||||
nsGlobalNameStruct*
|
||||
nsScriptNameSpaceManager::GetConstructorProto(const nsGlobalNameStruct* aStruct)
|
||||
{
|
||||
NS_ASSERTION(aStruct->mType == nsGlobalNameStruct::eTypeExternalConstructorAlias,
|
||||
"This function only works on constructor aliases!");
|
||||
if (!aStruct->mAlias->mProto) {
|
||||
auto proto = static_cast<GlobalNameMapEntry*>
|
||||
(mGlobalNames.Search(&aStruct->mAlias->mProtoName));
|
||||
if (proto) {
|
||||
aStruct->mAlias->mProto = &proto->mGlobalName;
|
||||
}
|
||||
}
|
||||
return aStruct->mAlias->mProto;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsScriptNameSpaceManager::FillHash(nsICategoryManager *aCategoryManager,
|
||||
const char *aCategory)
|
||||
@ -187,116 +157,6 @@ nsScriptNameSpaceManager::FillHash(nsICategoryManager *aCategoryManager,
|
||||
}
|
||||
|
||||
|
||||
nsresult
|
||||
nsScriptNameSpaceManager::RegisterExternalInterfaces(bool aAsProto)
|
||||
{
|
||||
nsresult rv;
|
||||
nsCOMPtr<nsICategoryManager> cm =
|
||||
do_GetService(NS_CATEGORYMANAGER_CONTRACTID, &rv);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsCOMPtr<nsIInterfaceInfoManager>
|
||||
iim(do_GetService(NS_INTERFACEINFOMANAGER_SERVICE_CONTRACTID));
|
||||
NS_ENSURE_TRUE(iim, NS_ERROR_NOT_AVAILABLE);
|
||||
|
||||
nsCOMPtr<nsISimpleEnumerator> enumerator;
|
||||
rv = cm->EnumerateCategory(JAVASCRIPT_DOM_INTERFACE,
|
||||
getter_AddRefs(enumerator));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsXPIDLCString IID_string;
|
||||
nsAutoCString category_entry;
|
||||
const char* if_name;
|
||||
nsCOMPtr<nsISupports> entry;
|
||||
nsCOMPtr<nsIInterfaceInfo> if_info;
|
||||
bool found_old, dom_prefix;
|
||||
|
||||
while (NS_SUCCEEDED(enumerator->GetNext(getter_AddRefs(entry)))) {
|
||||
nsCOMPtr<nsISupportsCString> category(do_QueryInterface(entry));
|
||||
|
||||
if (!category) {
|
||||
NS_WARNING("Category entry not an nsISupportsCString!");
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
rv = category->GetData(category_entry);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = cm->GetCategoryEntry(JAVASCRIPT_DOM_INTERFACE, category_entry.get(),
|
||||
getter_Copies(IID_string));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsIID primary_IID;
|
||||
if (!primary_IID.Parse(IID_string) ||
|
||||
primary_IID.Equals(NS_GET_IID(nsISupports))) {
|
||||
NS_ERROR("Invalid IID registered with the script namespace manager!");
|
||||
continue;
|
||||
}
|
||||
|
||||
iim->GetInfoForIID(&primary_IID, getter_AddRefs(if_info));
|
||||
|
||||
while (if_info) {
|
||||
const nsIID *iid;
|
||||
if_info->GetIIDShared(&iid);
|
||||
NS_ENSURE_TRUE(iid, NS_ERROR_UNEXPECTED);
|
||||
|
||||
if (iid->Equals(NS_GET_IID(nsISupports))) {
|
||||
break;
|
||||
}
|
||||
|
||||
if_info->GetNameShared(&if_name);
|
||||
dom_prefix = (strncmp(if_name, NS_DOM_INTERFACE_PREFIX,
|
||||
sizeof(NS_DOM_INTERFACE_PREFIX) - 1) == 0);
|
||||
|
||||
const char* name;
|
||||
if (dom_prefix) {
|
||||
name = if_name + sizeof(NS_DOM_INTERFACE_PREFIX) - 1;
|
||||
} else {
|
||||
name = if_name + sizeof(NS_INTERFACE_PREFIX) - 1;
|
||||
}
|
||||
|
||||
if (aAsProto) {
|
||||
RegisterClassProto(name, iid, &found_old);
|
||||
} else {
|
||||
RegisterInterface(name, iid, &found_old);
|
||||
}
|
||||
|
||||
if (found_old) {
|
||||
break;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIInterfaceInfo> tmp(if_info);
|
||||
tmp->GetParent(getter_AddRefs(if_info));
|
||||
}
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsScriptNameSpaceManager::RegisterInterface(const char* aIfName,
|
||||
const nsIID *aIfIID,
|
||||
bool* aFoundOld)
|
||||
{
|
||||
*aFoundOld = false;
|
||||
|
||||
nsGlobalNameStruct *s = AddToHash(&mGlobalNames, aIfName);
|
||||
NS_ENSURE_TRUE(s, NS_ERROR_OUT_OF_MEMORY);
|
||||
|
||||
if (s->mType != nsGlobalNameStruct::eTypeNotInitialized &&
|
||||
s->mType != nsGlobalNameStruct::eTypeNewDOMBinding) {
|
||||
*aFoundOld = true;
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
s->mType = nsGlobalNameStruct::eTypeInterface;
|
||||
s->mIID = *aIfIID;
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsScriptNameSpaceManager::Init()
|
||||
{
|
||||
@ -304,9 +164,6 @@ nsScriptNameSpaceManager::Init()
|
||||
|
||||
nsresult rv = NS_OK;
|
||||
|
||||
rv = RegisterExternalInterfaces(false);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsCOMPtr<nsICategoryManager> cm =
|
||||
do_GetService(NS_CATEGORYMANAGER_CONTRACTID, &rv);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
@ -389,8 +246,7 @@ nsScriptNameSpaceManager::RegisterClassName(const char *aClassName,
|
||||
}
|
||||
|
||||
NS_ASSERTION(s->mType == nsGlobalNameStruct::eTypeNotInitialized ||
|
||||
s->mType == nsGlobalNameStruct::eTypeNewDOMBinding ||
|
||||
s->mType == nsGlobalNameStruct::eTypeInterface,
|
||||
s->mType == nsGlobalNameStruct::eTypeNewDOMBinding,
|
||||
"Whaaa, JS environment name clash!");
|
||||
|
||||
s->mType = nsGlobalNameStruct::eTypeClassConstructor;
|
||||
@ -414,8 +270,7 @@ nsScriptNameSpaceManager::RegisterClassProto(const char *aClassName,
|
||||
NS_ENSURE_TRUE(s, NS_ERROR_OUT_OF_MEMORY);
|
||||
|
||||
if (s->mType != nsGlobalNameStruct::eTypeNotInitialized &&
|
||||
s->mType != nsGlobalNameStruct::eTypeNewDOMBinding &&
|
||||
s->mType != nsGlobalNameStruct::eTypeInterface) {
|
||||
s->mType != nsGlobalNameStruct::eTypeNewDOMBinding) {
|
||||
*aFoundOld = true;
|
||||
|
||||
return NS_OK;
|
||||
@ -427,77 +282,6 @@ nsScriptNameSpaceManager::RegisterClassProto(const char *aClassName,
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsScriptNameSpaceManager::RegisterExternalClassName(const char *aClassName,
|
||||
nsCID& aCID)
|
||||
{
|
||||
nsGlobalNameStruct *s = AddToHash(&mGlobalNames, aClassName);
|
||||
NS_ENSURE_TRUE(s, NS_ERROR_OUT_OF_MEMORY);
|
||||
|
||||
// If an external constructor is already defined with aClassName we
|
||||
// won't overwrite it.
|
||||
|
||||
if (s->mType == nsGlobalNameStruct::eTypeExternalConstructor) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_ASSERTION(s->mType == nsGlobalNameStruct::eTypeNotInitialized ||
|
||||
s->mType == nsGlobalNameStruct::eTypeNewDOMBinding ||
|
||||
s->mType == nsGlobalNameStruct::eTypeInterface,
|
||||
"Whaaa, JS environment name clash!");
|
||||
|
||||
s->mType = nsGlobalNameStruct::eTypeExternalClassInfoCreator;
|
||||
s->mCID = aCID;
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsScriptNameSpaceManager::RegisterDOMCIData(const char *aName,
|
||||
nsDOMClassInfoExternalConstructorFnc aConstructorFptr,
|
||||
const nsIID *aProtoChainInterface,
|
||||
const nsIID **aInterfaces,
|
||||
uint32_t aScriptableFlags,
|
||||
bool aHasClassInterface,
|
||||
const nsCID *aConstructorCID)
|
||||
{
|
||||
const char16_t* className;
|
||||
nsGlobalNameStruct *s = AddToHash(&mGlobalNames, aName, &className);
|
||||
NS_ENSURE_TRUE(s, NS_ERROR_OUT_OF_MEMORY);
|
||||
|
||||
// If an external constructor is already defined with aClassName we
|
||||
// won't overwrite it.
|
||||
|
||||
if (s->mType == nsGlobalNameStruct::eTypeClassConstructor ||
|
||||
s->mType == nsGlobalNameStruct::eTypeExternalClassInfo) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// XXX Should we bail out here?
|
||||
NS_ASSERTION(s->mType == nsGlobalNameStruct::eTypeNotInitialized ||
|
||||
s->mType == nsGlobalNameStruct::eTypeNewDOMBinding ||
|
||||
s->mType == nsGlobalNameStruct::eTypeExternalClassInfoCreator,
|
||||
"Someone tries to register classinfo data for a class that isn't new or external!");
|
||||
|
||||
s->mData = new nsExternalDOMClassInfoData;
|
||||
s->mType = nsGlobalNameStruct::eTypeExternalClassInfo;
|
||||
s->mData->mName = aName;
|
||||
s->mData->mNameUTF16 = className;
|
||||
if (aConstructorFptr)
|
||||
s->mData->u.mExternalConstructorFptr = aConstructorFptr;
|
||||
else
|
||||
// null constructor will cause us to use nsDOMGenericSH::doCreate
|
||||
s->mData->u.mExternalConstructorFptr = nullptr;
|
||||
s->mData->mCachedClassInfo = nullptr;
|
||||
s->mData->mProtoChainInterface = aProtoChainInterface;
|
||||
s->mData->mInterfaces = aInterfaces;
|
||||
s->mData->mScriptableFlags = aScriptableFlags;
|
||||
s->mData->mHasClassInterface = aHasClassInterface;
|
||||
s->mData->mConstructorCID = aConstructorCID;
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsScriptNameSpaceManager::OperateCategoryEntryHash(nsICategoryManager* aCategoryManager,
|
||||
const char* aCategory,
|
||||
@ -591,31 +375,6 @@ nsScriptNameSpaceManager::OperateCategoryEntryHash(nsICategoryManager* aCategory
|
||||
nsCID cid = *cidPtr;
|
||||
free(cidPtr);
|
||||
|
||||
if (type == nsGlobalNameStruct::eTypeExternalConstructor) {
|
||||
nsXPIDLCString constructorProto;
|
||||
rv = aCategoryManager->GetCategoryEntry(JAVASCRIPT_GLOBAL_CONSTRUCTOR_PROTO_ALIAS_CATEGORY,
|
||||
categoryEntry.get(),
|
||||
getter_Copies(constructorProto));
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
nsGlobalNameStruct *s = AddToHash(&mGlobalNames, categoryEntry.get());
|
||||
NS_ENSURE_TRUE(s, NS_ERROR_OUT_OF_MEMORY);
|
||||
|
||||
if (s->mType == nsGlobalNameStruct::eTypeNotInitialized ||
|
||||
s->mType == nsGlobalNameStruct::eTypeNewDOMBinding) {
|
||||
s->mAlias = new nsGlobalNameStruct::ConstructorAlias;
|
||||
s->mType = nsGlobalNameStruct::eTypeExternalConstructorAlias;
|
||||
s->mChromeOnly = false;
|
||||
s->mAlias->mCID = cid;
|
||||
AppendASCIItoUTF16(constructorProto, s->mAlias->mProtoName);
|
||||
s->mAlias->mProto = nullptr;
|
||||
} else {
|
||||
NS_WARNING("Global script name not overwritten!");
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
}
|
||||
|
||||
nsGlobalNameStruct *s = AddToHash(table, categoryEntry.get());
|
||||
NS_ENSURE_TRUE(s, NS_ERROR_OUT_OF_MEMORY);
|
||||
|
||||
|
@ -36,25 +36,14 @@
|
||||
|
||||
struct nsGlobalNameStruct
|
||||
{
|
||||
struct ConstructorAlias
|
||||
{
|
||||
nsCID mCID;
|
||||
nsString mProtoName;
|
||||
nsGlobalNameStruct* mProto;
|
||||
};
|
||||
|
||||
enum nametype {
|
||||
eTypeNotInitialized,
|
||||
eTypeNewDOMBinding,
|
||||
eTypeInterface,
|
||||
eTypeProperty,
|
||||
eTypeNavigatorProperty,
|
||||
eTypeExternalConstructor,
|
||||
eTypeClassConstructor,
|
||||
eTypeClassProto,
|
||||
eTypeExternalClassInfoCreator,
|
||||
eTypeExternalClassInfo,
|
||||
eTypeExternalConstructorAlias
|
||||
} mType;
|
||||
|
||||
// mChromeOnly is only used for structs that define non-WebIDL things
|
||||
@ -65,9 +54,7 @@ struct nsGlobalNameStruct
|
||||
|
||||
union {
|
||||
int32_t mDOMClassInfoID; // eTypeClassConstructor
|
||||
nsIID mIID; // eTypeInterface, eTypeClassProto
|
||||
nsExternalDOMClassInfoData* mData; // eTypeExternalClassInfo
|
||||
ConstructorAlias* mAlias; // eTypeExternalConstructorAlias
|
||||
nsIID mIID; // eTypeClassProto
|
||||
nsCID mCID; // All other types except eTypeNewDOMBinding
|
||||
};
|
||||
|
||||
@ -137,23 +124,6 @@ public:
|
||||
const nsIID *aConstructorProtoIID,
|
||||
bool *aFoundOld);
|
||||
|
||||
nsresult RegisterExternalInterfaces(bool aAsProto);
|
||||
|
||||
nsresult RegisterExternalClassName(const char *aClassName,
|
||||
nsCID& aCID);
|
||||
|
||||
// Register the info for an external class. aName must be static
|
||||
// data, it will not be deleted by the DOM code.
|
||||
nsresult RegisterDOMCIData(const char *aName,
|
||||
nsDOMClassInfoExternalConstructorFnc aConstructorFptr,
|
||||
const nsIID *aProtoChainInterface,
|
||||
const nsIID **aInterfaces,
|
||||
uint32_t aScriptableFlags,
|
||||
bool aHasClassInterface,
|
||||
const nsCID *aConstructorCID);
|
||||
|
||||
nsGlobalNameStruct* GetConstructorProto(const nsGlobalNameStruct* aStruct);
|
||||
|
||||
void RegisterDefineDOMInterface(const nsAFlatString& aName,
|
||||
mozilla::dom::DefineInterface aDefineDOMInterface,
|
||||
mozilla::dom::ConstructorEnabled* aConstructorEnabled);
|
||||
|
@ -2527,15 +2527,14 @@ nsXMLHttpRequest::Send(nsIVariant* aVariant, const Nullable<RequestBody>& aBody)
|
||||
|
||||
// Return error if we're already processing a request
|
||||
if (XML_HTTP_REQUEST_SENT & mState) {
|
||||
return NS_ERROR_FAILURE;
|
||||
return NS_ERROR_DOM_INVALID_STATE_ERR;
|
||||
}
|
||||
|
||||
// Make sure we've been opened
|
||||
if (!mChannel || !(XML_HTTP_REQUEST_OPENED & mState)) {
|
||||
return NS_ERROR_NOT_INITIALIZED;
|
||||
return NS_ERROR_DOM_INVALID_STATE_ERR;
|
||||
}
|
||||
|
||||
|
||||
// nsIRequest::LOAD_BACKGROUND prevents throbber from becoming active, which
|
||||
// in turn keeps STOP button from becoming active. If the consumer passed in
|
||||
// a progress event handler we must load with nsIRequest::LOAD_NORMAL or
|
||||
|
@ -20,8 +20,9 @@ function test_sendMouseEventDefaults() {
|
||||
window.addEventListener("mousedown", function listener(evt) {
|
||||
window.removeEventListener("mousedown", listener);
|
||||
// Mandatory args
|
||||
is(evt.clientX, x, "check x");
|
||||
is(evt.clientY, y, "check y");
|
||||
// coordinates may change slightly due to rounding
|
||||
ok((evt.clientX <= x+2) && (evt.clientX >= x-2), "check x");
|
||||
ok((evt.clientY <= y+2) && (evt.clientY >= y-2), "check y");
|
||||
is(evt.button, button, "check button");
|
||||
is(evt.detail, clickCount, "check click count");
|
||||
is(evt.getModifierState("Shift"), true, "check modifiers");
|
||||
|
134
dom/base/test/unit/test_cancelPrefetch.js
Normal file
134
dom/base/test/unit/test_cancelPrefetch.js
Normal file
@ -0,0 +1,134 @@
|
||||
//Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
const Cc = Components.classes;
|
||||
const Ci = Components.interfaces;
|
||||
var prefetch = Cc["@mozilla.org/prefetch-service;1"].
|
||||
getService(Ci.nsIPrefetchService);
|
||||
var ios = Cc["@mozilla.org/network/io-service;1"].
|
||||
getService(Ci.nsIIOService);
|
||||
var prefs = Cc["@mozilla.org/preferences-service;1"].
|
||||
getService(Ci.nsIPrefBranch);
|
||||
|
||||
var parser = Cc["@mozilla.org/xmlextras/domparser;1"].
|
||||
createInstance(Ci.nsIDOMParser);
|
||||
|
||||
var doc;
|
||||
|
||||
var docbody = '<html xmlns="http://www.w3.org/1999/xhtml"><head></head><body>' +
|
||||
'<link id="node1"/><link id="node2"/>' +
|
||||
'</body></html>';
|
||||
|
||||
var node1;
|
||||
var node2;
|
||||
|
||||
function run_test() {
|
||||
prefs.setBoolPref("network.prefetch-next", true);
|
||||
|
||||
parser.init();
|
||||
doc = parser.parseFromString(docbody, "text/html");
|
||||
|
||||
node1 = doc.getElementById("node1");
|
||||
node2 = doc.getElementById("node2");
|
||||
|
||||
run_next_test();
|
||||
}
|
||||
|
||||
add_test(function test_cancel1() {
|
||||
|
||||
var uri = ios.newURI("http://localhost/1", null, null);
|
||||
prefetch.prefetchURI(uri, uri, node1, true);
|
||||
|
||||
do_check_true(prefetch.hasMoreElements(), 'There is a request in the queue');
|
||||
|
||||
// Trying to prefetch again the same uri with the same node will fail.
|
||||
var didFail = 0;
|
||||
|
||||
try {
|
||||
prefetch.prefetchURI(uri, uri, node1, true);
|
||||
} catch(e) {
|
||||
didFail = 1;
|
||||
}
|
||||
|
||||
do_check_true(didFail == 1, 'Prefetching the same request with the same ' +
|
||||
'node fails.');
|
||||
|
||||
do_check_true(prefetch.hasMoreElements(), 'There is still request in ' +
|
||||
'the queue');
|
||||
|
||||
prefetch.cancelPrefetchURI(uri, node1);
|
||||
|
||||
do_check_false(prefetch.hasMoreElements(), 'There is no request in the ' +
|
||||
'queue');
|
||||
run_next_test();
|
||||
});
|
||||
|
||||
add_test(function test_cancel2() {
|
||||
// Prefetch a uri with 2 different nodes. There should be 2 request
|
||||
// in the queue and canceling one will not cancel the other.
|
||||
|
||||
var uri = ios.newURI("http://localhost/1", null, null);
|
||||
prefetch.prefetchURI(uri, uri, node1, true);
|
||||
prefetch.prefetchURI(uri, uri, node2, true);
|
||||
|
||||
do_check_true(prefetch.hasMoreElements(), 'There are requests in the queue');
|
||||
|
||||
prefetch.cancelPrefetchURI(uri, node1);
|
||||
|
||||
do_check_true(prefetch.hasMoreElements(), 'There is still one more request ' +
|
||||
'in the queue');
|
||||
|
||||
prefetch.cancelPrefetchURI(uri, node2);
|
||||
|
||||
do_check_false(prefetch.hasMoreElements(), 'There is no request in the queue');
|
||||
run_next_test();
|
||||
});
|
||||
|
||||
add_test(function test_cancel3() {
|
||||
// Request a prefetch of a uri. Trying to cancel a prefetch for the same uri
|
||||
// with a different node will fail.
|
||||
var uri = ios.newURI("http://localhost/1", null, null);
|
||||
prefetch.prefetchURI(uri, uri, node1, true);
|
||||
|
||||
do_check_true(prefetch.hasMoreElements(), 'There is a request in the queue');
|
||||
|
||||
var didFail = 0;
|
||||
|
||||
try {
|
||||
prefetch.cancelPrefetchURI(uri, node2);
|
||||
} catch(e) {
|
||||
didFail = 1;
|
||||
}
|
||||
do_check_true(didFail == 1, 'Canceling the request failed');
|
||||
|
||||
do_check_true(prefetch.hasMoreElements(), 'There is still a request ' +
|
||||
'in the queue');
|
||||
|
||||
prefetch.cancelPrefetchURI(uri, node1);
|
||||
do_check_false(prefetch.hasMoreElements(), 'There is no request in the queue');
|
||||
run_next_test();
|
||||
});
|
||||
|
||||
add_test(function test_cancel4() {
|
||||
// Request a prefetch of a uri. Trying to cancel a prefetch for a different uri
|
||||
// with the same node will fail.
|
||||
var uri1 = ios.newURI("http://localhost/1", null, null);
|
||||
var uri2 = ios.newURI("http://localhost/2", null, null);
|
||||
prefetch.prefetchURI(uri1, uri1, node1, true);
|
||||
|
||||
do_check_true(prefetch.hasMoreElements(), 'There is a request in the queue');
|
||||
|
||||
var didFail = 0;
|
||||
|
||||
try {
|
||||
prefetch.cancelPrefetchURI(uri2, node1);
|
||||
} catch(e) {
|
||||
didFail = 1;
|
||||
}
|
||||
do_check_true(didFail == 1, 'Canceling the request failed');
|
||||
|
||||
do_check_true(prefetch.hasMoreElements(), 'There is still a request ' +
|
||||
'in the queue');
|
||||
|
||||
prefetch.cancelPrefetchURI(uri1, node1);
|
||||
do_check_false(prefetch.hasMoreElements(), 'There is no request in the queue');
|
||||
run_next_test();
|
||||
});
|
@ -50,3 +50,4 @@ head = head_xml.js
|
||||
[test_xml_serializer.js]
|
||||
head = head_xml.js
|
||||
[test_xmlserializer.js]
|
||||
[test_cancelPrefetch.js]
|
||||
|
@ -1595,7 +1595,7 @@ DOMInterfaces = {
|
||||
'headerFile': 'mozilla/dom/WorkerScope.h',
|
||||
'nativeType': 'mozilla::dom::workers::WorkerDebuggerGlobalScope',
|
||||
'implicitJSContext': [
|
||||
'dump', 'global', 'setImmediate', 'reportError',
|
||||
'dump', 'global', 'reportError',
|
||||
],
|
||||
},
|
||||
|
||||
|
@ -73,3 +73,4 @@ skip-if = debug == false
|
||||
[test_iterable.html]
|
||||
skip-if = debug == false
|
||||
[test_oom_reporting.html]
|
||||
[test_domProxyArrayLengthGetter.html]
|
||||
|
28
dom/bindings/test/test_domProxyArrayLengthGetter.html
Normal file
28
dom/bindings/test/test_domProxyArrayLengthGetter.html
Normal file
@ -0,0 +1,28 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=1221421
|
||||
-->
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Test for Bug 1221421</title>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||
<script type="text/javascript">
|
||||
|
||||
var x = document.documentElement.style;
|
||||
x.__proto__ = [1, 2, 3];
|
||||
|
||||
var res = 0;
|
||||
for (var h = 0; h < 5000; ++h) {
|
||||
res += x.length;
|
||||
}
|
||||
is(res, 15000, "length getter should return array length");
|
||||
|
||||
</script>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1221421">Mozilla Bug 1221421</a>
|
||||
</body>
|
||||
</html>
|
@ -1915,7 +1915,7 @@ BrowserElementChild.prototype = {
|
||||
sendAsyncMsg('error', { type: 'cspBlocked' });
|
||||
return;
|
||||
case Cr.NS_ERROR_PHISHING_URI :
|
||||
sendAsyncMsg('error', { type: 'phishingBlocked' });
|
||||
sendAsyncMsg('error', { type: 'deceptiveBlocked' });
|
||||
return;
|
||||
case Cr.NS_ERROR_MALWARE_URI :
|
||||
sendAsyncMsg('error', { type: 'malwareBlocked' });
|
||||
|
@ -166,7 +166,7 @@ tags = audiochannel
|
||||
skip-if = buildapp == 'b2g'
|
||||
[test_browserElement_inproc_AlertInFrame.html]
|
||||
[test_browserElement_inproc_AppFramePermission.html]
|
||||
skip-if = toolkit == 'android' || buildapp != 'mulet'
|
||||
skip-if = buildapp != 'mulet'
|
||||
[test_browserElement_inproc_AppWindowNamespace.html]
|
||||
skip-if = toolkit == 'android' || buildapp == 'b2g' # android(TIMED_OUT, bug 783509) androidx86(TIMED_OUT, bug 783509)
|
||||
[test_browserElement_inproc_AudioChannelMutedByDefault.html]
|
||||
@ -192,7 +192,7 @@ skip-if = (os == "android") # Disabled on Android, see bug 1230421
|
||||
[test_browserElement_inproc_DOMRequestError.html]
|
||||
[test_browserElement_inproc_DataURI.html]
|
||||
[test_browserElement_inproc_DisallowEmbedAppsInOOP.html]
|
||||
skip-if = os == "android" || toolkit == 'gonk' || buildapp != 'mulet' # embed-apps doesn't work in the mochitest app
|
||||
skip-if = buildapp != 'mulet'
|
||||
[test_browserElement_inproc_DocumentFirstPaint.html]
|
||||
[test_browserElement_inproc_Download.html]
|
||||
disabled = bug 1022281
|
||||
|
@ -795,10 +795,16 @@ CanvasDrawObserver::FrameEnd()
|
||||
// If we don't have enough data, don't bother changing...
|
||||
if (mGPUPreferredCalls > mMinCallsBeforeDecision ||
|
||||
mSoftwarePreferredCalls > mMinCallsBeforeDecision) {
|
||||
CanvasRenderingContext2D::RenderingMode switchToMode;
|
||||
if (mGPUPreferredCalls >= mSoftwarePreferredCalls) {
|
||||
mCanvasContext->SwitchRenderingMode(CanvasRenderingContext2D::RenderingMode::OpenGLBackendMode);
|
||||
switchToMode = CanvasRenderingContext2D::RenderingMode::OpenGLBackendMode;
|
||||
} else {
|
||||
mCanvasContext->SwitchRenderingMode(CanvasRenderingContext2D::RenderingMode::SoftwareBackendMode);
|
||||
switchToMode = CanvasRenderingContext2D::RenderingMode::SoftwareBackendMode;
|
||||
}
|
||||
if (switchToMode != mCanvasContext->mRenderingMode) {
|
||||
if (!mCanvasContext->SwitchRenderingMode(switchToMode)) {
|
||||
gfxDebug() << "Canvas acceleration failed mode switch to " << switchToMode;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -968,12 +974,10 @@ CanvasRenderingContext2D::CanvasRenderingContext2D()
|
||||
sNumLivingContexts++;
|
||||
|
||||
// The default is to use OpenGL mode
|
||||
if (!gfxPlatform::GetPlatform()->UseAcceleratedSkiaCanvas()) {
|
||||
mRenderingMode = RenderingMode::SoftwareBackendMode;
|
||||
}
|
||||
|
||||
if (gfxPlatform::GetPlatform()->HaveChoiceOfHWAndSWCanvas()) {
|
||||
if (gfxPlatform::GetPlatform()->UseAcceleratedCanvas()) {
|
||||
mDrawObserver = new CanvasDrawObserver(this);
|
||||
} else {
|
||||
mRenderingMode = RenderingMode::SoftwareBackendMode;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1208,8 +1212,7 @@ bool CanvasRenderingContext2D::SwitchRenderingMode(RenderingMode aRenderingMode)
|
||||
#ifdef USE_SKIA_GPU
|
||||
// Do not attempt to switch into GL mode if the platform doesn't allow it.
|
||||
if ((aRenderingMode == RenderingMode::OpenGLBackendMode) &&
|
||||
(!gfxPlatform::GetPlatform()->HaveChoiceOfHWAndSWCanvas() ||
|
||||
!gfxPlatform::GetPlatform()->UseAcceleratedSkiaCanvas())) {
|
||||
!gfxPlatform::GetPlatform()->UseAcceleratedCanvas()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -1416,7 +1419,7 @@ CanvasRenderingContext2D::EnsureTarget(RenderingMode aRenderingMode)
|
||||
|
||||
if (layerManager) {
|
||||
if (mode == RenderingMode::OpenGLBackendMode &&
|
||||
gfxPlatform::GetPlatform()->UseAcceleratedSkiaCanvas() &&
|
||||
gfxPlatform::GetPlatform()->UseAcceleratedCanvas() &&
|
||||
CheckSizeForSkiaGL(size)) {
|
||||
DemoteOldestContextIfNecessary();
|
||||
mBufferProvider = nullptr;
|
||||
|
@ -894,7 +894,7 @@ AsyncFulfillImageBitmapPromise(Promise* aPromise, ImageBitmap* aImageBitmap)
|
||||
} else {
|
||||
RefPtr<FulfillImageBitmapPromiseWorkerTask> task =
|
||||
new FulfillImageBitmapPromiseWorkerTask(aPromise, aImageBitmap);
|
||||
task->Dispatch(GetCurrentThreadWorkerPrivate()->GetJSContext()); // Actually, to the current worker-thread.
|
||||
task->Dispatch(); // Actually, to the current worker-thread.
|
||||
}
|
||||
}
|
||||
|
||||
@ -1167,7 +1167,7 @@ AsyncCreateImageBitmapFromBlob(Promise* aPromise, nsIGlobalObject* aGlobal,
|
||||
} else {
|
||||
RefPtr<CreateImageBitmapFromBlobWorkerTask> task =
|
||||
new CreateImageBitmapFromBlobWorkerTask(aPromise, aGlobal, aBlob, aCropRect);
|
||||
task->Dispatch(GetCurrentThreadWorkerPrivate()->GetJSContext()); // Actually, to the current worker-thread.
|
||||
task->Dispatch(); // Actually, to the current worker-thread.
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -838,7 +838,7 @@ WebGLContext::GetRenderbufferParameter(GLenum target, GLenum pname)
|
||||
case LOCAL_GL_RENDERBUFFER_SAMPLES:
|
||||
if (!IsWebGL2())
|
||||
break;
|
||||
// fallthrough
|
||||
MOZ_FALLTHROUGH;
|
||||
|
||||
case LOCAL_GL_RENDERBUFFER_WIDTH:
|
||||
case LOCAL_GL_RENDERBUFFER_HEIGHT:
|
||||
|
@ -64,7 +64,7 @@ function IsAcceleratedSkia() {
|
||||
|
||||
try {
|
||||
var props = Cc["@mozilla.org/gfx/info;1"].getService(SpecialPowers.Ci.nsIGfxInfo).getInfo();
|
||||
enabled = props.AzureCanvasBackend == "skia" && props.AzureSkiaAccelerated;
|
||||
enabled = props.AzureCanvasBackend == "skia" && props.AzureCanvasAccelerated;
|
||||
} catch(e) { }
|
||||
|
||||
return enabled;
|
||||
|
@ -59,7 +59,7 @@ MouseEvent::InitMouseEvent(const nsAString& aType,
|
||||
int32_t aScreenX,
|
||||
int32_t aScreenY,
|
||||
int32_t aClientX,
|
||||
int32_t aClientY,
|
||||
int32_t aClientY,
|
||||
bool aCtrlKey,
|
||||
bool aAltKey,
|
||||
bool aShiftKey,
|
||||
@ -94,7 +94,35 @@ MouseEvent::InitMouseEvent(const nsAString& aType,
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
MouseEvent::InitMouseEvent(const nsAString& aType,
|
||||
bool aCanBubble,
|
||||
bool aCancelable,
|
||||
mozIDOMWindow* aView,
|
||||
int32_t aDetail,
|
||||
int32_t aScreenX,
|
||||
int32_t aScreenY,
|
||||
int32_t aClientX,
|
||||
int32_t aClientY,
|
||||
bool aCtrlKey,
|
||||
bool aAltKey,
|
||||
bool aShiftKey,
|
||||
bool aMetaKey,
|
||||
uint16_t aButton,
|
||||
nsIDOMEventTarget* aRelatedTarget)
|
||||
{
|
||||
MouseEvent::InitMouseEvent(aType, aCanBubble, aCancelable,
|
||||
nsGlobalWindow::Cast(aView), aDetail,
|
||||
aScreenX, aScreenY,
|
||||
aClientX, aClientY,
|
||||
aCtrlKey, aAltKey, aShiftKey,
|
||||
aMetaKey, aButton,
|
||||
static_cast<EventTarget *>(aRelatedTarget));
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void
|
||||
MouseEvent::InitMouseEvent(const nsAString& aType,
|
||||
|
@ -21,6 +21,7 @@
|
||||
#include "nsStringStream.h"
|
||||
|
||||
#include "mozilla/ErrorResult.h"
|
||||
#include "mozilla/dom/BodyUtil.h"
|
||||
#include "mozilla/dom/EncodingUtils.h"
|
||||
#include "mozilla/dom/Exceptions.h"
|
||||
#include "mozilla/dom/FetchDriver.h"
|
||||
@ -42,7 +43,6 @@
|
||||
#include "WorkerRunnable.h"
|
||||
#include "WorkerScope.h"
|
||||
#include "Workers.h"
|
||||
#include "FetchUtil.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
@ -326,9 +326,7 @@ WorkerFetchResolver::OnResponseAvailableInternal(InternalResponse* aResponse)
|
||||
new WorkerFetchResponseRunnable(mPromiseProxy->GetWorkerPrivate(), this,
|
||||
aResponse);
|
||||
|
||||
AutoJSAPI jsapi;
|
||||
jsapi.Init();
|
||||
if (!r->Dispatch(jsapi.cx())) {
|
||||
if (!r->Dispatch()) {
|
||||
NS_WARNING("Could not dispatch fetch response");
|
||||
}
|
||||
}
|
||||
@ -345,9 +343,7 @@ WorkerFetchResolver::OnResponseEnd()
|
||||
RefPtr<WorkerFetchResponseEndRunnable> r =
|
||||
new WorkerFetchResponseEndRunnable(mPromiseProxy->GetWorkerPrivate(), this);
|
||||
|
||||
AutoJSAPI jsapi;
|
||||
jsapi.Init();
|
||||
if (!r->Dispatch(jsapi.cx())) {
|
||||
if (!r->Dispatch()) {
|
||||
NS_WARNING("Could not dispatch fetch response end");
|
||||
}
|
||||
}
|
||||
@ -611,8 +607,7 @@ public:
|
||||
if (mBody->mWorkerPrivate) {
|
||||
RefPtr<FailConsumeBodyWorkerRunnable<Derived>> r =
|
||||
new FailConsumeBodyWorkerRunnable<Derived>(mBody);
|
||||
AutoSafeJSContext cx;
|
||||
if (!r->Dispatch(cx)) {
|
||||
if (!r->Dispatch()) {
|
||||
MOZ_CRASH("We are going to leak");
|
||||
}
|
||||
} else {
|
||||
@ -662,8 +657,7 @@ public:
|
||||
aStatus,
|
||||
aResultLength,
|
||||
nonconstResult);
|
||||
AutoSafeJSContext cx;
|
||||
if (!r->Dispatch(cx)) {
|
||||
if (!r->Dispatch()) {
|
||||
// XXXcatalinb: The worker is shutting down, the pump will be canceled
|
||||
// by FetchBodyFeature::Notify.
|
||||
NS_WARNING("Could not dispatch ConsumeBodyRunnable");
|
||||
@ -1010,7 +1004,7 @@ FetchBody<Derived>::ContinueConsumeBody(nsresult aStatus, uint32_t aResultLength
|
||||
switch (mConsumeType) {
|
||||
case CONSUME_ARRAYBUFFER: {
|
||||
JS::Rooted<JSObject*> arrayBuffer(cx);
|
||||
FetchUtil::ConsumeArrayBuffer(cx, &arrayBuffer, aResultLength, aResult,
|
||||
BodyUtil::ConsumeArrayBuffer(cx, &arrayBuffer, aResultLength, aResult,
|
||||
error);
|
||||
|
||||
if (!error.Failed()) {
|
||||
@ -1024,7 +1018,7 @@ FetchBody<Derived>::ContinueConsumeBody(nsresult aStatus, uint32_t aResultLength
|
||||
break;
|
||||
}
|
||||
case CONSUME_BLOB: {
|
||||
RefPtr<dom::Blob> blob = FetchUtil::ConsumeBlob(
|
||||
RefPtr<dom::Blob> blob = BodyUtil::ConsumeBlob(
|
||||
DerivedClass()->GetParentObject(), NS_ConvertUTF8toUTF16(mMimeType),
|
||||
aResultLength, aResult, error);
|
||||
if (!error.Failed()) {
|
||||
@ -1039,7 +1033,7 @@ FetchBody<Derived>::ContinueConsumeBody(nsresult aStatus, uint32_t aResultLength
|
||||
data.Adopt(reinterpret_cast<char*>(aResult), aResultLength);
|
||||
autoFree.Reset();
|
||||
|
||||
RefPtr<dom::FormData> fd = FetchUtil::ConsumeFormData(
|
||||
RefPtr<dom::FormData> fd = BodyUtil::ConsumeFormData(
|
||||
DerivedClass()->GetParentObject(),
|
||||
mMimeType, data, error);
|
||||
if (!error.Failed()) {
|
||||
@ -1051,12 +1045,12 @@ FetchBody<Derived>::ContinueConsumeBody(nsresult aStatus, uint32_t aResultLength
|
||||
// fall through handles early exit.
|
||||
case CONSUME_JSON: {
|
||||
nsString decoded;
|
||||
if (NS_SUCCEEDED(FetchUtil::ConsumeText(aResultLength, aResult, decoded))) {
|
||||
if (NS_SUCCEEDED(BodyUtil::ConsumeText(aResultLength, aResult, decoded))) {
|
||||
if (mConsumeType == CONSUME_TEXT) {
|
||||
localPromise->MaybeResolve(decoded);
|
||||
} else {
|
||||
JS::Rooted<JS::Value> json(cx);
|
||||
FetchUtil::ConsumeJson(cx, &json, decoded, error);
|
||||
BodyUtil::ConsumeJson(cx, &json, decoded, error);
|
||||
if (!error.Failed()) {
|
||||
localPromise->MaybeResolve(cx, json);
|
||||
}
|
||||
|
@ -9,55 +9,6 @@
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
namespace {
|
||||
class StreamDecoder final
|
||||
{
|
||||
nsCOMPtr<nsIUnicodeDecoder> mDecoder;
|
||||
nsString mDecoded;
|
||||
|
||||
public:
|
||||
StreamDecoder()
|
||||
: mDecoder(EncodingUtils::DecoderForEncoding("UTF-8"))
|
||||
{
|
||||
MOZ_ASSERT(mDecoder);
|
||||
}
|
||||
|
||||
nsresult
|
||||
AppendText(const char* aSrcBuffer, uint32_t aSrcBufferLen)
|
||||
{
|
||||
int32_t destBufferLen;
|
||||
nsresult rv =
|
||||
mDecoder->GetMaxLength(aSrcBuffer, aSrcBufferLen, &destBufferLen);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
if (!mDecoded.SetCapacity(mDecoded.Length() + destBufferLen, fallible)) {
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
char16_t* destBuffer = mDecoded.BeginWriting() + mDecoded.Length();
|
||||
int32_t totalChars = mDecoded.Length();
|
||||
|
||||
int32_t srcLen = (int32_t) aSrcBufferLen;
|
||||
int32_t outLen = destBufferLen;
|
||||
rv = mDecoder->Convert(aSrcBuffer, &srcLen, destBuffer, &outLen);
|
||||
MOZ_ASSERT(NS_SUCCEEDED(rv));
|
||||
|
||||
totalChars += outLen;
|
||||
mDecoded.SetLength(totalChars);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsString&
|
||||
GetText()
|
||||
{
|
||||
return mDecoded;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
// static
|
||||
nsresult
|
||||
FetchUtil::GetValidRequestMethod(const nsACString& aMethod, nsCString& outMethod)
|
||||
@ -86,42 +37,6 @@ FetchUtil::GetValidRequestMethod(const nsACString& aMethod, nsCString& outMethod
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// static
|
||||
void
|
||||
FetchUtil::ConsumeArrayBuffer(JSContext* aCx,
|
||||
JS::MutableHandle<JSObject*> aValue,
|
||||
uint32_t aInputLength, uint8_t* aInput,
|
||||
ErrorResult& aRv)
|
||||
{
|
||||
JS::Rooted<JSObject*> arrayBuffer(aCx);
|
||||
arrayBuffer = JS_NewArrayBufferWithContents(aCx, aInputLength,
|
||||
reinterpret_cast<void *>(aInput));
|
||||
if (!arrayBuffer) {
|
||||
JS_ClearPendingException(aCx);
|
||||
aRv.Throw(NS_ERROR_OUT_OF_MEMORY);
|
||||
return;
|
||||
}
|
||||
aValue.set(arrayBuffer);
|
||||
}
|
||||
|
||||
// static
|
||||
already_AddRefed<Blob>
|
||||
FetchUtil::ConsumeBlob(nsISupports* aParent, const nsString& aMimeType,
|
||||
uint32_t aInputLength, uint8_t* aInput,
|
||||
ErrorResult& aRv)
|
||||
{
|
||||
RefPtr<Blob> blob =
|
||||
Blob::CreateMemoryBlob(aParent,
|
||||
reinterpret_cast<void *>(aInput), aInputLength,
|
||||
aMimeType);
|
||||
|
||||
if (!blob) {
|
||||
aRv.Throw(NS_ERROR_DOM_UNKNOWN_ERR);
|
||||
return nullptr;
|
||||
}
|
||||
return blob.forget();
|
||||
}
|
||||
|
||||
static bool
|
||||
FindCRLF(nsACString::const_iterator& aStart,
|
||||
nsACString::const_iterator& aEnd)
|
||||
@ -189,450 +104,5 @@ FetchUtil::ExtractHeader(nsACString::const_iterator& aStart,
|
||||
return PushOverLine(aStart);
|
||||
}
|
||||
|
||||
namespace {
|
||||
class MOZ_STACK_CLASS FillFormIterator final
|
||||
: public URLSearchParams::ForEachIterator
|
||||
{
|
||||
public:
|
||||
explicit FillFormIterator(FormData* aFormData)
|
||||
: mFormData(aFormData)
|
||||
{
|
||||
MOZ_ASSERT(aFormData);
|
||||
}
|
||||
|
||||
bool URLParamsIterator(const nsString& aName,
|
||||
const nsString& aValue) override
|
||||
{
|
||||
ErrorResult rv;
|
||||
mFormData->Append(aName, aValue, rv);
|
||||
MOZ_ASSERT(!rv.Failed());
|
||||
return true;
|
||||
}
|
||||
|
||||
private:
|
||||
FormData* mFormData;
|
||||
};
|
||||
|
||||
/**
|
||||
* A simple multipart/form-data parser as defined in RFC 2388 and RFC 2046.
|
||||
* This does not respect any encoding specified per entry, using UTF-8
|
||||
* throughout. This is as the Fetch spec states in the consume body algorithm.
|
||||
* Borrows some things from Necko's nsMultiMixedConv, but is simpler since
|
||||
* unlike Necko we do not have to deal with receiving incomplete chunks of data.
|
||||
*
|
||||
* This parser will fail the entire parse on any invalid entry, so it will
|
||||
* never return a partially filled FormData.
|
||||
* The content-disposition header is used to figure out the name and filename
|
||||
* entries. The inclusion of the filename parameter decides if the entry is
|
||||
* inserted into the FormData as a string or a File.
|
||||
*
|
||||
* File blobs are copies of the underlying data string since we cannot adopt
|
||||
* char* chunks embedded within the larger body without significant effort.
|
||||
* FIXME(nsm): Bug 1127552 - We should add telemetry to calls to formData() and
|
||||
* friends to figure out if Fetch ends up copying big blobs to see if this is
|
||||
* worth optimizing.
|
||||
*/
|
||||
class MOZ_STACK_CLASS FormDataParser
|
||||
{
|
||||
private:
|
||||
RefPtr<FormData> mFormData;
|
||||
nsCString mMimeType;
|
||||
nsCString mData;
|
||||
|
||||
// Entry state, reset in START_PART.
|
||||
nsCString mName;
|
||||
nsCString mFilename;
|
||||
nsCString mContentType;
|
||||
|
||||
enum
|
||||
{
|
||||
START_PART,
|
||||
PARSE_HEADER,
|
||||
PARSE_BODY,
|
||||
} mState;
|
||||
|
||||
nsIGlobalObject* mParentObject;
|
||||
|
||||
// Reads over a boundary and sets start to the position after the end of the
|
||||
// boundary. Returns false if no boundary is found immediately.
|
||||
bool
|
||||
PushOverBoundary(const nsACString& aBoundaryString,
|
||||
nsACString::const_iterator& aStart,
|
||||
nsACString::const_iterator& aEnd)
|
||||
{
|
||||
// We copy the end iterator to keep the original pointing to the real end
|
||||
// of the string.
|
||||
nsACString::const_iterator end(aEnd);
|
||||
const char* beginning = aStart.get();
|
||||
if (FindInReadable(aBoundaryString, aStart, end)) {
|
||||
// We either should find the body immediately, or after 2 chars with the
|
||||
// 2 chars being '-', everything else is failure.
|
||||
if ((aStart.get() - beginning) == 0) {
|
||||
aStart.advance(aBoundaryString.Length());
|
||||
return true;
|
||||
}
|
||||
|
||||
if ((aStart.get() - beginning) == 2) {
|
||||
if (*(--aStart) == '-' && *(--aStart) == '-') {
|
||||
aStart.advance(aBoundaryString.Length() + 2);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
ParseHeader(nsACString::const_iterator& aStart,
|
||||
nsACString::const_iterator& aEnd,
|
||||
bool* aWasEmptyHeader)
|
||||
{
|
||||
nsAutoCString headerName, headerValue;
|
||||
if (!FetchUtil::ExtractHeader(aStart, aEnd,
|
||||
headerName, headerValue,
|
||||
aWasEmptyHeader)) {
|
||||
return false;
|
||||
}
|
||||
if (*aWasEmptyHeader) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (headerName.LowerCaseEqualsLiteral("content-disposition")) {
|
||||
nsCCharSeparatedTokenizer tokenizer(headerValue, ';');
|
||||
bool seenFormData = false;
|
||||
while (tokenizer.hasMoreTokens()) {
|
||||
const nsDependentCSubstring& token = tokenizer.nextToken();
|
||||
if (token.IsEmpty()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (token.EqualsLiteral("form-data")) {
|
||||
seenFormData = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (seenFormData &&
|
||||
StringBeginsWith(token, NS_LITERAL_CSTRING("name="))) {
|
||||
mName = StringTail(token, token.Length() - 5);
|
||||
mName.Trim(" \"");
|
||||
continue;
|
||||
}
|
||||
|
||||
if (seenFormData &&
|
||||
StringBeginsWith(token, NS_LITERAL_CSTRING("filename="))) {
|
||||
mFilename = StringTail(token, token.Length() - 9);
|
||||
mFilename.Trim(" \"");
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (mName.IsVoid()) {
|
||||
// Could not parse a valid entry name.
|
||||
return false;
|
||||
}
|
||||
} else if (headerName.LowerCaseEqualsLiteral("content-type")) {
|
||||
mContentType = headerValue;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// The end of a body is marked by a CRLF followed by the boundary. So the
|
||||
// CRLF is part of the boundary and not the body, but any prior CRLFs are
|
||||
// part of the body. This will position the iterator at the beginning of the
|
||||
// boundary (after the CRLF).
|
||||
bool
|
||||
ParseBody(const nsACString& aBoundaryString,
|
||||
nsACString::const_iterator& aStart,
|
||||
nsACString::const_iterator& aEnd)
|
||||
{
|
||||
const char* beginning = aStart.get();
|
||||
|
||||
// Find the boundary marking the end of the body.
|
||||
nsACString::const_iterator end(aEnd);
|
||||
if (!FindInReadable(aBoundaryString, aStart, end)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// We found a boundary, strip the just prior CRLF, and consider
|
||||
// everything else the body section.
|
||||
if (aStart.get() - beginning < 2) {
|
||||
// Only the first entry can have a boundary right at the beginning. Even
|
||||
// an empty body will have a CRLF before the boundary. So this is
|
||||
// a failure.
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check that there is a CRLF right before the boundary.
|
||||
aStart.advance(-2);
|
||||
|
||||
// Skip optional hyphens.
|
||||
if (*aStart == '-' && *(aStart.get()+1) == '-') {
|
||||
if (aStart.get() - beginning < 2) {
|
||||
return false;
|
||||
}
|
||||
|
||||
aStart.advance(-2);
|
||||
}
|
||||
|
||||
if (*aStart != nsCRT::CR || *(aStart.get()+1) != nsCRT::LF) {
|
||||
return false;
|
||||
}
|
||||
|
||||
nsAutoCString body(beginning, aStart.get() - beginning);
|
||||
|
||||
// Restore iterator to after the \r\n as we promised.
|
||||
// We do not need to handle the extra hyphens case since our boundary
|
||||
// parser in PushOverBoundary()
|
||||
aStart.advance(2);
|
||||
|
||||
if (!mFormData) {
|
||||
mFormData = new FormData();
|
||||
}
|
||||
|
||||
NS_ConvertUTF8toUTF16 name(mName);
|
||||
|
||||
if (mFilename.IsVoid()) {
|
||||
ErrorResult rv;
|
||||
mFormData->Append(name, NS_ConvertUTF8toUTF16(body), rv);
|
||||
MOZ_ASSERT(!rv.Failed());
|
||||
} else {
|
||||
// Unfortunately we've to copy the data first since all our strings are
|
||||
// going to free it. We also need fallible alloc, so we can't just use
|
||||
// ToNewCString().
|
||||
char* copy = static_cast<char*>(moz_xmalloc(body.Length()));
|
||||
if (!copy) {
|
||||
NS_WARNING("Failed to copy File entry body.");
|
||||
return false;
|
||||
}
|
||||
nsCString::const_iterator bodyIter, bodyEnd;
|
||||
body.BeginReading(bodyIter);
|
||||
body.EndReading(bodyEnd);
|
||||
char *p = copy;
|
||||
while (bodyIter != bodyEnd) {
|
||||
*p++ = *bodyIter++;
|
||||
}
|
||||
p = nullptr;
|
||||
|
||||
RefPtr<Blob> file =
|
||||
File::CreateMemoryFile(mParentObject,
|
||||
reinterpret_cast<void *>(copy), body.Length(),
|
||||
NS_ConvertUTF8toUTF16(mFilename),
|
||||
NS_ConvertUTF8toUTF16(mContentType), /* aLastModifiedDate */ 0);
|
||||
Optional<nsAString> dummy;
|
||||
ErrorResult rv;
|
||||
mFormData->Append(name, *file, dummy, rv);
|
||||
if (NS_WARN_IF(rv.Failed())) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public:
|
||||
FormDataParser(const nsACString& aMimeType, const nsACString& aData, nsIGlobalObject* aParent)
|
||||
: mMimeType(aMimeType), mData(aData), mState(START_PART), mParentObject(aParent)
|
||||
{
|
||||
}
|
||||
|
||||
bool
|
||||
Parse()
|
||||
{
|
||||
// Determine boundary from mimetype.
|
||||
const char* boundaryId = nullptr;
|
||||
boundaryId = strstr(mMimeType.BeginWriting(), "boundary");
|
||||
if (!boundaryId) {
|
||||
return false;
|
||||
}
|
||||
|
||||
boundaryId = strchr(boundaryId, '=');
|
||||
if (!boundaryId) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Skip over '='.
|
||||
boundaryId++;
|
||||
|
||||
char *attrib = (char *) strchr(boundaryId, ';');
|
||||
if (attrib) *attrib = '\0';
|
||||
|
||||
nsAutoCString boundaryString(boundaryId);
|
||||
if (attrib) *attrib = ';';
|
||||
|
||||
boundaryString.Trim(" \"");
|
||||
|
||||
if (boundaryString.Length() == 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
nsACString::const_iterator start, end;
|
||||
mData.BeginReading(start);
|
||||
// This should ALWAYS point to the end of data.
|
||||
// Helpers make copies.
|
||||
mData.EndReading(end);
|
||||
|
||||
while (start != end) {
|
||||
switch(mState) {
|
||||
case START_PART:
|
||||
mName.SetIsVoid(true);
|
||||
mFilename.SetIsVoid(true);
|
||||
mContentType = NS_LITERAL_CSTRING("text/plain");
|
||||
|
||||
// MUST start with boundary.
|
||||
if (!PushOverBoundary(boundaryString, start, end)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (start != end && *start == '-') {
|
||||
// End of data.
|
||||
if (!mFormData) {
|
||||
mFormData = new FormData();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!PushOverLine(start)) {
|
||||
return false;
|
||||
}
|
||||
mState = PARSE_HEADER;
|
||||
break;
|
||||
|
||||
case PARSE_HEADER:
|
||||
bool emptyHeader;
|
||||
if (!ParseHeader(start, end, &emptyHeader)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (emptyHeader && !PushOverLine(start)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
mState = emptyHeader ? PARSE_BODY : PARSE_HEADER;
|
||||
break;
|
||||
|
||||
case PARSE_BODY:
|
||||
if (mName.IsVoid()) {
|
||||
NS_WARNING("No content-disposition header with a valid name was "
|
||||
"found. Failing at body parse.");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!ParseBody(boundaryString, start, end)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
mState = START_PART;
|
||||
break;
|
||||
|
||||
default:
|
||||
MOZ_CRASH("Invalid case");
|
||||
}
|
||||
}
|
||||
|
||||
NS_NOTREACHED("Should never reach here.");
|
||||
return false;
|
||||
}
|
||||
|
||||
already_AddRefed<FormData> GetFormData()
|
||||
{
|
||||
return mFormData.forget();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
// static
|
||||
already_AddRefed<FormData>
|
||||
FetchUtil::ConsumeFormData(nsIGlobalObject* aParent, const nsCString& aMimeType,
|
||||
const nsCString& aStr, ErrorResult& aRv)
|
||||
{
|
||||
NS_NAMED_LITERAL_CSTRING(formDataMimeType, "multipart/form-data");
|
||||
|
||||
// Allow semicolon separated boundary/encoding suffix like multipart/form-data; boundary=
|
||||
// but disallow multipart/form-datafoobar.
|
||||
bool isValidFormDataMimeType = StringBeginsWith(aMimeType, formDataMimeType);
|
||||
|
||||
if (isValidFormDataMimeType && aMimeType.Length() > formDataMimeType.Length()) {
|
||||
isValidFormDataMimeType = aMimeType[formDataMimeType.Length()] == ';';
|
||||
}
|
||||
|
||||
if (isValidFormDataMimeType) {
|
||||
FormDataParser parser(aMimeType, aStr, aParent);
|
||||
if (!parser.Parse()) {
|
||||
aRv.ThrowTypeError<MSG_BAD_FORMDATA>();
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
RefPtr<FormData> fd = parser.GetFormData();
|
||||
MOZ_ASSERT(fd);
|
||||
return fd.forget();
|
||||
}
|
||||
|
||||
NS_NAMED_LITERAL_CSTRING(urlDataMimeType, "application/x-www-form-urlencoded");
|
||||
bool isValidUrlEncodedMimeType = StringBeginsWith(aMimeType, urlDataMimeType);
|
||||
|
||||
if (isValidUrlEncodedMimeType && aMimeType.Length() > urlDataMimeType.Length()) {
|
||||
isValidUrlEncodedMimeType = aMimeType[urlDataMimeType.Length()] == ';';
|
||||
}
|
||||
|
||||
if (isValidUrlEncodedMimeType) {
|
||||
URLParams params;
|
||||
params.ParseInput(aStr);
|
||||
|
||||
RefPtr<FormData> fd = new FormData(aParent);
|
||||
FillFormIterator iterator(fd);
|
||||
DebugOnly<bool> status = params.ForEach(iterator);
|
||||
MOZ_ASSERT(status);
|
||||
|
||||
return fd.forget();
|
||||
}
|
||||
|
||||
aRv.ThrowTypeError<MSG_BAD_FORMDATA>();
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// static
|
||||
nsresult
|
||||
FetchUtil::ConsumeText(uint32_t aInputLength, uint8_t* aInput,
|
||||
nsString& aText)
|
||||
{
|
||||
StreamDecoder decoder;
|
||||
nsresult rv = decoder.AppendText(reinterpret_cast<char*>(aInput),
|
||||
aInputLength);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
aText = decoder.GetText();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// static
|
||||
void
|
||||
FetchUtil::ConsumeJson(JSContext* aCx, JS::MutableHandle<JS::Value> aValue,
|
||||
const nsString& aStr, ErrorResult& aRv)
|
||||
{
|
||||
aRv.MightThrowJSException();
|
||||
|
||||
AutoForceSetExceptionOnContext forceExn(aCx);
|
||||
JS::Rooted<JS::Value> json(aCx);
|
||||
if (!JS_ParseJSON(aCx, aStr.get(), aStr.Length(), &json)) {
|
||||
if (!JS_IsExceptionPending(aCx)) {
|
||||
aRv.Throw(NS_ERROR_DOM_UNKNOWN_ERR);
|
||||
return;
|
||||
}
|
||||
|
||||
JS::Rooted<JS::Value> exn(aCx);
|
||||
DebugOnly<bool> gotException = JS_GetPendingException(aCx, &exn);
|
||||
MOZ_ASSERT(gotException);
|
||||
|
||||
JS_ClearPendingException(aCx);
|
||||
aRv.ThrowJSException(aCx, exn);
|
||||
return;
|
||||
}
|
||||
|
||||
aValue.set(json);
|
||||
}
|
||||
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
@ -26,46 +26,6 @@ public:
|
||||
static nsresult
|
||||
GetValidRequestMethod(const nsACString& aMethod, nsCString& outMethod);
|
||||
|
||||
/**
|
||||
* Creates an array buffer from an array, assigning the result to |aValue|.
|
||||
* The array buffer takes ownership of |aInput|, which must be allocated
|
||||
* by |malloc|.
|
||||
*/
|
||||
static void
|
||||
ConsumeArrayBuffer(JSContext* aCx, JS::MutableHandle<JSObject*> aValue,
|
||||
uint32_t aInputLength, uint8_t* aInput, ErrorResult& aRv);
|
||||
|
||||
/**
|
||||
* Creates an in-memory blob from an array. The blob takes ownership of
|
||||
* |aInput|, which must be allocated by |malloc|.
|
||||
*/
|
||||
static already_AddRefed<Blob>
|
||||
ConsumeBlob(nsISupports* aParent, const nsString& aMimeType,
|
||||
uint32_t aInputLength, uint8_t* aInput, ErrorResult& aRv);
|
||||
|
||||
/**
|
||||
* Creates a form data object from a UTF-8 encoded |aStr|. Returns |nullptr|
|
||||
* and sets |aRv| to MSG_BAD_FORMDATA if |aStr| contains invalid data.
|
||||
*/
|
||||
static already_AddRefed<FormData>
|
||||
ConsumeFormData(nsIGlobalObject* aParent, const nsCString& aMimeType,
|
||||
const nsCString& aStr, ErrorResult& aRv);
|
||||
|
||||
/**
|
||||
* UTF-8 decodes |aInput| into |aText|. The caller may free |aInput|
|
||||
* once this method returns.
|
||||
*/
|
||||
static nsresult
|
||||
ConsumeText(uint32_t aInputLength, uint8_t* aInput, nsString& aText);
|
||||
|
||||
/**
|
||||
* Parses a UTF-8 encoded |aStr| as JSON, assigning the result to |aValue|.
|
||||
* Sets |aRv| to a syntax error if |aStr| contains invalid data.
|
||||
*/
|
||||
static void
|
||||
ConsumeJson(JSContext* aCx, JS::MutableHandle<JS::Value> aValue,
|
||||
const nsString& aStr, ErrorResult& aRv);
|
||||
|
||||
/**
|
||||
* Extracts an HTTP header from a substring range.
|
||||
*/
|
||||
|
@ -180,10 +180,7 @@ HTMLLinkElement::BindToTree(nsIDocument* aDocument, nsIContent* aParent,
|
||||
}
|
||||
|
||||
if (IsInComposedDoc()) {
|
||||
UpdatePreconnect();
|
||||
if (HasDNSPrefetchRel()) {
|
||||
TryDNSPrefetch();
|
||||
}
|
||||
TryDNSPrefetchPreconnectOrPrefetch();
|
||||
}
|
||||
|
||||
void (HTMLLinkElement::*update)() = &HTMLLinkElement::UpdateStyleSheetInternal;
|
||||
@ -217,6 +214,7 @@ HTMLLinkElement::UnbindFromTree(bool aDeep, bool aNullParent)
|
||||
// mCachedURI based on data that is invalid - due to a call to GetHostname.
|
||||
CancelDNSPrefetch(HTML_LINK_DNS_PREFETCH_DEFERRED,
|
||||
HTML_LINK_DNS_PREFETCH_REQUESTED);
|
||||
CancelPrefetch();
|
||||
|
||||
// If this link is ever reinserted into a document, it might
|
||||
// be under a different xml:base, so forget the cached state now.
|
||||
@ -344,41 +342,6 @@ HTMLLinkElement::UpdateImport()
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
HTMLLinkElement::UpdatePreconnect()
|
||||
{
|
||||
// rel type should be preconnect
|
||||
nsAutoString rel;
|
||||
if (!GetAttr(kNameSpaceID_None, nsGkAtoms::rel, rel)) {
|
||||
return;
|
||||
}
|
||||
|
||||
uint32_t linkTypes = nsStyleLinkElement::ParseLinkTypes(rel, NodePrincipal());
|
||||
if (!(linkTypes & ePRECONNECT)) {
|
||||
return;
|
||||
}
|
||||
|
||||
nsIDocument *owner = OwnerDoc();
|
||||
if (owner) {
|
||||
nsCOMPtr<nsIURI> uri = GetHrefURI();
|
||||
if (uri) {
|
||||
owner->MaybePreconnect(uri, GetCORSMode());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
HTMLLinkElement::HasDNSPrefetchRel()
|
||||
{
|
||||
nsAutoString rel;
|
||||
if (GetAttr(kNameSpaceID_None, nsGkAtoms::rel, rel)) {
|
||||
return !!(ParseLinkTypes(rel, NodePrincipal()) &
|
||||
nsStyleLinkElement::eDNS_PREFETCH);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
nsresult
|
||||
HTMLLinkElement::BeforeSetAttr(int32_t aNameSpaceID, nsIAtom* aName,
|
||||
nsAttrValueOrString* aValue, bool aNotify)
|
||||
@ -387,6 +350,7 @@ HTMLLinkElement::BeforeSetAttr(int32_t aNameSpaceID, nsIAtom* aName,
|
||||
(aName == nsGkAtoms::href || aName == nsGkAtoms::rel)) {
|
||||
CancelDNSPrefetch(HTML_LINK_DNS_PREFETCH_DEFERRED,
|
||||
HTML_LINK_DNS_PREFETCH_REQUESTED);
|
||||
CancelPrefetch();
|
||||
}
|
||||
|
||||
return nsGenericHTMLElement::BeforeSetAttr(aNameSpaceID, aName,
|
||||
@ -427,21 +391,16 @@ HTMLLinkElement::AfterSetAttr(int32_t aNameSpaceID, nsIAtom* aName,
|
||||
dropSheet = !(linkTypes & nsStyleLinkElement::eSTYLESHEET);
|
||||
} else if (linkTypes & eHTMLIMPORT) {
|
||||
UpdateImport();
|
||||
} else if ((linkTypes & ePRECONNECT) && IsInComposedDoc()) {
|
||||
UpdatePreconnect();
|
||||
}
|
||||
}
|
||||
|
||||
if (aName == nsGkAtoms::href) {
|
||||
UpdateImport();
|
||||
if (IsInComposedDoc()) {
|
||||
UpdatePreconnect();
|
||||
}
|
||||
}
|
||||
|
||||
if ((aName == nsGkAtoms::rel || aName == nsGkAtoms::href) &&
|
||||
HasDNSPrefetchRel() && IsInComposedDoc()) {
|
||||
TryDNSPrefetch();
|
||||
IsInComposedDoc()) {
|
||||
TryDNSPrefetchPreconnectOrPrefetch();
|
||||
}
|
||||
|
||||
UpdateStyleSheetInternal(nullptr, nullptr,
|
||||
|
@ -44,7 +44,6 @@ public:
|
||||
void LinkRemoved();
|
||||
|
||||
void UpdateImport();
|
||||
void UpdatePreconnect();
|
||||
|
||||
// nsIDOMEventTarget
|
||||
virtual nsresult PreHandleEvent(EventChainPreVisitor& aVisitor) override;
|
||||
@ -174,8 +173,6 @@ protected:
|
||||
virtual void GetItemValueText(DOMString& text) override;
|
||||
virtual void SetItemValueText(const nsAString& text) override;
|
||||
|
||||
bool HasDNSPrefetchRel();
|
||||
|
||||
RefPtr<nsDOMTokenList > mRelList;
|
||||
private:
|
||||
RefPtr<ImportLoader> mImportLoader;
|
||||
|
@ -2492,6 +2492,9 @@ nsGenericHTMLFormElement::IsElementDisabledForEvents(EventMessage aMessage,
|
||||
case ePointerOut:
|
||||
case ePointerEnter:
|
||||
case ePointerLeave:
|
||||
case eWheel:
|
||||
case eLegacyMouseLineOrPageScroll:
|
||||
case eLegacyMousePixelScroll:
|
||||
return false;
|
||||
default:
|
||||
break;
|
||||
|
@ -943,7 +943,7 @@ public:
|
||||
RefPtr<WorkerPermissionOperationCompleted> runnable =
|
||||
new WorkerPermissionOperationCompleted(mWorkerPrivate, this);
|
||||
|
||||
MOZ_ALWAYS_TRUE(runnable->Dispatch(nullptr));
|
||||
MOZ_ALWAYS_TRUE(runnable->Dispatch());
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -334,6 +334,55 @@ IDBKeyRange::GetUpper(JSContext* aCx, JS::MutableHandle<JS::Value> aResult,
|
||||
aResult.set(mCachedUpperVal);
|
||||
}
|
||||
|
||||
bool
|
||||
IDBKeyRange::Includes(JSContext* aCx,
|
||||
JS::Handle<JS::Value> aValue,
|
||||
ErrorResult& aRv) const
|
||||
{
|
||||
Key key;
|
||||
aRv = GetKeyFromJSVal(aCx, aValue, key);
|
||||
if (aRv.Failed()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
switch (Key::CompareKeys(Lower(), key)) {
|
||||
case 1:
|
||||
return false;
|
||||
case 0:
|
||||
// Identical keys.
|
||||
if (LowerOpen()) {
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
case -1:
|
||||
if (IsOnly()) {
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
MOZ_CRASH();
|
||||
}
|
||||
|
||||
if (!IsOnly()) {
|
||||
switch (Key::CompareKeys(key, Upper())) {
|
||||
case 1:
|
||||
return false;
|
||||
case 0:
|
||||
// Identical keys.
|
||||
if (UpperOpen()) {
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
case -1:
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
MOZ_ASSERT(key == Lower());
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// static
|
||||
already_AddRefed<IDBKeyRange>
|
||||
IDBKeyRange::Only(const GlobalObject& aGlobal,
|
||||
|
@ -125,6 +125,11 @@ public:
|
||||
return mIsOnly ? mLower : mUpper;
|
||||
}
|
||||
|
||||
bool
|
||||
Includes(JSContext* aCx,
|
||||
JS::Handle<JS::Value> aKey,
|
||||
ErrorResult& aRv) const;
|
||||
|
||||
bool
|
||||
IsOnly() const
|
||||
{
|
||||
|
@ -235,7 +235,7 @@ public:
|
||||
SetFromValueArray(mozIStorageValueArray* aValues, uint32_t aIndex);
|
||||
|
||||
static int16_t
|
||||
CompareKeys(Key& aFirst, Key& aSecond)
|
||||
CompareKeys(const Key& aFirst, const Key& aSecond)
|
||||
{
|
||||
int32_t result = Compare(aFirst.mBuffer, aSecond.mBuffer);
|
||||
|
||||
|
@ -13,7 +13,7 @@
|
||||
* http://www.w3.org/TR/DOM-Level-2-Events/
|
||||
*/
|
||||
|
||||
[builtinclass, uuid(7e9a1eff-2007-45f9-8f28-cc47a7b80bd5)]
|
||||
[builtinclass, uuid(5bdab8d8-7933-4c5c-b6d1-ab34481237f7)]
|
||||
interface nsIDOMMouseEvent : nsIDOMUIEvent
|
||||
{
|
||||
readonly attribute long screenX;
|
||||
@ -34,6 +34,23 @@ interface nsIDOMMouseEvent : nsIDOMUIEvent
|
||||
readonly attribute unsigned short buttons;
|
||||
readonly attribute nsIDOMEventTarget relatedTarget;
|
||||
|
||||
void initMouseEvent(in DOMString typeArg,
|
||||
in boolean canBubbleArg,
|
||||
in boolean cancelableArg,
|
||||
in mozIDOMWindow viewArg,
|
||||
in long detailArg,
|
||||
in long screenXArg,
|
||||
in long screenYArg,
|
||||
in long clientXArg,
|
||||
in long clientYArg,
|
||||
in boolean ctrlKeyArg,
|
||||
in boolean altKeyArg,
|
||||
in boolean shiftKeyArg,
|
||||
in boolean metaKeyArg,
|
||||
in unsigned short buttonArg,
|
||||
in nsIDOMEventTarget relatedTargetArg);
|
||||
|
||||
|
||||
// Finger or touch pressure event value
|
||||
// ranges between 0.0 and 1.0
|
||||
readonly attribute float mozPressure;
|
||||
|
@ -19,7 +19,6 @@ interface nsINotificationStorageCallback : nsISupports
|
||||
* @param body: the notification body
|
||||
* @param tag: the notification tag
|
||||
*/
|
||||
[implicit_jscontext]
|
||||
void handle(in DOMString id,
|
||||
in DOMString title,
|
||||
in DOMString dir,
|
||||
@ -35,7 +34,6 @@ interface nsINotificationStorageCallback : nsISupports
|
||||
* Callback function used to notify C++ the we have returned
|
||||
* all notification objects for this Notification.get call.
|
||||
*/
|
||||
[implicit_jscontext]
|
||||
void done();
|
||||
};
|
||||
|
||||
|
@ -102,6 +102,7 @@
|
||||
#include "nsISpellChecker.h"
|
||||
#include "nsClipboardProxy.h"
|
||||
#include "nsISystemMessageCache.h"
|
||||
#include "nsDirectoryService.h"
|
||||
#include "nsDirectoryServiceUtils.h"
|
||||
#include "nsDirectoryServiceDefs.h"
|
||||
#include "nsContentPermissionHelper.h"
|
||||
@ -1410,12 +1411,29 @@ StartMacOSContentSandbox()
|
||||
MOZ_CRASH("Error resolving child process path");
|
||||
}
|
||||
|
||||
// During sandboxed content process startup, before reaching
|
||||
// this point, NS_OS_TEMP_DIR is modified to refer to a sandbox-
|
||||
// writable temporary directory
|
||||
nsCOMPtr<nsIFile> tempDir;
|
||||
nsresult rv = nsDirectoryService::gService->Get(NS_OS_TEMP_DIR,
|
||||
NS_GET_IID(nsIFile), getter_AddRefs(tempDir));
|
||||
if (NS_FAILED(rv)) {
|
||||
MOZ_CRASH("Failed to get NS_OS_TEMP_DIR");
|
||||
}
|
||||
|
||||
nsAutoCString tempDirPath;
|
||||
rv = tempDir->GetNativePath(tempDirPath);
|
||||
if (NS_FAILED(rv)) {
|
||||
MOZ_CRASH("Failed to get NS_OS_TEMP_DIR path");
|
||||
}
|
||||
|
||||
MacSandboxInfo info;
|
||||
info.type = MacSandboxType_Content;
|
||||
info.level = Preferences::GetInt("security.sandbox.content.level");
|
||||
info.appPath.assign(appPath.get());
|
||||
info.appBinaryPath.assign(appBinaryPath.get());
|
||||
info.appDir.assign(appDir.get());
|
||||
info.appTempDir.assign(tempDirPath.get());
|
||||
|
||||
std::string err;
|
||||
if (!mozilla::StartMacSandbox(info, err)) {
|
||||
|
@ -9,8 +9,11 @@
|
||||
#include "ContentProcess.h"
|
||||
|
||||
#if defined(XP_WIN) && defined(MOZ_CONTENT_SANDBOX)
|
||||
#include "mozilla/Preferences.h"
|
||||
#include "mozilla/WindowsVersion.h"
|
||||
#endif
|
||||
|
||||
#if (defined(XP_WIN) || defined(XP_MACOSX)) && defined(MOZ_CONTENT_SANDBOX)
|
||||
#include "mozilla/Preferences.h"
|
||||
#include "nsDirectoryService.h"
|
||||
#include "nsDirectoryServiceDefs.h"
|
||||
#endif
|
||||
@ -21,29 +24,60 @@ namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
#if defined(XP_WIN) && defined(MOZ_CONTENT_SANDBOX)
|
||||
static bool
|
||||
IsSandboxTempDirRequired()
|
||||
{
|
||||
// On Windows, a sandbox-writable temp directory is only used
|
||||
// for Vista or later with sandbox pref level >= 1.
|
||||
return (IsVistaOrLater() &&
|
||||
(Preferences::GetInt("security.sandbox.content.level") >= 1));
|
||||
}
|
||||
|
||||
static const char*
|
||||
SandboxTempDirParent()
|
||||
{
|
||||
// On Windows, the sandbox-writable temp directory resides in the
|
||||
// low integrity sandbox base directory.
|
||||
return NS_WIN_LOW_INTEGRITY_TEMP_BASE;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(XP_MACOSX) && defined(MOZ_CONTENT_SANDBOX)
|
||||
static bool
|
||||
IsSandboxTempDirRequired()
|
||||
{
|
||||
// On OSX, use the sandbox-writable temp when the pref level >= 1.
|
||||
return (Preferences::GetInt("security.sandbox.content.level") >= 1);
|
||||
}
|
||||
|
||||
static const char*
|
||||
SandboxTempDirParent()
|
||||
{
|
||||
return NS_OS_TEMP_DIR;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if (defined(XP_WIN) || defined(XP_MACOSX)) && defined(MOZ_CONTENT_SANDBOX)
|
||||
static void
|
||||
SetUpSandboxEnvironment()
|
||||
{
|
||||
MOZ_ASSERT(nsDirectoryService::gService,
|
||||
"SetUpSandboxEnvironment relies on nsDirectoryService being initialized");
|
||||
|
||||
// A low integrity temp only currently makes sense for Vista or Later and
|
||||
// sandbox pref level >= 1.
|
||||
if (!IsVistaOrLater() ||
|
||||
Preferences::GetInt("security.sandbox.content.level") < 1) {
|
||||
if (!IsSandboxTempDirRequired()) {
|
||||
return;
|
||||
}
|
||||
|
||||
nsAdoptingString tempDirSuffix =
|
||||
Preferences::GetString("security.sandbox.content.tempDirSuffix");
|
||||
if (tempDirSuffix.IsEmpty()) {
|
||||
NS_WARNING("Low integrity temp suffix pref not set.");
|
||||
NS_WARNING("Sandbox-writable temp directory suffix pref not set.");
|
||||
return;
|
||||
}
|
||||
|
||||
// Get the base low integrity Mozilla temp directory.
|
||||
// Get the parent of our sandbox writable temp directory.
|
||||
nsCOMPtr<nsIFile> lowIntegrityTemp;
|
||||
nsresult rv = nsDirectoryService::gService->Get(NS_WIN_LOW_INTEGRITY_TEMP_BASE,
|
||||
nsresult rv = nsDirectoryService::gService->Get(SandboxTempDirParent(),
|
||||
NS_GET_IID(nsIFile),
|
||||
getter_AddRefs(lowIntegrityTemp));
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
@ -56,7 +90,7 @@ SetUpSandboxEnvironment()
|
||||
return;
|
||||
}
|
||||
|
||||
// Change the gecko defined temp directory to our low integrity one.
|
||||
// Change the gecko defined temp directory to our sandbox-writable one.
|
||||
// Undefine returns a failure if the property is not already set.
|
||||
Unused << nsDirectoryService::gService->Undefine(NS_OS_TEMP_DIR);
|
||||
rv = nsDirectoryService::gService->Set(NS_OS_TEMP_DIR, lowIntegrityTemp);
|
||||
@ -82,10 +116,10 @@ ContentProcess::Init()
|
||||
mContent.InitXPCOM();
|
||||
mContent.InitGraphicsDeviceData();
|
||||
|
||||
#if defined(XP_WIN) && defined(MOZ_CONTENT_SANDBOX)
|
||||
#if (defined(XP_WIN) || defined(XP_MACOSX)) && defined(MOZ_CONTENT_SANDBOX)
|
||||
SetUpSandboxEnvironment();
|
||||
#endif
|
||||
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user