Merge inbound to central, a=merge

This commit is contained in:
Wes Kocher 2015-06-11 17:02:47 -07:00
Родитель bce194793c 6bced0aeb7
Коммит 2aa142fe5e
1598 изменённых файлов: 26286 добавлений и 6235 удалений

Просмотреть файл

@ -11,6 +11,7 @@
#include "InterfaceInitFuncs.h"
#include "nsAccUtils.h"
#include "mozilla/a11y/PDocAccessible.h"
#include "OuterDocAccessible.h"
#include "ProxyAccessible.h"
#include "RootAccessible.h"
#include "nsMai.h"
@ -96,7 +97,7 @@ static GType GetAtkTypeForMai(MaiInterfaceType type)
return G_TYPE_INVALID;
}
static const char* kNonUserInputEvent = ":system";
#define NON_USER_EVENT ":system"
static const GInterfaceInfo atk_if_infos[] = {
{(GInterfaceInitFunc)componentInterfaceInitCB,
@ -828,26 +829,45 @@ getChildCountCB(AtkObject *aAtkObj)
AtkObject *
refChildCB(AtkObject *aAtkObj, gint aChildIndex)
{
// aChildIndex should not be less than zero
if (aChildIndex < 0) {
// aChildIndex should not be less than zero
if (aChildIndex < 0) {
return nullptr;
}
AtkObject* childAtkObj = nullptr;
AccessibleWrap* accWrap = GetAccessibleWrap(aAtkObj);
if (accWrap) {
if (nsAccUtils::MustPrune(accWrap)) {
return nullptr;
}
AccessibleWrap* accWrap = GetAccessibleWrap(aAtkObj);
if (!accWrap || nsAccUtils::MustPrune(accWrap)) {
return nullptr;
}
Accessible* accChild = accWrap->GetEmbeddedChildAt(aChildIndex);
if (!accChild)
return nullptr;
if (accChild) {
childAtkObj = AccessibleWrap::GetAtkObject(accChild);
} else {
OuterDocAccessible* docOwner = accWrap->AsOuterDoc();
if (docOwner) {
ProxyAccessible* proxyDoc = docOwner->RemoteChildDoc();
if (proxyDoc)
childAtkObj = GetWrapperFor(proxyDoc);
}
}
} else if (ProxyAccessible* proxy = GetProxy(aAtkObj)) {
if (proxy->MustPruneChildren())
return nullptr;
AtkObject* childAtkObj = AccessibleWrap::GetAtkObject(accChild);
ProxyAccessible* child = proxy->EmbeddedChildAt(aChildIndex);
if (child)
childAtkObj = GetWrapperFor(child);
} else {
return nullptr;
}
NS_ASSERTION(childAtkObj, "Fail to get AtkObj");
if (!childAtkObj)
return nullptr;
g_object_ref(childAtkObj);
NS_ASSERTION(childAtkObj, "Fail to get AtkObj");
if (!childAtkObj)
return nullptr;
g_object_ref(childAtkObj);
if (aAtkObj != childAtkObj->accessible_parent)
atk_object_set_parent(childAtkObj, aAtkObj);
@ -1431,6 +1451,21 @@ MaiAtkObject::FireStateChangeEvent(uint64_t aState, bool aEnabled)
}
}
#define OLD_TEXT_INSERTED "text_changed::insert"
#define OLD_TEXT_REMOVED "text_changed::delete"
static const char* oldTextChangeStrings[2][2] = {
{ OLD_TEXT_REMOVED NON_USER_EVENT, OLD_TEXT_INSERTED NON_USER_EVENT },
{ OLD_TEXT_REMOVED, OLD_TEXT_INSERTED }
};
#define TEXT_INSERTED "text-insert"
#define TEXT_REMOVED "text-remove"
#define NON_USER_DETAIL "::system"
static const char* textChangedStrings[2][2] = {
{ TEXT_REMOVED NON_USER_DETAIL, TEXT_INSERTED NON_USER_DETAIL },
{ TEXT_REMOVED, TEXT_INSERTED}
};
nsresult
AccessibleWrap::FireAtkTextChangedEvent(AccEvent* aEvent,
AtkObject* aObject)
@ -1442,7 +1477,6 @@ AccessibleWrap::FireAtkTextChangedEvent(AccEvent* aEvent,
uint32_t length = event->GetLength();
bool isInserted = event->IsTextInserted();
bool isFromUserInput = aEvent->IsFromUserInput();
char* signal_name = nullptr;
if (gAvailableAtkSignals == eUnknown)
gAvailableAtkSignals =
@ -1453,23 +1487,29 @@ AccessibleWrap::FireAtkTextChangedEvent(AccEvent* aEvent,
// XXX remove this code and the gHaveNewTextSignals check when we can
// stop supporting old atk since it doesn't really work anyway
// see bug 619002
signal_name = g_strconcat(isInserted ? "text_changed::insert" :
"text_changed::delete",
isFromUserInput ? "" : kNonUserInputEvent, nullptr);
const char* signal_name =
oldTextChangeStrings[isFromUserInput][isInserted];
g_signal_emit_by_name(aObject, signal_name, start, length);
} else {
nsAutoString text;
event->GetModifiedText(text);
signal_name = g_strconcat(isInserted ? "text-insert" : "text-remove",
isFromUserInput ? "" : "::system", nullptr);
const char* signal_name =
textChangedStrings[isFromUserInput][isInserted];
g_signal_emit_by_name(aObject, signal_name, start, length,
NS_ConvertUTF16toUTF8(text).get());
}
g_free(signal_name);
return NS_OK;
}
#define ADD_EVENT "children_changed::add"
#define HIDE_EVENT "children_changed::remove"
static const char *kMutationStrings[2][2] = {
{ HIDE_EVENT NON_USER_EVENT, ADD_EVENT NON_USER_EVENT },
{ HIDE_EVENT, ADD_EVENT },
};
nsresult
AccessibleWrap::FireAtkShowHideEvent(AccEvent* aEvent,
AtkObject* aObject, bool aIsAdded)
@ -1479,10 +1519,8 @@ AccessibleWrap::FireAtkShowHideEvent(AccEvent* aEvent,
NS_ENSURE_STATE(parentObject);
bool isFromUserInput = aEvent->IsFromUserInput();
char *signal_name = g_strconcat(aIsAdded ? "children_changed::add" : "children_changed::remove",
isFromUserInput ? "" : kNonUserInputEvent, nullptr);
const char *signal_name = kMutationStrings[isFromUserInput][aIsAdded];
g_signal_emit_by_name(parentObject, signal_name, indexInParent, aObject, nullptr);
g_free(signal_name);
return NS_OK;
}

Просмотреть файл

@ -38,6 +38,7 @@ class HTMLLIAccessible;
class HyperTextAccessible;
class ImageAccessible;
class KeyBinding;
class OuterDocAccessible;
class ProxyAccessible;
class Relation;
class RootAccessible;
@ -619,6 +620,9 @@ public:
return mBits.proxy;
}
bool IsOuterDoc() const { return mType == eOuterDocType; }
OuterDocAccessible* AsOuterDoc();
bool IsProgress() const { return mType == eProgressType; }
bool IsRoot() const { return mType == eRootType; }

Просмотреть файл

@ -8,6 +8,8 @@
#include "Accessible-inl.h"
#include "nsAccUtils.h"
#include "DocAccessible-inl.h"
#include "mozilla/a11y/DocAccessibleParent.h"
#include "mozilla/dom/TabParent.h"
#include "Role.h"
#include "States.h"
@ -26,6 +28,7 @@ OuterDocAccessible::
OuterDocAccessible(nsIContent* aContent, DocAccessible* aDoc) :
AccessibleWrap(aContent, aDoc)
{
mType = eOuterDocType;
}
OuterDocAccessible::~OuterDocAccessible()
@ -181,3 +184,24 @@ OuterDocAccessible::CacheChildren()
GetAccService()->GetDocAccessible(innerDoc);
}
}
ProxyAccessible*
OuterDocAccessible::RemoteChildDoc() const
{
dom::TabParent* tab = dom::TabParent::GetFrom(GetContent());
if (!tab)
return nullptr;
// XXX Consider managing non top level remote documents with there parent
// document.
const nsTArray<PDocAccessibleParent*>& docs = tab->ManagedPDocAccessibleParent();
size_t docCount = docs.Length();
for (size_t i = 0; i < docCount; i++) {
auto doc = static_cast<DocAccessibleParent*>(docs[i]);
if (!doc->ParentDoc())
return doc;
}
MOZ_ASSERT(false, "no top level tab document?");
return nullptr;
}

Просмотреть файл

@ -10,6 +10,7 @@
namespace mozilla {
namespace a11y {
class ProxyAccessible;
/**
* Used for <browser>, <frame>, <iframe>, <page> or editor> elements.
@ -27,6 +28,8 @@ public:
NS_DECL_ISUPPORTS_INHERITED
ProxyAccessible* RemoteChildDoc() const;
// Accessible
virtual void Shutdown() override;
virtual mozilla::a11y::role NativeRole() override;
@ -44,6 +47,11 @@ protected:
virtual void CacheChildren() override;
};
inline OuterDocAccessible*
Accessible::AsOuterDoc()
{
return IsOuterDoc() ? static_cast<OuterDocAccessible*>(this) : nullptr;
}
} // namespace a11y
} // namespace mozilla

Просмотреть файл

@ -1637,6 +1637,21 @@ DocAccessibleChild::RecvIndexOfEmbeddedChild(const uint64_t& aID,
return true;
}
bool
DocAccessibleChild::RecvEmbeddedChildAt(const uint64_t& aID,
const uint32_t& aIdx,
uint64_t* aChildID)
{
*aChildID = 0;
Accessible* acc = IdToAccessible(aID);
if (!acc)
return true;
*aChildID = reinterpret_cast<uintptr_t>(acc->GetEmbeddedChildAt(aIdx));
return true;
}
bool
DocAccessibleChild::RecvChildAtPoint(const uint64_t& aID,
const int32_t& aX,

Просмотреть файл

@ -408,6 +408,9 @@ public:
const uint64_t& aChildID,
uint32_t* aChildIdx) override final;
virtual bool RecvEmbeddedChildAt(const uint64_t& aID, const uint32_t& aIdx,
uint64_t* aChildID) override final;
virtual bool RecvChildAtPoint(const uint64_t& aID,
const int32_t& aX,
const int32_t& aY,

Просмотреть файл

@ -213,8 +213,11 @@ DocAccessibleParent::Destroy()
mAccessibles.EnumerateEntries(ShutdownAccessibles, nullptr);
ProxyDestroyed(this);
mParentDoc ? mParentDoc->RemoveChildDoc(this)
: GetAccService()->RemoteDocShutdown(this);
}
}
if (mParentDoc)
mParentDoc->RemoveChildDoc(this);
else if (IsTopLevel())
GetAccService()->RemoteDocShutdown(this);
}
} // a11y
} // mozilla

Просмотреть файл

@ -26,7 +26,8 @@ class DocAccessibleParent : public ProxyAccessible,
{
public:
DocAccessibleParent() :
ProxyAccessible(this), mParentDoc(nullptr), mShutdown(false)
ProxyAccessible(this), mParentDoc(nullptr),
mTopLevel(false), mShutdown(false)
{ MOZ_COUNT_CTOR_INHERITED(DocAccessibleParent, ProxyAccessible); }
~DocAccessibleParent()
{
@ -35,6 +36,9 @@ public:
MOZ_ASSERT(!ParentDoc());
}
void SetTopLevel() { mTopLevel = true; }
bool IsTopLevel() const { return mTopLevel; }
/*
* Called when a message from a document in a child process notifies the main
* process it is firing an event.
@ -151,6 +155,7 @@ private:
* proxy object so we can't use a real map.
*/
nsTHashtable<ProxyEntry> mAccessibles;
bool mTopLevel;
bool mShutdown;
};

Просмотреть файл

@ -218,6 +218,8 @@ child:
prio(high) sync TakeFocus(uint64_t aID);
prio(high) sync IndexOfEmbeddedChild(uint64_t aID, uint64_t aChildID)
returns(uint32_t childIdx);
prio(high) sync EmbeddedChildAt(uint64_t aID, uint32_t aChildIdx)
returns(uint64_t aChild);
prio(high) sync ChildAtPoint(uint64_t aID, int32_t aX, int32_t aY, uint32_t aWhich)
returns(uint64_t aChild, bool aOk);
prio(high) sync Bounds(uint64_t aID) returns(nsIntRect aRect);

Просмотреть файл

@ -916,6 +916,14 @@ ProxyAccessible::IndexOfEmbeddedChild(const ProxyAccessible* aChild)
return childIdx;
}
ProxyAccessible*
ProxyAccessible::EmbeddedChildAt(size_t aChildIdx)
{
uint64_t childID;
unused << mDoc->SendEmbeddedChildAt(mID, aChildIdx, &childID);
return mDoc->GetAccessible(childID);
}
ProxyAccessible*
ProxyAccessible::ChildAtPoint(int32_t aX, int32_t aY,
Accessible::EWhichChildAtPoint aWhichChild)

Просмотреть файл

@ -49,6 +49,7 @@ public:
// XXX evaluate if this is fast enough.
size_t IndexInParent() const { return Parent()->mChildren.IndexOf(this); }
int32_t IndexOfEmbeddedChild(const ProxyAccessible*);
ProxyAccessible* EmbeddedChildAt(size_t aChildIdx);
bool MustPruneChildren() const;
void Shutdown();

Просмотреть файл

@ -600,12 +600,13 @@ struct RoleDescrComparator
{
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NIL;
AccessibleWrap* accWrap = [self getGeckoAccessible];
if (accWrap->IsDefunct())
return nil;
nsAutoString desc;
accWrap->Description(desc);
if (AccessibleWrap* accWrap = [self getGeckoAccessible])
accWrap->Description(desc);
else if (ProxyAccessible* proxy = [self getProxyAccessible])
proxy->Description(desc);
else
return nil;
return nsCocoaUtils::ToNSString(desc);

Просмотреть файл

@ -1004,6 +1004,10 @@ pref("network.proxy.browsing.app_origins", "app://system.gaiamobile.org");
// Enable Web Speech synthesis API
pref("media.webspeech.synth.enabled", true);
// Enable Web Speech recognition API
pref("media.webspeech.recognition.enable", true);
pref("media.webspeech.service.default", "pocketsphinx");
// Downloads API
pref("dom.mozDownloads.enabled", true);
pref("dom.downloads.max_retention_days", 7);

Просмотреть файл

@ -29,13 +29,12 @@ NSS_DISABLE_DBM=1
MOZ_NO_EV_CERTS=1
MOZ_DISABLE_EXPORT_JS=1
# Bug 1171082 - Broken on Windows B2G Desktop
if test "$OS_TARGET" != "WINNT"; then
MOZ_WEBSPEECH=1
if test -n "$NIGHTLY_BUILD"; then
MOZ_WEBSPEECH_MODELS=1
MOZ_WEBSPEECH_POCKETSPHINX=1
fi
MOZ_WEBSPEECH_TEST_BACKEND=1
fi # !WINNT
if test "$OS_TARGET" = "Android"; then
MOZ_CAPTURE=1

Просмотреть файл

@ -1235,9 +1235,14 @@
<svg:svg height="0">
#include tab-shape.inc.svg
#if defined(XP_UNIX) && !defined(XP_MACOSX)
<svg:clipPath id="urlbar-clip-path" clipPathUnits="userSpaceOnUse">
<svg:path d="m 1,-5 l 0,50 l 10000,0 l 0,-50 z"/>
</svg:clipPath>
#endif
<svg:clipPath id="urlbar-back-button-clip-path" clipPathUnits="userSpaceOnUse">
#ifndef XP_MACOSX
<svg:path d="m 1,-5 l 0,7.8 c 2.5,3.2 4,6.2 4,10.2 c 0,4 -1.5,7 -4,10 l 0,22l10000,0 l 0,-50 l -10000,0 z"/>
<svg:path d="m 1,-5 l 0,7.8 c 2.5,3.2 4,6.2 4,10.2 c 0,4 -1.5,7 -4,10 l 0,22 l 10000,0 l 0,-50 l -10000,0 z"/>
#else
<svg:path d="M -11,-5 a 16 16 0 0 1 0,34 l 10000,0 l 0,-34 l -10000,0 z"/>
#endif

Просмотреть файл

@ -107,7 +107,8 @@ a setTimeout.
## GarbageCollection
Emitted after a full GC has occurred (which will emit past incremental events).
Emitted after a full GC cycle has completed (which is after any number of
incremental slices).
* DOMString causeName - The reason for a GC event to occur. A full list of
GC reasons can be found [on MDN](https://developer.mozilla.org/en-US/docs/Tools/Debugger-API/Debugger.Memory#Debugger.Memory_Handler_Functions).
@ -115,6 +116,17 @@ Emitted after a full GC has occurred (which will emit past incremental events).
GC (smaller, quick GC events), and we have to walk the entire heap and
GC everything marked, then the reason listed here is why.
## nsCycleCollector::Collect
An `nsCycleCollector::Collect` marker is emitted for each incremental cycle
collection slice and each non-incremental cycle collection.
# nsCycleCollector::ForgetSkippable
`nsCycleCollector::ForgetSkippable` is presented as "Cycle Collection", but in
reality it is preparation/pre-optimization for cycle collection, and not the
actual tracing of edges and collecting of cycles.
## ConsoleTime
A marker generated via `console.time()` and `console.timeEnd()`.

Просмотреть файл

@ -435,6 +435,13 @@ const Formatters = {
return { "Restyle Hint": marker.restyleHint.replace(/eRestyle_/g, "") };
}
},
CycleCollectionFields: function (marker) {
let Type = PREFS["show-platform-data"]
? marker.name
: marker.name.replace(/nsCycleCollector::/g, "");
return { Type };
},
};
exports.getMarkerLabel = getMarkerLabel;

