Merge m-c to fx-team, a=merge CLOSED TREE

This commit is contained in:
Wes Kocher 2015-06-11 17:55:46 -07:00
commit 4df9511095
1663 changed files with 26859 additions and 6621 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -15,7 +15,7 @@
<project name="platform_build" path="build" remote="b2g" revision="e862ab9177af664f00b4522e2350f4cb13866d73">
<copyfile dest="Makefile" src="core/root.mk"/>
</project>
<project name="gaia" path="gaia" remote="mozillaorg" revision="d2f31eb85837aae6eca04d022d1f5b2023bc778c"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="9f36b711af7597a6a32471c3305cf1e2d6947d39"/>
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="3477513bcd385571aa01c0d074849e35bd5e2376"/>
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
@ -23,7 +23,7 @@
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
<project name="valgrind" path="external/valgrind" remote="b2g" revision="daa61633c32b9606f58799a3186395fd2bbb8d8c"/>
<project name="vex" path="external/VEX" remote="b2g" revision="47f031c320888fe9f3e656602588565b52d43010"/>
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="70b7fcbf7ff0ef38d04f82d68a56f2bb44ec694a"/>
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="41efd945c841175f733ef764fe5f6a85c592970b"/>
<!-- Stock Android things -->
<project groups="linux" name="platform/prebuilts/gcc/linux-x86/host/i686-linux-glibc2.7-4.6" path="prebuilts/gcc/linux-x86/host/i686-linux-glibc2.7-4.6" revision="95bb5b66b3ec5769c3de8d3f25d681787418e7d2"/>
<project groups="linux" name="platform/prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.7-4.6" path="prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.7-4.6" revision="ebdad82e61c16772f6cd47e9f11936bf6ebe9aa0"/>

View File

@ -15,7 +15,7 @@
<project name="platform_build" path="build" remote="b2g" revision="e862ab9177af664f00b4522e2350f4cb13866d73">
<copyfile dest="Makefile" src="core/root.mk"/>
</project>
<project name="gaia" path="gaia" remote="mozillaorg" revision="d2f31eb85837aae6eca04d022d1f5b2023bc778c"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="9f36b711af7597a6a32471c3305cf1e2d6947d39"/>
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="3477513bcd385571aa01c0d074849e35bd5e2376"/>
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
@ -23,7 +23,7 @@
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
<project name="valgrind" path="external/valgrind" remote="b2g" revision="daa61633c32b9606f58799a3186395fd2bbb8d8c"/>
<project name="vex" path="external/VEX" remote="b2g" revision="47f031c320888fe9f3e656602588565b52d43010"/>
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="70b7fcbf7ff0ef38d04f82d68a56f2bb44ec694a"/>
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="41efd945c841175f733ef764fe5f6a85c592970b"/>
<!-- Stock Android things -->
<project groups="linux" name="platform/prebuilts/gcc/linux-x86/host/i686-linux-glibc2.7-4.6" path="prebuilts/gcc/linux-x86/host/i686-linux-glibc2.7-4.6" revision="95bb5b66b3ec5769c3de8d3f25d681787418e7d2"/>
<project groups="linux" name="platform/prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.7-4.6" path="prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.7-4.6" revision="ebdad82e61c16772f6cd47e9f11936bf6ebe9aa0"/>

View File

@ -19,7 +19,7 @@
<copyfile dest="Makefile" src="core/root.mk"/>
</project>
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="d2f31eb85837aae6eca04d022d1f5b2023bc778c"/>
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="9f36b711af7597a6a32471c3305cf1e2d6947d39"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="3477513bcd385571aa01c0d074849e35bd5e2376"/>
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
<project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="87a2d8ab9248540910e56921654367b78a587095"/>

View File

@ -17,10 +17,10 @@
</project>
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="d2f31eb85837aae6eca04d022d1f5b2023bc778c"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="9f36b711af7597a6a32471c3305cf1e2d6947d39"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="3477513bcd385571aa01c0d074849e35bd5e2376"/>
<project name="moztt" path="external/moztt" remote="b2g" revision="46da1a05ac04157669685246d70ac59d48699c9e"/>
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="70b7fcbf7ff0ef38d04f82d68a56f2bb44ec694a"/>
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="41efd945c841175f733ef764fe5f6a85c592970b"/>
<project name="valgrind" path="external/valgrind" remote="b2g" revision="daa61633c32b9606f58799a3186395fd2bbb8d8c"/>
<project name="vex" path="external/VEX" remote="b2g" revision="47f031c320888fe9f3e656602588565b52d43010"/>
<!-- Stock Android things -->

