зеркало из https://github.com/mozilla/gecko-dev.git
Merge inbound to central, a=merge
This commit is contained in:
Коммит
2aa142fe5e
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
10
configure.in
10
configure.in
|
@ -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'
|
||||
|
|
Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше
Загрузка…
Ссылка в новой задаче