Просмотреть файл

@ -113,6 +113,20 @@ const TIMELINE_BLUEPRINT = {
{ property: "nonincrementalReason", label: "Non-incremental Reason:" }
],
},
"nsCycleCollector::Collect": {
group: 1,
colorName: "graphs-red",
collapseFunc: either(collapse.parent, collapse.child),
label: "Cycle Collection",
fields: Formatters.CycleCollectionFields,
},
"nsCycleCollector::ForgetSkippable": {
group: 1,
colorName: "graphs-red",
collapseFunc: either(collapse.parent, collapse.child),
label: "Cycle Collection",
fields: Formatters.CycleCollectionFields,
},
/* Group 2 - User Controlled */
"ConsoleTime": {

Просмотреть файл

@ -2,6 +2,7 @@
tags = devtools
subsuite = devtools
support-files =
doc_force_cc.html
doc_force_gc.html
doc_innerHTML.html
doc_markers.html
@ -13,6 +14,7 @@ support-files =
[browser_aaa-run-first-leaktest.js]
[browser_marker-utils.js]
[browser_markers-cycle-collection.js]
[browser_markers-gc.js]
[browser_markers-parse-html.js]
[browser_markers-styles.js]

Просмотреть файл

@ -0,0 +1,50 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
/**
* Test that we get "nsCycleCollector::Collect" and
* "nsCycleCollector::ForgetSkippable" markers when we force cycle collection.
*/
const TEST_URL = EXAMPLE_URL + "doc_force_cc.html"
function waitForMarkerType(front, type) {
info("Waiting for marker of type = " + type);
const { promise, resolve } = Promise.defer();
const handler = (_, name, markers) => {
if (name !== "markers") {
return;
}
info("Got markers: " + JSON.stringify(markers, null, 2));
if (markers.some(m => m.name === type)) {
ok(true, "Found marker of type = " + type);
front.off("timeline-data", handler);
resolve();
}
};
front.on("timeline-data", handler);
return promise;
}
function* spawnTest () {
// This test runs very slowly on linux32 debug EC2 instances.
requestLongerTimeout(2);
let { target, front } = yield initBackend(TEST_URL);
yield front.startRecording({ withMarkers: true, withTicks: true });
yield Promise.all([
waitForMarkerType(front, "nsCycleCollector::Collect"),
waitForMarkerType(front, "nsCycleCollector::ForgetSkippable")
]);
ok(true, "Got expected cycle collection events");
yield front.stopRecording();
yield removeTab(target.tab);
finish();
}

Просмотреть файл

@ -0,0 +1,29 @@
<!-- Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ -->
<!doctype html>
<html>
<head>
<meta charset="utf-8"/>
<title>Performance tool + cycle collection test page</title>
</head>
<body>
<script type="text/javascript">
window.test = function () {
document.body.expando1 = { cycle: document.body };
SpecialPowers.Cu.forceCC();
document.body.expando2 = { cycle: document.body };
SpecialPowers.Cu.forceCC();
document.body.expando3 = { cycle: document.body };
SpecialPowers.Cu.forceCC();
setTimeout(window.test, 100);
};
test();
</script>
</body>
</html>

Просмотреть файл

@ -1,6 +1,6 @@
[DEFAULT]
tags = devtools
skip-if = buildapp == 'b2g'
skip-if = buildapp == 'b2g' || (os == "mac" && (os_version == "10.8" || os_version == "10.10") && debug) # Bug 1135315 - assertions
support-files =
app/index.html
app/manifest.webapp

Просмотреть файл

@ -1,6 +1,6 @@
[DEFAULT]
tags = devtools
skip-if = buildapp == 'b2g'
skip-if = buildapp == 'b2g' || (os == "mac" && (os_version == "10.8" || os_version == "10.10") && debug) # Bug 1135315 - assertions
support-files =
../app/index.html
../app/manifest.webapp

Просмотреть файл

@ -313,6 +313,7 @@ let ProcessHangMonitor = {
for (let [otherReport, otherTimer] of this._activeReports) {
if (otherTimer === timer) {
this.removeReport(otherReport);
otherReport.userCanceled();
break;
}
}

Просмотреть файл

@ -680,17 +680,17 @@ toolbarbutton[constrain-size="true"][cui-areatype="toolbar"] > .toolbarbutton-ba
}
#back-button {
padding-top: 3px;
padding-bottom: 3px;
-moz-padding-start: 5px;
-moz-padding-end: 0;
margin-top: 3px;
margin-bottom: 3px;
-moz-margin-start: 5px;
padding: 0;
position: relative;
z-index: 1;
border-radius: 0 10000px 10000px 0;
border-radius: 10000px;
}
#back-button:-moz-locale-dir(rtl) {
border-radius: 10000px 0 0 10000px;
#back-button:not(:-moz-lwtheme) {
background-color: -moz-dialog;
}
#back-button > menupopup {
@ -894,13 +894,17 @@ toolbarbutton[constrain-size="true"][cui-areatype="toolbar"] > .toolbarbutton-ba
}
@conditionalForwardWithUrlbar@ {
clip-path: url("chrome://browser/content/browser.xul#urlbar-back-button-clip-path");
clip-path: url("chrome://browser/content/browser.xul#urlbar-clip-path");
-moz-margin-start: -5px;
}
@conditionalForwardWithUrlbar@:-moz-lwtheme {
clip-path: url("chrome://browser/content/browser.xul#urlbar-back-button-clip-path");
}
@conditionalForwardWithUrlbar@:-moz-locale-dir(rtl),
@conditionalForwardWithUrlbar@ > #urlbar:-moz-locale-dir(rtl) {
/* let urlbar-back-button-clip-path clip the urlbar's right side for RTL */
/* Let clip-path clip the urlbar-wrapper's right side for RTL. */
transform: scaleX(-1);
}

Просмотреть файл

@ -5132,11 +5132,6 @@ fi
dnl ========================================================
dnl = Disable Speech API pocketsphinx backend
dnl ========================================================
MOZ_ARG_DISABLE_BOOL(webspeechpocketsphinx,
[ --disable-webspeechpocketsphinx Disable support for HTML Speech API Pocketsphinx Backend],
MOZ_WEBSPEECH_POCKETSPHINX=,
MOZ_WEBSPEECH_POCKETSPHINX=1)
if test -n "$MOZ_WEBSPEECH_POCKETSPHINX"; then
AC_DEFINE(MOZ_WEBSPEECH_POCKETSPHINX)
fi
@ -5178,11 +5173,6 @@ AC_SUBST(MOZ_WEBSPEECH_TEST_BACKEND)
dnl ========================================================
dnl = Disable Speech API models
dnl ========================================================
MOZ_ARG_DISABLE_BOOL(webspeechmodels,
[ --disable-webspeechmodels Disable support for HTML Speech API Models],
MOZ_WEBSPEECH_MODELS=,
MOZ_WEBSPEECH_MODELS=1)
if test -z "$MOZ_WEBSPEECH"; then
MOZ_WEBSPEECH_MODELS=
fi

Просмотреть файл

@ -0,0 +1,105 @@
/* -*- 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/. */
#include "mozilla/AutoTimelineMarker.h"
#include "MainThreadUtils.h"
#include "nsDocShell.h"
#include "mozilla/Move.h"
namespace mozilla {
bool
AutoTimelineMarker::DocShellIsRecording(nsDocShell& aDocShell)
{
bool isRecording = false;
if (nsDocShell::gProfileTimelineRecordingsCount > 0) {
aDocShell.GetRecordProfileTimelineMarkers(&isRecording);
}
return isRecording;
}
AutoTimelineMarker::AutoTimelineMarker(nsIDocShell* aDocShell, const char* aName
MOZ_GUARD_OBJECT_NOTIFIER_PARAM_IN_IMPL)
: mDocShell(nullptr)
, mName(aName)
{
MOZ_GUARD_OBJECT_NOTIFIER_INIT;
MOZ_ASSERT(NS_IsMainThread());
nsDocShell* docShell = static_cast<nsDocShell*>(aDocShell);
if (docShell && DocShellIsRecording(*docShell)) {
mDocShell = docShell;
mDocShell->AddProfileTimelineMarker(mName, TRACING_INTERVAL_START);
}
}
AutoTimelineMarker::~AutoTimelineMarker()
{
if (mDocShell) {
mDocShell->AddProfileTimelineMarker(mName, TRACING_INTERVAL_END);
}
}
void
AutoGlobalTimelineMarker::PopulateDocShells()
{
const LinkedList<nsDocShell::ObservedDocShell>& docShells =
nsDocShell::GetObservedDocShells();
MOZ_ASSERT(!docShells.isEmpty());
for (const nsDocShell::ObservedDocShell* ds = docShells.getFirst();
ds;
ds = ds->getNext()) {
mOk = mDocShells.append(**ds);
if (!mOk) {
return;
}
}
}
AutoGlobalTimelineMarker::AutoGlobalTimelineMarker(const char* aName
MOZ_GUARD_OBJECT_NOTIFIER_PARAM_IN_IMPL)
: mOk(true)
, mDocShells()
, mName(aName)
{
MOZ_GUARD_OBJECT_NOTIFIER_INIT;
MOZ_ASSERT(NS_IsMainThread());
if (nsDocShell::gProfileTimelineRecordingsCount == 0) {
return;
}
PopulateDocShells();
if (!mOk) {
// If we don't successfully populate our vector with *all* docshells being
// observed, don't add markers to *any* of them.
return;
}
for (Vector<nsRefPtr<nsDocShell>>::Range range = mDocShells.all();
!range.empty();
range.popFront()) {
range.front()->AddProfileTimelineMarker(mName, TRACING_INTERVAL_START);
}
}
AutoGlobalTimelineMarker::~AutoGlobalTimelineMarker()
{
if (!mOk) {
return;
}
for (Vector<nsRefPtr<nsDocShell>>::Range range = mDocShells.all();
!range.empty();
range.popFront()) {
range.front()->AddProfileTimelineMarker(mName, TRACING_INTERVAL_END);
}
}
} // namespace mozilla

Просмотреть файл