View File

@ -15,7 +15,7 @@
<project name="platform_build" path="build" remote="b2g" revision="e862ab9177af664f00b4522e2350f4cb13866d73">
<copyfile dest="Makefile" src="core/root.mk"/>
</project>
<project name="gaia" path="gaia" remote="mozillaorg" revision="d2f31eb85837aae6eca04d022d1f5b2023bc778c"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="9f36b711af7597a6a32471c3305cf1e2d6947d39"/>
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="3477513bcd385571aa01c0d074849e35bd5e2376"/>
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
@ -23,7 +23,7 @@
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
<project name="valgrind" path="external/valgrind" remote="b2g" revision="daa61633c32b9606f58799a3186395fd2bbb8d8c"/>
<project name="vex" path="external/VEX" remote="b2g" revision="47f031c320888fe9f3e656602588565b52d43010"/>
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="70b7fcbf7ff0ef38d04f82d68a56f2bb44ec694a"/>
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="41efd945c841175f733ef764fe5f6a85c592970b"/>
<!-- Stock Android things -->
<project groups="linux" name="platform/prebuilts/gcc/linux-x86/host/i686-linux-glibc2.7-4.6" path="prebuilts/gcc/linux-x86/host/i686-linux-glibc2.7-4.6" revision="f92a936f2aa97526d4593386754bdbf02db07a12"/>
<project groups="linux" name="platform/prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.7-4.6" path="prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.7-4.6" revision="6e47ff2790f5656b5b074407829ceecf3e6188c4"/>

View File

@ -15,7 +15,7 @@
<project name="platform_build" path="build" remote="b2g" revision="61e82f99bb8bc78d52b5717e9a2481ec7267fa33">
<copyfile dest="Makefile" src="core/root.mk"/>
</project>
<project name="gaia" path="gaia" remote="mozillaorg" revision="d2f31eb85837aae6eca04d022d1f5b2023bc778c"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="9f36b711af7597a6a32471c3305cf1e2d6947d39"/>
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="3477513bcd385571aa01c0d074849e35bd5e2376"/>
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
@ -23,7 +23,7 @@
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
<project name="valgrind" path="external/valgrind" remote="b2g" revision="daa61633c32b9606f58799a3186395fd2bbb8d8c"/>
<project name="vex" path="external/VEX" remote="b2g" revision="47f031c320888fe9f3e656602588565b52d43010"/>
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="70b7fcbf7ff0ef38d04f82d68a56f2bb44ec694a"/>
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="41efd945c841175f733ef764fe5f6a85c592970b"/>
<!-- Stock Android things -->
<project groups="pdk,linux" name="platform/prebuilts/clang/linux-x86/host/3.5" path="prebuilts/clang/linux-x86/host/3.5" revision="ffc05a232799fe8fcb3e47b7440b52b1fb4244c0"/>
<project groups="pdk,linux,arm" name="platform/prebuilts/gcc/linux-x86/aarch64/aarch64-linux-android-4.8" path="prebuilts/gcc/linux-x86/aarch64/aarch64-linux-android-4.8" revision="337e0ef5e40f02a1ae59b90db0548976c70a7226"/>

View File

@ -19,7 +19,7 @@
<copyfile dest="Makefile" src="core/root.mk"/>
</project>
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="d2f31eb85837aae6eca04d022d1f5b2023bc778c"/>
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="9f36b711af7597a6a32471c3305cf1e2d6947d39"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="3477513bcd385571aa01c0d074849e35bd5e2376"/>
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
<project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="87a2d8ab9248540910e56921654367b78a587095"/>

View File

@ -15,7 +15,7 @@
<project name="platform_build" path="build" remote="b2g" revision="e862ab9177af664f00b4522e2350f4cb13866d73">
<copyfile dest="Makefile" src="core/root.mk"/>
</project>
<project name="gaia" path="gaia" remote="mozillaorg" revision="d2f31eb85837aae6eca04d022d1f5b2023bc778c"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="9f36b711af7597a6a32471c3305cf1e2d6947d39"/>
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="3477513bcd385571aa01c0d074849e35bd5e2376"/>
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
@ -23,7 +23,7 @@
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
<project name="valgrind" path="external/valgrind" remote="b2g" revision="daa61633c32b9606f58799a3186395fd2bbb8d8c"/>
<project name="vex" path="external/VEX" remote="b2g" revision="47f031c320888fe9f3e656602588565b52d43010"/>
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="70b7fcbf7ff0ef38d04f82d68a56f2bb44ec694a"/>
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="41efd945c841175f733ef764fe5f6a85c592970b"/>
<!-- Stock Android things -->
<project groups="linux" name="platform/prebuilts/gcc/linux-x86/host/i686-linux-glibc2.7-4.6" path="prebuilts/gcc/linux-x86/host/i686-linux-glibc2.7-4.6" revision="95bb5b66b3ec5769c3de8d3f25d681787418e7d2"/>
<project groups="linux" name="platform/prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.7-4.6" path="prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.7-4.6" revision="ebdad82e61c16772f6cd47e9f11936bf6ebe9aa0"/>

View File

@ -1,9 +1,9 @@
{
"git": {
"git_revision": "d2f31eb85837aae6eca04d022d1f5b2023bc778c",
"git_revision": "9f36b711af7597a6a32471c3305cf1e2d6947d39",
"remote": "https://git.mozilla.org/releases/gaia.git",
"branch": ""
},
"revision": "2e9a1e5808b983fe4aa50a169b0e36fb3f0b43a3",
"revision": "8583025b84cda74c63e83bbbdfd7a4f33b917f20",
"repo_path": "integration/gaia-central"
}

View File

@ -17,10 +17,10 @@
</project>
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="d2f31eb85837aae6eca04d022d1f5b2023bc778c"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="9f36b711af7597a6a32471c3305cf1e2d6947d39"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="3477513bcd385571aa01c0d074849e35bd5e2376"/>
<project name="moztt" path="external/moztt" remote="b2g" revision="46da1a05ac04157669685246d70ac59d48699c9e"/>
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="70b7fcbf7ff0ef38d04f82d68a56f2bb44ec694a"/>
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="41efd945c841175f733ef764fe5f6a85c592970b"/>
<project name="valgrind" path="external/valgrind" remote="b2g" revision="daa61633c32b9606f58799a3186395fd2bbb8d8c"/>
<project name="vex" path="external/VEX" remote="b2g" revision="47f031c320888fe9f3e656602588565b52d43010"/>
<!-- Stock Android things -->

View File

@ -15,7 +15,7 @@
<project name="platform_build" path="build" remote="b2g" revision="61e82f99bb8bc78d52b5717e9a2481ec7267fa33">
<copyfile dest="Makefile" src="core/root.mk"/>
</project>
<project name="gaia" path="gaia" remote="mozillaorg" revision="d2f31eb85837aae6eca04d022d1f5b2023bc778c"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="9f36b711af7597a6a32471c3305cf1e2d6947d39"/>
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="3477513bcd385571aa01c0d074849e35bd5e2376"/>
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
@ -23,7 +23,7 @@
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
<project name="valgrind" path="external/valgrind" remote="b2g" revision="daa61633c32b9606f58799a3186395fd2bbb8d8c"/>
<project name="vex" path="external/VEX" remote="b2g" revision="47f031c320888fe9f3e656602588565b52d43010"/>
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="70b7fcbf7ff0ef38d04f82d68a56f2bb44ec694a"/>
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="41efd945c841175f733ef764fe5f6a85c592970b"/>
<!-- Stock Android things -->
<project groups="pdk,linux" name="platform/prebuilts/clang/linux-x86/host/3.5" path="prebuilts/clang/linux-x86/host/3.5" revision="ffc05a232799fe8fcb3e47b7440b52b1fb4244c0"/>
<project groups="pdk,linux,arm" name="platform/prebuilts/gcc/linux-x86/aarch64/aarch64-linux-android-4.8" path="prebuilts/gcc/linux-x86/aarch64/aarch64-linux-android-4.8" revision="337e0ef5e40f02a1ae59b90db0548976c70a7226"/>

View File

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

View File

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

View File

@ -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()`.

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -115,6 +115,12 @@ OriginAttributes::PopulateFromSuffix(const nsACString& aStr)
return usp->ForEach(iterator);
}
void
OriginAttributes::CookieJar(nsACString& aStr)
{
mozilla::GetJarPrefix(mAppId, mInBrowser, aStr);
}
BasePrincipal::BasePrincipal()
{}
@ -223,7 +229,7 @@ BasePrincipal::GetJarPrefix(nsACString& aJarPrefix)
{
MOZ_ASSERT(AppId() != nsIScriptSecurityManager::UNKNOWN_APP_ID);
mozilla::GetJarPrefix(AppId(), IsInBrowserElement(), aJarPrefix);
mOriginAttributes.CookieJar(aJarPrefix);
return NS_OK;
}
@ -246,10 +252,8 @@ BasePrincipal::GetOriginSuffix(nsACString& aOriginAttributes)
NS_IMETHODIMP
BasePrincipal::GetCookieJar(nsACString& aCookieJar)
{
// We just forward to .jarPrefix for now, which is a nice compact
// stringification of the (appId, inBrowser) tuple. This will eventaully be
// swapped out for an origin attribute - see the comment in nsIPrincipal.idl.
return GetJarPrefix(aCookieJar);
mOriginAttributes.CookieJar(aCookieJar);
return NS_OK;
}
NS_IMETHODIMP

View File

@ -11,7 +11,7 @@
#include "nsIScriptSecurityManager.h"
#include "nsJSPrincipals.h"
#include "mozilla/dom/SystemDictionariesBinding.h"
#include "mozilla/dom/ChromeUtilsBinding.h"
class nsIContentSecurityPolicy;
class nsIObjectOutputStream;
@ -28,6 +28,8 @@ public:
mAppId = aAppId;
mInBrowser = aInBrowser;
}
explicit OriginAttributes(const OriginAttributesDictionary& aOther)
: OriginAttributesDictionary(aOther) {}
bool operator==(const OriginAttributes& aOther) const
{
@ -44,6 +46,8 @@ public:
// returns an empty string.
void CreateSuffix(nsACString& aStr) const;
bool PopulateFromSuffix(const nsACString& aStr);
void CookieJar(nsACString& aStr);
};
/*

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -42,17 +42,6 @@ UuidToString(const BluetoothUuid& aUuid, nsAString& aString)
aString.AssignLiteral(uuidStr);
}
void
ReversedUuidToString(const BluetoothUuid& aUuid, nsAString& aString)
{
BluetoothUuid uuid;
for (uint8_t i = 0; i < 16; i++) {
uuid.mUuid[i] = aUuid.mUuid[15 - i];
}
UuidToString(uuid, aString);
}
void
StringToUuid(const char* aString, BluetoothUuid& aUuid)
{
@ -98,24 +87,16 @@ GenerateUuid(nsAString &aUuidString)
aUuidString.Assign(Substring(uuidString, 1, NSID_LENGTH - 3));
}
void
GeneratePathFromGattId(const BluetoothGattId& aId,
nsAString& aPath,
nsAString& aUuidStr)
{
ReversedUuidToString(aId.mUuid, aUuidStr);
aPath.Assign(aUuidStr);
aPath.AppendLiteral("_");
aPath.AppendInt(aId.mInstanceId);
}
void
GeneratePathFromGattId(const BluetoothGattId& aId,
nsAString& aPath)
{
nsString uuidStr;
GeneratePathFromGattId(aId, aPath, uuidStr);
UuidToString(aId.mUuid, uuidStr);
aPath.Assign(uuidStr);
aPath.AppendLiteral("_");
aPath.AppendInt(aId.mInstanceId);
}
void

View File

@ -29,19 +29,6 @@ class BluetoothValue;
void
UuidToString(const BluetoothUuid& aUuid, nsAString& aString);
/**
* Convert BluetoothUuid object in a reversed byte order to
* xxxxxxxx-xxxx-xxxx-xxxxxxxxxxxx uuid string.
* Bluedroid stack reports the BluetoothUuid in a reversed byte order for
* GATT service, characteristic, descriptor uuids.
*
* Note: This utility function is used by gecko internal only to convert
* BluetoothUuid in a reversed byte order created by bluetooth stack to uuid
* string representation.
*/
void
ReversedUuidToString(const BluetoothUuid& aUuid, nsAString& aString);
/**
* Convert xxxxxxxx-xxxx-xxxx-xxxxxxxxxxxx uuid string to BluetoothUuid object.
*
@ -63,18 +50,6 @@ GenerateUuid(nsAString &aUuidString);
// Generate bluetooth signal path from GattId
//
/**
* Generate bluetooth signal path and UUID string from a GattId.
*
* @param aId [in] GattId value to convert.
* @param aPath [out] Bluetooth signal path generated from aId.
* @param aUuidStr [out] UUID string generated from aId.
*/
void
GeneratePathFromGattId(const BluetoothGattId& aId,
nsAString& aPath,
nsAString& aUuidStr);
/**
* Generate bluetooth signal path from a GattId.
*

View File

@ -259,7 +259,9 @@ BluetoothDaemonGattModule::ClientSearchServiceCmd(
16)); // UUID
nsresult rv = PackPDU(PackConversion<int, int32_t>(aConnId),
PackConversion<bool, uint8_t>(aFiltered), aUuid, *pdu);
PackConversion<bool, uint8_t>(aFiltered),
PackReversed<BluetoothUuid>(aUuid),
*pdu);
if (NS_FAILED(rv)) {
return rv;
}

View File

@ -1409,7 +1409,7 @@ PackPDU(const BluetoothUuid& aIn, BluetoothDaemonPDU& aPDU)
nsresult
PackPDU(const BluetoothGattId& aIn, BluetoothDaemonPDU& aPDU)
{
nsresult rv = PackPDU(aIn.mUuid, aPDU);
nsresult rv = PackPDU(PackReversed<BluetoothUuid>(aIn.mUuid), aPDU);
if (NS_FAILED(rv)) {
return rv;
}
@ -1734,7 +1734,7 @@ nsresult
UnpackPDU(BluetoothDaemonPDU& aPDU, BluetoothGattId& aOut)
{
/* unpack UUID */
nsresult rv = UnpackPDU(aPDU, aOut.mUuid);
nsresult rv = UnpackPDU(aPDU, UnpackReversed<BluetoothUuid>(aOut.mUuid));
if (NS_FAILED(rv)) {
return rv;
}

View File

@ -579,6 +579,57 @@ PackPDU(const PackCString0& aIn, BluetoothDaemonPDU& aPDU)
aIn.mString.Length() + 1), aPDU);
}
/* |PackReversed| is a helper for packing data in reversed order. Pass an
* instance of this structure as the first argument to |PackPDU| to pack data
* in reversed order.
*/
template<typename T>
struct PackReversed
{
PackReversed(const T& aValue)
: mValue(aValue)
{ }
const T& mValue;
};
/* No general rules to pack data in reversed order. Signal a link error if the
* type |T| of |PackReversed| is not defined explicitly.
*/
template<typename T>
nsresult
PackPDU(const PackReversed<T>& aIn, BluetoothDaemonPDU& aPDU);
/* This implementation of |PackPDU| packs elements in |PackArray| in reversed
* order. (ex. reversed GATT UUID, see bug 1171866)
*/
template<typename U>
inline nsresult
PackPDU(const PackReversed<PackArray<U>>& aIn, BluetoothDaemonPDU& aPDU)
{
for (size_t i = 0; i < aIn.mValue.mLength; ++i) {
nsresult rv = PackPDU(aIn.mValue.mData[aIn.mValue.mLength - i - 1], aPDU);
if (NS_FAILED(rv)) {
return rv;
}
}
return NS_OK;
}
/* This implementation of |PackPDU| packs |BluetoothUuid| in reversed order.
* (ex. reversed GATT UUID, see bug 1171866)
*/
template <>
inline nsresult
PackPDU<BluetoothUuid>(const PackReversed<BluetoothUuid>& aIn,
BluetoothDaemonPDU& aPDU)
{
return PackPDU(
PackReversed<PackArray<uint8_t>>(
PackArray<uint8_t>(aIn.mValue.mUuid, sizeof(aIn.mValue.mUuid))),
aPDU);
}
template <typename T1, typename T2>
inline nsresult
PackPDU(const T1& aIn1, const T2& aIn2, BluetoothDaemonPDU& aPDU)
@ -1099,6 +1150,59 @@ struct UnpackString0
nsresult
UnpackPDU(BluetoothDaemonPDU& aPDU, const UnpackString0& aOut);
/* |UnpackReversed| is a helper for unpacking data in reversed order. Pass an
* instance of this structure as the second argument to |UnpackPDU| to unpack
* data in reversed order.
*/
template<typename T>
struct UnpackReversed
{
UnpackReversed(T& aValue)
: mValue(&aValue)
{ }
UnpackReversed(T&& aValue)
: mValue(&aValue)
{ }
T* mValue;
};
/* No general rules to unpack data in reversed order. Signal a link error if
* the type |T| of |UnpackReversed| is not defined explicitly.
*/
template<typename T>
nsresult
UnpackPDU(BluetoothDaemonPDU& aPDU, const UnpackReversed<T>& aOut);
template<typename U>
inline nsresult
UnpackPDU(BluetoothDaemonPDU& aPDU, const UnpackReversed<UnpackArray<U>>& aOut)
{
for (size_t i = 0; i < aOut.mValue->mLength; ++i) {
nsresult rv = UnpackPDU(aPDU,
aOut.mValue->mData[aOut.mValue->mLength - i - 1]);
if (NS_FAILED(rv)) {
return rv;
}
}
return NS_OK;
}
/* This implementation of |UnpackPDU| unpacks |BluetoothUuid| in reversed
* order. (ex. reversed GATT UUID, see bug 1171866)
*/
template<>
inline nsresult
UnpackPDU<BluetoothUuid>(BluetoothDaemonPDU& aPDU,
const UnpackReversed<BluetoothUuid>& aOut)
{
return UnpackPDU(
aPDU,
UnpackReversed<UnpackArray<uint8_t>>(
UnpackArray<uint8_t>(aOut.mValue->mUuid, sizeof(aOut.mValue->mUuid))));
}
//
// Init operators
//

View File

@ -234,15 +234,35 @@ Convert(const btrc_player_settings_t& aIn, BluetoothAvrcpPlayerSettings& aOut)
nsresult
Convert(const BluetoothGattId& aIn, btgatt_gatt_id_t& aOut)
{
nsresult rv = Convert(aIn.mUuid, aOut.uuid);
if (NS_FAILED(rv)) {
return rv;
}
// HAL uses reversed UUID for GATT
for (uint8_t i = 0; i < sizeof(aOut.uuid.uu) / 2; i++) {
auto temp = aOut.uuid.uu[i];
aOut.uuid.uu[i] = aOut.uuid.uu[sizeof(aOut.uuid.uu) - i - 1];
aOut.uuid.uu[sizeof(aOut.uuid.uu) - i - 1] = temp;
}
aOut.inst_id = aIn.mInstanceId;
return Convert(aIn.mUuid, aOut.uuid);
return NS_OK;
}
nsresult
Convert(const btgatt_gatt_id_t& aIn, BluetoothGattId& aOut)
{
nsresult rv = Convert(aIn.uuid, aOut.mUuid);
if (NS_FAILED(rv)) {
return rv;
}
// HAL uses reversed UUID for GATT
for (uint8_t i = 0; i < sizeof(aOut.mUuid.mUuid) / 2; i++) {
auto temp = aOut.mUuid.mUuid[i];
aOut.mUuid.mUuid[i] = aOut.mUuid.mUuid[sizeof(aOut.mUuid.mUuid) - i - 1];
aOut.mUuid.mUuid[sizeof(aOut.mUuid.mUuid) - i - 1] = temp;
}
aOut.mInstanceId = aIn.inst_id;
return Convert(aIn.uuid, aOut.mUuid);
return NS_OK;
}
nsresult

View File

@ -68,10 +68,11 @@ BluetoothGattCharacteristic::BluetoothGattCharacteristic(
MOZ_ASSERT(aOwner);
MOZ_ASSERT(mService);
// Generate bluetooth signal path and a string representation to provide uuid
// of this characteristic to applications
UuidToString(mCharId.mUuid, mUuidStr);
// Generate bluetooth signal path of this characteristic to applications
nsString path;
GeneratePathFromGattId(mCharId, path, mUuidStr);
GeneratePathFromGattId(mCharId, path);
RegisterBluetoothSignalHandler(path, this);
}

View File

@ -63,10 +63,11 @@ BluetoothGattDescriptor::BluetoothGattDescriptor(
MOZ_ASSERT(aOwner);
MOZ_ASSERT(aCharacteristic);
// Generate bluetooth signal path and a string representation to provide uuid
// of this descriptor to applications
UuidToString(mDescriptorId.mUuid, mUuidStr);
// Generate bluetooth signal path of this descriptor to applications
nsString path;
GeneratePathFromGattId(mDescriptorId, path, mUuidStr);
GeneratePathFromGattId(mDescriptorId, path);
RegisterBluetoothSignalHandler(path, this);
}

View File

@ -62,10 +62,11 @@ BluetoothGattService::BluetoothGattService(
MOZ_ASSERT(aOwner);
MOZ_ASSERT(!mAppUuid.IsEmpty());
// Generate bluetooth signal path and a string representation to provide
// uuid of this service to applications
UuidToString(mServiceId.mId.mUuid, mUuidStr);
// Generate bluetooth signal path of this service to applications
nsString path;
GeneratePathFromGattId(mServiceId.mId, path, mUuidStr);
GeneratePathFromGattId(mServiceId.mId, path);
RegisterBluetoothSignalHandler(path, this);
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

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