merge mozilla-inbound to mozilla-central a=merge

This commit is contained in:
Carsten "Tomcat" Book 2016-02-29 11:35:30 +01:00
commit add1a88604
1082 changed files with 6649 additions and 13881 deletions

View File

@ -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();

View File

@ -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;
};

View File

@ -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));

View File

@ -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

View File

@ -359,9 +359,6 @@ protected:
void LastRelease();
// Accessible
virtual void CacheChildren() override;
// DocAccessible
virtual nsresult AddEventListeners();
virtual nsresult RemoveEventListeners();

View File

@ -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
////////////////////////////////////////////////////////////////////////////////

View File

@ -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;
};
/*

View File

@ -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;

View File

@ -102,7 +102,7 @@
}
}
// gA11yEventDumpToConsole = true;
//gA11yEventDumpToConsole = true;
function doTest()
{

View File

@ -42,5 +42,4 @@ skip-if = true
[tab-close-on-startup.xpi]
[toolkit-require-reload.xpi]
[translators.xpi]
[unpacked.xpi]
[unsafe-content-script.xpi]

View File

@ -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});

View File

@ -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);

View File

@ -1,6 +0,0 @@
{
"id": "test-url@jetpack",
"unpack": true,
"main": "./main.js",
"version": "0.0.1"
}

View File

@ -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.

View File

@ -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

View File

@ -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>

View File

@ -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>

View File

@ -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")

View File

@ -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');
}

View File

@ -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');"

View File

@ -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);
}
});

View File

@ -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) {

View File

@ -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) {

View File

@ -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]

View 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");
});
});

View File

@ -0,0 +1,6 @@
<!doctype html>
<html>
<script>
sessionStorage
</script>
</html>

View File

@ -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

View File

@ -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) -->

View File

@ -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">

View File

@ -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.

View File

@ -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>">

View File

@ -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 -)

View File

@ -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 -->

View File

@ -15,3 +15,7 @@ FINAL_TARGET_PP_FILES += [
'bootstrap.js',
'install.rdf',
]
TEST_HARNESS_FILES.testing.mochitest.extensions += [
'mozscreenshots-signed.xpi',
]

View File

@ -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.

View File

@ -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.

View File

@ -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

View File

@ -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

View File

@ -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,

View File

@ -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

View File

@ -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) {

View File

@ -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

View File

@ -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

View File

@ -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;

View File

@ -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

View File

@ -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

View File

@ -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();

View File

@ -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>

View File

@ -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
View 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
View 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

View File

@ -371,7 +371,7 @@ private:
RefPtr<WorkerControlRunnable> runnable =
new ConsoleReleaseRunnable(mWorkerPrivate, this);
runnable->Dispatch(nullptr);
runnable->Dispatch();
}
void

View File

@ -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)
{

View File

@ -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();

View File

@ -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;
}

View File

@ -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',

View File

@ -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

View File

@ -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)
{

View File

@ -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

View File

@ -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);

View File

@ -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;

View File

@ -60,10 +60,6 @@ NS_GetDOMClassInfoInstance(nsDOMClassInfoID aID);
} \
} else
#else
// See nsIDOMClassInfo.h
#endif // MOZILLA_INTERNAL_API
#endif // nsDOMClassInfoID_h__

View File

@ -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);
}

View File

@ -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;
};

View File

@ -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"

View File

@ -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___ */

View File

@ -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__ */

View File

@ -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__ */

View File

@ -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;
}

View File

@ -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);

View File

@ -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);

View File

@ -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

View File

@ -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");

View 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();
});

View File

@ -50,3 +50,4 @@ head = head_xml.js
[test_xml_serializer.js]
head = head_xml.js
[test_xmlserializer.js]
[test_cancelPrefetch.js]

View File

@ -1595,7 +1595,7 @@ DOMInterfaces = {
'headerFile': 'mozilla/dom/WorkerScope.h',
'nativeType': 'mozilla::dom::workers::WorkerDebuggerGlobalScope',
'implicitJSContext': [
'dump', 'global', 'setImmediate', 'reportError',
'dump', 'global', 'reportError',
],
},

View File

@ -73,3 +73,4 @@ skip-if = debug == false
[test_iterable.html]
skip-if = debug == false
[test_oom_reporting.html]
[test_domProxyArrayLengthGetter.html]

View 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>

View File

@ -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' });

View File

@ -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

View File

@ -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;

View File

@ -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.
}
}

View File

@ -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:

View File

@ -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;

View File

@ -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,

View File

@ -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);
}

View File

@ -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

View File

@ -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.
*/

View File

@ -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,

View File

@ -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;

View File

@ -2492,6 +2492,9 @@ nsGenericHTMLFormElement::IsElementDisabledForEvents(EventMessage aMessage,
case ePointerOut:
case ePointerEnter:
case ePointerLeave:
case eWheel:
case eLegacyMouseLineOrPageScroll:
case eLegacyMousePixelScroll:
return false;
default:
break;

View File

@ -943,7 +943,7 @@ public:
RefPtr<WorkerPermissionOperationCompleted> runnable =
new WorkerPermissionOperationCompleted(mWorkerPrivate, this);
MOZ_ALWAYS_TRUE(runnable->Dispatch(nullptr));
MOZ_ALWAYS_TRUE(runnable->Dispatch());
return;
}

View File

@ -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,

View File

@ -125,6 +125,11 @@ public:
return mIsOnly ? mLower : mUpper;
}
bool
Includes(JSContext* aCx,
JS::Handle<JS::Value> aKey,
ErrorResult& aRv) const;
bool
IsOnly() const
{

View File

@ -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);

View File

@ -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;

View File

@ -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();
};

View File

@ -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)) {

View File

@ -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