@ -8,10 +8,13 @@
#define AutoTimelineMarker_h__
#include "mozilla/GuardObjects.h"
#include "mozilla/Move.h"
#include "nsDocShell.h"
#include "mozilla/Vector.h"
#include "nsRefPtr.h"
class nsIDocShell;
class nsDocShell;
namespace mozilla {
// # AutoTimelineMarker
@ -27,7 +30,6 @@ namespace mozilla {
// nsresult rv = ParseTheCSSFile(mFile);
// ...
// }
class MOZ_STACK_CLASS AutoTimelineMarker
{
MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER;
@ -35,42 +37,57 @@ class MOZ_STACK_CLASS AutoTimelineMarker
nsRefPtr<nsDocShell> mDocShell;
const char* mName;
bool
DocShellIsRecording(nsDocShell& aDocShell)
{
bool isRecording = false;
if (nsDocShell::gProfileTimelineRecordingsCount > 0) {
aDocShell.GetRecordProfileTimelineMarkers(&isRecording);
}
return isRecording;
}
bool DocShellIsRecording(nsDocShell& aDocShell);
public:
explicit AutoTimelineMarker(nsIDocShell* aDocShell, const char* aName
MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
: mDocShell(nullptr)
, mName(aName)
{
MOZ_GUARD_OBJECT_NOTIFIER_INIT;
nsDocShell* docShell = static_cast<nsDocShell*>(aDocShell);
if (docShell && DocShellIsRecording(*docShell)) {
mDocShell = docShell;
mDocShell->AddProfileTimelineMarker(mName, TRACING_INTERVAL_START);
}
}
~AutoTimelineMarker()
{
if (mDocShell) {
mDocShell->AddProfileTimelineMarker(mName, TRACING_INTERVAL_END);
}
}
MOZ_GUARD_OBJECT_NOTIFIER_PARAM);
~AutoTimelineMarker();
AutoTimelineMarker(const AutoTimelineMarker& aOther) = delete;
void operator=(const AutoTimelineMarker& aOther) = delete;
};
// # AutoGlobalTimelineMarker
//
// Similar to `AutoTimelineMarker`, but adds its traced marker to all docshells,
// not a single particular one. This is useful for operations that aren't
// associated with any one particular doc shell, or when it isn't clear which
// doc shell triggered the operation.
//
// Example usage:
//
// {
// AutoGlobalTimelineMarker marker("Cycle Collection");
// nsCycleCollector* cc = GetCycleCollector();
// cc->Collect();
// ...
// }
class MOZ_STACK_CLASS AutoGlobalTimelineMarker
{
MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER;
// True as long as no operation has failed, eg due to OOM.
bool mOk;
// The set of docshells that are being observed and will get markers.
mozilla::Vector<nsRefPtr<nsDocShell>> mDocShells;
// The name of the marker we are adding.
const char* mName;
void PopulateDocShells();
public:
explicit AutoGlobalTimelineMarker(const char* aName
MOZ_GUARD_OBJECT_NOTIFIER_PARAM);
~AutoGlobalTimelineMarker();
AutoGlobalTimelineMarker(const AutoGlobalTimelineMarker& aOther) = delete;
void operator=(const AutoGlobalTimelineMarker& aOther) = delete;
};
} // namespace mozilla
#endif /* AutoTimelineMarker_h__ */

Просмотреть файл

@ -48,6 +48,7 @@ EXPORTS.mozilla += [
]
UNIFIED_SOURCES += [
'AutoTimelineMarker.cpp',
'LoadContext.cpp',
'nsAboutRedirector.cpp',
'nsDefaultURIFixup.cpp',

Просмотреть файл

@ -200,6 +200,12 @@
#include "nsIBrowserSearchService.h"
#endif
#include "mozIThirdPartyUtil.h"
// Values for the network.cookie.cookieBehavior pref are documented in
// nsCookieService.cpp
#define COOKIE_BEHAVIOR_ACCEPT 0 // Allow all cookies.
#define COOKIE_BEHAVIOR_REJECT_FOREIGN 1 // Reject all third-party cookies.
static NS_DEFINE_CID(kAppShellCID, NS_APPSHELL_CID);
#if defined(DEBUG_bryner) || defined(DEBUG_chb)
@ -944,7 +950,7 @@ nsDocShell::nsDocShell()
nsDocShell::~nsDocShell()
{
MOZ_ASSERT(!mProfileTimelineRecording);
MOZ_ASSERT(!IsObserved());
Destroy();
@ -2927,6 +2933,8 @@ nsDocShell::HistoryTransactionRemoved(int32_t aIndex)
unsigned long nsDocShell::gProfileTimelineRecordingsCount = 0;
mozilla::LinkedList<nsDocShell::ObservedDocShell>* nsDocShell::gObservedDocShells = nullptr;
NS_IMETHODIMP
nsDocShell::SetRecordProfileTimelineMarkers(bool aValue)
{
@ -2935,11 +2943,16 @@ nsDocShell::SetRecordProfileTimelineMarkers(bool aValue)
if (aValue) {
++gProfileTimelineRecordingsCount;
UseEntryScriptProfiling();
mProfileTimelineRecording = true;
MOZ_ASSERT(!mObserved);
mObserved.reset(new ObservedDocShell(this));
GetOrCreateObservedDocShells().insertFront(mObserved.get());
} else {
--gProfileTimelineRecordingsCount;
UnuseEntryScriptProfiling();
mProfileTimelineRecording = false;
mObserved.reset(nullptr);
ClearProfileTimelineMarkers();
}
}
@ -2950,7 +2963,7 @@ nsDocShell::SetRecordProfileTimelineMarkers(bool aValue)
NS_IMETHODIMP
nsDocShell::GetRecordProfileTimelineMarkers(bool* aValue)
{
*aValue = mProfileTimelineRecording;
*aValue = IsObserved();
return NS_OK;
}
@ -3090,7 +3103,7 @@ void
nsDocShell::AddProfileTimelineMarker(const char* aName,
TracingMetadata aMetaData)
{
if (mProfileTimelineRecording) {
if (IsObserved()) {
TimelineMarker* marker = new TimelineMarker(this, aName, aMetaData);
mProfileTimelineMarkers.AppendElement(marker);
}
@ -3099,7 +3112,7 @@ nsDocShell::AddProfileTimelineMarker(const char* aName,
void
nsDocShell::AddProfileTimelineMarker(UniquePtr<TimelineMarker>&& aMarker)
{
if (mProfileTimelineRecording) {
if (IsObserved()) {
mProfileTimelineMarkers.AppendElement(Move(aMarker));
}
}
@ -14044,6 +14057,32 @@ nsDocShell::ShouldPrepareForIntercept(nsIURI* aURI, bool aIsNavigate,
return NS_OK;
}
nsresult result;
nsCOMPtr<mozIThirdPartyUtil> thirdPartyUtil =
do_GetService(THIRDPARTYUTIL_CONTRACTID, &result);
NS_ENSURE_SUCCESS(result, result);
if (mCurrentURI) {
nsAutoCString uriSpec;
mCurrentURI->GetSpec(uriSpec);
if (!(uriSpec.EqualsLiteral("about:blank"))) {
// Reject the interception of third-party iframes if the cookie behaviour
// is set to reject all third-party cookies (1). In case that this pref
// is not set or can't be read, we default to allow all cookies (0) as
// this is the default value in all.js.
bool isThirdPartyURI = true;
result = thirdPartyUtil->IsThirdPartyURI(mCurrentURI, aURI,
&isThirdPartyURI);
NS_ENSURE_SUCCESS(result, result);
if (isThirdPartyURI &&
(Preferences::GetInt("network.cookie.cookieBehavior",
COOKIE_BEHAVIOR_ACCEPT) ==
COOKIE_BEHAVIOR_REJECT_FOREIGN)) {
return NS_OK;
}
}
}
if (aIsNavigate) {
OriginAttributes attrs(GetAppId(), GetIsInBrowserElement());
*aShouldIntercept = swm->IsAvailable(attrs, aURI);

Просмотреть файл

@ -23,6 +23,7 @@
#include "mozilla/TimeStamp.h"
#include "GeckoProfiler.h"
#include "mozilla/dom/ProfileTimelineMarkerBinding.h"
#include "mozilla/LinkedList.h"
#include "jsapi.h"
// Helper Classes
@ -266,6 +267,43 @@ public:
// timeline markers
static unsigned long gProfileTimelineRecordingsCount;
class ObservedDocShell : public mozilla::LinkedListElement<ObservedDocShell>
{
public:
explicit ObservedDocShell(nsDocShell* aDocShell)
: mDocShell(aDocShell)
{ }
nsDocShell* operator*() const { return mDocShell.get(); }
private:
nsRefPtr<nsDocShell> mDocShell;
};
private:
static mozilla::LinkedList<ObservedDocShell>* gObservedDocShells;
static mozilla::LinkedList<ObservedDocShell>& GetOrCreateObservedDocShells()
{
if (!gObservedDocShells) {
gObservedDocShells = new mozilla::LinkedList<ObservedDocShell>();
}
return *gObservedDocShells;
}
// Never null if timeline markers are being observed.
mozilla::UniquePtr<ObservedDocShell> mObserved;
// Return true if timeline markers are being observed for this docshell. False
// otherwise.
bool IsObserved() const { return !!mObserved; }
public:
static const mozilla::LinkedList<ObservedDocShell>& GetObservedDocShells()
{
return GetOrCreateObservedDocShells();
}
// Tell the favicon service that aNewURI has the same favicon as aOldURI.
static void CopyFavicon(nsIURI* aOldURI,
nsIURI* aNewURI,
@ -973,9 +1011,6 @@ private:
// has been called without a matching NotifyRunToCompletionStop.
uint32_t mJSRunToCompletionDepth;
// True if recording profiles.
bool mProfileTimelineRecording;
nsTArray<mozilla::UniquePtr<TimelineMarker>> mProfileTimelineMarkers;
// Get rid of all the timeline markers accumulated so far

Просмотреть файл

@ -71,6 +71,10 @@ this.timelineContentTest = function(tests) {
info("Waiting for new markers on the docShell");
let markers = yield onMarkers;
// Cycle collection markers are non-deterministic, and none of these tests
// expect them to show up.
markers = markers.filter(m => m.name.indexOf("nsCycleCollector") === -1);
info("Running the test check function");
check(markers);
}

Просмотреть файл

@ -186,7 +186,14 @@ TextInputProcessor::BeginInputTransactionInternal(
// This instance has finished preparing to link to the dispatcher. Therefore,
// let's forget the old dispatcher and purpose.
UnlinkFromTextEventDispatcher();
if (mDispatcher) {
mDispatcher->EndInputTransaction(this);
if (NS_WARN_IF(mDispatcher)) {
// Forcibly initialize the members if we failed to end the input
// transaction.
UnlinkFromTextEventDispatcher();
}
}
if (aForTests) {
rv = dispatcher->BeginInputTransactionForTests(this);

Просмотреть файл

@ -139,9 +139,25 @@ URL::CreateObjectURL(const GlobalObject& aGlobal, MediaSource& aSource,
nsAString& aResult,
ErrorResult& aError)
{
CreateObjectURLInternal(aGlobal, &aSource,
NS_LITERAL_CSTRING(MEDIASOURCEURI_SCHEME), aOptions,
aResult, aError);
nsCOMPtr<nsIPrincipal> principal = nsContentUtils::ObjectPrincipal(aGlobal.Get());
nsCString url;
nsresult rv = nsHostObjectProtocolHandler::
AddDataEntry(NS_LITERAL_CSTRING(MEDIASOURCEURI_SCHEME),
&aSource, principal, url);
if (NS_FAILED(rv)) {
aError.Throw(rv);
return;
}
nsCOMPtr<nsIRunnable> revocation = NS_NewRunnableFunction(
[url] {
nsHostObjectProtocolHandler::RemoveDataEntry(url);
});
nsContentUtils::RunInStableState(revocation.forget());
CopyASCIItoUTF16(url, aResult);
}
void

Просмотреть файл

@ -92,6 +92,7 @@
#include "nsHostObjectProtocolHandler.h"
#include "nsHtml5Module.h"
#include "nsHtml5StringParser.h"
#include "nsIAppShell.h"
#include "nsIAsyncVerifyRedirectCallback.h"
#include "nsICategoryManager.h"
#include "nsIChannelEventSink.h"
@ -182,6 +183,7 @@
#include "nsUnicodeProperties.h"
#include "nsViewManager.h"
#include "nsViewportInfo.h"
#include "nsWidgetsCID.h"
#include "nsWrapperCacheInlines.h"
#include "nsXULPopupManager.h"
#include "xpcprivate.h" // nsXPConnect
@ -337,6 +339,7 @@ namespace {
static NS_DEFINE_CID(kParserServiceCID, NS_PARSERSERVICE_CID);
static NS_DEFINE_CID(kCParserCID, NS_PARSER_CID);
static NS_DEFINE_CID(kAppShellCID, NS_APPSHELL_CID);
static PLDHashTable* sEventListenerManagersHash;
@ -5148,6 +5151,20 @@ nsContentUtils::AddScriptRunner(nsIRunnable* aRunnable)
return true;
}
/* static */
void
nsContentUtils::RunInStableState(already_AddRefed<nsIRunnable> aRunnable,
DispatchFailureHandling aHandling)
{
nsCOMPtr<nsIRunnable> runnable = aRunnable;
nsCOMPtr<nsIAppShell> appShell(do_GetService(kAppShellCID));
if (!appShell) {
MOZ_ASSERT(aHandling == DispatchFailureHandling::IgnoreFailure);
return;
}
appShell->RunInStableState(runnable.forget());
}
void
nsContentUtils::EnterMicroTask()
{
@ -7414,7 +7431,9 @@ nsContentUtils::GetSurfaceData(mozilla::gfx::DataSourceSurface* aSurface,
size_t* aLength, int32_t* aStride)
{
mozilla::gfx::DataSourceSurface::MappedSurface map;
aSurface->Map(mozilla::gfx::DataSourceSurface::MapType::READ, &map);
if (NS_WARN_IF(!aSurface->Map(mozilla::gfx::DataSourceSurface::MapType::READ, &map))) {
return nullptr;
}
mozilla::gfx::IntSize size = aSurface->GetSize();
mozilla::CheckedInt32 requiredBytes =
mozilla::CheckedInt32(map.mStride) * mozilla::CheckedInt32(size.height);

Просмотреть файл

@ -1576,6 +1576,27 @@ public:
*/
static void WarnScriptWasIgnored(nsIDocument* aDocument);
/**
* Whether to assert that RunInStableState() succeeds, or ignore failure,
* which may happen late in shutdown.
*/
enum class DispatchFailureHandling { AssertSuccess, IgnoreFailure };
/**
* Add a "synchronous section", in the form of an nsIRunnable run once the
* event loop has reached a "stable state". |aRunnable| must not cause any
* queued events to be processed (i.e. must not spin the event loop).
* We've reached a stable state when the currently executing task/event has
* finished, see
* http://www.whatwg.org/specs/web-apps/current-work/multipage/webappapis.html#synchronous-section
* In practice this runs aRunnable once the currently executing event
* finishes. If called multiple times per task/event, all the runnables will
* be executed, in the order in which RunInStableState() was called.
*/
static void RunInStableState(already_AddRefed<nsIRunnable> aRunnable,
DispatchFailureHandling aHandling =
DispatchFailureHandling::AssertSuccess);
/**
* Retrieve information about the viewport as a data structure.
* This will return information in the viewport META data section

Просмотреть файл

@ -1509,18 +1509,23 @@ nsDOMWindowUtils::CompareCanvases(nsIDOMHTMLCanvasElement *aCanvas1,
RefPtr<DataSourceSurface> img1 = CanvasToDataSourceSurface(aCanvas1);
RefPtr<DataSourceSurface> img2 = CanvasToDataSourceSurface(aCanvas2);
DataSourceSurface::ScopedMap map1(img1, DataSourceSurface::READ);
DataSourceSurface::ScopedMap map2(img2, DataSourceSurface::READ);
if (img1 == nullptr || img2 == nullptr ||
!map1.IsMapped() || !map2.IsMapped() ||
img1->GetSize() != img2->GetSize() ||
img1->Stride() != img2->Stride())
map1.GetStride() != map2.GetStride()) {
return NS_ERROR_FAILURE;
}
int v;
IntSize size = img1->GetSize();
uint32_t stride = img1->Stride();
int32_t stride = map1.GetStride();
// we can optimize for the common all-pass case
if (stride == (uint32_t) size.width * 4) {
v = memcmp(img1->GetData(), img2->GetData(), size.width * size.height * 4);
if (stride == size.width * 4) {
v = memcmp(map1.GetData(), map2.GetData(), size.width * size.height * 4);
if (v == 0) {
if (aMaxDifference)
*aMaxDifference = 0;
@ -1533,8 +1538,8 @@ nsDOMWindowUtils::CompareCanvases(nsIDOMHTMLCanvasElement *aCanvas1,
uint32_t different = 0;
for (int j = 0; j < size.height; j++) {
unsigned char *p1 = img1->GetData() + j*stride;
unsigned char *p2 = img2->GetData() + j*stride;
unsigned char *p1 = map1.GetData() + j*stride;
unsigned char *p2 = map2.GetData() + j*stride;
v = memcmp(p1, p2, stride);
if (v) {
@ -3441,16 +3446,14 @@ nsDOMWindowUtils::DispatchEventToChromeOnly(nsIDOMEventTarget* aTarget,
}
NS_IMETHODIMP
nsDOMWindowUtils::RunInStableState(nsIRunnable *runnable)
nsDOMWindowUtils::RunInStableState(nsIRunnable *aRunnable)
{
MOZ_RELEASE_ASSERT(nsContentUtils::IsCallerChrome());
nsCOMPtr<nsIAppShell> appShell(do_GetService(kAppShellCID));
if (!appShell) {
return NS_ERROR_NOT_AVAILABLE;
}
nsCOMPtr<nsIRunnable> runnable = aRunnable;
nsContentUtils::RunInStableState(runnable.forget());
return appShell->RunInStableState(runnable);
return NS_OK;
}
NS_IMETHODIMP

Просмотреть файл

@ -711,17 +711,6 @@ public:
nsIDocument *mSubDocument;
};
struct FindContentData
{
explicit FindContentData(nsIDocument* aSubDoc)
: mSubDocument(aSubDoc), mResult(nullptr)
{
}
nsISupports *mSubDocument;
Element *mResult;
};
/**
* A struct that holds all the information about a radio group.
@ -1858,22 +1847,6 @@ NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_THIS_BEGIN(nsDocument)
return Element::CanSkipThis(tmp);
NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_THIS_END
static PLDHashOperator
SubDocTraverser(PLDHashTable *table, PLDHashEntryHdr *hdr, uint32_t number,
void *arg)
{
SubDocMapEntry *entry = static_cast<SubDocMapEntry*>(hdr);
nsCycleCollectionTraversalCallback *cb =
static_cast<nsCycleCollectionTraversalCallback*>(arg);
NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(*cb, "mSubDocuments entry->mKey");
cb->NoteXPCOMChild(entry->mKey);
NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(*cb, "mSubDocuments entry->mSubDocument");
cb->NoteXPCOMChild(entry->mSubDocument);
return PL_DHASH_NEXT;
}
static PLDHashOperator
RadioGroupsTraverser(const nsAString& aKey, nsRadioGroupStruct* aData,
void* aClosure)
@ -2033,7 +2006,17 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INTERNAL(nsDocument)
}
if (tmp->mSubDocuments) {
PL_DHashTableEnumerate(tmp->mSubDocuments, SubDocTraverser, &cb);
PLDHashTable::Iterator iter(tmp->mSubDocuments);
while (iter.HasMoreEntries()) {
auto entry = static_cast<SubDocMapEntry*>(iter.NextEntry());
NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb,
"mSubDocuments entry->mKey");
cb.NoteXPCOMChild(entry->mKey);
NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb,
"mSubDocuments entry->mSubDocument");
cb.NoteXPCOMChild(entry->mSubDocument);
}
}
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mCSSLoader)
@ -4031,22 +4014,6 @@ nsDocument::GetSubDocumentFor(nsIContent *aContent) const
return nullptr;
}
static PLDHashOperator
FindContentEnumerator(PLDHashTable *table, PLDHashEntryHdr *hdr,
uint32_t number, void *arg)
{
SubDocMapEntry *entry = static_cast<SubDocMapEntry*>(hdr);
FindContentData *data = static_cast<FindContentData*>(arg);
if (entry->mSubDocument == data->mSubDocument) {
data->mResult = entry->mKey;
return PL_DHASH_STOP;
}
return PL_DHASH_NEXT;
}
Element*
nsDocument::FindContentForSubDocument(nsIDocument *aDocument) const
{
@ -4056,10 +4023,14 @@ nsDocument::FindContentForSubDocument(nsIDocument *aDocument) const
return nullptr;
}
FindContentData data(aDocument);
PL_DHashTableEnumerate(mSubDocuments, FindContentEnumerator, &data);
return data.mResult;
PLDHashTable::Iterator iter(mSubDocuments);
while (iter.HasMoreEntries()) {
auto entry = static_cast<SubDocMapEntry*>(iter.NextEntry());
if (entry->mSubDocument == aDocument) {
return entry->mKey;
}
}
return nullptr;
}
bool
@ -8739,45 +8710,22 @@ struct SubDocEnumArgs
void *data;
};
static PLDHashOperator
SubDocHashEnum(PLDHashTable *table, PLDHashEntryHdr *hdr,
uint32_t number, void *arg)
{
SubDocMapEntry *entry = static_cast<SubDocMapEntry*>(hdr);
SubDocEnumArgs *args = static_cast<SubDocEnumArgs*>(arg);
nsIDocument *subdoc = entry->mSubDocument;
bool next = subdoc ? args->callback(subdoc, args->data) : true;
return next ? PL_DHASH_NEXT : PL_DHASH_STOP;
}
void
nsDocument::EnumerateSubDocuments(nsSubDocEnumFunc aCallback, void *aData)
{
if (mSubDocuments) {
SubDocEnumArgs args = { aCallback, aData };
PL_DHashTableEnumerate(mSubDocuments, SubDocHashEnum, &args);
}
}
static PLDHashOperator
CanCacheSubDocument(PLDHashTable *table, PLDHashEntryHdr *hdr,
uint32_t number, void *arg)
{
SubDocMapEntry *entry = static_cast<SubDocMapEntry*>(hdr);
bool *canCacheArg = static_cast<bool*>(arg);
nsIDocument *subdoc = entry->mSubDocument;
// The aIgnoreRequest we were passed is only for us, so don't pass it on.
bool canCache = subdoc ? subdoc->CanSavePresentation(nullptr) : false;
if (!canCache) {
*canCacheArg = false;
return PL_DHASH_STOP;
if (!mSubDocuments) {
return;
}
return PL_DHASH_NEXT;
PLDHashTable::Iterator iter(mSubDocuments);
while (iter.HasMoreEntries()) {
auto entry = static_cast<SubDocMapEntry*>(iter.NextEntry());
nsIDocument* subdoc = entry->mSubDocument;
bool next = subdoc ? aCallback(subdoc, aData) : true;
if (!next) {
break;
}
}
}
#ifdef DEBUG_bryner
@ -8878,11 +8826,21 @@ nsDocument::CanSavePresentation(nsIRequest *aNewRequest)
return false;
}
bool canCache = true;
if (mSubDocuments)
PL_DHashTableEnumerate(mSubDocuments, CanCacheSubDocument, &canCache);
if (mSubDocuments) {
PLDHashTable::Iterator iter(mSubDocuments);
while (iter.HasMoreEntries()) {
auto entry = static_cast<SubDocMapEntry*>(iter.NextEntry());
nsIDocument* subdoc = entry->mSubDocument;
return canCache;
// The aIgnoreRequest we were passed is only for us, so don't pass it on.
bool canCache = subdoc ? subdoc->CanSavePresentation(nullptr) : false;
if (!canCache) {
return false;
}
}
}
return true;
}
void

Просмотреть файл

@ -133,30 +133,16 @@ nsPropertyTable::Enumerate(nsPropertyOwner aObject,
}
}
struct PropertyEnumeratorData
{
nsIAtom* mName;
NSPropertyFunc mCallBack;
void* mData;
};
static PLDHashOperator
PropertyEnumerator(PLDHashTable* aTable, PLDHashEntryHdr* aHdr,
uint32_t aNumber, void* aArg)
{
PropertyListMapEntry* entry = static_cast<PropertyListMapEntry*>(aHdr);
PropertyEnumeratorData* data = static_cast<PropertyEnumeratorData*>(aArg);
data->mCallBack(const_cast<void*>(entry->key), data->mName, entry->value,
data->mData);
return PL_DHASH_NEXT;
}
void
nsPropertyTable::EnumerateAll(NSPropertyFunc aCallBack, void* aData)
{
for (PropertyList* prop = mPropertyList; prop; prop = prop->mNext) {
PropertyEnumeratorData data = { prop->mName, aCallBack, aData };
PL_DHashTableEnumerate(&prop->mObjectValueMap, PropertyEnumerator, &data);
PLDHashTable::Iterator iter(&prop->mObjectValueMap);
while (iter.HasMoreEntries()) {
auto entry = static_cast<PropertyListMapEntry*>(iter.NextEntry());
aCallBack(const_cast<void*>(entry->key), prop->mName, entry->value,
aData);
}
}
}
@ -294,25 +280,17 @@ nsPropertyTable::PropertyList::~PropertyList()
{
}
static PLDHashOperator
DestroyPropertyEnumerator(PLDHashTable *table, PLDHashEntryHdr *hdr,
uint32_t number, void *arg)
{
nsPropertyTable::PropertyList *propList =
static_cast<nsPropertyTable::PropertyList*>(arg);
PropertyListMapEntry* entry = static_cast<PropertyListMapEntry*>(hdr);
propList->mDtorFunc(const_cast<void*>(entry->key), propList->mName,
entry->value, propList->mDtorData);
return PL_DHASH_NEXT;
}
void
nsPropertyTable::PropertyList::Destroy()
{
// Enumerate any remaining object/value pairs and destroy the value object
if (mDtorFunc)
PL_DHashTableEnumerate(&mObjectValueMap, DestroyPropertyEnumerator, this);
// Enumerate any remaining object/value pairs and destroy the value object.
if (mDtorFunc) {
PLDHashTable::Iterator iter(&mObjectValueMap);
while (iter.HasMoreEntries()) {
auto entry = static_cast<PropertyListMapEntry*>(iter.NextEntry());
mDtorFunc(const_cast<void*>(entry->key), mName, entry->value, mDtorData);
}
}
}
bool

Просмотреть файл

@ -47,7 +47,7 @@ nsReferencedElement::Reset(nsIContent* aFromContent, nsIURI* aURI,
return;
// Get the current document
nsIDocument *doc = aFromContent->GetComposedDoc();
nsIDocument *doc = aFromContent->OwnerDoc();
if (!doc)
return;
@ -124,7 +124,7 @@ void
nsReferencedElement::ResetWithID(nsIContent* aFromContent, const nsString& aID,
bool aWatch)
{
nsIDocument *doc = aFromContent->GetComposedDoc();
nsIDocument *doc = aFromContent->OwnerDoc();
if (!doc)
return;

Просмотреть файл

@ -3205,6 +3205,12 @@ class IDLInterfaceMember(IDLObjectWithIdentifier, IDLExposureMixins):
"That seems rather unlikely.",
[self.location])
if self.getExtendedAttribute("NewObject"):
if self.dependsOn == "Nothing" or self.dependsOn == "DOMState":
raise WebIDLError("A [NewObject] method is not idempotent, "
"so it has to depend on something other than DOM state.",
[self.location])
def _setDependsOn(self, dependsOn):
if self.dependsOn != "Everything":
raise WebIDLError("Trying to specify multiple different DependsOn, "

Просмотреть файл

@ -229,7 +229,10 @@ BrowserElementChild.prototype = {
"activate-next-paint-listener": this._activateNextPaintListener.bind(this),
"set-input-method-active": this._recvSetInputMethodActive.bind(this),
"deactivate-next-paint-listener": this._deactivateNextPaintListener.bind(this),
"do-command": this._recvDoCommand
"do-command": this._recvDoCommand,
"find-all": this._recvFindAll.bind(this),
"find-next": this._recvFindNext.bind(this),
"clear-match": this._recvClearMatch.bind(this),
}
addMessageListener("browser-element-api:call", function(aMessage) {
@ -1240,6 +1243,57 @@ BrowserElementChild.prototype = {
}
},
_initFinder: function() {
if (!this._finder) {
try {
this._findLimit = Services.prefs.getIntPref("accessibility.typeaheadfind.matchesCountLimit");
} catch (e) {
// Pref not available, assume 0, no match counting.
this._findLimit = 0;
}
let {Finder} = Components.utils.import("resource://gre/modules/Finder.jsm", {});
this._finder = new Finder(docShell);
this._finder.addResultListener({
onMatchesCountResult: (data) => {
sendAsyncMsg('findchange', {
active: true,
searchString: this._finder.searchString,
searchLimit: this._findLimit,
activeMatchOrdinal: data.current,
numberOfMatches: data.total
});
}
});
}
},
_recvFindAll: function(data) {
this._initFinder();
let searchString = data.json.searchString;
this._finder.caseSensitive = data.json.caseSensitive;
this._finder.fastFind(searchString, false, false);
this._finder.requestMatchesCount(searchString, this._findLimit, false);
},
_recvFindNext: function(data) {
if (!this._finder) {
debug("findNext() called before findAll()");
return;
}
this._finder.findAgain(data.json.backward, false, false);
this._finder.requestMatchesCount(this._finder.searchString, this._findLimit, false);
},
_recvClearMatch: function(data) {
if (!this._finder) {
debug("clearMach() called before findAll()");
return;
}
this._finder.removeSelection();
sendAsyncMsg('findchange', {active: false});
},
_recvSetInputMethodActive: function(data) {
let msgData = { id: data.json.id };
if (!this._isContentWindowCreated) {

Просмотреть файл

@ -206,6 +206,7 @@ BrowserElementParent.prototype = {
"selectionstatechanged": this._handleSelectionStateChanged,
"scrollviewchange": this._handleScrollViewChange,
"caretstatechanged": this._handleCaretStateChanged,
"findchange": this._handleFindChange
};
let mmSecuritySensitiveCalls = {
@ -475,6 +476,12 @@ BrowserElementParent.prototype = {
this._frameElement.dispatchEvent(evt);
},
_handleFindChange: function(data) {
let evt = this._createEvent("findchange", data.json,
/* cancelable = */ false);
this._frameElement.dispatchEvent(evt);
},
_createEvent: function(evtName, detail, cancelable) {
// This will have to change if we ever want to send a CustomEvent with null
// detail. For now, it's OK.
@ -646,6 +653,23 @@ BrowserElementParent.prototype = {
getCanGoForward: defineDOMRequestMethod('get-can-go-forward'),
getContentDimensions: defineDOMRequestMethod('get-contentdimensions'),
findAll: defineNoReturnMethod(function(searchString, caseSensitivity) {
return this._sendAsyncMsg('find-all', {
searchString,
caseSensitive: caseSensitivity == Ci.nsIBrowserElementAPI.FIND_CASE_SENSITIVE
});
}),
findNext: defineNoReturnMethod(function(direction) {
return this._sendAsyncMsg('find-next', {
backward: direction == Ci.nsIBrowserElementAPI.FIND_BACKWARD
});
}),
clearMatch: defineNoReturnMethod(function() {
return this._sendAsyncMsg('clear-match');
}),
goBack: defineNoReturnMethod(function() {
this._sendAsyncMsg('go-back');
}),

Просмотреть файл

@ -0,0 +1,146 @@
/* Any copyright is dedicated to the public domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
// Bug 1163961 - Test search API
"use strict";
SimpleTest.waitForExplicitFinish();
browserElementTestHelpers.setEnabledPref(true);
browserElementTestHelpers.addPermission();
function runTest() {
let iframe = document.createElement('iframe');
iframe.setAttribute('mozbrowser', 'true');
iframe.src = 'data:text/html,foo bar foo XXX Foo BAR foobar foobar';
const once = (eventName) => {
return new Promise((resolve) => {
iframe.addEventListener(eventName, function onEvent(...args) {
iframe.removeEventListener(eventName, onEvent);
resolve(...args);
});
});
}
// Test if all key=>value pairs in o1 are present in o2.
const c = (o1, o2) => Object.keys(o1).every(k => o1[k] == o2[k]);
let testCount = 0;
once('mozbrowserloadend').then(() => {
iframe.findAll('foo', 'case-insensitive');
return once('mozbrowserfindchange');
}).then(({detail}) => {
ok(c(detail, {
msg_name: "findchange",
active: true,
searchString: 'foo',
searchLimit: 100,
activeMatchOrdinal: 1,
numberOfMatches: 5,
}), `test ${testCount++}`);
iframe.findNext('forward');
return once('mozbrowserfindchange');
}).then(({detail}) => {
ok(c(detail, {
msg_name: "findchange",
active: true,
searchString: 'foo',
searchLimit: 100,
activeMatchOrdinal: 2,
numberOfMatches: 5,
}), `test ${testCount++}`);
iframe.findNext('backward');
return once('mozbrowserfindchange');
}).then(({detail}) => {
ok(c(detail, {
msg_name: "findchange",
active: true,
searchString: 'foo',
searchLimit: 100,
activeMatchOrdinal: 1,
numberOfMatches: 5,
}), `test ${testCount++}`);
iframe.findAll('xxx', 'case-sensitive');
return once('mozbrowserfindchange');
}).then(({detail}) => {
ok(c(detail, {
msg_name: "findchange",
active: true,
searchString: 'xxx',
searchLimit: 100,
activeMatchOrdinal: 0,
numberOfMatches: 0,
}), `test ${testCount++}`);
iframe.findAll('bar', 'case-insensitive');
return once('mozbrowserfindchange');
}).then(({detail}) => {
ok(c(detail, {
msg_name: "findchange",
active: true,
searchString: 'bar',
searchLimit: 100,
activeMatchOrdinal: 1,
numberOfMatches: 4,
}), `test ${testCount++}`);
iframe.findNext('forward');
return once('mozbrowserfindchange');
}).then(({detail}) => {
ok(c(detail, {
msg_name: "findchange",
active: true,
searchString: 'bar',
searchLimit: 100,
activeMatchOrdinal: 2,
numberOfMatches: 4,
}), `test ${testCount++}`);
iframe.findNext('forward');
return once('mozbrowserfindchange');
}).then(({detail}) => {
ok(c(detail, {
msg_name: "findchange",
active: true,
searchString: 'bar',
searchLimit: 100,
activeMatchOrdinal: 3,
numberOfMatches: 4,
}), `test ${testCount++}`);
iframe.findNext('forward');
return once('mozbrowserfindchange');
}).then(({detail}) => {
ok(c(detail, {
msg_name: "findchange",
active: true,
searchString: 'bar',
searchLimit: 100,
activeMatchOrdinal: 4,
numberOfMatches: 4,
}), `test ${testCount++}`);
iframe.findNext('forward');
return once('mozbrowserfindchange');
}).then(({detail}) => {
ok(c(detail, {
msg_name: "findchange",
active: true,
searchString: 'bar',
searchLimit: 100,
activeMatchOrdinal: 1,
numberOfMatches: 4,
}), `test ${testCount++}`);
iframe.clearMatch();
return once('mozbrowserfindchange');
}).then(({detail}) => {
ok(c(detail, {
msg_name: "findchange",
active: false
}), `test ${testCount++}`);
SimpleTest.finish();
});
document.body.appendChild(iframe);
}
addEventListener('testready', runTest);

Просмотреть файл

@ -7,6 +7,7 @@ skip-if = os == "android" || (toolkit == "cocoa" && debug) || buildapp == 'mulet
support-files =
browserElement_OpenMixedProcess.js
file_browserElement_OpenMixedProcess.html
browserElement_Find.js
browserElement_OpenTab.js
[test_browserElement_oop_Viewmode.html]
@ -41,6 +42,7 @@ skip-if = (toolkit == 'gonk' && !debug)
disabled = bug 1022281
[test_browserElement_oop_ErrorSecurity.html]
skip-if = (toolkit == 'gonk' && !debug)
[test_browserElement_oop_Find.html]
[test_browserElement_oop_FirstPaint.html]
[test_browserElement_oop_ForwardName.html]
[test_browserElement_oop_FrameWrongURI.html]

Просмотреть файл

@ -29,6 +29,7 @@ support-files =
browserElement_Download.js
browserElement_ErrorSecurity.js
browserElement_ExposableURI.js
browserElement_Find.js
browserElement_FirstPaint.js
browserElement_ForwardName.js
browserElement_FrameWrongURI.js
@ -159,6 +160,7 @@ skip-if = os == "android" || toolkit == 'gonk' # embed-apps doesn't work in the
[test_browserElement_inproc_Download.html]
disabled = bug 1022281
[test_browserElement_inproc_ExposableURI.html]
[test_browserElement_inproc_Find.html]
[test_browserElement_inproc_FirstPaint.html]
[test_browserElement_inproc_ForwardName.html]
[test_browserElement_inproc_FrameWrongURI.html]

Просмотреть файл

@ -0,0 +1,19 @@
<!DOCTYPE HTML>
<html>
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=1163961
-->
<head>
<title>Test for Bug 1163961</title>
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<script type="application/javascript" src="browserElementTestHelpers.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
</head>
<body>
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1163961">Mozilla Bug 1163961</a>
<script type="application/javascript;version=1.7" src="browserElement_Find.js">
</script>
</body>
</html>

Просмотреть файл

@ -0,0 +1,19 @@
<!DOCTYPE HTML>
<html>
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=1163961
-->
<head>
<title>Test for Bug 1163961</title>
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<script type="application/javascript" src="browserElementTestHelpers.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
</head>
<body>
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1163961">Mozilla Bug 1163961</a>
<script type="application/javascript;version=1.7" src="browserElement_Find.js">
</script>
</body>
</html>

Просмотреть файл

@ -26,9 +26,15 @@ interface nsIBrowserElementNextPaintListener : nsISupports
* Interface to the BrowserElementParent implementation. All methods
* but setFrameLoader throw when the remote process is dead.
*/
[scriptable, uuid(3811446f-90bb-42c1-b2b6-aae3603b61e1)]
[scriptable, uuid(8ecb598c-f886-11e4-9915-778f934fbf93)]
interface nsIBrowserElementAPI : nsISupports
{
const long FIND_CASE_SENSITIVE = 0;
const long FIND_CASE_INSENSITIVE = 1;
const long FIND_FORWARD = 0;
const long FIND_BACKWARD = 1;
void setFrameLoader(in nsIFrameLoader frameLoader);
void setVisible(in boolean visible);
@ -67,6 +73,10 @@ interface nsIBrowserElementAPI : nsISupports
nsIDOMDOMRequest getCanGoForward();
nsIDOMDOMRequest getContentDimensions();
void findAll(in DOMString searchString, in long caseSensitivity);
void findNext(in long direction);
void clearMatch();
void addNextPaintListener(in nsIBrowserElementNextPaintListener listener);
void removeNextPaintListener(in nsIBrowserElementNextPaintListener listener);

Просмотреть файл

@ -2352,11 +2352,16 @@ private:
void
CanvasRenderingContext2D::UpdateFilter()
{
nsIPresShell* presShell = GetPresShell();
nsCOMPtr<nsIPresShell> presShell = GetPresShell();
if (!presShell || presShell->IsDestroying()) {
return;
}
// The filter might reference an SVG filter that is declared inside this
// document. Flush frames so that we'll have an nsSVGFilterFrame to work
// with.
presShell->FlushPendingNotifications(Flush_Frames);
CurrentState().filter =
nsFilterInstance::GetFilterDescription(mCanvasElement,
CurrentState().filterChain,
@ -4700,11 +4705,17 @@ CanvasRenderingContext2D::DrawWindow(nsGlobalWindow& window, double x,
RefPtr<SourceSurface> snapshot = drawDT->Snapshot();
RefPtr<DataSourceSurface> data = snapshot->GetDataSurface();
DataSourceSurface::MappedSurface rawData;
if (NS_WARN_IF(!data->Map(DataSourceSurface::READ, &rawData))) {
error.Throw(NS_ERROR_FAILURE);
return;
}
RefPtr<SourceSurface> source =
mTarget->CreateSourceSurfaceFromData(data->GetData(),
mTarget->CreateSourceSurfaceFromData(rawData.mData,
data->GetSize(),
data->Stride(),
rawData.mStride,
data->GetFormat());
data->Unmap();
if (!source) {
error.Throw(NS_ERROR_FAILURE);
@ -4979,12 +4990,13 @@ CanvasRenderingContext2D::GetImageDataArray(JSContext* aCx,
IntRect destRect(aX, aY, aWidth, aHeight);
IntRect srcReadRect = srcRect.Intersect(destRect);
RefPtr<DataSourceSurface> readback;
DataSourceSurface::MappedSurface rawData;
if (!srcReadRect.IsEmpty() && !mZero) {
RefPtr<SourceSurface> snapshot = mTarget->Snapshot();
if (snapshot) {
readback = snapshot->GetDataSurface();
}
if (!readback || !readback->GetData()) {
if (!readback || !readback->Map(DataSourceSurface::READ, &rawData)) {
return NS_ERROR_OUT_OF_MEMORY;
}
}
@ -5006,8 +5018,8 @@ CanvasRenderingContext2D::GetImageDataArray(JSContext* aCx,
uint32_t srcStride;
if (readback) {
srcStride = readback->Stride();
src = readback->GetData() + srcReadRect.y * srcStride + srcReadRect.x * 4;
srcStride = rawData.mStride;
src = rawData.mData + srcReadRect.y * srcStride + srcReadRect.x * 4;
}
JS::AutoCheckCannotGC nogc;
@ -5071,6 +5083,10 @@ CanvasRenderingContext2D::GetImageDataArray(JSContext* aCx,
dst += (aWidth * 4) - (dstWriteRect.width * 4);
}
if (readback) {
readback->Unmap();
}
*aRetval = darray;
return NS_OK;
}

Просмотреть файл

@ -884,6 +884,7 @@ protected:
fillRule(mozilla::gfx::FillRule::FILL_WINDING),
lineCap(mozilla::gfx::CapStyle::BUTT),
lineJoin(mozilla::gfx::JoinStyle::MITER_OR_BEVEL),
filterString(MOZ_UTF16("none")),
imageSmoothingEnabled(true),
fontExplicitLanguage(false)
{ }

Просмотреть файл

@ -324,6 +324,7 @@ public:
void BindBufferBase(GLenum target, GLuint index, WebGLBuffer* buffer);
void BindBufferRange(GLenum target, GLuint index, WebGLBuffer* buffer, GLintptr offset, GLsizeiptr size);
*/
virtual JS::Value GetParameter(JSContext* cx, GLenum pname, ErrorResult& rv) override;
void GetIndexedParameter(GLenum target, GLuint index,
dom::Nullable<dom::OwningWebGLBufferOrLongLong>& retval);
void GetUniformIndices(WebGLProgram* program,

Просмотреть файл

@ -36,6 +36,12 @@ WebGL2Context::DeleteSampler(WebGLSampler* sampler)
if (!sampler || sampler->IsDeleted())
return;
for (int n = 0; n < mGLMaxTextureUnits; n++) {
if (mBoundSamplers[n] == sampler) {
mBoundSamplers[n] = nullptr;
}
}
sampler->RequestDelete();
}
@ -74,6 +80,8 @@ WebGL2Context::BindSampler(GLuint unit, WebGLSampler* sampler)
return ErrorInvalidOperation("bindSampler: binding deleted sampler");
WebGLContextUnchecked::BindSampler(unit, sampler);
mBoundSamplers[unit] = sampler;
}
void

Просмотреть файл

@ -0,0 +1,177 @@
/* -*- 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/. */
#include "WebGL2Context.h"
#include "WebGLContextUtils.h"
namespace mozilla {
JS::Value
WebGL2Context::GetParameter(JSContext* cx, GLenum pname, ErrorResult& rv)
{
// The following cases are handled in WebGLContext::GetParameter():
// case LOCAL_GL_MAX_COLOR_ATTACHMENTS:
// case LOCAL_GL_MAX_DRAW_BUFFERS:
// case LOCAL_GL_DRAW_BUFFERi:
if (IsContextLost())
return JS::NullValue();
MakeContextCurrent();
switch (pname) {
/* GLboolean */
case LOCAL_GL_RASTERIZER_DISCARD:
case LOCAL_GL_SAMPLE_ALPHA_TO_COVERAGE:
case LOCAL_GL_SAMPLE_COVERAGE:
case LOCAL_GL_TRANSFORM_FEEDBACK_PAUSED:
case LOCAL_GL_TRANSFORM_FEEDBACK_ACTIVE:
case LOCAL_GL_UNPACK_SKIP_IMAGES:
case LOCAL_GL_UNPACK_SKIP_PIXELS:
case LOCAL_GL_UNPACK_SKIP_ROWS: {
realGLboolean b = 0;
gl->fGetBooleanv(pname, &b);
return JS::BooleanValue(bool(b));
}
/* GLenum */
case LOCAL_GL_READ_BUFFER: {
if (mBoundReadFramebuffer) {
GLint val = LOCAL_GL_NONE;
gl->fGetIntegerv(pname, &val);
return JS::Int32Value(val);
}
return JS::Int32Value(LOCAL_GL_BACK);
}
case LOCAL_GL_FRAGMENT_SHADER_DERIVATIVE_HINT:
/* fall through */
/* GLint */
case LOCAL_GL_MAX_3D_TEXTURE_SIZE:
case LOCAL_GL_MAX_ARRAY_TEXTURE_LAYERS:
case LOCAL_GL_MAX_COMBINED_UNIFORM_BLOCKS:
case LOCAL_GL_MAX_ELEMENTS_INDICES:
case LOCAL_GL_MAX_ELEMENTS_VERTICES:
case LOCAL_GL_MAX_FRAGMENT_INPUT_COMPONENTS:
case LOCAL_GL_MAX_FRAGMENT_UNIFORM_BLOCKS:
case LOCAL_GL_MAX_FRAGMENT_UNIFORM_COMPONENTS:
case LOCAL_GL_MAX_PROGRAM_TEXEL_OFFSET:
case LOCAL_GL_MAX_SAMPLES:
case LOCAL_GL_MAX_TEXTURE_LOD_BIAS:
case LOCAL_GL_MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS:
case LOCAL_GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS:
case LOCAL_GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_COMPONENTS:
case LOCAL_GL_MAX_UNIFORM_BUFFER_BINDINGS:
case LOCAL_GL_MAX_VERTEX_OUTPUT_COMPONENTS:
case LOCAL_GL_MAX_VERTEX_UNIFORM_BLOCKS:
case LOCAL_GL_MAX_VERTEX_UNIFORM_COMPONENTS:
case LOCAL_GL_MIN_PROGRAM_TEXEL_OFFSET:
case LOCAL_GL_PACK_ROW_LENGTH:
case LOCAL_GL_PACK_SKIP_PIXELS:
case LOCAL_GL_PACK_SKIP_ROWS:
case LOCAL_GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT:
case LOCAL_GL_UNPACK_IMAGE_HEIGHT:
case LOCAL_GL_UNPACK_ROW_LENGTH: {
GLint val;
gl->fGetIntegerv(pname, &val);
return JS::Int32Value(val);
}
case LOCAL_GL_MAX_VARYING_COMPONENTS: {
// On OS X Core Profile this is buggy. The spec says that the
// value is 4 * GL_MAX_VARYING_VECTORS
GLint val;
gl->fGetIntegerv(LOCAL_GL_MAX_VARYING_VECTORS, &val);
return JS::Int32Value(4*val);
}
/* GLint64 */
case LOCAL_GL_MAX_CLIENT_WAIT_TIMEOUT_WEBGL:
return JS::NumberValue(0); // TODO
case LOCAL_GL_MAX_ELEMENT_INDEX:
// GL_MAX_ELEMENT_INDEX becomes available in GL 4.3 or via ES3
// compatibility
if (!gl->IsSupported(gl::GLFeature::ES3_compatibility))
return JS::NumberValue(0);
/*** fall through to fGetInteger64v ***/
case LOCAL_GL_MAX_COMBINED_FRAGMENT_UNIFORM_COMPONENTS:
case LOCAL_GL_MAX_COMBINED_VERTEX_UNIFORM_COMPONENTS:
case LOCAL_GL_MAX_UNIFORM_BLOCK_SIZE: {
GLint64 val;
gl->fGetInteger64v(pname, &val);
return JS::DoubleValue(static_cast<double>(val));
}
/* GLuint64 */
case LOCAL_GL_MAX_SERVER_WAIT_TIMEOUT: {
GLuint64 val;
gl->fGetInteger64v(pname, (GLint64*) &val);
return JS::DoubleValue(static_cast<double>(val));
}
case LOCAL_GL_COPY_READ_BUFFER_BINDING:
return WebGLObjectAsJSValue(cx, mBoundCopyReadBuffer.get(), rv);
case LOCAL_GL_COPY_WRITE_BUFFER_BINDING:
return WebGLObjectAsJSValue(cx, mBoundCopyWriteBuffer.get(), rv);
case LOCAL_GL_PIXEL_PACK_BUFFER_BINDING:
return WebGLObjectAsJSValue(cx, mBoundPixelPackBuffer.get(), rv);
case LOCAL_GL_PIXEL_UNPACK_BUFFER_BINDING:
return WebGLObjectAsJSValue(cx, mBoundPixelUnpackBuffer.get(), rv);
case LOCAL_GL_TRANSFORM_FEEDBACK_BUFFER_BINDING:
return WebGLObjectAsJSValue(cx, mBoundTransformFeedbackBuffer.get(), rv);
case LOCAL_GL_UNIFORM_BUFFER_BINDING:
return WebGLObjectAsJSValue(cx, mBoundUniformBuffer.get(), rv);
// DRAW_FRAMEBUFFER_BINDING is the same as FRAMEBUFFER_BINDING.
case LOCAL_GL_READ_FRAMEBUFFER_BINDING:
return WebGLObjectAsJSValue(cx, mBoundReadFramebuffer.get(), rv);
case LOCAL_GL_SAMPLER_BINDING:
return WebGLObjectAsJSValue(cx, mBoundSamplers[mActiveTexture].get(), rv);
case LOCAL_GL_TEXTURE_BINDING_2D_ARRAY:
// TODO: Implement gl.TEXTURE_2D_ARRAY
// return WebGLObjectAsJSValue(cx, mBound2DTextureArrays[mActiveTexture].get(), rv);
return JS::NullValue();
case LOCAL_GL_TEXTURE_BINDING_3D:
return WebGLObjectAsJSValue(cx, mBound3DTextures[mActiveTexture].get(), rv);
case LOCAL_GL_TRANSFORM_FEEDBACK_BINDING: {
WebGLTransformFeedback* tf =
(mBoundTransformFeedback != mDefaultTransformFeedback) ? mBoundTransformFeedback.get() : nullptr;
return WebGLObjectAsJSValue(cx, tf, rv);
}
case LOCAL_GL_VERTEX_ARRAY_BINDING: {
WebGLVertexArray* vao =
(mBoundVertexArray != mDefaultVertexArray) ? mBoundVertexArray.get() : nullptr;
return WebGLObjectAsJSValue(cx, vao, rv);
}
case LOCAL_GL_VERSION:
return StringValue(cx, "WebGL 2.0", rv);
case LOCAL_GL_SHADING_LANGUAGE_VERSION:
return StringValue(cx, "WebGL GLSL ES 3.00", rv);
default:
return WebGLContext::GetParameter(cx, pname, rv);
}
}
} // namespace mozilla

Просмотреть файл

@ -325,6 +325,7 @@ WebGLContext::DestroyResourcesAndContext()
mBound2DTextures.Clear();
mBoundCubeMapTextures.Clear();
mBound3DTextures.Clear();
mBoundSamplers.Clear();
mBoundArrayBuffer = nullptr;
mBoundCopyReadBuffer = nullptr;
mBoundCopyWriteBuffer = nullptr;
@ -1949,6 +1950,7 @@ NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(WebGLContext,
mBound2DTextures,
mBoundCubeMapTextures,
mBound3DTextures,
mBoundSamplers,
mBoundArrayBuffer,
mBoundCopyReadBuffer,
mBoundCopyWriteBuffer,

Просмотреть файл

@ -65,6 +65,16 @@ class nsIDocShell;
#define MINVALUE_GL_MAX_RENDERBUFFER_SIZE 1024 // Different from the spec, which sets it to 1 on page 164
#define MINVALUE_GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS 8 // Page 164
/*
* WebGL-only GLenums
*/
#define LOCAL_GL_BROWSER_DEFAULT_WEBGL 0x9244
#define LOCAL_GL_CONTEXT_LOST_WEBGL 0x9242
#define LOCAL_GL_MAX_CLIENT_WAIT_TIMEOUT_WEBGL 0x9247
#define LOCAL_GL_UNPACK_COLORSPACE_CONVERSION_WEBGL 0x9243
#define LOCAL_GL_UNPACK_FLIP_Y_WEBGL 0x9240
#define LOCAL_GL_UNPACK_PREMULTIPLY_ALPHA_WEBGL 0x9241
namespace mozilla {
class WebGLActiveInfo;
@ -955,7 +965,7 @@ public:
void Disable(GLenum cap);
void Enable(GLenum cap);
bool GetStencilBits(GLint* out_stencilBits);
JS::Value GetParameter(JSContext* cx, GLenum pname, ErrorResult& rv);
virtual JS::Value GetParameter(JSContext* cx, GLenum pname, ErrorResult& rv);
void GetParameter(JSContext* cx, GLenum pname,
JS::MutableHandle<JS::Value> retval, ErrorResult& rv)
@ -1435,6 +1445,7 @@ protected:
nsTArray<WebGLRefPtr<WebGLTexture> > mBound2DTextures;
nsTArray<WebGLRefPtr<WebGLTexture> > mBoundCubeMapTextures;
nsTArray<WebGLRefPtr<WebGLTexture> > mBound3DTextures;
nsTArray<WebGLRefPtr<WebGLSampler> > mBoundSamplers;
void ResolveTexturesForDraw() const;

Просмотреть файл

@ -58,18 +58,6 @@ WebGLContext::Enable(GLenum cap)
gl->fEnable(cap);
}
static JS::Value
StringValue(JSContext* cx, const char* chars, ErrorResult& rv)
{
JSString* str = JS_NewStringCopyZ(cx, chars);
if (!str) {
rv.Throw(NS_ERROR_OUT_OF_MEMORY);
return JS::NullValue();
}
return JS::StringValue(str);
}
bool
WebGLContext::GetStencilBits(GLint* out_stencilBits)
{
@ -150,18 +138,15 @@ WebGLContext::GetParameter(JSContext* cx, GLenum pname, ErrorResult& rv)
} else if (pname >= LOCAL_GL_DRAW_BUFFER0 &&
pname < GLenum(LOCAL_GL_DRAW_BUFFER0 + mGLMaxDrawBuffers))
{
if (mBoundDrawFramebuffer) {
GLint iv = 0;
gl->fGetIntegerv(pname, &iv);
return JS::Int32Value(iv);
}
GLint iv = 0;
gl->fGetIntegerv(pname, &iv);
if (iv == GLint(LOCAL_GL_COLOR_ATTACHMENT0 + pname - LOCAL_GL_DRAW_BUFFER0)) {
if (mBoundDrawFramebuffer)
return JS::Int32Value(iv);
const GLint index = (pname - LOCAL_GL_DRAW_BUFFER0);
if (iv == LOCAL_GL_COLOR_ATTACHMENT0 + index)
return JS::Int32Value(LOCAL_GL_BACK);
}
return JS::Int32Value(LOCAL_GL_NONE);
}
@ -169,11 +154,9 @@ WebGLContext::GetParameter(JSContext* cx, GLenum pname, ErrorResult& rv)
if (IsExtensionEnabled(WebGLExtensionID::OES_vertex_array_object)) {
if (pname == LOCAL_GL_VERTEX_ARRAY_BINDING) {
if (mBoundVertexArray == mDefaultVertexArray){
return WebGLObjectAsJSValue(cx, (WebGLVertexArray *) nullptr, rv);
}
return WebGLObjectAsJSValue(cx, mBoundVertexArray.get(), rv);
WebGLVertexArray* vao =
(mBoundVertexArray != mDefaultVertexArray) ? mBoundVertexArray.get() : nullptr;
return WebGLObjectAsJSValue(cx, vao, rv);
}
}
@ -181,10 +164,12 @@ WebGLContext::GetParameter(JSContext* cx, GLenum pname, ErrorResult& rv)
if (pname == LOCAL_GL_TIMESTAMP_EXT) {
GLuint64 iv = 0;
gl->fGetInteger64v(pname, (GLint64*) &iv);
return JS::NumberValue(uint64_t(iv));
// TODO: JS doesn't support 64-bit integers. Be lossy and
// cast to double (53 bits)
return JS::NumberValue(static_cast<double>(iv));
} else if (pname == LOCAL_GL_GPU_DISJOINT_EXT) {
// When disjoint isn't supported, leave as false.
realGLboolean disjoint = 0;
realGLboolean disjoint = LOCAL_GL_FALSE;
if (gl->IsExtensionSupported(gl::GLContext::EXT_disjoint_timer_query)) {
gl->fGetBooleanv(pname, &disjoint);
}
@ -192,40 +177,35 @@ WebGLContext::GetParameter(JSContext* cx, GLenum pname, ErrorResult& rv)
}
}
if (IsWebGL2()) {
// Privileged string params exposed by WEBGL_debug_renderer_info:
if (IsExtensionEnabled(WebGLExtensionID::WEBGL_debug_renderer_info)) {
switch (pname) {
case LOCAL_GL_MAX_SAMPLES:
case LOCAL_GL_MAX_UNIFORM_BLOCK_SIZE:
case LOCAL_GL_MAX_VERTEX_UNIFORM_COMPONENTS: {
GLint val;
gl->fGetIntegerv(pname, &val);
return JS::NumberValue(uint32_t(val));
case UNMASKED_VENDOR_WEBGL:
case UNMASKED_RENDERER_WEBGL:
GLenum glstringname = LOCAL_GL_NONE;
if (pname == UNMASKED_VENDOR_WEBGL) {
glstringname = LOCAL_GL_VENDOR;
} else if (pname == UNMASKED_RENDERER_WEBGL) {
glstringname = LOCAL_GL_RENDERER;
}
const GLchar* string = (const GLchar*) gl->fGetString(glstringname);
return StringValue(cx, string, rv);
}
}
case LOCAL_GL_TEXTURE_BINDING_3D:
return WebGLObjectAsJSValue(cx, mBound3DTextures[mActiveTexture].get(), rv);
if (IsExtensionEnabled(WebGLExtensionID::OES_standard_derivatives)) {
if (pname == LOCAL_GL_FRAGMENT_SHADER_DERIVATIVE_HINT) {
GLint i = 0;
gl->fGetIntegerv(pname, &i);
return JS::Int32Value(i);
}
}
// DRAW_FRAMEBUFFER_BINDING is the same as FRAMEBUFFER_BINDING.
case LOCAL_GL_READ_FRAMEBUFFER_BINDING:
return WebGLObjectAsJSValue(cx, mBoundReadFramebuffer.get(), rv);
case LOCAL_GL_PIXEL_PACK_BUFFER_BINDING:
return WebGLObjectAsJSValue(cx, mBoundPixelPackBuffer.get(), rv);
case LOCAL_GL_PIXEL_UNPACK_BUFFER_BINDING:
return WebGLObjectAsJSValue(cx, mBoundPixelUnpackBuffer.get(), rv);
case LOCAL_GL_UNIFORM_BUFFER_BINDING:
return WebGLObjectAsJSValue(cx, mBoundUniformBuffer.get(), rv);
case LOCAL_GL_TRANSFORM_FEEDBACK_BUFFER_BINDING:
return WebGLObjectAsJSValue(cx, mBoundTransformFeedbackBuffer.get(), rv);
case LOCAL_GL_COPY_READ_BUFFER_BINDING:
return WebGLObjectAsJSValue(cx, mBoundCopyReadBuffer.get(), rv);
case LOCAL_GL_COPY_WRITE_BUFFER_BINDING:
return WebGLObjectAsJSValue(cx, mBoundCopyWriteBuffer.get(), rv);
if (IsExtensionEnabled(WebGLExtensionID::EXT_texture_filter_anisotropic)) {
if (pname == LOCAL_GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT) {
GLfloat f = 0.f;
gl->fGetFloatv(pname, &f);
return JS::NumberValue(f);
}
}
@ -234,42 +214,13 @@ WebGLContext::GetParameter(JSContext* cx, GLenum pname, ErrorResult& rv)
// String params
//
case LOCAL_GL_VENDOR:
return StringValue(cx, "Mozilla", rv);
case LOCAL_GL_RENDERER:
return StringValue(cx, "Mozilla", rv);
case LOCAL_GL_VERSION: {
const char* version = 0;
if (IsWebGL2()) {
version = "WebGL 2.0";
} else {
version = "WebGL 1.0";
}
MOZ_ASSERT(version != 0);
return StringValue(cx, version, rv);
}
case LOCAL_GL_VERSION:
return StringValue(cx, "WebGL 1.0", rv);
case LOCAL_GL_SHADING_LANGUAGE_VERSION:
return StringValue(cx, "WebGL GLSL ES 1.0", rv);
// Privileged string params exposed by WEBGL_debug_renderer_info:
case UNMASKED_VENDOR_WEBGL:
case UNMASKED_RENDERER_WEBGL: {
// The privilege check is done in WebGLContext::IsExtensionSupported.
// So here we just have to check that the extension is enabled.
if (!IsExtensionEnabled(WebGLExtensionID::WEBGL_debug_renderer_info)) {
break;
}
GLenum glstringname = LOCAL_GL_NONE;
if (pname == UNMASKED_VENDOR_WEBGL) {
glstringname = LOCAL_GL_VENDOR;
} else if (pname == UNMASKED_RENDERER_WEBGL) {
glstringname = LOCAL_GL_RENDERER;
}
const char* string = reinterpret_cast<const char*>(gl->fGetString(glstringname));
return StringValue(cx, string, rv);
}
////////////////////////////////
// Single-value params
@ -380,15 +331,6 @@ WebGLContext::GetParameter(JSContext* cx, GLenum pname, ErrorResult& rv)
}
return JS::Int32Value(i);
}
case LOCAL_GL_FRAGMENT_SHADER_DERIVATIVE_HINT: {
if (IsExtensionEnabled(WebGLExtensionID::OES_standard_derivatives)) {
GLint i = 0;
gl->fGetIntegerv(pname, &i);
return JS::Int32Value(i);
} else {
break;
}
}
case LOCAL_GL_MAX_TEXTURE_SIZE:
return JS::Int32Value(mGLMaxTextureSize);
@ -417,38 +359,22 @@ WebGLContext::GetParameter(JSContext* cx, GLenum pname, ErrorResult& rv)
}
return JS::ObjectOrNullValue(obj);
}
case LOCAL_GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS: {
if (!IsWebGL2()) {
break;
}
return JS::Int32Value(mGLMaxTransformFeedbackSeparateAttribs);
}
// unsigned int. here we may have to return very large values like 2^32-1 that can't be represented as
// javascript integer values. We just return them as doubles and javascript doesn't care.
case LOCAL_GL_STENCIL_BACK_VALUE_MASK: {
case LOCAL_GL_STENCIL_BACK_VALUE_MASK:
return JS::DoubleValue(mStencilValueMaskBack); // pass as FP value to allow large values such as 2^32-1.
}
case LOCAL_GL_STENCIL_BACK_WRITEMASK: {
case LOCAL_GL_STENCIL_BACK_WRITEMASK:
return JS::DoubleValue(mStencilWriteMaskBack);
}
case LOCAL_GL_STENCIL_VALUE_MASK: {
case LOCAL_GL_STENCIL_VALUE_MASK:
return JS::DoubleValue(mStencilValueMaskFront);
}
case LOCAL_GL_STENCIL_WRITEMASK: {
case LOCAL_GL_STENCIL_WRITEMASK:
return JS::DoubleValue(mStencilWriteMaskFront);
}
// float
case LOCAL_GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT: {
if (IsExtensionEnabled(WebGLExtensionID::EXT_texture_filter_anisotropic)) {
GLfloat f = 0.f;
gl->fGetFloatv(pname, &f);
return JS::DoubleValue(f);
} else {
break;
}
}
case LOCAL_GL_DEPTH_CLEAR_VALUE:
case LOCAL_GL_LINE_WIDTH:
case LOCAL_GL_POLYGON_OFFSET_FACTOR:

Просмотреть файл

@ -75,6 +75,18 @@ TexImageTargetToTexTarget(TexImageTarget texImageTarget)
}
}
JS::Value
StringValue(JSContext* cx, const char* chars, ErrorResult& rv)
{
JSString* str = JS_NewStringCopyZ(cx, chars);
if (!str) {
rv.Throw(NS_ERROR_OUT_OF_MEMORY);
return JS::NullValue();
}
return JS::StringValue(str);
}
GLComponents::GLComponents(TexInternalFormat internalformat)
{
TexInternalFormat unsizedformat = UnsizedInternalFormatFromInternalFormat(internalformat);

Просмотреть файл

@ -56,6 +56,9 @@ size_t GetBitsPerTexel(TexInternalFormat effectiveinternalformat);
// Returns GL_NONE if passed an invalid texture image target
TexTarget TexImageTargetToTexTarget(TexImageTarget texImageTarget);
// Helper function to create a JS::Value from a C string
JS::Value StringValue(JSContext* cx, const char* str, ErrorResult& rv);
struct GLComponents
{
unsigned char mComponents;

Просмотреть файл

@ -1755,6 +1755,7 @@ WebGLContext::InitAndValidateGL()
mBound2DTextures.Clear();
mBoundCubeMapTextures.Clear();
mBound3DTextures.Clear();
mBoundSamplers.Clear();
mBoundArrayBuffer = nullptr;
mBoundTransformFeedbackBuffer = nullptr;
@ -1798,6 +1799,7 @@ WebGLContext::InitAndValidateGL()
mBound2DTextures.SetLength(mGLMaxTextureUnits);
mBoundCubeMapTextures.SetLength(mGLMaxTextureUnits);
mBound3DTextures.SetLength(mGLMaxTextureUnits);
mBoundSamplers.SetLength(mGLMaxTextureUnits);
if (MinCapabilityMode()) {
mGLMaxTextureSize = MINVALUE_GL_MAX_TEXTURE_SIZE;

Просмотреть файл

@ -7,6 +7,7 @@
#ifndef WEBGL_TIMER_QUERY_H_
#define WEBGL_TIMER_QUERY_H_
#include "GLConsts.h"
#include "nsWrapperCache.h"
#include "WebGLObjectModel.h"

Просмотреть файл

@ -61,6 +61,7 @@ UNIFIED_SOURCES += [
'WebGL2ContextPrograms.cpp',
'WebGL2ContextQueries.cpp',
'WebGL2ContextSamplers.cpp',
'WebGL2ContextState.cpp',
'WebGL2ContextSync.cpp',
'WebGL2ContextTextures.cpp',
'WebGL2ContextTransformFeedback.cpp',

Просмотреть файл

@ -249,3 +249,4 @@ skip-if = (buildapp == 'b2g' && toolkit != 'gonk') # bug 1040965
[test_2d_composite_canvaspattern_setTransform.html]
[test_createPattern_broken.html]
[test_setlinedash.html]
[test_filter.html]

Просмотреть файл

@ -0,0 +1,16 @@
<!DOCTYPE html>
<html>
<body>
<canvas id="canvas" width="100" height="100"></canvas>
<script>
var canvas = document.getElementById('canvas');
var ctx = canvas.getContext('2d');
ctx.filter = 'drop-shadow(0 10px)';
ctx.fillStyle = '#0f0';
ctx.fillRect(25, 25, 50, 40);
</script>
</body>
</html>

Просмотреть файл

@ -0,0 +1,17 @@
<!DOCTYPE html>
<html>
<body>
<canvas id="canvas" width="100" height="100"></canvas>
<script>
var canvas = document.getElementById('canvas');
var ctx = canvas.getContext('2d');
ctx.fillStyle = '#0f0';
ctx.scale(-1, -1);
ctx.filter = 'drop-shadow(0 10px black)';
ctx.fillRect(-75, -65, 50, 40);
</script>
</body>
</html>

Просмотреть файл

@ -0,0 +1,16 @@
<!DOCTYPE html>
<html>
<body>
<canvas id="canvas" width="100" height="100"></canvas>
<script>
var canvas = document.getElementById('canvas');
var ctx = canvas.getContext('2d');
ctx.filter = 'drop-shadow(0 10px black)';
ctx.fillStyle = '#0f0';
ctx.fillRect(25, 25, 50, 40);
</script>
</body>
</html>

Просмотреть файл

@ -0,0 +1,18 @@
<!DOCTYPE html>
<html>
<body>
<canvas id="canvas" width="100" height="100"></canvas>
<script>
var canvas = document.getElementById('canvas');
var ctx = canvas.getContext('2d');
ctx.globalAlpha = 0.5;
ctx.fillStyle = '#000';
ctx.fillRect(25, 35, 50, 40);
ctx.fillStyle = '#0f0';
ctx.fillRect(25, 25, 50, 40);
</script>
</body>
</html>

Просмотреть файл

@ -0,0 +1,17 @@
<!DOCTYPE html>
<html>
<body>
<canvas id="canvas" width="100" height="100"></canvas>
<script>
var canvas = document.getElementById('canvas');
var ctx = canvas.getContext('2d');
ctx.filter = 'drop-shadow(0 10px black)';
ctx.globalAlpha = 0.5;
ctx.fillStyle = '#0f0';
ctx.fillRect(25, 25, 50, 40);
</script>
</body>
</html>

Просмотреть файл

@ -0,0 +1,26 @@
<!DOCTYPE html>
<html>
<body>
<canvas id="canvas" width="100" height="100"></canvas>
<script>
var canvas = document.getElementById('canvas');
var ctx = canvas.getContext('2d');
ctx.fillStyle = '#000';
ctx.arc(50, 50, 25, 0, Math.PI * 2, true);
ctx.fill();
var tmp_canvas = canvas.cloneNode();
var tmp_ctx = tmp_canvas.getContext('2d');
tmp_ctx.fillStyle = '#0f0';
tmp_ctx.fillRect(25, 25, 50, 50);
tmp_ctx.fillStyle = '#000';
tmp_ctx.fillRect(25, 65, 50, 10);
ctx.globalCompositeOperation = 'source-in';
ctx.drawImage(tmp_canvas, 0, 0);
</script>
</body>
</html>

Просмотреть файл

@ -0,0 +1,21 @@
<!DOCTYPE html>
<html>
<body>
<canvas id="canvas" width="100" height="100"></canvas>
<script>
var canvas = document.getElementById('canvas');
var ctx = canvas.getContext('2d');
ctx.fillStyle = '#000';
ctx.arc(50, 50, 25, 0, Math.PI * 2, true);
ctx.fill();
ctx.filter = 'drop-shadow(0 10px black)';
ctx.globalCompositeOperation = 'source-in';
ctx.fillStyle = '#0f0';
ctx.fillRect(25, 25, 50, 40);
</script>
</body>
</html>

Просмотреть файл

@ -0,0 +1,18 @@
<!DOCTYPE html>
<html>
<body>
<canvas id="canvas" width="100" height="100"></canvas>
<script>
var canvas = document.getElementById('canvas');
var ctx = canvas.getContext('2d');
ctx.font = '10px sans-serif';
ctx.filter = 'drop-shadow(0 .5em black)';
ctx.font = '20px sans-serif';
ctx.fillStyle = '#0f0';
ctx.fillRect(25, 25, 50, 40);
</script>
</body>
</html>

Просмотреть файл

@ -0,0 +1,16 @@
<!DOCTYPE html>
<html>
<body>
<canvas id="canvas" width="100" height="100"></canvas>
<script>
var canvas = document.getElementById('canvas');
var ctx = canvas.getContext('2d');
ctx.fillStyle = '#0f0';
ctx.filter = 'drop-shadow(0 10px black) drop-shadow(10px 0 #ccc)';
ctx.fillRect(20, 25, 50, 40);
</script>
</body>
</html>

Просмотреть файл

@ -0,0 +1,17 @@
<!DOCTYPE html>
<html>
<body>
<canvas id="canvas" width="100" height="100"></canvas>
<script>
var canvas = document.getElementById('canvas');
var ctx = canvas.getContext('2d');
ctx.fillStyle = '#0f0';
ctx.fillRect(25, 25, 50, 40);
ctx.fillStyle = '#000';
ctx.fillRect(25, 65, 50, 10);
</script>
</body>
</html>

Просмотреть файл

@ -0,0 +1,20 @@
default-preferences pref(canvas.filters.enabled,true)
== default-color.html ref.html
== drop-shadow.html ref.html
== drop-shadow-transformed.html ref.html
== global-alpha.html global-alpha-ref.html
== global-composite-operation.html global-composite-operation-ref.html
== liveness.html ref.html
== multiple-drop-shadows.html shadow-ref.html
== shadow.html shadow-ref.html
== subregion-fill-paint.html subregion-ref.html
== subregion-stroke-paint.html subregion-ref.html
== svg-bbox.html svg-bbox-ref.html
== svg-inline.html ref.html
== svg-liveness.html ref.html
== svg-off-screen.html ref.html
== units.html ref.html
== units-em.html ref.html
== units-ex.html ref.html
== units-off-screen.html ref.html

Просмотреть файл

@ -0,0 +1,19 @@
<!DOCTYPE html>
<html>
<body>
<canvas id="canvas" width="100" height="100"></canvas>
<script>
var canvas = document.getElementById('canvas');
var ctx = canvas.getContext('2d');
ctx.fillStyle = '#0f0';
ctx.shadowOffsetX = 10;
ctx.shadowColor = '#ccc';
ctx.fillRect(20, 25, 50, 40);
ctx.fillStyle = '#000';
ctx.fillRect(20, 65, 50, 10);
</script>
</body>
</html>

Просмотреть файл

@ -0,0 +1,18 @@
<!DOCTYPE html>
<html>
<body>
<canvas id="canvas" width="100" height="100"></canvas>
<script>
var canvas = document.getElementById('canvas');
var ctx = canvas.getContext('2d');
ctx.fillStyle = '#0f0';
ctx.filter = 'drop-shadow(0 10px black)';
ctx.shadowOffsetX = 10;
ctx.shadowColor = '#ccc';
ctx.fillRect(20, 25, 50, 40);
</script>
</body>
</html>

Просмотреть файл

@ -0,0 +1,27 @@
<!DOCTYPE html>
<html>
<body>
<svg style="display: block; width: 0; height: 0">
<defs>
<filter id="merge" primitiveUnits="objectBoundingBox">
<feMerge x="25%" y="25%" width="50%" height="50%">
<feMergeNode in="SourceGraphic"/>
<feMergeNode in="FillPaint"/>
</feMerge>
</filter>
</defs>
</svg>
<canvas id="canvas" width="100" height="100"></canvas>
<script>
var canvas = document.getElementById('canvas');
var ctx = canvas.getContext('2d');
ctx.filter = 'url(#merge)';
ctx.fillStyle = '#0f0';
ctx.arc(50, 50, 25, 0, Math.PI * 2, true);
ctx.fill();
</script>
</body>
</html>

Просмотреть файл

@ -0,0 +1,15 @@
<!DOCTYPE html>
<html>
<body>
<canvas id="canvas" width="100" height="100"></canvas>
<script>
var canvas = document.getElementById('canvas');
var ctx = canvas.getContext('2d');
ctx.fillStyle = '#0f0';
ctx.fillRect(25, 25, 50, 50);
</script>
</body>
</html>

Просмотреть файл

@ -0,0 +1,27 @@
<!DOCTYPE html>
<html>
<body>
<svg style="display: block; width: 0; height: 0">
<defs>
<filter id="merge" primitiveUnits="objectBoundingBox">
<feMerge x="25%" y="25%" width="50%" height="50%">
<feMergeNode in="SourceGraphic"/>
<feMergeNode in="StrokePaint"/>
</feMerge>
</filter>
</defs>
</svg>
<canvas id="canvas" width="100" height="100"></canvas>
<script>
var canvas = document.getElementById('canvas');
var ctx = canvas.getContext('2d');
ctx.filter = 'url(#merge)';
ctx.strokeStyle = '#0f0';
ctx.arc(50, 50, 25, 0, Math.PI * 2, true);
ctx.fill();
</script>
</body>
</html>

Просмотреть файл

@ -0,0 +1,15 @@
<!DOCTYPE html>
<html>
<body>
<canvas id="canvas" width="100" height="100"></canvas>
<script>
var canvas = document.getElementById('canvas');
var ctx = canvas.getContext('2d');
ctx.fillStyle = '#0f0';
ctx.fillRect(0, 0, 100, 100);
</script>
</body>
</html>

Просмотреть файл

@ -0,0 +1,27 @@
<!DOCTYPE html>
<html>
<body>
<svg style="display: block; width: 0; height: 0">
<defs>
<filter id="color-matrix">
<feColorMatrix type="matrix" in="SourceGraphic"
values="0 0 0 0 0
0 0 0 0 255
0 0 0 0 0
0 0 0 0 255"/>
</filter>
</defs>
</svg>
<canvas id="canvas" width="100" height="100"></canvas>
<script>
var canvas = document.getElementById('canvas');
var ctx = canvas.getContext('2d');
ctx.filter = 'url(#color-matrix)';
ctx.fillStyle = '#fff';
ctx.fillRect(25, 25, 50, 50);
</script>
</body>
</html>

Просмотреть файл

@ -0,0 +1,30 @@
<!DOCTYPE html>
<html>
<body>
<svg style="display: block; width: 0; height: 0">
<defs>
<filter id="drop-shadow">
<feGaussianBlur in="SourceAlpha" stdDeviation="0"/>
<feOffset dx="0" dy="10" result="offsetblur"/>
<feFlood flood-color="rgba(0,0,0,1)"/>
<feComposite in2="offsetblur" operator="in"/>
<feMerge>
<feMergeNode/>
<feMergeNode in="SourceGraphic"/>
</feMerge>
</filter>
</defs>
</svg>
<canvas id="canvas" width="100" height="100"></canvas>
<script>
var canvas = document.getElementById('canvas');
var ctx = canvas.getContext('2d');
ctx.filter = 'url(#drop-shadow)';
ctx.fillStyle = '#0f0';
ctx.fillRect(25, 25, 50, 40);
</script>
</body>
</html>

Просмотреть файл

@ -0,0 +1,64 @@
<!DOCTYPE html>
<html>
<body>
<script>
var svg = document.createElementNS('http://www.w3.org/2000/svg', 'svg');
svg.setAttribute('style', 'display: block; width: 0; height: 0');
var defs = document.createElementNS('http://www.w3.org/2000/svg', 'defs');
var dropShadowFilter = document.createElementNS('http://www.w3.org/2000/svg', 'filter');
dropShadowFilter.setAttribute('id', 'drop-shadow');
var gaussianFilter = document.createElementNS('http://www.w3.org/2000/svg', 'feGaussianBlur');
gaussianFilter.setAttribute('in', 'SourceAlpha');
gaussianFilter.setAttribute('stdDeviation', '0');
dropShadowFilter.appendChild(gaussianFilter);
var offset = document.createElementNS('http://www.w3.org/2000/svg', 'feOffset');
offset.setAttribute('dx', '0');
offset.setAttribute('dy', '0');
offset.setAttribute('result', 'offsetblur');
dropShadowFilter.appendChild(offset);
var flood = document.createElementNS('http://www.w3.org/2000/svg', 'feFlood');
flood.setAttribute('flood-color', 'rgba(0,0,0,1)');
dropShadowFilter.appendChild(flood);
var composite = document.createElementNS('http://www.w3.org/2000/svg', 'feComposite');
composite.setAttribute('in2', 'offsetblur');
composite.setAttribute('operator', 'in');
dropShadowFilter.appendChild(composite);
var merge = document.createElementNS('http://www.w3.org/2000/svg', 'feMerge');
var mergeNode = document.createElementNS('http://www.w3.org/2000/svg', 'feMergeNode');
merge.appendChild(mergeNode);
var mergeNode = document.createElementNS('http://www.w3.org/2000/svg', 'feMergeNode');
mergeNode.setAttribute('in', 'SourceGraphic');
merge.appendChild(mergeNode);
dropShadowFilter.appendChild(merge);
defs.appendChild(dropShadowFilter);
svg.appendChild(defs);
document.body.appendChild(svg);
</script>
<canvas id="canvas" width="100" height="100"></canvas>
<script>
var canvas = document.getElementById('canvas');
var ctx = canvas.getContext('2d');
ctx.filter = 'url(#drop-shadow)';
offset.setAttribute('dy', '10');
ctx.fillStyle = '#0f0';
ctx.fillRect(25, 25, 50, 40);
</script>
</body>
</html>

Просмотреть файл

@ -0,0 +1,33 @@
<!DOCTYPE html>
<html>
<body>
<svg style="display: block; width: 0; height: 0">
<defs>
<filter id="drop-shadow">
<feGaussianBlur in="SourceAlpha" stdDeviation="0"/>
<feOffset dx="0" dy="10" result="offsetblur"/>
<feFlood flood-color="rgba(0,0,0,1)"/>
<feComposite in2="offsetblur" operator="in"/>
<feMerge>
<feMergeNode/>
<feMergeNode in="SourceGraphic"/>
</feMerge>
</filter>
</defs>
</svg>
<script>
var canvas = document.createElement('canvas');
canvas.width = 100;
canvas.height = 100;
var ctx = canvas.getContext('2d');
ctx.filter = 'url(#drop-shadow)';
ctx.fillStyle = '#0f0';
ctx.fillRect(25, 25, 50, 40);
document.body.appendChild(canvas);
</script>
</body>
</html>

Просмотреть файл

@ -0,0 +1,17 @@
<!DOCTYPE html>
<html>
<body>
<canvas id="canvas" width="100" height="100"></canvas>
<script>
var canvas = document.getElementById('canvas');
var ctx = canvas.getContext('2d');
ctx.font = '20px sans-serif';
ctx.filter = 'drop-shadow(0 .5em black)';
ctx.fillStyle = '#0f0';
ctx.fillRect(25, 25, 25, 40);
canvas.style.fontSize = '5px';
ctx.font = '4em sans-serif';
ctx.filter = 'drop-shadow(0 .5em black)';

Просмотреть файл

@ -0,0 +1,17 @@
<!DOCTYPE html>
<html>
<body>
<canvas id="canvas" width="100" height="100"></canvas>
<script>
var canvas = document.getElementById('canvas');
var ctx = canvas.getContext('2d');
ctx.font = '10px sans-serif';
ctx.filter = 'drop-shadow(0 2ex black)';
ctx.fillStyle = '#0f0';
ctx.fillRect(25, 25, 50, 40);
</script>
</body>
</html>

Просмотреть файл

@ -0,0 +1,21 @@
<!DOCTYPE html>
<html>
<body>
<script>
var canvas = document.createElement('canvas');
canvas.width = 500;
canvas.height = 500;
canvas.style.width = '100px';
canvas.style.height = '100px';
var ctx = canvas.getContext('2d');
ctx.filter = 'drop-shadow(0 50px black)';
ctx.fillStyle = '#0f0';
ctx.fillRect(125, 125, 250, 200);
document.body.appendChild(canvas);
</script>
</body>
</html>

Просмотреть файл

@ -0,0 +1,16 @@
<!DOCTYPE html>
<html>
<body>
<canvas id="canvas" width="100" height="100"></canvas>
<script>
var canvas = document.getElementById('canvas');
var ctx = canvas.getContext('2d');
ctx.filter = 'drop-shadow(0 10mm black)';
ctx.fillStyle = '#0f0';
ctx.fillRect(25, 25, 50, 40);
</script>
</body>
</html>

Просмотреть файл

@ -0,0 +1,16 @@
<!DOCTYPE html>
<html>
<body>
<canvas id="canvas" width="500" height="500" style="width: 100px; height: 100px"></canvas>
<script>
var canvas = document.getElementById('canvas');
var ctx = canvas.getContext('2d');
ctx.filter = 'drop-shadow(0 50px black)';
ctx.fillStyle = '#0f0';
ctx.fillRect(125, 125, 250, 200);
</script>
</body>
</html>

Просмотреть файл

@ -0,0 +1,45 @@
<!DOCTYPE HTML>
<script src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" href="/tests/SimpleTest/test.css">
<body>
<script>
SpecialPowers.pushPrefEnv({ 'set': [['canvas.filters.enabled', true]] }, function () {
var canvas = document.createElement('canvas');
var ctx = canvas.getContext('2d');
is(ctx.filter, 'none', 'filter should intialy be set to \'none\'');
ctx.filter = 'blur(5px)';
is(ctx.filter, 'blur(5px)', 'valid filter should round-trip');
ctx.save();
ctx.filter = 'none';
is(ctx.filter, 'none', 'none should unset the filter');
ctx.restore();
is(ctx.filter, 'blur(5px)', 'filter should be part of the state');
ctx.filter = 'blur(10)';
is(ctx.filter, 'blur(5px)', 'invalid filter should be ignored');
ctx.filter = 'blur 10px';
is(ctx.filter, 'blur(5px)', 'syntax error should be ignored');
ctx.filter = 'inherit';
is(ctx.filter, 'blur(5px)', 'inherit should be ignored');
ctx.filter = 'initial';
is(ctx.filter, 'blur(5px)', 'initial should be ignored');
ctx.filter = '';
is(ctx.filter, 'blur(5px)', 'empty string should be ignored and not unset the filter');
ctx.filter = null;
is(ctx.filter, 'blur(5px)', 'null should be ignored and not unset the filter');
ctx.filter = undefined;
is(ctx.filter, 'blur(5px)', 'undefined should be ignored and not unset the filter');
SimpleTest.finish();
});
SimpleTest.waitForExplicitFinish();
</script>

Просмотреть файл

@ -427,6 +427,10 @@ const kEventConstructors = {
return e;
},
},
SpeechRecognitionError: { create: function (aName, aProps) {
return new SpeechRecognitionError(aName, aProps);
},
},
SpeechRecognitionEvent: { create: function (aName, aProps) {
return new SpeechRecognitionEvent(aName, aProps);
},

Просмотреть файл

@ -17,8 +17,6 @@
#include "nsIURL.h"
#include "nsIIOService.h"
#include "nsIServiceManager.h"
#include "nsIAppShell.h"
#include "nsWidgetsCID.h"
#include "nsNetUtil.h"
#include "nsContentUtils.h"
#include "nsContainerFrame.h"
@ -53,8 +51,6 @@
#include "mozilla/Preferences.h"
static const char *kPrefSrcsetEnabled = "dom.image.srcset.enabled";
static NS_DEFINE_CID(kAppShellCID, NS_APPSHELL_CID);
NS_IMPL_NS_NEW_HTML_ELEMENT(Image)
#ifdef DEBUG
@ -882,15 +878,11 @@ HTMLImageElement::QueueImageLoadTask()
return;
}
// The task checks this to determine if it was the last queued event, so this
// implicitly cancels earlier tasks
mPendingImageLoadTask = new ImageLoadTask(this);
nsCOMPtr<nsIAppShell> appShell = do_GetService(kAppShellCID);
if (appShell) {
appShell->RunInStableState(mPendingImageLoadTask);
} else {
MOZ_ASSERT(false, "expect appshell for HTMLImageElement");
}
nsCOMPtr<nsIRunnable> task = new ImageLoadTask(this);
// The task checks this to determine if it was the last
// queued event, and so earlier tasks are implicitly canceled.
mPendingImageLoadTask = task;
nsContentUtils::RunInStableState(task.forget());
}
bool

Просмотреть файл

@ -61,8 +61,6 @@
#include "Layers.h"
#include <limits>
#include "nsIAsyncVerifyRedirectCallback.h"
#include "nsIAppShell.h"
#include "nsWidgetsCID.h"
#include "nsMediaFragmentURIParser.h"
#include "nsURIHashKey.h"
#include "nsJSUtils.h"
@ -758,13 +756,10 @@ public:
}
};
static NS_DEFINE_CID(kAppShellCID, NS_APPSHELL_CID);
void HTMLMediaElement::RunInStableState(nsIRunnable* aRunnable)
{
nsCOMPtr<nsIRunnable> event = new nsSyncSection(this, aRunnable);
nsCOMPtr<nsIAppShell> appShell = do_GetService(kAppShellCID);
appShell->RunInStableState(event);
nsContentUtils::RunInStableState(event.forget());
}
void HTMLMediaElement::QueueLoadFromSourceTask()

Просмотреть файл

@ -161,7 +161,12 @@ HTMLObjectElement::OnFocusBlurPlugin(Element* aElement, bool aFocus)
nsCOMPtr<nsIObjectLoadingContent> olc = do_QueryInterface(aElement);
bool hasRunningPlugin = false;
if (olc) {
olc->GetHasRunningPlugin(&hasRunningPlugin);
// nsIObjectLoadingContent::GetHasRunningPlugin() fails when
// nsContentUtils::IsCallerChrome() returns false (which it can do even
// when we're processing a trusted focus event). We work around this by
// calling nsObjectLoadingContent::HasRunningPlugin() directly.
hasRunningPlugin =
static_cast<nsObjectLoadingContent*>(olc.get())->HasRunningPlugin();
}
if (!hasRunningPlugin) {
aFocus = false;

Просмотреть файл

@ -376,6 +376,62 @@ nsBrowserElement::GetContentDimensions(ErrorResult& aRv)
return req.forget().downcast<DOMRequest>();
}
void
nsBrowserElement::FindAll(const nsAString& aSearchString,
BrowserFindCaseSensitivity aCaseSensitivity,
ErrorResult& aRv)
{
NS_ENSURE_TRUE_VOID(IsBrowserElementOrThrow(aRv));
NS_ENSURE_TRUE_VOID(IsNotWidgetOrThrow(aRv));
uint32_t caseSensitivity;
if (aCaseSensitivity == BrowserFindCaseSensitivity::Case_insensitive) {
caseSensitivity = nsIBrowserElementAPI::FIND_CASE_INSENSITIVE;
} else {
caseSensitivity = nsIBrowserElementAPI::FIND_CASE_SENSITIVE;
}
nsresult rv = mBrowserElementAPI->FindAll(aSearchString, caseSensitivity);
if (NS_FAILED(rv)) {
aRv.Throw(rv);
}
}
void
nsBrowserElement::FindNext(BrowserFindDirection aDirection,
ErrorResult& aRv)
{
NS_ENSURE_TRUE_VOID(IsBrowserElementOrThrow(aRv));
NS_ENSURE_TRUE_VOID(IsNotWidgetOrThrow(aRv));
uint32_t direction;
if (aDirection == BrowserFindDirection::Backward) {
direction = nsIBrowserElementAPI::FIND_BACKWARD;
} else {
direction = nsIBrowserElementAPI::FIND_FORWARD;
}
nsresult rv = mBrowserElementAPI->FindNext(direction);
if (NS_FAILED(rv)) {
aRv.Throw(rv);
}
}
void
nsBrowserElement::ClearMatch(ErrorResult& aRv)
{
NS_ENSURE_TRUE_VOID(IsBrowserElementOrThrow(aRv));
NS_ENSURE_TRUE_VOID(IsNotWidgetOrThrow(aRv));
nsresult rv = mBrowserElementAPI->ClearMatch();
if (NS_FAILED(rv)) {
aRv.Throw(rv);
}
}
void
nsBrowserElement::AddNextPaintListener(BrowserElementNextPaintEventCallback& aListener,
ErrorResult& aRv)

Просмотреть файл

@ -20,6 +20,8 @@ namespace dom {
struct BrowserElementDownloadOptions;
class BrowserElementNextPaintEventCallback;
class DOMRequest;
enum class BrowserFindCaseSensitivity: uint32_t;
enum class BrowserFindDirection: uint32_t;
} // namespace dom
class ErrorResult;
@ -80,6 +82,11 @@ public:
already_AddRefed<dom::DOMRequest> GetCanGoForward(ErrorResult& aRv);
already_AddRefed<dom::DOMRequest> GetContentDimensions(ErrorResult& aRv);
void FindAll(const nsAString& aSearchString, dom::BrowserFindCaseSensitivity aCaseSensitivity,
ErrorResult& aRv);
void FindNext(dom::BrowserFindDirection aDirection, ErrorResult& aRv);
void ClearMatch(ErrorResult& aRv);
void AddNextPaintListener(dom::BrowserElementNextPaintEventCallback& listener,
ErrorResult& aRv);
void RemoveNextPaintListener(dom::BrowserElementNextPaintEventCallback& listener,

Просмотреть файл

@ -2518,6 +2518,7 @@ BackgroundCursorChild::HandleResponse(
auto& response = const_cast<ObjectStoreCursorResponse&>(aResponse);
StructuredCloneReadInfo cloneReadInfo(Move(response.cloneInfo()));
cloneReadInfo.mDatabase = mTransaction->Database();
ConvertActorsToBlobs(mTransaction->Database(),
response.cloneInfo(),
@ -2579,6 +2580,7 @@ BackgroundCursorChild::HandleResponse(const IndexCursorResponse& aResponse)
auto& response = const_cast<IndexCursorResponse&>(aResponse);
StructuredCloneReadInfo cloneReadInfo(Move(response.cloneInfo()));
cloneReadInfo.mDatabase = mTransaction->Database();
ConvertActorsToBlobs(mTransaction->Database(),
aResponse.cloneInfo(),

Просмотреть файл

@ -367,15 +367,14 @@ IDBFactory::AllowedForWindowInternal(nsPIDOMWindow* aWindow,
return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR;
}
if (nsContentUtils::IsSystemPrincipal(principal)) {
principal.forget(aPrincipal);
return NS_OK;
bool isSystemPrincipal;
if (!AllowedForPrincipal(principal, &isSystemPrincipal)) {
return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR;
}
bool isNullPrincipal;
if (NS_WARN_IF(NS_FAILED(principal->GetIsNullPrincipal(&isNullPrincipal))) ||
isNullPrincipal) {
return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR;
if (isSystemPrincipal) {
principal.forget(aPrincipal);
return NS_OK;
}
// Whitelist about:home, since it doesn't have a base domain it would not
@ -424,6 +423,36 @@ IDBFactory::AllowedForWindowInternal(nsPIDOMWindow* aWindow,
return NS_OK;
}
// static
bool
IDBFactory::AllowedForPrincipal(nsIPrincipal* aPrincipal,
bool* aIsSystemPrincipal)
{
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(aPrincipal);
if (NS_WARN_IF(!IndexedDatabaseManager::GetOrCreate())) {
return false;
}
if (nsContentUtils::IsSystemPrincipal(aPrincipal)) {
if (aIsSystemPrincipal) {
*aIsSystemPrincipal = true;
}
return true;
} else if (aIsSystemPrincipal) {
*aIsSystemPrincipal = false;
}
bool isNullPrincipal;
if (NS_WARN_IF(NS_FAILED(aPrincipal->GetIsNullPrincipal(&isNullPrincipal))) ||
isNullPrincipal) {
return false;
}
return true;
}
#ifdef DEBUG
void

Просмотреть файл

@ -105,6 +105,10 @@ public:
static bool
AllowedForWindow(nsPIDOMWindow* aWindow);
static bool
AllowedForPrincipal(nsIPrincipal* aPrincipal,
bool* aIsSystemPrincipal = nullptr);
void
AssertIsOnOwningThread() const
#ifdef DEBUG

Просмотреть файл

@ -12,6 +12,8 @@ support-files =
file_app_isolation.js
helpers.js
leaving_page_iframe.html
service_worker.js
service_worker_client.html
third_party_iframe1.html
third_party_iframe2.html
unit/test_add_put.js
@ -196,6 +198,9 @@ skip-if = buildapp == 'b2g' || buildapp == 'mulet' || e10s
[test_filehandle_getFile.html]
# FileHandle is not supported in child processes.
skip-if = buildapp == 'b2g' || buildapp == 'mulet' || e10s
[test_filehandle_iteration.html]
# FileHandle is not supported in child processes.
skip-if = buildapp == 'b2g' || buildapp == 'mulet' || e10s
[test_filehandle_lifetimes.html]
# FileHandle is not supported in child processes.
skip-if = buildapp == 'b2g' || buildapp == 'mulet' || e10s
@ -374,3 +379,5 @@ skip-if = buildapp == 'b2g' || buildapp == 'mulet' || e10s || toolkit == 'androi
# The clearBrowserData tests are only supposed to run in the main process.
# They currently time out on android.
skip-if = buildapp == 'b2g' || buildapp == 'mulet' || e10s || toolkit == 'android'
[test_serviceworker.html]
skip-if = buildapp == 'b2g'

Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше