Merge m-c to inbound. a=merge

This commit is contained in:
Ryan VanderMeulen 2015-08-18 23:06:17 -04:00
commit ac665ca41c
233 changed files with 3540 additions and 2331 deletions

View File

@ -822,12 +822,20 @@ getParentCB(AtkObject *aAtkObj)
gint
getChildCountCB(AtkObject *aAtkObj)
{
AccessibleWrap* accWrap = GetAccessibleWrap(aAtkObj);
if (!accWrap || nsAccUtils::MustPrune(accWrap)) {
return 0;
if (AccessibleWrap* accWrap = GetAccessibleWrap(aAtkObj)) {
if (nsAccUtils::MustPrune(accWrap)) {
return 0;
}
return static_cast<gint>(accWrap->EmbeddedChildCount());
}
ProxyAccessible* proxy = GetProxy(aAtkObj);
if (proxy && !proxy->MustPruneChildren()) {
return proxy->EmbeddedChildCount();
}
return 0;
}
AtkObject *

View File

@ -248,12 +248,7 @@ EventQueue::CoalesceReorderEvents(AccEvent* aTailEvent)
// Coalesce earlier event of the same target.
if (thisEvent->mAccessible == aTailEvent->mAccessible) {
if (thisEvent->mEventRule == AccEvent::eDoNotEmit) {
AccReorderEvent* tailReorder = downcast_accEvent(aTailEvent);
tailReorder->DoNotEmitAll();
} else {
thisEvent->mEventRule = AccEvent::eDoNotEmit;
}
thisEvent->mEventRule = AccEvent::eDoNotEmit;
return;
}

View File

@ -690,8 +690,9 @@ GroupPos
ARIAGridCellAccessible::GroupPosition()
{
int32_t count = 0, index = 0;
if (nsCoreUtils::GetUIntAttr(Table()->AsAccessible()->GetContent(),
nsGkAtoms::aria_colcount, &count) &&
Accessible* table = Table()->AsAccessible();
if (table && nsCoreUtils::GetUIntAttr(table->GetContent(),
nsGkAtoms::aria_colcount, &count) &&
nsCoreUtils::GetUIntAttr(mContent, nsGkAtoms::aria_colindex, &index)) {
return GroupPos(0, index, count);
}

View File

@ -147,8 +147,9 @@ GroupPos
HTMLTableCellAccessible::GroupPosition()
{
int32_t count = 0, index = 0;
if (nsCoreUtils::GetUIntAttr(Table()->AsAccessible()->GetContent(),
nsGkAtoms::aria_colcount, &count) &&
Accessible* table = Table()->AsAccessible();
if (table && nsCoreUtils::GetUIntAttr(table->GetContent(),
nsGkAtoms::aria_colcount, &count) &&
nsCoreUtils::GetUIntAttr(mContent, nsGkAtoms::aria_colindex, &index)) {
return GroupPos(0, index, count);
}

View File

@ -1727,6 +1727,22 @@ DocAccessibleChild::RecvTakeFocus(const uint64_t& aID)
return true;
}
bool
DocAccessibleChild::RecvEmbeddedChildCount(const uint64_t& aID,
uint32_t* aCount)
{
*aCount = 0;
Accessible* acc = IdToAccessible(aID);
if (!acc) {
return true;
}
*aCount = acc->EmbeddedChildCount();
return true;
}
bool
DocAccessibleChild::RecvIndexOfEmbeddedChild(const uint64_t& aID,
const uint64_t& aChildID,

View File

@ -434,6 +434,9 @@ public:
virtual bool RecvTakeFocus(const uint64_t& aID) override;
virtual bool RecvEmbeddedChildCount(const uint64_t& aID, uint32_t* aCount)
override final;
virtual bool RecvIndexOfEmbeddedChild(const uint64_t& aID,
const uint64_t& aChildID,
uint32_t* aChildIdx) override final;

View File

@ -226,6 +226,7 @@ child:
prio(high) sync Step(uint64_t aID) returns(double aStep);
prio(high) sync TakeFocus(uint64_t aID);
prio(high) sync EmbeddedChildCount(uint64_t aID) returns(uint32_t aCount);
prio(high) sync IndexOfEmbeddedChild(uint64_t aID, uint64_t aChildID)
returns(uint32_t childIdx);
prio(high) sync EmbeddedChildAt(uint64_t aID, uint32_t aChildIdx)

View File

@ -979,6 +979,14 @@ ProxyAccessible::TakeFocus()
unused << mDoc->SendTakeFocus(mID);
}
uint32_t
ProxyAccessible::EmbeddedChildCount() const
{
uint32_t count;
unused << mDoc->SendEmbeddedChildCount(mID, &count);
return count;
}
int32_t
ProxyAccessible::IndexOfEmbeddedChild(const ProxyAccessible* aChild)
{

View File

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

View File

@ -8,6 +8,7 @@
[test_bug1040735.html]
[test_bug1100602.html]
[test_bug1175913.html]
[test_bug1189277.html]
[test_canvas.html]
[test_colorpicker.xul]
[test_contextmenu.xul]

View File

@ -0,0 +1,85 @@
<html>
<head>
<title>Test hide/show events for HTMLListBulletAccessibles on list restyle</title>
<link rel="stylesheet" type="text/css"
href="chrome://mochikit/content/tests/SimpleTest/test.css" />
<script type="application/javascript"
src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
<script type="application/javascript"
src="../common.js"></script>
<script type="application/javascript"
src="../name.js"></script>
<script type="application/javascript"
src="../events.js"></script>
<script type="application/javascript">
function runTest()
{
this.containerNode = getNode("outerDiv");
this.eventSeq = [
new invokerChecker(EVENT_HIDE, getNode("child")),
new invokerChecker(EVENT_REORDER, this.containerNode),
new invokerChecker(EVENT_HIDE, getNode("childDoc")),
new invokerChecker(EVENT_SHOW, "newChildDoc")
];
this.invoke = function runTest_invoke()
{
this.containerNode.removeChild(getNode("child"));
var docContainer = getNode("docContainer");
var iframe = document.createElement("iframe");
iframe.setAttribute("src", "http://example.com");
iframe.setAttribute("id", "newChildDoc");
docContainer.removeChild(getNode("childDoc"));
docContainer.appendChild(iframe);
}
this.getID = function runTest_getID()
{
return "check show events are not incorrectly coalesced";
}
}
gA11yEventDumpToConsole = true;
var gQueue = null;
function doTest()
{
gQueue = new eventQueue();
gQueue.push(new runTest());
gQueue.invoke(); // SimpleTest.finish();
}
SimpleTest.waitForExplicitFinish();
addA11yLoadEvent(doTest);
</script>
</head>
<body>
<a target="_blank"
href="https://bugzilla.mozilla.org/show_bug.cgi?id=1189277"
title="content process crash caused by missing show event">
Mozilla Bug 1189277
</a>
<p id="display"></p>
<div id="content" style="display: none"></div>
<pre id="test">
</pre>
<div id="outerDiv">
<div id="child">foo</div>
<div id="docContainer">
<iframe id="childDoc" src="about:blank">
</iframe>
</div>
</div>
</body>
</html>

View File

@ -1160,14 +1160,6 @@ pref("browser.flash-protected-mode-flip.enable", false);
// Whether we've already flipped protected mode automatically
pref("browser.flash-protected-mode-flip.done", false);
#ifdef XP_MACOSX
// On mac, the default pref is per-architecture
pref("dom.ipc.plugins.enabled.i386", true);
pref("dom.ipc.plugins.enabled.x86_64", true);
#else
pref("dom.ipc.plugins.enabled", true);
#endif
pref("dom.ipc.shims.enabledWarnings", false);
// Start the browser in e10s mode

View File

@ -188,8 +188,11 @@ function initIndexedDBRow()
var quotaManager = Components.classes["@mozilla.org/dom/quota/manager;1"]
.getService(nsIQuotaManager);
let principal = Components.classes["@mozilla.org/scriptsecuritymanager;1"]
.getService(Components.interfaces.nsIScriptSecurityManager)
.createCodebasePrincipal(gPermURI, {});
gUsageRequest =
quotaManager.getUsageForURI(gPermURI, onIndexedDBUsageCallback);
quotaManager.getUsageForPrincipal(principal, onIndexedDBUsageCallback);
var status = document.getElementById("indexedDBStatus");
var button = document.getElementById("indexedDBClear");
@ -201,9 +204,13 @@ function initIndexedDBRow()
function onIndexedDBClear()
{
let principal = Components.classes["@mozilla.org/scriptsecuritymanager;1"]
.getService(Components.interfaces.nsIScriptSecurityManager)
.createCodebasePrincipal(gPermURI, {});
Components.classes["@mozilla.org/dom/quota/manager;1"]
.getService(nsIQuotaManager)
.clearStoragesForURI(gPermURI);
.clearStoragesForPrincipal(principal);
Components.classes["@mozilla.org/serviceworkers/manager;1"]
.getService(Components.interfaces.nsIServiceWorkerManager)
@ -213,8 +220,9 @@ function onIndexedDBClear()
initIndexedDBRow();
}
function onIndexedDBUsageCallback(uri, usage, fileUsage)
function onIndexedDBUsageCallback(principal, usage, fileUsage)
{
let uri = principal.URI;
if (!uri.equals(gPermURI)) {
throw new Error("Callback received for bad URI: " + uri);
}

View File

@ -257,8 +257,8 @@ public:
}
void dumpAnnotationReason(DiagnosticsEngine &Diag, QualType T, SourceLocation Loc);
void reportErrorIfAbsent(DiagnosticsEngine &Diag, QualType T, SourceLocation Loc,
unsigned ErrorID, unsigned NoteID) {
void reportErrorIfPresent(DiagnosticsEngine &Diag, QualType T, SourceLocation Loc,
unsigned ErrorID, unsigned NoteID) {
if (hasEffectiveAnnotation(T)) {
Diag.Report(Loc, ErrorID) << T;
Diag.Report(Loc, NoteID);
@ -1127,24 +1127,24 @@ void DiagnosticsMatcher::ScopeChecker::run(
return;
case AV_Global:
StackClass.reportErrorIfAbsent(Diag, T, Loc, StackID, GlobalNoteID);
HeapClass.reportErrorIfAbsent(Diag, T, Loc, HeapID, GlobalNoteID);
StackClass.reportErrorIfPresent(Diag, T, Loc, StackID, GlobalNoteID);
HeapClass.reportErrorIfPresent(Diag, T, Loc, HeapID, GlobalNoteID);
break;
case AV_Automatic:
GlobalClass.reportErrorIfAbsent(Diag, T, Loc, GlobalID, StackNoteID);
HeapClass.reportErrorIfAbsent(Diag, T, Loc, HeapID, StackNoteID);
GlobalClass.reportErrorIfPresent(Diag, T, Loc, GlobalID, StackNoteID);
HeapClass.reportErrorIfPresent(Diag, T, Loc, HeapID, StackNoteID);
break;
case AV_Temporary:
GlobalClass.reportErrorIfAbsent(Diag, T, Loc, GlobalID, TemporaryNoteID);
HeapClass.reportErrorIfAbsent(Diag, T, Loc, HeapID, TemporaryNoteID);
GlobalClass.reportErrorIfPresent(Diag, T, Loc, GlobalID, TemporaryNoteID);
HeapClass.reportErrorIfPresent(Diag, T, Loc, HeapID, TemporaryNoteID);
break;
case AV_Heap:
GlobalClass.reportErrorIfAbsent(Diag, T, Loc, GlobalID, HeapNoteID);
StackClass.reportErrorIfAbsent(Diag, T, Loc, StackID, HeapNoteID);
NonHeapClass.reportErrorIfAbsent(Diag, T, Loc, NonHeapID, HeapNoteID);
GlobalClass.reportErrorIfPresent(Diag, T, Loc, GlobalID, HeapNoteID);
StackClass.reportErrorIfPresent(Diag, T, Loc, StackID, HeapNoteID);
NonHeapClass.reportErrorIfPresent(Diag, T, Loc, NonHeapID, HeapNoteID);
break;
}
}

View File

@ -29,15 +29,15 @@ want to export this environment variable from your shell's init scripts.
NO_MERCURIAL_SETUP = '''
*** MERCURIAL NOT CONFIGURED ***
mach has detected that you have never run `mach mercurial-setup`.
mach has detected that you have never run `{mach} mercurial-setup`.
Running this command will ensure your Mercurial version control tool is up
to date and optimally configured for a better, more productive experience
when working on Mozilla projects.
Please run `mach mercurial-setup` now.
Please run `{mach} mercurial-setup` now.
Note: `mach mercurial-setup` does not make any changes without prompting
Note: `{mach} mercurial-setup` does not make any changes without prompting
you first.
'''.strip()
@ -45,18 +45,18 @@ OLD_MERCURIAL_TOOLS = '''
*** MERCURIAL CONFIGURATION POTENTIALLY OUT OF DATE ***
mach has detected that it has been a while since you have run
`mach mercurial-setup`.
`{mach} mercurial-setup`.
Having the latest Mercurial tools and configuration should lead to a better,
more productive experience when working on Mozilla projects.
Please run `mach mercurial-setup` now.
Please run `{mach} mercurial-setup` now.
Reminder: `mach mercurial-setup` does not make any changes without
Reminder: `{mach} mercurial-setup` does not make any changes without
prompting you first.
To avoid this message in the future, run `mach mercurial-setup` once a month.
Or, schedule `mach mercurial-setup --update-only` to run automatically in
To avoid this message in the future, run `{mach} mercurial-setup` once a month.
Or, schedule `{mach} mercurial-setup --update-only` to run automatically in
the background at least once a month.
'''.strip()
@ -275,10 +275,10 @@ def bootstrap(topsrcdir, mozilla_dir=None):
# No last run file means mercurial-setup has never completed.
if mtime is None:
print(NO_MERCURIAL_SETUP, file=sys.stderr)
print(NO_MERCURIAL_SETUP.format(mach=sys.argv[0]), file=sys.stderr)
sys.exit(2)
elif time.time() - mtime > MERCURIAL_SETUP_FATAL_INTERVAL:
print(OLD_MERCURIAL_TOOLS, file=sys.stderr)
print(OLD_MERCURIAL_TOOLS.format(mach=sys.argv[0]), file=sys.stderr)
sys.exit(2)
def populate_context(context, key=None):

View File

@ -86,6 +86,12 @@ nsNullPrincipalURI::GetAsciiHost(nsACString &_host)
return NS_OK;
}
NS_IMETHODIMP
nsNullPrincipalURI::GetAsciiHostPort(nsACString &_hostport)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
nsNullPrincipalURI::GetAsciiSpec(nsACString &_spec)
{

View File

@ -111,7 +111,7 @@ nsPrincipal::GetOriginForURI(nsIURI* aURI, nsACString& aOrigin)
return NS_ERROR_FAILURE;
}
nsAutoCString host;
nsAutoCString hostPort;
// chrome: URLs don't have a meaningful origin, so make
// sure we just get the full spec for them.
@ -120,10 +120,10 @@ nsPrincipal::GetOriginForURI(nsIURI* aURI, nsACString& aOrigin)
bool isChrome;
nsresult rv = origin->SchemeIs("chrome", &isChrome);
if (NS_SUCCEEDED(rv) && !isChrome) {
rv = origin->GetAsciiHost(host);
rv = origin->GetAsciiHostPort(hostPort);
// Some implementations return an empty string, treat it as no support
// for asciiHost by that implementation.
if (host.IsEmpty()) {
if (hostPort.IsEmpty()) {
rv = NS_ERROR_FAILURE;
}
}
@ -153,26 +153,7 @@ nsPrincipal::GetOriginForURI(nsIURI* aURI, nsACString& aOrigin)
return NS_OK;
}
int32_t port;
if (NS_SUCCEEDED(rv) && !isChrome) {
rv = origin->GetPort(&port);
}
if (NS_SUCCEEDED(rv) && !isChrome) {
nsAutoCString hostPort;
if (host.FindChar(':') != -1) {
hostPort.Assign("[");
hostPort.Append(host);
hostPort.Append("]");
} else {
hostPort.Assign(host);
}
if (port != -1) {
hostPort.Append(':');
hostPort.AppendInt(port, 10);
}
rv = origin->GetScheme(aOrigin);
NS_ENSURE_SUCCESS(rv, rv);
aOrigin.AppendLiteral("://");

View File

@ -2251,8 +2251,10 @@ ia64*-hpux*)
_DEFINES_CXXFLAGS='-FI $(DEPTH)/dist/include/mozilla-config.h -DMOZILLA_CLIENT'
CFLAGS="$CFLAGS -W3 -Gy"
CXXFLAGS="$CXXFLAGS -W3 -Gy"
if test "$CPU_ARCH" = "x86"; then
if test "$CPU_ARCH" = "x86" -a -z "$CLANG_CL"; then
dnl VS2012+ defaults to -arch:SSE2.
dnl Clang-cl gets confused by -arch:IA32, so don't add it.
dnl (See https://llvm.org/bugs/show_bug.cgi?id=24335)
CFLAGS="$CFLAGS -arch:IA32"
CXXFLAGS="$CXXFLAGS -arch:IA32"
fi

View File

@ -5,20 +5,29 @@
#ifndef UseCounter_h_
#define UseCounter_h_
#include <stdint.h>
namespace mozilla {
enum UseCounter {
enum UseCounter : int16_t {
eUseCounter_UNKNOWN = -1,
#define USE_COUNTER_DOM_METHOD(interface_, name_) \
eUseCounter_##interface_##_##name_,
#define USE_COUNTER_DOM_ATTRIBUTE(interface_, name_) \
eUseCounter_##interface_##_##name_,
eUseCounter_##interface_##_##name_##_getter, \
eUseCounter_##interface_##_##name_##_setter,
#define USE_COUNTER_CSS_PROPERTY(name_, id_) \
eUseCounter_property_##id_,
#include "mozilla/dom/UseCounterList.h"
#undef USE_COUNTER_DOM_METHOD
#undef USE_COUNTER_DOM_ATTRIBUTE
#undef USE_COUNTER_CSS_PROPERTY
#define DEPRECATED_OPERATION(op_) \
eUseCounter_##op_,
#include "nsDeprecatedOperationList.h"
#undef DEPRECATED_OPERATION
eUseCounter_Count
};

View File

@ -18,12 +18,18 @@
//
// method <IDL interface name>.<IDL operation name>
// attribute <IDL interface name>.<IDL attribute name>
// property <CSS property name>
// property <CSS property method name>
//
// The |CSS property method name| should be identical to the |method|
// argument to CSS_PROP and related macros. The method name is
// identical to the name of the property, except that all hyphens are
// removed and CamelCase naming is used. See nsCSSPropList.h for
// further details.
//
// To actually cause use counters to be incremented, DOM methods
// and attributes must have a [UseCounter] extended attribute in
// the Web IDL file, and CSS properties must be declared with
// the CSS_PROPERTY_HAS_USE_COUNTER flag in nsCSSPropList.h.
// the Web IDL file. CSS properties require no special treatment
// beyond being listed below.
//
// You might reasonably ask why we have this file and we require
// annotating things with [UseCounter] in the relevant WebIDL file as
@ -31,3 +37,8 @@
// dependencies were correct would have been rather difficult, and
// annotating the WebIDL files does nothing for identifying CSS
// property usage, which we would also like to track.
method SVGSVGElement.getElementById
attribute SVGSVGElement.currentScale
property Fill
property FillOpacity

View File

@ -45,7 +45,7 @@ def generate_list(f, counters):
print('USE_COUNTER_DOM_ATTRIBUTE(%s, %s)' % (counter['interface_name'], counter['attribute_name']), file=f)
elif counter['type'] == 'property':
prop = counter['property_name']
print('USE_COUNTER_CSS_PROPERTY(%s, %s)' % (prop, prop.replace('-', '_')), file=f)
print('USE_COUNTER_CSS_PROPERTY(%s, %s)' % (prop, prop), file=f)
print_optional_macro_undeclare('USE_COUNTER_DOM_METHOD')
print_optional_macro_undeclare('USE_COUNTER_DOM_ATTRIBUTE')
@ -55,19 +55,20 @@ def generate_property_map(f, counters):
print(AUTOGENERATED_WARNING_COMMENT, file=f)
print('''
enum {
// XXX is this the right define?
#define CSS_PROP_PUBLIC_OR_PRIVATE(publicname_, privatename_) privatename_
#define CSS_PROP_LIST_INCLUDE_LOGICAL
#define CSS_PROP(name_, id_, method_, flags_, pref_, parsevariant_, \\
kwtable_, stylestruct_, stylestructoffset_, animtype_) \\
USE_COUNTER_FOR_CSS_PROPERTY_##id_ = eUseCounter_UNKNOWN,
USE_COUNTER_FOR_CSS_PROPERTY_##method_ = eUseCounter_UNKNOWN,
#include "nsCSSPropList.h"
#undef CSS_PROP
#undef CSS_PROP_LIST_INCLUDE_LOGICAL
#undef CSS_PROP_PUBLIC_OR_PRIVATE
};
''', file=f)
for counter in counters:
if counter['type'] == 'property':
prop = counter['property_name'].replace('-', '_')
prop = counter['property_name']
print('#define USE_COUNTER_FOR_CSS_PROPERTY_%s eUseCounter_property_%s' % (prop, prop), file=f)
def use_counter_list(output_header, conf_filename):

View File

@ -103,6 +103,9 @@
#include "nsIStyleSheetService.h"
#include "nsContentPermissionHelper.h"
#include "nsNetUtil.h"
#include "nsDocument.h"
#include "HTMLImageElement.h"
#include "mozilla/css/ImageLoader.h"
#ifdef XP_WIN
#undef GetClassName
@ -3163,30 +3166,6 @@ nsDOMWindowUtils::SetScrollPositionClampingScrollPortSize(float aWidth, float aH
return NS_OK;
}
NS_IMETHODIMP
nsDOMWindowUtils::SetContentDocumentFixedPositionMargins(float aTop, float aRight,
float aBottom, float aLeft)
{
MOZ_RELEASE_ASSERT(nsContentUtils::IsCallerChrome());
if (!(aTop >= 0.0f && aRight >= 0.0f && aBottom >= 0.0f && aLeft >= 0.0f)) {
return NS_ERROR_ILLEGAL_VALUE;
}
nsIPresShell* presShell = GetPresShell();
if (!presShell) {
return NS_ERROR_FAILURE;
}
nsMargin margins(nsPresContext::CSSPixelsToAppUnits(aTop),
nsPresContext::CSSPixelsToAppUnits(aRight),
nsPresContext::CSSPixelsToAppUnits(aBottom),
nsPresContext::CSSPixelsToAppUnits(aLeft));
presShell->SetContentDocumentFixedPositionMargins(margins);
return NS_OK;
}
nsresult
nsDOMWindowUtils::RemoteFrameFullscreenChanged(nsIDOMElement* aFrameElement)
{
@ -3919,6 +3898,30 @@ nsDOMWindowUtils::LeaveChaosMode()
return NS_OK;
}
NS_IMETHODIMP
nsDOMWindowUtils::ForceUseCounterFlush(nsIDOMNode *aNode)
{
MOZ_RELEASE_ASSERT(nsContentUtils::IsCallerChrome());
NS_ENSURE_ARG_POINTER(aNode);
if (nsCOMPtr<nsIDocument> doc = do_QueryInterface(aNode)) {
mozilla::css::ImageLoader* loader = doc->StyleImageLoader();
loader->FlushUseCounters();
static_cast<nsDocument*>(doc.get())->ReportUseCounters();
return NS_OK;
}
if (nsCOMPtr<nsIContent> content = do_QueryInterface(aNode)) {
if (HTMLImageElement* img = HTMLImageElement::FromContent(content)) {
img->FlushUseCounters();
return NS_OK;
}
}
return NS_OK;
}
NS_IMETHODIMP
nsDOMWindowUtils::HasRuleProcessorUsedByMultipleStyleSets(uint32_t aSheetType,
bool* aRetVal)
@ -3934,6 +3937,21 @@ nsDOMWindowUtils::HasRuleProcessorUsedByMultipleStyleSets(uint32_t aSheetType,
aRetVal);
}
NS_IMETHODIMP
nsDOMWindowUtils::SetNextPaintSyncId(int32_t aSyncId)
{
MOZ_RELEASE_ASSERT(nsContentUtils::IsCallerChrome());
if (nsIWidget* widget = GetWidget()) {
nsRefPtr<LayerManager> lm = widget->GetLayerManager();
if (lm && lm->GetBackendType() == LayersBackend::LAYERS_CLIENT) {
ClientLayerManager* clm = static_cast<ClientLayerManager*>(lm.get());
clm->SetNextPaintSyncId(aSyncId);
}
}
return NS_OK;
}
NS_INTERFACE_MAP_BEGIN(nsTranslationNodeList)
NS_INTERFACE_MAP_ENTRY(nsISupports)
NS_INTERFACE_MAP_ENTRY(nsITranslationNodeList)

View File

@ -1647,6 +1647,8 @@ nsDocument::~nsDocument()
}
}
ReportUseCounters();
mInDestructor = true;
mInUnlinkOrDeletion = true;
@ -4595,6 +4597,8 @@ nsIDocument::SetContainer(nsDocShell* aContainer)
if (sameTypeRoot == aContainer) {
static_cast<nsDocument*>(this)->SetIsTopLevelContentDocument(true);
}
static_cast<nsDocument*>(this)->SetIsContentDocument(true);
}
}
@ -4794,6 +4798,18 @@ nsDocument::SetIsTopLevelContentDocument(bool aIsTopLevelContentDocument)
mIsTopLevelContentDocument = aIsTopLevelContentDocument;
}
bool
nsDocument::IsContentDocument() const
{
return mIsContentDocument;
}
void
nsDocument::SetIsContentDocument(bool aIsContentDocument)
{
mIsContentDocument = aIsContentDocument;
}
nsPIDOMWindow *
nsDocument::GetWindowInternal() const
{
@ -10389,6 +10405,19 @@ static const char* kDocumentWarnings[] = {
};
#undef DOCUMENT_WARNING
static UseCounter
OperationToUseCounter(nsIDocument::DeprecatedOperations aOperation)
{
switch(aOperation) {
#define DEPRECATED_OPERATION(_op) \
case nsIDocument::e##_op: return eUseCounter_##_op;
#include "nsDeprecatedOperationList.h"
#undef DEPRECATED_OPERATION
default:
MOZ_CRASH();
}
}
bool
nsIDocument::HasWarnedAbout(DeprecatedOperations aOperation) const
{
@ -10404,6 +10433,7 @@ nsIDocument::WarnOnceAbout(DeprecatedOperations aOperation,
return;
}
mDeprecationWarnedAbout[aOperation] = true;
const_cast<nsIDocument*>(this)->SetDocumentAndPageUseCounter(OperationToUseCounter(aOperation));
uint32_t flags = asError ? nsIScriptError::errorFlag
: nsIScriptError::warningFlag;
nsContentUtils::ReportToConsole(flags,
@ -12756,6 +12786,196 @@ nsDocument::Evaluate(const nsAString& aExpression, nsIDOMNode* aContextNode,
aInResult, aResult);
}
nsIDocument*
nsIDocument::GetTopLevelContentDocument()
{
nsDocument* parent;
if (!mLoadedAsData) {
parent = static_cast<nsDocument*>(this);
} else {
nsCOMPtr<nsPIDOMWindow> window = do_QueryInterface(GetScopeObject());
if (!window) {
return nullptr;
}
parent = static_cast<nsDocument*>(window->GetExtantDoc());
if (!parent) {
return nullptr;
}
}
do {
if (parent->IsTopLevelContentDocument()) {
break;
}
// If we ever have a non-content parent before we hit a toplevel content
// parent, then we're never going to find one. Just bail.
if (!parent->IsContentDocument()) {
return nullptr;
}
nsIDocument* candidate = parent->GetParentDocument();
parent = static_cast<nsDocument*>(candidate);
} while (parent);
return parent;
}
void
nsIDocument::PropagateUseCounters(nsIDocument* aParentDocument)
{
MOZ_ASSERT(this != aParentDocument);
// What really matters here is that our use counters get propagated as
// high up in the content document hierarchy as possible. So,
// starting with aParentDocument, we need to find the toplevel content
// document, and propagate our use counters into its
// mChildDocumentUseCounters.
nsIDocument* contentParent = aParentDocument->GetTopLevelContentDocument();
if (!contentParent) {
return;
}
contentParent->mChildDocumentUseCounters |= mUseCounters;
contentParent->mChildDocumentUseCounters |= mChildDocumentUseCounters;
}
void
nsIDocument::SetPageUseCounter(UseCounter aUseCounter)
{
// We want to set the use counter on the "page" that owns us; the definition
// of "page" depends on what kind of document we are. See the comments below
// for details. In any event, checking all the conditions below is
// reasonably expensive, so we cache whether we've notified our owning page.
if (mNotifiedPageForUseCounter[aUseCounter]) {
return;
}
mNotifiedPageForUseCounter[aUseCounter] = true;
if (mDisplayDocument) {
// If we are a resource document, we won't have a docshell and so we won't
// record any page use counters on this document. Instead, we should
// forward it up to the document that loaded us.
MOZ_ASSERT(!mDocumentContainer);
mDisplayDocument->SetChildDocumentUseCounter(aUseCounter);
return;
}
if (IsBeingUsedAsImage()) {
// If this is an SVG image document, we also won't have a docshell.
MOZ_ASSERT(!mDocumentContainer);
return;
}
// We only care about use counters in content. If we're already a toplevel
// content document, then we should have already set the use counter on
// ourselves, and we are done.
nsIDocument* contentParent = GetTopLevelContentDocument();
if (!contentParent) {
return;
}
if (this == contentParent) {
MOZ_ASSERT(GetUseCounter(aUseCounter));
return;
}
contentParent->SetChildDocumentUseCounter(aUseCounter);
}
static bool
MightBeAboutOrChromeScheme(nsIURI* aURI)
{
MOZ_ASSERT(aURI);
bool isAbout = true;
bool isChrome = true;
aURI->SchemeIs("about", &isAbout);
aURI->SchemeIs("chrome", &isChrome);
return isAbout || isChrome;
}
void
nsDocument::ReportUseCounters()
{
static const bool sDebugUseCounters = false;
if (mReportedUseCounters) {
return;
}
mReportedUseCounters = true;
if (Telemetry::HistogramUseCounterCount > 0 &&
(IsContentDocument() || IsResourceDoc())) {
nsCOMPtr<nsIURI> uri;
NodePrincipal()->GetURI(getter_AddRefs(uri));
if (!uri || MightBeAboutOrChromeScheme(uri)) {
return;
}
if (sDebugUseCounters) {
nsCString spec;
uri->GetSpec(spec);
// URIs can be rather long for data documents, so truncate them to
// some reasonable length.
spec.Truncate(std::min(128U, spec.Length()));
printf("-- Use counters for %s --\n", spec.get());
}
// We keep separate counts for individual documents and top-level
// pages to more accurately track how many web pages might break if
// certain features were removed. Consider the case of a single
// HTML document with several SVG images and/or iframes with
// sub-documents of their own. If we maintained a single set of use
// counters and all the sub-documents use a particular feature, then
// telemetry would indicate that we would be breaking N documents if
// that feature were removed. Whereas with a document/top-level
// page split, we can see that N documents would be affected, but
// only a single web page would be affected.
for (int32_t c = 0;
c < eUseCounter_Count; ++c) {
UseCounter uc = static_cast<UseCounter>(c);
Telemetry::ID id =
static_cast<Telemetry::ID>(Telemetry::HistogramFirstUseCounter + uc * 2);
bool value = GetUseCounter(uc);
if (sDebugUseCounters && value) {
const char* name = Telemetry::GetHistogramName(id);
if (name) {
printf(" %s", name);
} else {
printf(" #%d", id);
}
printf(": %d\n", value);
}
Telemetry::Accumulate(id, value);
if (IsTopLevelContentDocument()) {
id = static_cast<Telemetry::ID>(Telemetry::HistogramFirstUseCounter +
uc * 2 + 1);
value = GetUseCounter(uc) || GetChildDocumentUseCounter(uc);
if (sDebugUseCounters && value) {
const char* name = Telemetry::GetHistogramName(id);
if (name) {
printf(" %s", name);
} else {
printf(" #%d", id);
}
printf(": %d\n", value);
}
Telemetry::Accumulate(id, value);
}
}
}
}
XPathEvaluator*
nsIDocument::XPathEvaluator()
{

View File

@ -972,6 +972,8 @@ public:
*/
void OnAppThemeChanged();
void ReportUseCounters();
private:
void AddOnDemandBuiltInUASheet(mozilla::CSSStyleSheet* aSheet);
nsRadioGroupStruct* GetRadioGroupInternal(const nsAString& aName) const;
@ -1478,12 +1480,15 @@ public:
static void XPCOMShutdown();
bool mIsTopLevelContentDocument:1;
bool mIsTopLevelContentDocument: 1;
bool mIsContentDocument: 1;
bool IsTopLevelContentDocument();
void SetIsTopLevelContentDocument(bool aIsTopLevelContentDocument);
bool IsContentDocument() const;
void SetIsContentDocument(bool aIsContentDocument);
js::ExpandoAndGeneration mExpandoAndGeneration;
#ifdef MOZ_EME
@ -1676,6 +1681,14 @@ public:
// The value is saturated to kPointerLockRequestLimit+1 = 3.
uint8_t mCancelledPointerLockRequests:2;
// Whether we have reported use counters for this document with Telemetry yet.
// Normally this is only done at document destruction time, but for image
// documents (SVG documents) that are not guaranteed to be destroyed, we
// report use counters when the image cache no longer has any imgRequestProxys
// pointing to them. We track whether we ever reported use counters so
// that we only report them once for the document.
bool mReportedUseCounters:1;
uint8_t mPendingFullscreenRequests;
uint8_t mXMLDeclarationBits;

View File

@ -25,6 +25,7 @@
#include "mozilla/net/ReferrerPolicy.h" // for member
#include "nsWeakReference.h"
#include "mozilla/dom/DocumentBinding.h"
#include "mozilla/UseCounter.h"
#include "mozilla/WeakPtr.h"
#include "Units.h"
#include "nsExpirationTracker.h"
@ -1714,7 +1715,7 @@ public:
bool IsResourceDoc() const {
return IsBeingUsedAsImage() || // Are we a helper-doc for an SVG image?
!!mDisplayDocument; // Are we an external resource doc?
mHasDisplayDocument; // Are we an external resource doc?
}
/**
@ -1743,6 +1744,7 @@ public:
NS_PRECONDITION(!aDisplayDocument->GetDisplayDocument(),
"Display documents should not nest");
mDisplayDocument = aDisplayDocument;
mHasDisplayDocument = !!aDisplayDocument;
}
/**
@ -2316,6 +2318,8 @@ public:
eAttributeChanged
};
nsIDocument* GetTopLevelContentDocument();
/**
* Registers an unresolved custom element that is a candidate for
* upgrade when the definition is registered via registerElement.
@ -2579,6 +2583,41 @@ public:
bool DidFireDOMContentLoaded() const { return mDidFireDOMContentLoaded; }
void SetDocumentUseCounter(mozilla::UseCounter aUseCounter)
{
if (!mUseCounters[aUseCounter]) {
mUseCounters[aUseCounter] = true;
}
}
void SetPageUseCounter(mozilla::UseCounter aUseCounter);
void SetDocumentAndPageUseCounter(mozilla::UseCounter aUseCounter)
{
SetDocumentUseCounter(aUseCounter);
SetPageUseCounter(aUseCounter);
}
void PropagateUseCounters(nsIDocument* aParentDocument);
protected:
bool GetUseCounter(mozilla::UseCounter aUseCounter)
{
return mUseCounters[aUseCounter];
}
void SetChildDocumentUseCounter(mozilla::UseCounter aUseCounter)
{
if (!mChildDocumentUseCounters[aUseCounter]) {
mChildDocumentUseCounters[aUseCounter] = true;
}
}
bool GetChildDocumentUseCounter(mozilla::UseCounter aUseCounter)
{
return mChildDocumentUseCounters[aUseCounter];
}
private:
mutable std::bitset<eDeprecatedOperationCount> mDeprecationWarnedAbout;
mutable std::bitset<eDocumentWarningCount> mDocWarningWarnedAbout;
@ -2810,6 +2849,12 @@ protected:
// caches.
bool mDidDocumentOpen : 1;
// Whether this document has a display document and thus is considered to
// be a resource document. Normally this is the same as !!mDisplayDocument,
// but mDisplayDocument is cleared during Unlink. mHasDisplayDocument is
// valid in the document's destructor.
bool mHasDisplayDocument : 1;
// Is the current mFontFaceSet valid?
bool mFontFaceSetDirty : 1;
@ -2956,6 +3001,14 @@ protected:
// Our live MediaQueryLists
PRCList mDOMMediaQueryLists;
// Flags for use counters used directly by this document.
std::bitset<mozilla::eUseCounter_Count> mUseCounters;
// Flags for use counters used by any child documents of this document.
std::bitset<mozilla::eUseCounter_Count> mChildDocumentUseCounters;
// Flags for whether we've notified our top-level "page" of a use counter
// for this child document.
std::bitset<mozilla::eUseCounter_Count> mNotifiedPageForUseCounter;
};
NS_DEFINE_STATIC_IID_ACCESSOR(nsIDocument, NS_IDOCUMENT_IID)

View File

@ -191,6 +191,12 @@ nsImageLoadingContent::Notify(imgIRequest* aRequest,
}
if (aType == imgINotificationObserver::DECODE_COMPLETE) {
nsCOMPtr<imgIContainer> container;
aRequest->GetImage(getter_AddRefs(container));
if (container) {
container->PropagateUseCounters(GetOurOwnerDoc());
}
UpdateImageState(true);
}

View File

@ -1,6 +1,15 @@
[DEFAULT]
support-files =
file_messagemanager_unload.html
file_use_counter_outer.html
file_use_counter_svg_getElementById.svg
file_use_counter_svg_currentScale.svg
file_use_counter_svg_background.html
file_use_counter_svg_list_style_image.html
file_use_counter_svg_fill_pattern_definition.svg
file_use_counter_svg_fill_pattern.svg
file_use_counter_svg_fill_pattern_internal.svg
file_use_counter_svg_fill_pattern_data.svg
[browser_bug593387.js]
skip-if = e10s # Bug ?????? - test directly touches content (contentWindow.iframe.addEventListener)
@ -17,3 +26,4 @@ skip-if = e10s # this tests non-e10s behavior. it's not expected to work in e10s
skip-if = true # Intermittent failures - bug 987493. Restore the skip-if above once fixed
[browser_bug1058164.js]
skip-if = e10s # We need bug 918634 to land before this can be tested with e10s.
[browser_use_counters.js]

View File

@ -0,0 +1,276 @@
/* -*- Mode: javascript; tab-width: 2; indent-tabs-mode: nil; js-indent-level: 2 -*- */
let {Promise: promise} = Cu.import("resource://gre/modules/Promise.jsm", {});
const gHttpTestRoot = "http://example.com/browser/dom/base/test/";
/**
* Enable local telemetry recording for the duration of the tests.
*/
let gOldContentCanRecord = false;
add_task(function* test_initialize() {
gOldContentCanRecord = yield ContentTask.spawn(gBrowser.selectedBrowser, {}, function () {
let telemetry = Cc["@mozilla.org/base/telemetry;1"].getService(Ci.nsITelemetry);
let old = telemetry.canRecordExtended;
telemetry.canRecordExtended = true;
return old;
});
info("canRecord for content: " + gOldContentCanRecord);
});
add_task(function* () {
// Check that use counters are incremented by SVGs loaded directly in iframes.
yield check_use_counter_iframe("file_use_counter_svg_getElementById.svg",
"SVGSVGELEMENT_GETELEMENTBYID");
yield check_use_counter_iframe("file_use_counter_svg_currentScale.svg",
"SVGSVGELEMENT_CURRENTSCALE_getter");
yield check_use_counter_iframe("file_use_counter_svg_currentScale.svg",
"SVGSVGELEMENT_CURRENTSCALE_setter");
// Check that use counters are incremented by SVGs loaded as images.
// Note that SVG images are not permitted to execute script, so we can only
// check for properties here.
yield check_use_counter_img("file_use_counter_svg_getElementById.svg",
"PROPERTY_FILL");
yield check_use_counter_img("file_use_counter_svg_currentScale.svg",
"PROPERTY_FILL");
// Check that use counters are incremented by directly loading SVGs
// that reference patterns defined in another SVG file.
yield check_use_counter_direct("file_use_counter_svg_fill_pattern.svg",
"PROPERTY_FILLOPACITY", /*xfail=*/true);
// Check that use counters are incremented by directly loading SVGs
// that reference patterns defined in the same file or in data: URLs.
yield check_use_counter_direct("file_use_counter_svg_fill_pattern_internal.svg",
"PROPERTY_FILLOPACITY");
// data: URLs don't correctly propagate to their referring document yet.
//yield check_use_counter_direct("file_use_counter_svg_fill_pattern_data.svg",
// "PROPERTY_FILL_OPACITY");
// Check that use counters are incremented by SVGs loaded as CSS images in
// pages loaded in iframes. Again, SVG images in CSS aren't permitted to
// execute script, so we need to use properties here.
yield check_use_counter_iframe("file_use_counter_svg_background.html",
"PROPERTY_FILL");
yield check_use_counter_iframe("file_use_counter_svg_list_style_image.html",
"PROPERTY_FILL");
// Check that even loads from the imglib cache update use counters. The
// background images should still be there, because we just loaded them
// in the last set of tests. But we won't get updated counts for the
// document counters, because we won't be re-parsing the SVG documents.
yield check_use_counter_iframe("file_use_counter_svg_background.html",
"PROPERTY_FILL", false);
yield check_use_counter_iframe("file_use_counter_svg_list_style_image.html",
"PROPERTY_FILL", false);
});
add_task(function* () {
yield ContentTask.spawn(gBrowser.selectedBrowser, { oldCanRecord: gOldContentCanRecord }, function (arg) {
Cu.import("resource://gre/modules/PromiseUtils.jsm");
yield new Promise(resolve => {
let telemetry = Cc["@mozilla.org/base/telemetry;1"].getService(Ci.nsITelemetry);
telemetry.canRecordExtended = arg.oldCanRecord;
resolve();
});
});
});
function waitForDestroyedDocuments() {
let deferred = promise.defer();
SpecialPowers.exactGC(window, deferred.resolve);
return deferred.promise;
}
function waitForPageLoad(browser) {
return ContentTask.spawn(browser, null, function*() {
Cu.import("resource://gre/modules/PromiseUtils.jsm");
yield new Promise(resolve => {
let listener = () => {
removeEventListener("load", listener, true);
resolve();
}
addEventListener("load", listener, true);
});
});
}
function grabHistogramsFromContent(browser, use_counter_middlefix) {
return ContentTask.spawn(browser, { middlefix: use_counter_middlefix }, function* (arg) {
let telemetry = Cc["@mozilla.org/base/telemetry;1"].getService(Ci.nsITelemetry);
function snapshot_histogram(name) {
return telemetry.getHistogramById(name).snapshot();
}
let histogram_page_name = "USE_COUNTER_" + arg.middlefix + "_PAGE";
let histogram_document_name = "USE_COUNTER_" + arg.middlefix + "_DOCUMENT";
let histogram_page = snapshot_histogram(histogram_page_name);
let histogram_document = snapshot_histogram(histogram_document_name);
return [histogram_page.sum, histogram_document.sum];
});
}
let check_use_counter_iframe = Task.async(function* (file, use_counter_middlefix, check_documents=true) {
info("checking " + file + " with histogram " + use_counter_middlefix);
let newTab = gBrowser.addTab( "about:blank");
gBrowser.selectedTab = newTab;
newTab.linkedBrowser.stop();
// Hold on to the current values of the telemetry histograms we're
// interested in.
let [histogram_page_before, histogram_document_before] =
yield grabHistogramsFromContent(gBrowser.selectedBrowser, use_counter_middlefix);
gBrowser.selectedBrowser.loadURI(gHttpTestRoot + "file_use_counter_outer.html");
yield waitForPageLoad(gBrowser.selectedBrowser);
// Inject our desired file into the iframe of the newly-loaded page.
yield ContentTask.spawn(gBrowser.selectedBrowser, { file: file }, function(opts) {
Cu.import("resource://gre/modules/PromiseUtils.jsm");
let deferred = PromiseUtils.defer();
let wu = content.window.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIDOMWindowUtils);
let iframe = content.document.getElementById('content');
iframe.src = opts.file;
let listener = (event) => {
event.target.removeEventListener("load", listener, true);
// We flush the main document first, then the iframe's document to
// ensure any propagation that might happen from child->parent should
// have already happened when counters are reported to telemetry.
wu.forceUseCounterFlush(content.document);
wu.forceUseCounterFlush(iframe.contentDocument);
deferred.resolve();
};
iframe.addEventListener("load", listener, true);
return deferred.promise;
});
// Tear down the page.
gBrowser.removeTab(newTab);
// The histograms only get recorded when the document actually gets
// destroyed, which might not have happened yet due to GC/CC effects, etc.
// Try to force document destruction.
yield waitForDestroyedDocuments();
// Grab histograms again and compare.
let [histogram_page_after, histogram_document_after] =
yield grabHistogramsFromContent(gBrowser.selectedBrowser, use_counter_middlefix);
is(histogram_page_after, histogram_page_before + 1,
"page counts for " + use_counter_middlefix + " after are correct");
if (check_documents) {
is(histogram_document_after, histogram_document_before + 1,
"document counts " + use_counter_middlefix + " after are correct");
}
});
let check_use_counter_img = Task.async(function* (file, use_counter_middlefix) {
info("checking " + file + " as image with histogram " + use_counter_middlefix);
let newTab = gBrowser.addTab("about:blank");
gBrowser.selectedTab = newTab;
newTab.linkedBrowser.stop();
// Hold on to the current values of the telemetry histograms we're
// interested in.
let [histogram_page_before, histogram_document_before] =
yield grabHistogramsFromContent(gBrowser.selectedBrowser, use_counter_middlefix);
gBrowser.selectedBrowser.loadURI(gHttpTestRoot + "file_use_counter_outer.html");
yield waitForPageLoad(gBrowser.selectedBrowser);
// Inject our desired file into the img of the newly-loaded page.
yield ContentTask.spawn(gBrowser.selectedBrowser, { file: file }, function(opts) {
Cu.import("resource://gre/modules/PromiseUtils.jsm");
let deferred = PromiseUtils.defer();
let img = content.document.getElementById('display');
img.src = opts.file;
let listener = (event) => {
img.removeEventListener("load", listener, true);
// Flush for the image. It matters what order we do these in, so that
// the image can propagate its use counters to the document prior to the
// document reporting its use counters.
let wu = content.window.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIDOMWindowUtils);
wu.forceUseCounterFlush(img);
// Flush for the main window.
wu.forceUseCounterFlush(content.document);
deferred.resolve();
};
img.addEventListener("load", listener, true);
return deferred.promise;
});
// Tear down the page.
gBrowser.removeTab(newTab);
// The histograms only get recorded when the document actually gets
// destroyed, which might not have happened yet due to GC/CC effects, etc.
// Try to force document destruction.
yield waitForDestroyedDocuments();
// Grab histograms again and compare.
let [histogram_page_after, histogram_document_after] =
yield grabHistogramsFromContent(gBrowser.selectedBrowser, use_counter_middlefix);
is(histogram_page_after, histogram_page_before + 1,
"page counts for " + use_counter_middlefix + " after are correct");
is(histogram_document_after, histogram_document_before + 1,
"document counts " + use_counter_middlefix + " after are correct");
});
let check_use_counter_direct = Task.async(function* (file, use_counter_middlefix, xfail=false) {
info("checking " + file + " with histogram " + use_counter_middlefix);
let newTab = gBrowser.addTab( "about:blank");
gBrowser.selectedTab = newTab;
newTab.linkedBrowser.stop();
// Hold on to the current values of the telemetry histograms we're
// interested in.
let [histogram_page_before, histogram_document_before] =
yield grabHistogramsFromContent(gBrowser.selectedBrowser, use_counter_middlefix);
gBrowser.selectedBrowser.loadURI(gHttpTestRoot + file);
yield ContentTask.spawn(gBrowser.selectedBrowser, null, function*() {
Cu.import("resource://gre/modules/PromiseUtils.jsm");
yield new Promise(resolve => {
let listener = () => {
removeEventListener("load", listener, true);
let wu = content.window.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIDOMWindowUtils);
wu.forceUseCounterFlush(content.document);
setTimeout(resolve, 0);
}
addEventListener("load", listener, true);
});
});
// Tear down the page.
gBrowser.removeTab(newTab);
// The histograms only get recorded when the document actually gets
// destroyed, which might not have happened yet due to GC/CC effects, etc.
// Try to force document destruction.
yield waitForDestroyedDocuments();
// Grab histograms again and compare.
let [histogram_page_after, histogram_document_after] =
yield grabHistogramsFromContent(gBrowser.selectedBrowser, use_counter_middlefix);
(xfail ? todo_is : is)(histogram_page_after, histogram_page_before + 1,
"page counts for " + use_counter_middlefix + " after are correct");
(xfail ? todo_is : is)(histogram_document_after, histogram_document_before + 1,
"document counts " + use_counter_middlefix + " after are correct");
});

View File

@ -0,0 +1,17 @@
<!DOCTYPE HTML>
<html>
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=968923
-->
<head>
<meta charset="utf-8">
<title>Test for Bug 968923</title>
</head>
<body>
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=968923">Mozilla Bug 968923</a>
<img id="display" />
<iframe id="content">
</iframe>
</body>
</html>

View File

@ -0,0 +1,22 @@
<!DOCTYPE HTML>
<html>
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=968923
-->
<head>
<meta charset="utf-8">
<title>Test for Bug 968923</title>
<style>
/* Use a query string to work around imagelib caching.
Otherwise, we won't get use counters for this file. */
body { background-image: url('file_use_counter_svg_getElementById.svg?asbackground=1') }
</style>
</head>
<body>
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=968923">Mozilla Bug 968923</a>
<img id="display" />
<iframe id="content" src="about:blank">
</iframe>
</body>
</html>

View File

@ -0,0 +1,18 @@
<?xml version="1.0" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg width="4in" height="3in" version="1.1"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink">
<desc>Test graphic for hitting currentScale
</desc>
<script type="text/javascript"> <![CDATA[
document.documentElement.currentScale = document.documentElement.currentScale;
]]>
</script>
<image id="i1" x="200" y="200" width="100px" height="80px"
xlink:href="no-such-scheme:nothing">
</image>
<circle cx="100" cy="50" r="40" stroke="black" stroke-width="2" fill="red"/>
</svg>

After

Width:  |  Height:  |  Size: 680 B

View File

@ -0,0 +1,15 @@
<?xml version="1.0" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg width="8cm" height="4cm" viewBox="0 0 800 400" version="1.1"
xmlns="http://www.w3.org/2000/svg">
<desc>Borrowed from http://www.w3.org/TR/SVG/pservers.html</desc>
<!-- Outline the drawing area in blue -->
<rect fill="none" stroke="blue"
x="1" y="1" width="798" height="398"/>
<!-- The ellipse is filled using a triangle pattern paint server
and stroked with black -->
<ellipse fill="url(http://example.com/browser/dom/base/test/file_use_counter_svg_fill_pattern_definition.svg#TrianglePattern)" stroke="black" stroke-width="5"
cx="400" cy="200" rx="350" ry="150" />
</svg>

After

Width:  |  Height:  |  Size: 763 B

View File

@ -0,0 +1,15 @@
<?xml version="1.0" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg width="8cm" height="4cm" viewBox="0 0 800 400" version="1.1"
xmlns="http://www.w3.org/2000/svg">
<desc>Borrowed from http://www.w3.org/TR/SVG/pservers.html</desc>
<!-- Outline the drawing area in blue -->
<rect fill="none" stroke="blue"
x="1" y="1" width="798" height="398"/>
<!-- The ellipse is filled using a triangle pattern paint server
and stroked with black -->
<ellipse fill="url(data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBzdGFuZGFsb25lPSJubyI/Pgo8IURPQ1RZUEUgc3ZnIFBVQkxJQyAiLS8vVzNDLy9EVEQgU1ZHIDEuMS8vRU4iIAogICJodHRwOi8vd3d3LnczLm9yZy9HcmFwaGljcy9TVkcvMS4xL0RURC9zdmcxMS5kdGQiPgo8c3ZnIHdpZHRoPSI4Y20iIGhlaWdodD0iNGNtIiB2aWV3Qm94PSIwIDAgODAwIDQwMCIgdmVyc2lvbj0iMS4xIgogICAgIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+CiAgPGRlc2M+Qm9ycm93ZWQgZnJvbSBodHRwOi8vd3d3LnczLm9yZy9UUi9TVkcvcHNlcnZlcnMuaHRtbDwvZGVzYz4KICA8ZGVmcz4KICAgIDxwYXR0ZXJuIGlkPSJUcmlhbmdsZVBhdHRlcm4iIHBhdHRlcm5Vbml0cz0idXNlclNwYWNlT25Vc2UiCiAgICAgICAgICAgICB4PSIwIiB5PSIwIiB3aWR0aD0iMTAwIiBoZWlnaHQ9IjEwMCIKICAgICAgICAgICAgIHZpZXdCb3g9IjAgMCAxMCAxMCIgPgogICAgICA8cGF0aCBkPSJNIDAgMCBMIDcgMCBMIDMuNSA3IHoiIGZpbGw9InJlZCIgZmlsbC1vcGFjaXR5PSIwLjciIHN0cm9rZT0iYmx1ZSIgLz4KICAgIDwvcGF0dGVybj4gCiAgPC9kZWZzPgo8L3N2Zz4K#TrianglePattern)" stroke="black" stroke-width="5"
cx="400" cy="200" rx="350" ry="150" />
</svg>

After

Width:  |  Height:  |  Size: 1.5 KiB

View File

@ -0,0 +1,14 @@
<?xml version="1.0" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg width="8cm" height="4cm" viewBox="0 0 800 400" version="1.1"
xmlns="http://www.w3.org/2000/svg">
<desc>Borrowed from http://www.w3.org/TR/SVG/pservers.html</desc>
<defs>
<pattern id="TrianglePattern" patternUnits="userSpaceOnUse"
x="0" y="0" width="100" height="100"
viewBox="0 0 10 10" >
<path d="M 0 0 L 7 0 L 3.5 7 z" fill="red" fill-opacity="0.7" stroke="blue" />
</pattern>
</defs>
</svg>

After

Width:  |  Height:  |  Size: 591 B

View File

@ -0,0 +1,23 @@
<?xml version="1.0" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg width="8cm" height="4cm" viewBox="0 0 800 400" version="1.1"
xmlns="http://www.w3.org/2000/svg">
<desc>Borrowed from http://www.w3.org/TR/SVG/pservers.html</desc>
<!-- Outline the drawing area in blue -->
<rect fill="none" stroke="blue"
x="1" y="1" width="798" height="398"/>
<defs>
<pattern id="TrianglePattern" patternUnits="userSpaceOnUse"
x="0" y="0" width="100" height="100"
viewBox="0 0 10 10" >
<path d="M 0 0 L 7 0 L 3.5 7 z" fill="red" fill-opacity="0.7" stroke="blue" />
</pattern>
</defs>
<!-- The ellipse is filled using a triangle pattern paint server
and stroked with black -->
<ellipse fill="url(#TrianglePattern)" stroke="black" stroke-width="5"
cx="400" cy="200" rx="350" ry="150" />
</svg>

After

Width:  |  Height:  |  Size: 944 B

View File

@ -0,0 +1,23 @@
<?xml version="1.0" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg width="4in" height="3in" version="1.1"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink">
<desc>Test graphic for hitting getElementById
</desc>
<image id="i1" x="200" y="200" width="100px" height="80px"
xlink:href="no-such-scheme:nothing">
</image>
<circle cx="100" cy="50" r="40" stroke="black" stroke-width="2" fill="red"/>
<script type="text/javascript"> <![CDATA[
var image = document.documentElement.getElementById("i1");
image.addEventListener("load",
function() {
document.documentElement.removeAttribute("class");
},
false);
]]>
</script>
</svg>

After

Width:  |  Height:  |  Size: 881 B

View File

@ -0,0 +1,22 @@
<!DOCTYPE HTML>
<html>
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=968923
-->
<head>
<meta charset="utf-8">
<title>Test for Bug 968923</title>
<style>
/* Use a query string to work around imagelib caching.
Otherwise, we won't get use counters for this file. */
ul { list-style-image: url('file_use_counter_svg_currentScale.svg?asliststyleimage=1') }
</style>
</head>
<body>
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=968923">Mozilla Bug 968923</a>
<ul>
<li>Some text</li>
<li>Some other text</li>
</ul>
</body>
</html>

View File

@ -41,7 +41,7 @@ def read_conf(conf_filename):
'interface_name': interface_name,
'attribute_name': attribute_name }
continue
m = re.match(r'property ([a-z0-9-]+)$', line)
m = re.match(r'property ([A-Za-z0-9]+)$', line)
if m:
property_name = m.group(1)
yield { 'type': 'property',
@ -70,7 +70,9 @@ def generate_histograms(filename):
append_counters(method.replace('.', '_').upper(), 'called %s' % method)
elif counter['type'] == 'attribute':
attr = '%s.%s' % (counter['interface_name'], counter['attribute_name'])
append_counters(attr.replace('.', '_').upper(), 'got or set %s' % attr)
counter_name = attr.replace('.', '_').upper()
append_counters('%s_getter' % counter_name, 'got %s' % attr)
append_counters('%s_setter' % counter_name, 'set %s' % attr)
elif counter['type'] == 'property':
prop = counter['property_name']
append_counters('PROPERTY_%s' % prop.replace('-', '_').upper(), "used the '%s' property" % prop)

View File

@ -14,6 +14,7 @@
#include "mozilla/Assertions.h"
#include "mozilla/Preferences.h"
#include "mozilla/unused.h"
#include "mozilla/UseCounter.h"
#include "AccessCheck.h"
#include "jsfriendapi.h"
@ -30,6 +31,7 @@
#include "XrayWrapper.h"
#include "nsPrintfCString.h"
#include "prprf.h"
#include "nsGlobalWindow.h"
#include "mozilla/dom/ScriptSettings.h"
#include "mozilla/dom/DOMError.h"
@ -46,6 +48,7 @@
#include "WorkerPrivate.h"
#include "nsDOMClassInfo.h"
#include "ipc/ErrorIPCUtils.h"
#include "mozilla/UseCounter.h"
namespace mozilla {
namespace dom {
@ -3050,5 +3053,15 @@ AssertReflectorHasGivenProto(JSContext* aCx, JSObject* aReflector,
} // namespace binding_detail
#endif // DEBUG
void
SetDocumentAndPageUseCounter(JSContext* aCx, JSObject* aObject,
UseCounter aUseCounter)
{
nsGlobalWindow* win = xpc::WindowGlobalOrNull(js::UncheckedUnwrap(aObject));
if (win && win->GetDocument()) {
win->GetDocument()->SetDocumentAndPageUseCounter(aUseCounter);
}
}
} // namespace dom
} // namespace mozilla

View File

@ -42,6 +42,9 @@ class nsIJSID;
class nsPIDOMWindow;
namespace mozilla {
enum UseCounter : int16_t;
namespace dom {
template<typename DataType> class MozMap;
@ -3317,6 +3320,10 @@ bool
GetDesiredProto(JSContext* aCx, const JS::CallArgs& aCallArgs,
JS::MutableHandle<JSObject*> aDesiredProto);
void
SetDocumentAndPageUseCounter(JSContext* aCx, JSObject* aObject,
UseCounter aUseCounter);
} // namespace dom
} // namespace mozilla

View File

@ -6836,7 +6836,8 @@ class CGPerSignatureCall(CGThing):
def __init__(self, returnType, arguments, nativeMethodName, static,
descriptor, idlNode, argConversionStartsAt=0, getter=False,
setter=False, isConstructor=False, resultVar=None):
setter=False, isConstructor=False, useCounterName=None,
resultVar=None):
assert idlNode.isMethod() == (not getter and not setter)
assert idlNode.isAttr() == (getter or setter)
# Constructors are always static
@ -7047,6 +7048,12 @@ class CGPerSignatureCall(CGThing):
self.getArguments(), argsPre, returnType,
self.extendedAttributes, descriptor, nativeMethodName,
static, argsPost=argsPost, resultVar=resultVar))
if useCounterName:
# Generate a telemetry call for when [UseCounter] is used.
code = "SetDocumentAndPageUseCounter(cx, obj, eUseCounter_%s);\n" % useCounterName
cgThings.append(CGGeneric(code))
self.cgRoot = CGList(cgThings)
def getArguments(self):
@ -7211,6 +7218,11 @@ class CGMethodCall(CGThing):
methodName = "%s.%s" % (descriptor.interface.identifier.name, method.identifier.name)
argDesc = "argument %d of " + methodName
if method.getExtendedAttribute("UseCounter"):
useCounterName = methodName.replace(".", "_")
else:
useCounterName = None
def requiredArgCount(signature):
arguments = signature[1]
if len(arguments) == 0:
@ -7225,7 +7237,8 @@ class CGMethodCall(CGThing):
nativeMethodName, static, descriptor,
method,
argConversionStartsAt=argConversionStartsAt,
isConstructor=isConstructor)
isConstructor=isConstructor,
useCounterName=useCounterName)
def filteredSignatures(signatures, descriptor):
def typeExposedInWorkers(type):
@ -7630,9 +7643,14 @@ class CGGetterCall(CGPerSignatureCall):
getter.
"""
def __init__(self, returnType, nativeMethodName, descriptor, attr):
if attr.getExtendedAttribute("UseCounter"):
useCounterName = "%s_%s_getter" % (descriptor.interface.identifier.name,
attr.identifier.name)
else:
useCounterName = None
CGPerSignatureCall.__init__(self, returnType, [], nativeMethodName,
attr.isStatic(), descriptor, attr,
getter=True)
getter=True, useCounterName=useCounterName)
class FakeIdentifier():
@ -7679,10 +7697,15 @@ class CGSetterCall(CGPerSignatureCall):
setter.
"""
def __init__(self, argType, nativeMethodName, descriptor, attr):
if attr.getExtendedAttribute("UseCounter"):
useCounterName = "%s_%s_setter" % (descriptor.interface.identifier.name,
attr.identifier.name)
else:
useCounterName = None
CGPerSignatureCall.__init__(self, None,
[FakeArgument(argType, attr, allowTreatNonCallableAsNull=True)],
nativeMethodName, attr.isStatic(),
descriptor, attr, setter=True)
descriptor, attr, setter=True, useCounterName=useCounterName)
def wrap_return_value(self):
attr = self.idlNode
@ -12855,6 +12878,13 @@ class CGBindingRoot(CGThing):
bindingHeaders["mozilla/dom/ScriptSettings.h"] = dictionaries # AutoJSAPI
bindingHeaders["xpcpublic.h"] = dictionaries # xpc::UnprivilegedJunkScope
# For things that have [UseCounter]
def descriptorRequiresTelemetry(desc):
iface = desc.interface
return any(m.getExtendedAttribute("UseCounter") for m in iface.members)
bindingHeaders["mozilla/UseCounter.h"] = any(
descriptorRequiresTelemetry(d) for d in descriptors)
cgthings.extend(traverseMethods)
cgthings.extend(unlinkMethods)

View File

@ -4026,6 +4026,11 @@ class IDLAttribute(IDLInterfaceMember):
"readonly attributes" % attr.value(),
[attr.location, self.location])
self._setDependsOn(attr.value())
elif identifier == "UseCounter":
if self.stringifier:
raise WebIDLError("[UseCounter] must not be used on a "
"stringifier attribute",
[attr.location, self.location])
elif (identifier == "Pref" or
identifier == "Deprecated" or
identifier == "SetterThrows" or
@ -4431,6 +4436,15 @@ class IDLMethod(IDLInterfaceMember, IDLScope):
"""
return self.maplikeOrSetlike is not None
def isSpecial(self):
return (self.isGetter() or
self.isSetter() or
self.isCreator() or
self.isDeleter() or
self.isLegacycaller() or
self.isStringifier() or
self.isJsonifier())
def hasOverloads(self):
return self._hasOverloads
@ -4712,6 +4726,11 @@ class IDLMethod(IDLInterfaceMember, IDLScope):
raise WebIDLError("[Alias] takes an identifier or string",
[attr.location])
self._addAlias(attr.value())
elif identifier == "UseCounter":
if self.isSpecial():
raise WebIDLError("[UseCounter] must not be used on a special "
"operation",
[attr.location, self.location])
elif (identifier == "Throws" or
identifier == "NewObject" or
identifier == "ChromeOnly" or

View File

@ -7,6 +7,7 @@
#include "mozilla/dom/ChannelInfo.h"
#include "nsCOMPtr.h"
#include "nsIChannel.h"
#include "nsIDocument.h"
#include "nsIHttpChannel.h"
#include "nsSerializationHelper.h"
#include "mozilla/net/HttpBaseChannel.h"
@ -18,6 +19,26 @@
using namespace mozilla;
using namespace mozilla::dom;
void
ChannelInfo::InitFromDocument(nsIDocument* aDoc)
{
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(!mInited, "Cannot initialize the object twice");
nsCOMPtr<nsISupports> securityInfo = aDoc->GetSecurityInfo();
if (securityInfo) {
SetSecurityInfo(securityInfo);
}
// mRedirected flag and mRedirectedURISpec are only important for maintaining
// the channel's redirected status. If the ChannelInfo is initialized from
// a document, that document has already asked the channel from which it was
// loaded about the current channel URI, so it won't matter if a future
// ResurrectInfoOnChannel() call misses whether the channel was redirected.
mRedirected = false;
mInited = true;
}
void
ChannelInfo::InitFromChannel(nsIChannel* aChannel)
{

View File

@ -11,6 +11,7 @@
#include "nsCOMPtr.h"
class nsIChannel;
class nsIDocument;
class nsIURI;
namespace mozilla {
@ -66,6 +67,7 @@ public:
return *this;
}
void InitFromDocument(nsIDocument* aDoc);
void InitFromChannel(nsIChannel* aChannel);
void InitFromIPCChannelInfo(const IPCChannelInfo& aChannelInfo);

View File

@ -159,6 +159,22 @@ Response::Constructor(const GlobalObject& aGlobal,
nsRefPtr<InternalResponse> internalResponse =
new InternalResponse(aInit.mStatus, statusText);
// Grab a valid channel info from the global so this response is 'valid' for
// interception.
if (NS_IsMainThread()) {
nsCOMPtr<nsPIDOMWindow> window = do_QueryInterface(global);
MOZ_ASSERT(window);
nsIDocument* doc = window->GetExtantDoc();
MOZ_ASSERT(doc);
ChannelInfo info;
info.InitFromDocument(doc);
internalResponse->InitChannelInfo(info);
} else {
workers::WorkerPrivate* worker = workers::GetCurrentThreadWorkerPrivate();
MOZ_ASSERT(worker);
internalResponse->InitChannelInfo(worker->GetChannelInfo());
}
nsRefPtr<Response> r = new Response(global, internalResponse);
if (aInit.mHeaders.WasPassed()) {

View File

@ -11,6 +11,7 @@
#include "nsPresContext.h"
#include "nsMappedAttributes.h"
#include "nsSize.h"
#include "nsDocument.h"
#include "nsIDocument.h"
#include "nsIDOMMutationEvent.h"
#include "nsIScriptContext.h"
@ -27,6 +28,7 @@
#include "mozilla/dom/HTMLFormElement.h"
#include "nsAttrValueOrString.h"
#include "imgLoader.h"
#include "Image.h"
// Responsive images!
#include "mozilla/dom/HTMLSourceElement.h"
@ -1301,6 +1303,18 @@ HTMLImageElement::MediaFeatureValuesChanged()
QueueImageLoadTask();
}
void
HTMLImageElement::FlushUseCounters()
{
nsCOMPtr<imgIRequest> request;
GetRequest(CURRENT_REQUEST, getter_AddRefs(request));
nsCOMPtr<imgIContainer> container;
request->GetImage(getter_AddRefs(container));
static_cast<image::Image*>(container.get())->ReportUseCounters();
}
} // namespace dom
} // namespace mozilla

View File

@ -265,6 +265,12 @@ public:
const nsAString& aMediaAttr,
nsAString& aResult);
/**
* If this image's src pointers to an SVG document, flush the SVG document's
* use counters to telemetry. Only used for testing purposes.
*/
void FlushUseCounters();
protected:
virtual ~HTMLImageElement();

View File

@ -236,6 +236,7 @@ LOCAL_INCLUDES += [
'/dom/xul',
'/editor/libeditor',
'/editor/txmgr',
'/image',
'/layout/forms',
'/layout/generic',
'/layout/style',

View File

@ -6,13 +6,16 @@ const nsIQuotaManager = Components.interfaces.nsIQuotaManager;
let gURI = Components.classes["@mozilla.org/network/io-service;1"].getService(Components.interfaces.nsIIOService).newURI("http://localhost", null, null);
function onUsageCallback(uri, usage, fileUsage) {}
function onUsageCallback(principal, usage, fileUsage) {}
function onLoad()
{
var quotaManager = Components.classes["@mozilla.org/dom/quota/manager;1"]
.getService(nsIQuotaManager);
var quotaRequest = quotaManager.getUsageForURI(gURI, onUsageCallback);
let principal = Components.classes["@mozilla.org/scriptsecuritymanager;1"]
.getService(Components.interfaces.nsIScriptSecurityManager)
.createCodebasePrincipal(gURI, {});
var quotaRequest = quotaManager.getUsageForPrincipal(principal, onUsageCallback);
quotaRequest.cancel();
Components.classes["@mozilla.org/observer-service;1"]
.getService(Components.interfaces.nsIObserverService)

View File

@ -92,7 +92,7 @@ function testSteps()
let usageBeforeMaintenance;
quotaManager.getUsageForURI(uri, (url, usage) => {
quotaManager.getUsageForPrincipal(principal, (principal, usage) => {
ok(usage > 0, "Usage is non-zero");
usageBeforeMaintenance = usage;
continueToNextStep();
@ -118,7 +118,7 @@ function testSteps()
let usageAfterMaintenance;
quotaManager.getUsageForURI(uri, (url, usage) => {
quotaManager.getUsageForPrincipal(principal, (principal, usage) => {
ok(usage > 0, "Usage is non-zero");
usageAfterMaintenance = usage;
continueToNextStep();

View File

@ -259,7 +259,10 @@ function resetOrClearAllDatabases(callback, clear) {
let uri = Cc["@mozilla.org/network/io-service;1"]
.getService(Ci.nsIIOService)
.newURI("http://foo.com", null, null);
quotaManager.getUsageForURI(uri, function(usage, fileUsage) {
let principal = Cc["@mozilla.org/scriptsecuritymanager;1"]
.getService(Ci.nsIScriptSecurityManager)
.createCodebasePrincipal(uri, {});
quotaManager.getUsageForPrincipal(principal, function(principal, usage, fileUsage) {
callback();
});
}

View File

@ -49,7 +49,7 @@ interface nsIJSRAIIHelper;
interface nsIContentPermissionRequest;
interface nsIObserver;
[scriptable, uuid(47fa312b-2ad1-4b80-8a0a-c9822e2d1ec9)]
[scriptable, uuid(6ddc9a79-18cd-4dbc-9975-68928e6c9857)]
interface nsIDOMWindowUtils : nsISupports {
/**
@ -1625,19 +1625,6 @@ interface nsIDOMWindowUtils : nsISupports {
*/
void setScrollPositionClampingScrollPortSize(in float aWidth, in float aHeight);
/**
* Set margins for the layout of fixed position elements in the content
* document. These are used on mobile, where the viewable area can be
* temporarily obscured by the browser chrome. In this situation, we're ok
* with scrollable page content being obscured, but fixed position content
* cannot be revealed without removing the obscuring chrome, so we use these
* margins so that it can remain visible.
*
* The caller of this method must have chrome privileges.
*/
void setContentDocumentFixedPositionMargins(in float aTop, in float aRight,
in float aBottom, in float aLeft);
/**
* These are used to control whether dialogs (alert, prompt, confirm) are
* allowed.
@ -1847,6 +1834,19 @@ interface nsIDOMWindowUtils : nsISupports {
* @param aSheetType One of the nsIStyleSheetService.*_SHEET constants.
*/
bool hasRuleProcessorUsedByMultipleStyleSets(in unsigned long aSheetType);
/*
* Force the use counters for the node's associated document(s) to be
* flushed to telemetry. For example, a document node will flush its own
* counters and an image node with an SVG source will flush the SVG
* document's counters. Normally, use counters are flushed to telemetry
* upon document destruction, but as document destruction is somewhat
* non-deterministic, we have this method here for more determinism when
* running tests.
*/
void forceUseCounterFlush(in nsIDOMNode aNode);
void setNextPaintSyncId(in long aSyncId);
};
[scriptable, uuid(c694e359-7227-4392-a138-33c0cc1f15a6)]

View File

@ -380,6 +380,7 @@ MP3TrackDemuxer::Duration(int64_t aNumFrames) const {
MediaByteRange
MP3TrackDemuxer::FindNextFrame() {
static const int BUFFER_SIZE = 4096;
static const int MAX_SKIPPED_BYTES = 10 * BUFFER_SIZE;
MP3DEMUXER_LOGV("FindNext() Begin mOffset=%" PRIu64 " mNumParsedFrames=%" PRIu64
" mFrameIndex=%" PRId64
@ -393,8 +394,13 @@ MP3TrackDemuxer::FindNextFrame() {
const uint8_t* frameBeg = nullptr;
const uint8_t* bufferEnd = nullptr;
while (frameBeg == bufferEnd &&
(read = Read(buffer, mOffset, BUFFER_SIZE)) > 0) {
while (frameBeg == bufferEnd) {
if ((!mParser.FirstFrame().Length() &&
mOffset - mParser.ID3Header().Size() > MAX_SKIPPED_BYTES) ||
(read = Read(buffer, mOffset, BUFFER_SIZE)) == 0) {
// This is not a valid MPEG audio stream or we've reached EOS, give up.
break;
}
MOZ_ASSERT(mOffset + read > mOffset);
mOffset += read;
bufferEnd = buffer + read;

View File

@ -132,8 +132,6 @@ MediaDecoder::InitStatics()
// Log modules.
gMediaDecoderLog = PR_NewLogModule("MediaDecoder");
gMozPromiseLog = PR_NewLogModule("MozPromise");
gStateWatchingLog = PR_NewLogModule("StateWatching");
gMediaTimerLog = PR_NewLogModule("MediaTimer");
gMediaSampleLog = PR_NewLogModule("MediaSample");
}

View File

@ -152,8 +152,6 @@ EXPORTS += [
EXPORTS.mozilla += [
'MediaManager.h',
'StateMirroring.h',
'StateWatching.h',
]
EXPORTS.mozilla.media.webrtc += [

View File

@ -44,6 +44,7 @@ using layers::ImageContainer;
using layers::D3D9SurfaceImage;
using layers::D3D9RecycleAllocator;
using layers::D3D11ShareHandleImage;
using layers::D3D11RecycleAllocator;
class D3D9DXVA2Manager : public DXVA2Manager
{
@ -71,6 +72,7 @@ private:
RefPtr<D3D9RecycleAllocator> mTextureClientAllocator;
nsRefPtr<IDirectXVideoDecoderService> mDecoderService;
UINT32 mResetToken;
bool mFirstFrame;
};
void GetDXVA2ExtendedFormatFromMFMediaType(IMFMediaType *pType,
@ -178,6 +180,7 @@ D3D9DXVA2Manager::SupportsConfig(IMFMediaType* aType)
D3D9DXVA2Manager::D3D9DXVA2Manager()
: mResetToken(0)
, mFirstFrame(true)
{
MOZ_COUNT_CTOR(D3D9DXVA2Manager);
MOZ_ASSERT(NS_IsMainThread());
@ -350,7 +353,8 @@ D3D9DXVA2Manager::CopyToImage(IMFSample* aSample,
"Wrong format?");
D3D9SurfaceImage* videoImage = static_cast<D3D9SurfaceImage*>(image.get());
hr = videoImage->SetData(D3D9SurfaceImage::Data(surface, aRegion, mTextureClientAllocator));
hr = videoImage->SetData(D3D9SurfaceImage::Data(surface, aRegion, mTextureClientAllocator, mFirstFrame));
mFirstFrame = false;
image.forget(aOutImage);
@ -412,12 +416,13 @@ private:
HRESULT CreateFormatConverter();
HRESULT CreateOutputSample(RefPtr<IMFSample>& aSample,
RefPtr<ID3D11Texture2D>& aTexture);
ID3D11Texture2D* aTexture);
RefPtr<ID3D11Device> mDevice;
RefPtr<ID3D11DeviceContext> mContext;
RefPtr<IMFDXGIDeviceManager> mDXGIDeviceManager;
RefPtr<MFTDecoder> mTransform;
RefPtr<D3D11RecycleAllocator> mTextureClientAllocator;
uint32_t mWidth;
uint32_t mHeight;
UINT mDeviceManagerToken;
@ -483,41 +488,27 @@ D3D11DXVA2Manager::Init(nsACString& aFailureReason)
return hr;
}
mTextureClientAllocator = new D3D11RecycleAllocator(layers::ImageBridgeChild::GetSingleton(),
mDevice);
mTextureClientAllocator->SetMaxPoolSize(5);
return S_OK;
}
HRESULT
D3D11DXVA2Manager::CreateOutputSample(RefPtr<IMFSample>& aSample, RefPtr<ID3D11Texture2D>& aTexture)
D3D11DXVA2Manager::CreateOutputSample(RefPtr<IMFSample>& aSample, ID3D11Texture2D* aTexture)
{
RefPtr<IMFSample> sample;
HRESULT hr = wmf::MFCreateSample(byRef(sample));
NS_ENSURE_TRUE(SUCCEEDED(hr), hr);
D3D11_TEXTURE2D_DESC desc;
desc.Width = mWidth;
desc.Height = mHeight;
desc.Format = DXGI_FORMAT_B8G8R8A8_UNORM;
desc.MipLevels = 1;
desc.ArraySize = 1;
desc.SampleDesc.Count = 1;
desc.SampleDesc.Quality = 0;
desc.Usage = D3D11_USAGE_DEFAULT;
desc.BindFlags = D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_RENDER_TARGET;
desc.CPUAccessFlags = 0;
desc.MiscFlags = D3D11_RESOURCE_MISC_SHARED_KEYEDMUTEX;
RefPtr<ID3D11Texture2D> texture;
hr = mDevice->CreateTexture2D(&desc, nullptr, byRef(texture));
NS_ENSURE_TRUE(SUCCEEDED(hr), hr);
RefPtr<IMFMediaBuffer> buffer;
hr = wmf::MFCreateDXGISurfaceBuffer(__uuidof(ID3D11Texture2D), texture, 0, FALSE, byRef(buffer));
hr = wmf::MFCreateDXGISurfaceBuffer(__uuidof(ID3D11Texture2D), aTexture, 0, FALSE, byRef(buffer));
NS_ENSURE_TRUE(SUCCEEDED(hr), hr);
sample->AddBuffer(buffer);
aSample = sample;
aTexture = texture;
return S_OK;
}
@ -535,11 +526,23 @@ D3D11DXVA2Manager::CopyToImage(IMFSample* aVideoSample,
// to create a copy of that frame as a sharable resource, save its share
// handle, and put that handle into the rendering pipeline.
HRESULT hr = mTransform->Input(aVideoSample);
ImageFormat format = ImageFormat::D3D11_SHARE_HANDLE_TEXTURE;
nsRefPtr<Image> image(aContainer->CreateImage(format));
NS_ENSURE_TRUE(image, E_FAIL);
NS_ASSERTION(image->GetFormat() == ImageFormat::D3D11_SHARE_HANDLE_TEXTURE,
"Wrong format?");
D3D11ShareHandleImage* videoImage = static_cast<D3D11ShareHandleImage*>(image.get());
HRESULT hr = videoImage->SetData(D3D11ShareHandleImage::Data(mTextureClientAllocator,
gfx::IntSize(mWidth, mHeight),
aRegion));
NS_ENSURE_TRUE(SUCCEEDED(hr), hr);
hr = mTransform->Input(aVideoSample);
NS_ENSURE_TRUE(SUCCEEDED(hr), hr);
RefPtr<IMFSample> sample;
RefPtr<ID3D11Texture2D> texture;
RefPtr<ID3D11Texture2D> texture = videoImage->GetTexture();
hr = CreateOutputSample(sample, texture);
NS_ENSURE_TRUE(SUCCEEDED(hr), hr);
@ -555,16 +558,6 @@ D3D11DXVA2Manager::CopyToImage(IMFSample* aVideoSample,
keyedMutex->ReleaseSync(0);
NS_ENSURE_TRUE(SUCCEEDED(hr), hr);
ImageFormat format = ImageFormat::D3D11_SHARE_HANDLE_TEXTURE;
nsRefPtr<Image> image(aContainer->CreateImage(format));
NS_ENSURE_TRUE(image, E_FAIL);
NS_ASSERTION(image->GetFormat() == ImageFormat::D3D11_SHARE_HANDLE_TEXTURE,
"Wrong format?");
D3D11ShareHandleImage* videoImage = static_cast<D3D11ShareHandleImage*>(image.get());
hr = videoImage->SetData(D3D11ShareHandleImage::Data(texture, mDevice, mContext, aRegion));
NS_ENSURE_TRUE(SUCCEEDED(hr), hr);
image.forget(aOutImage);
return S_OK;

View File

@ -36,7 +36,7 @@ interface nsIClearSiteDataCallback : nsISupports
void callback(in nsresult rv);
};
[scriptable, uuid(50677599-323f-4c7d-a450-307bdb7acbf0)]
[scriptable, uuid(0f73bbd2-fc89-41df-b31b-38c09903d187)]
interface nsIPluginHost : nsISupports
{
/**
@ -193,10 +193,4 @@ interface nsIPluginHost : nsISupports
* passed in the FakePluginTagInit when registering.
*/
void unregisterFakePlugin(in AUTF8String handlerURI);
/**
* Returns true if plugins with the given mimetype will run out of process.
*/
boolean isPluginOOP(in AUTF8String aMimeType);
};

View File

@ -249,157 +249,6 @@ nsNPAPIPlugin::PluginCrashed(const nsAString& pluginDumpID,
host->PluginCrashed(this, pluginDumpID, browserDumpID);
}
bool
nsNPAPIPlugin::RunPluginOOP(const nsPluginTag *aPluginTag)
{
if (XRE_IsContentProcess()) {
return true;
}
#if (MOZ_WIDGET_GTK == 3)
// We force OOP on Linux/GTK3 because some plugins use GTK2 and both GTK
// libraries can't be loaded in the same process.
return true;
#else
if (PR_GetEnv("MOZ_DISABLE_OOP_PLUGINS")) {
return false;
}
if (!aPluginTag) {
return false;
}
#ifdef ACCESSIBILITY
// Certain assistive technologies don't want oop Flash, thus we have a special
// pref for them to disable oop Flash (refer to bug 785047 for details).
bool useA11yPref = false;
#ifdef XP_WIN
useA11yPref = a11y::Compatibility::IsJAWS();
#endif
#endif
#ifdef XP_WIN
// On Windows Vista+, we force Flash to run in OOPP mode because Adobe
// doesn't test Flash in-process and there are known stability bugs.
if (aPluginTag->mIsFlashPlugin && IsVistaOrLater()) {
#ifdef ACCESSIBILITY
if (!useA11yPref)
return true;
#else
return true;
#endif
}
#endif
nsIPrefBranch* prefs = Preferences::GetRootBranch();
if (!prefs) {
return false;
}
// Get per-library whitelist/blacklist pref string
// "dom.ipc.plugins.enabled.filename.dll" and fall back to the default value
// of "dom.ipc.plugins.enabled"
// The "filename.dll" part can contain shell wildcard pattern
nsAutoCString prefFile(aPluginTag->mFullPath.get());
int32_t slashPos = prefFile.RFindCharInSet("/\\");
if (kNotFound == slashPos)
return false;
prefFile.Cut(0, slashPos + 1);
ToLowerCase(prefFile);
#ifdef XP_MACOSX
#if defined(__i386__)
nsAutoCString prefGroupKey("dom.ipc.plugins.enabled.i386.");
#elif defined(__x86_64__)
nsAutoCString prefGroupKey("dom.ipc.plugins.enabled.x86_64.");
#elif defined(__ppc__)
nsAutoCString prefGroupKey("dom.ipc.plugins.enabled.ppc.");
#endif
#else
nsAutoCString prefGroupKey("dom.ipc.plugins.enabled.");
#endif
#ifdef ACCESSIBILITY
if (useA11yPref)
prefGroupKey.AssignLiteral("dom.ipc.plugins.enabled.a11y.");
#endif
if (BrowserTabsRemoteAutostart()) {
// dom.ipc.plugins.java.enabled is obsolete in Nightly w/e10s, we've
// flipped the default to ON and now have a force-disable pref. This
// way we don't break non-e10s browsers.
if (aPluginTag->mIsJavaPlugin &&
Preferences::GetBool("dom.ipc.plugins.java.force-disable", false)) {
return false;
}
} else {
// Java plugins include a number of different file names,
// so use the mime type (mIsJavaPlugin) and a special pref.
if (aPluginTag->mIsJavaPlugin &&
!Preferences::GetBool("dom.ipc.plugins.java.enabled", true)) {
return false;
}
}
uint32_t prefCount;
char** prefNames;
nsresult rv = prefs->GetChildList(prefGroupKey.get(),
&prefCount, &prefNames);
bool oopPluginsEnabled = false;
bool prefSet = false;
if (NS_SUCCEEDED(rv) && prefCount > 0) {
uint32_t prefixLength = prefGroupKey.Length();
for (uint32_t currentPref = 0; currentPref < prefCount; currentPref++) {
// Get the mask
const char* maskStart = prefNames[currentPref] + prefixLength;
bool match = false;
int valid = NS_WildCardValid(maskStart);
if (valid == INVALID_SXP) {
continue;
}
else if(valid == NON_SXP) {
// mask is not a shell pattern, compare it as normal string
match = (strcmp(prefFile.get(), maskStart) == 0);
}
else {
match = (NS_WildCardMatch(prefFile.get(), maskStart, 0) == MATCH);
}
if (match && NS_SUCCEEDED(Preferences::GetBool(prefNames[currentPref],
&oopPluginsEnabled))) {
prefSet = true;
break;
}
}
NS_FREE_XPCOM_ALLOCATED_POINTER_ARRAY(prefCount, prefNames);
}
if (!prefSet) {
oopPluginsEnabled =
#ifdef XP_MACOSX
#if defined(__i386__)
Preferences::GetBool("dom.ipc.plugins.enabled.i386", false);
#elif defined(__x86_64__)
Preferences::GetBool("dom.ipc.plugins.enabled.x86_64", false);
#elif defined(__ppc__)
Preferences::GetBool("dom.ipc.plugins.enabled.ppc", false);
#endif
#else
#ifdef ACCESSIBILITY
useA11yPref ? Preferences::GetBool("dom.ipc.plugins.enabled.a11y", false) :
#endif
Preferences::GetBool("dom.ipc.plugins.enabled", false);
#endif
}
return oopPluginsEnabled;
#endif
}
inline PluginLibrary*
GetNewPluginLibrary(nsPluginTag *aPluginTag)
{
@ -411,10 +260,7 @@ GetNewPluginLibrary(nsPluginTag *aPluginTag)
return PluginModuleContentParent::LoadModule(aPluginTag->mId);
}
if (nsNPAPIPlugin::RunPluginOOP(aPluginTag)) {
return PluginModuleChromeParent::LoadModule(aPluginTag->mFullPath.get(), aPluginTag->mId, aPluginTag);
}
return new PluginPRLibrary(aPluginTag->mFullPath.get(), aPluginTag->mLibrary);
return PluginModuleChromeParent::LoadModule(aPluginTag->mFullPath.get(), aPluginTag->mId, aPluginTag);
}
// Creates an nsNPAPIPlugin object. One nsNPAPIPlugin object exists per plugin (not instance).

View File

@ -52,8 +52,6 @@ public:
// minidump was written.
void PluginCrashed(const nsAString& pluginDumpID,
const nsAString& browserDumpID);
static bool RunPluginOOP(const nsPluginTag *aPluginTag);
nsresult Shutdown();

View File

@ -1100,18 +1100,6 @@ nsPluginHost::GetBlocklistStateForType(const nsACString &aMimeType,
return tag->GetBlocklistState(aState);
}
NS_IMETHODIMP
nsPluginHost::IsPluginOOP(const nsACString& aMimeType,
bool* aResult)
{
nsPluginTag* tag = FindNativePluginForType(aMimeType, true);
if (!tag) {
return NS_ERROR_NOT_AVAILABLE;
}
*aResult = nsNPAPIPlugin::RunPluginOOP(tag);
return NS_OK;
}
NS_IMETHODIMP
nsPluginHost::GetPermissionStringForType(const nsACString &aMimeType,
uint32_t aExcludeFlags,
@ -1342,35 +1330,11 @@ nsPluginHost::FindNativePluginForExtension(const nsACString & aExtension,
return preferredPlugin;
}
static nsresult CreateNPAPIPlugin(nsPluginTag *aPluginTag,
nsNPAPIPlugin **aOutNPAPIPlugin)
{
// If this is an in-process plugin we'll need to load it here if we haven't already.
if (!nsNPAPIPlugin::RunPluginOOP(aPluginTag)) {
if (aPluginTag->mFullPath.IsEmpty())
return NS_ERROR_FAILURE;
nsCOMPtr<nsIFile> file = do_CreateInstance("@mozilla.org/file/local;1");
file->InitWithPath(NS_ConvertUTF8toUTF16(aPluginTag->mFullPath));
nsPluginFile pluginFile(file);
PRLibrary* pluginLibrary = nullptr;
if (NS_FAILED(pluginFile.LoadPlugin(&pluginLibrary)) || !pluginLibrary)
return NS_ERROR_FAILURE;
aPluginTag->mLibrary = pluginLibrary;
}
nsresult rv;
rv = nsNPAPIPlugin::CreatePlugin(aPluginTag, aOutNPAPIPlugin);
return rv;
}
nsresult nsPluginHost::EnsurePluginLoaded(nsPluginTag* aPluginTag)
{
nsRefPtr<nsNPAPIPlugin> plugin = aPluginTag->mPlugin;
if (!plugin) {
nsresult rv = CreateNPAPIPlugin(aPluginTag, getter_AddRefs(plugin));
nsresult rv = nsNPAPIPlugin::CreatePlugin(aPluginTag, getter_AddRefs(plugin));
if (NS_FAILED(rv)) {
return rv;
}
@ -2320,14 +2284,6 @@ nsresult nsPluginHost::ScanPluginsDirectory(nsIFile *pluginsDir,
*aPluginsChanged = true;
}
// Avoid adding different versions of the same plugin if they are running
// in-process, otherwise we risk undefined behaviour.
if (!nsNPAPIPlugin::RunPluginOOP(pluginTag)) {
if (HaveSamePlugin(pluginTag)) {
continue;
}
}
// Don't add the same plugin again if it hasn't changed
if (nsPluginTag* duplicate = FirstPluginWithPath(pluginTag->mFullPath)) {
if (pluginTag->mLastModifiedTime == duplicate->mLastModifiedTime) {
@ -2738,12 +2694,6 @@ nsPluginHost::FindPluginsForContent(uint32_t aPluginEpoch,
/// to be more sane and avoid this dance
nsPluginTag *tag = static_cast<nsPluginTag *>(basetag.get());
if (!nsNPAPIPlugin::RunPluginOOP(tag)) {
// Don't expose non-OOP plugins to content processes since we have no way
// to bridge them over.
continue;
}
aPlugins->AppendElement(PluginTag(tag->mId,
tag->Name(),
tag->Description(),

View File

@ -8,7 +8,7 @@ load 570884.html
# the X server, which is a bad assumption for <browser remote>.
# Plugin arch is going to change anyway with OOP content so skipping
# this test for now is OK.
skip-if(browserIsRemote||!haveTestPlugin||http.platform!="X11"||!testPluginIsOOP()) load 598862.html
skip-if(browserIsRemote||!haveTestPlugin||http.platform!="X11") load 598862.html
# SkiaGL is causing a compositor hang here, disable temporarily while that gets resolved in bug 908363
skip-if(Android) load 626602-1.html

View File

@ -11,12 +11,6 @@
setTestPluginEnabledState(SpecialPowers.Ci.nsIPluginTag.STATE_ENABLED);
window.frameLoaded = function frameLoaded_toCrash() {
if (!SimpleTest.testPluginIsOOP()) {
ok(true, "Skipping this test when test plugin is not OOP.");
SimpleTest.finish();
return;
}
SimpleTest.expectChildProcessCrash();
crashAndGetCrashServiceRecord("crash", function (cm, crash) {

View File

@ -11,12 +11,6 @@
setTestPluginEnabledState(SpecialPowers.Ci.nsIPluginTag.STATE_ENABLED);
window.frameLoaded = function frameLoaded_toCrash() {
if (!SimpleTest.testPluginIsOOP()) {
ok(true, "Skipping this test when test plugin is not OOP.");
SimpleTest.finish();
return;
}
SimpleTest.expectChildProcessCrash();
// the default timeout is annoying high for mochitest runs

View File

@ -15,18 +15,11 @@
setTestPluginEnabledState(SpecialPowers.Ci.nsIPluginTag.STATE_ENABLED);
function start() {
if (!SimpleTest.testPluginIsOOP()) {
ok(true, "Skipping this test when test plugin is not OOP.");
SimpleTest.finish();
return;
if (navigator.platform.startsWith("Win")) {
SimpleTest.expectAssertions(0, 350);
}
else {
if (navigator.platform.startsWith("Win")) {
SimpleTest.expectAssertions(0, 350);
}
setTimeout(checkGCRace, 1000);
}
setTimeout(checkGCRace, 1000);
}
var nested = false;

View File

@ -22,12 +22,6 @@
SimpleTest.waitForExplicitFinish();
function runTests() {
if (!SimpleTest.testPluginIsOOP()) {
ok(true, "Skipping this test when test plugin is not OOP.");
SimpleTest.finish();
return;
}
// Default plugin hang timeout is too high for mochitests
var prefs = Cc["@mozilla.org/preferences-service;1"]
.getService(Ci.nsIPrefBranch);

View File

@ -9,12 +9,6 @@
setTestPluginEnabledState(SpecialPowers.Ci.nsIPluginTag.STATE_ENABLED);
window.frameLoaded = function frameLoaded_toCrash() {
if (!SimpleTest.testPluginIsOOP()) {
ok(true, "Skipping this test when test plugin is not OOP.");
SimpleTest.finish();
return;
}
var iframe = document.getElementById('iframe1');
var p = iframe.contentDocument.getElementById('plugin1');

View File

@ -88,16 +88,10 @@ function onPluginCrashed(aEvent) {
}
function runTests() {
if (!SimpleTest.testPluginIsOOP()) {
ok(true, "Skipping this test when test plugin is not OOP.");
SimpleTest.finish();
return;
}
var os = Components.classes["@mozilla.org/observer-service;1"].
getService(Components.interfaces.nsIObserverService);
os.addObserver(testObserver, "plugin-crashed", true);
document.addEventListener("PluginCrashed", onPluginCrashed, false);
var pluginElement = document.getElementById("plugin1");

View File

@ -91,11 +91,6 @@ function onPluginCrashed(aEvent) {
}
function runTests() {
if (!SimpleTest.testPluginIsOOP()) {
ok(true, "Skipping this test when test plugin is not OOP.");
SimpleTest.finish();
return;
}
// the test harness will have set MOZ_CRASHREPORTER_NO_REPORT,
// ensure that we can change the setting and have our minidumps
// wind up in Crash Reports/pending
@ -106,7 +101,7 @@ function runTests() {
var os = Components.classes["@mozilla.org/observer-service;1"].
getService(Components.interfaces.nsIObserverService);
os.addObserver(testObserver, "plugin-crashed", true);
document.addEventListener("PluginCrashed", onPluginCrashed, false);
var pluginElement = document.getElementById("plugin1");

View File

@ -123,12 +123,6 @@ function onPluginCrashed(aEvent) {
}
function runTests() {
if (!SimpleTest.testPluginIsOOP()) {
todo(false, "Skipping this test when test plugin is not OOP.");
SimpleTest.finish();
return;
}
// the test harness will have set MOZ_CRASHREPORTER_NO_REPORT,
// ensure that we can change the setting and have our minidumps
// wind up in Crash Reports/pending
@ -142,7 +136,7 @@ function runTests() {
var os = Components.classes["@mozilla.org/observer-service;1"].
getService(Components.interfaces.nsIObserverService);
os.addObserver(testObserver, "crash-report-status", true);
document.addEventListener("PluginCrashed", onPluginCrashed, false);
var pluginElement = document.getElementById("plugin1");

View File

@ -9,12 +9,6 @@
setTestPluginEnabledState(SpecialPowers.Ci.nsIPluginTag.STATE_ENABLED);
window.frameLoaded = function frameLoaded_toCrash() {
if (!SimpleTest.testPluginIsOOP()) {
ok(true, "Skipping this test when test plugin is not OOP.");
SimpleTest.finish();
return;
}
SimpleTest.expectChildProcessCrash();
var iframe = document.getElementById('iframe1');

View File

@ -13,12 +13,6 @@
var iframe = document.getElementById('iframe1');
function mainLoaded() {
if (!SimpleTest.testPluginIsOOP()) {
ok(true, "Skipping this test when test plugin is not OOP.");
SimpleTest.finish();
return;
}
SimpleTest.expectChildProcessCrash();
var p = iframe.contentDocument.createElement('embed');

View File

@ -130,12 +130,6 @@ function onPluginCrashed(aEvent) {
}
function runTests() {
if (!SimpleTest.testPluginIsOOP()) {
todo(false, "Skipping this test when test plugin is not OOP.");
SimpleTest.finish();
return;
}
// Default plugin hang timeout is too high for mochitests
Services.prefs.setIntPref("dom.ipc.plugins.timeoutSecs", 1);

View File

@ -9,12 +9,6 @@
setTestPluginEnabledState(SpecialPowers.Ci.nsIPluginTag.STATE_ENABLED);
window.frameLoaded = function frameLoaded_toCrash() {
if (!SimpleTest.testPluginIsOOP()) {
ok(true, "Skipping this test when test plugin is not OOP.");
SimpleTest.finish();
return;
}
SimpleTest.expectChildProcessCrash();
// the default timeout is annoying high for mochitest runs

View File

@ -96,11 +96,6 @@ function finishTest() {
}
function runTests() {
if (!SimpleTest.testPluginIsOOP()) {
ok(true, "Skipping this test when test plugin is not OOP.");
SimpleTest.finish();
}
resetVars();
hanguiOperation("Prime ChromeWorker", 0, false, false, HANGUIOP_NOTHING, 0,

View File

@ -22,12 +22,6 @@
SimpleTest.waitForExplicitFinish();
function runTests() {
if (!SimpleTest.testPluginIsOOP()) {
ok(true, "Skipping this test when test plugin is not OOP.");
SimpleTest.finish();
return;
}
// Default plugin hang timeout is too high for mochitests
var prefs = Cc["@mozilla.org/preferences-service;1"]
.getService(Ci.nsIPrefBranch);

View File

@ -21,11 +21,9 @@
var didPaint = function() {};
function startTest() {
if (SimpleTest.testPluginIsOOP()) {
if (p.getPaintCount() < 1) {
setTimeout(startTest, 0);
return;
}
if (p.getPaintCount() < 1) {
setTimeout(startTest, 0);
return;
}
didPaint = function() {

View File

@ -1,16 +1,7 @@
function paintCountIs(plugin, expected, msg) {
var count = plugin.getPaintCount();
var realExpected = expected;
var isAsync = SimpleTest.testPluginIsOOP();
if (isAsync) {
++realExpected; // extra paint at startup for all async-rendering plugins
} else {
try {
if (SpecialPowers.Cc["@mozilla.org/gfx/info;1"].getService(SpecialPowers.Ci.nsIGfxInfo).D2DEnabled) {
realExpected *= 2;
}
} catch (e) {}
}
++realExpected; // extra paint at startup for all async-rendering plugins
ok(realExpected == count, msg + " (expected " + expected +
" independent paints, expected " + realExpected + " logged paints, got " +
count + " actual paints)");

View File

@ -8,8 +8,8 @@ random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) fails-if(!haveTestPlugin) =
random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) fails-if(!haveTestPlugin) == border-padding-2.html border-padding-2-ref.html # bug 629430
random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) skip-if(!haveTestPlugin) skip-if(Android||B2G) == border-padding-3.html border-padding-3-ref.html # bug 629430 # bug 773482
# The following two "pluginproblemui-direction" tests are unreliable on all platforms. They should be re-written or replaced.
#random-if(cocoaWidget||d2d||/^Windows\x20NT\x205\.1/.test(http.oscpu)) fails-if(!haveTestPlugin&&!Android) skip-if(!testPluginIsOOP()) == pluginproblemui-direction-1.html pluginproblemui-direction-1-ref.html # bug 567367
#random-if(cocoaWidget) fails-if(!haveTestPlugin&&!Android) skip-if(!testPluginIsOOP()) == pluginproblemui-direction-2.html pluginproblemui-direction-2-ref.html
#random-if(cocoaWidget||d2d||/^Windows\x20NT\x205\.1/.test(http.oscpu)) fails-if(!haveTestPlugin&&!Android) == pluginproblemui-direction-1.html pluginproblemui-direction-1-ref.html # bug 567367
#random-if(cocoaWidget) fails-if(!haveTestPlugin&&!Android) == pluginproblemui-direction-2.html pluginproblemui-direction-2-ref.html
fails-if(!haveTestPlugin) == plugin-canvas-alpha-zindex.html div-alpha-zindex.html
fails-if(!haveTestPlugin) == plugin-transform-alpha-zindex.html div-alpha-zindex.html
random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) fails-if(!haveTestPlugin) == plugin-busy-alpha-zindex.html div-alpha-zindex.html

View File

@ -27,6 +27,7 @@
#include <algorithm>
#include "GeckoProfiler.h"
#include "mozilla/Atomics.h"
#include "mozilla/BasePrincipal.h"
#include "mozilla/CondVar.h"
#include "mozilla/dom/PContent.h"
#include "mozilla/dom/asmjscache/AsmJSCache.h"
@ -669,20 +670,16 @@ class GetUsageOp
UsageInfo mUsageInfo;
const nsCString mGroup;
nsCOMPtr<nsIURI> mURI;
nsCOMPtr<nsIPrincipal> mPrincipal;
nsCOMPtr<nsIUsageCallback> mCallback;
const uint32_t mAppId;
const bool mIsApp;
const bool mInMozBrowserOnly;
public:
GetUsageOp(const nsACString& aGroup,
const nsACString& aOrigin,
bool aIsApp,
nsIURI* aURI,
nsIUsageCallback* aCallback,
uint32_t aAppId,
bool aInMozBrowserOnly);
nsIPrincipal* aPrincipal,
nsIUsageCallback* aCallback);
private:
~GetUsageOp()
@ -3404,32 +3401,6 @@ QuotaManager::GetStorageId(PersistenceType aPersistenceType,
aDatabaseId = str;
}
// static
nsresult
QuotaManager::GetInfoFromURI(nsIURI* aURI,
uint32_t aAppId,
bool aInMozBrowser,
nsACString* aGroup,
nsACString* aOrigin,
bool* aIsApp)
{
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(aURI);
nsIScriptSecurityManager* secMan = nsContentUtils::GetSecurityManager();
NS_ENSURE_TRUE(secMan, NS_ERROR_FAILURE);
nsCOMPtr<nsIPrincipal> principal;
nsresult rv = secMan->GetAppCodebasePrincipal(aURI, aAppId, aInMozBrowser,
getter_AddRefs(principal));
NS_ENSURE_SUCCESS(rv, rv);
rv = GetInfoFromPrincipal(principal, aGroup, aOrigin, aIsApp);
NS_ENSURE_SUCCESS(rv, rv);
return NS_OK;
}
static nsresult
TryGetInfoForAboutURI(nsIPrincipal* aPrincipal,
nsACString& aGroup,
@ -3709,36 +3680,27 @@ QuotaManager::GetDirectoryMetadata(nsIFile* aDirectory,
NS_IMPL_ISUPPORTS(QuotaManager, nsIQuotaManager, nsIObserver)
NS_IMETHODIMP
QuotaManager::GetUsageForURI(nsIURI* aURI,
nsIUsageCallback* aCallback,
uint32_t aAppId,
bool aInMozBrowserOnly,
uint8_t aOptionalArgCount,
nsIQuotaRequest** _retval)
QuotaManager::GetUsageForPrincipal(nsIPrincipal* aPrincipal,
nsIUsageCallback* aCallback,
nsIQuotaRequest** _retval)
{
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
NS_ENSURE_ARG_POINTER(aURI);
NS_ENSURE_ARG_POINTER(aPrincipal);
NS_ENSURE_ARG_POINTER(aCallback);
// This only works from the main process.
NS_ENSURE_TRUE(XRE_IsParentProcess(), NS_ERROR_NOT_AVAILABLE);
if (!aOptionalArgCount) {
aAppId = nsIScriptSecurityManager::NO_APP_ID;
}
// Figure out which origin we're dealing with.
nsCString group;
nsCString origin;
bool isApp;
nsresult rv = GetInfoFromURI(aURI, aAppId, aInMozBrowserOnly, &group, &origin,
&isApp);
nsresult rv = GetInfoFromPrincipal(aPrincipal, &group, &origin, &isApp);
NS_ENSURE_SUCCESS(rv, rv);
nsRefPtr<GetUsageOp> op =
new GetUsageOp(group, origin, isApp, aURI, aCallback, aAppId,
aInMozBrowserOnly);
new GetUsageOp(group, origin, isApp, aPrincipal, aCallback);
op->RunImmediately();
@ -3764,15 +3726,12 @@ QuotaManager::Clear()
}
NS_IMETHODIMP
QuotaManager::ClearStoragesForURI(nsIURI* aURI,
uint32_t aAppId,
bool aInMozBrowserOnly,
const nsACString& aPersistenceType,
uint8_t aOptionalArgCount)
QuotaManager::ClearStoragesForPrincipal(nsIPrincipal* aPrincipal,
const nsACString& aPersistenceType)
{
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
NS_ENSURE_ARG_POINTER(aURI);
NS_ENSURE_ARG_POINTER(aPrincipal);
Nullable<PersistenceType> persistenceType;
nsresult rv =
@ -3784,18 +3743,16 @@ QuotaManager::ClearStoragesForURI(nsIURI* aURI,
// This only works from the main process.
NS_ENSURE_TRUE(XRE_IsParentProcess(), NS_ERROR_NOT_AVAILABLE);
if (!aOptionalArgCount) {
aAppId = nsIScriptSecurityManager::NO_APP_ID;
}
// Figure out which origin we're dealing with.
nsCString origin;
rv = GetInfoFromURI(aURI, aAppId, aInMozBrowserOnly, nullptr, &origin,
nullptr);
rv = GetInfoFromPrincipal(aPrincipal, nullptr, &origin, nullptr);
NS_ENSURE_SUCCESS(rv, rv);
const mozilla::OriginAttributes& attrs =
mozilla::BasePrincipal::Cast(aPrincipal)->OriginAttributesRef();
nsAutoCString pattern;
GetOriginPatternString(aAppId, aInMozBrowserOnly, origin, pattern);
GetOriginPatternString(attrs.mAppId, attrs.mInBrowser, origin, pattern);
nsRefPtr<OriginClearOp> op =
new OriginClearOp(persistenceType, OriginScope::FromPattern(pattern));
@ -4625,24 +4582,20 @@ SaveOriginAccessTimeOp::DoDirectoryWork(QuotaManager* aQuotaManager)
GetUsageOp::GetUsageOp(const nsACString& aGroup,
const nsACString& aOrigin,
bool aIsApp,
nsIURI* aURI,
nsIUsageCallback* aCallback,
uint32_t aAppId,
bool aInMozBrowserOnly)
nsIPrincipal* aPrincipal,
nsIUsageCallback* aCallback)
: NormalOriginOperationBase(Nullable<PersistenceType>(),
OriginScope::FromOrigin(aOrigin),
/* aExclusive */ false)
, mGroup(aGroup)
, mURI(aURI)
, mPrincipal(aPrincipal)
, mCallback(aCallback)
, mAppId(aAppId)
, mIsApp(aIsApp)
, mInMozBrowserOnly(aInMozBrowserOnly)
{
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(!aGroup.IsEmpty());
MOZ_ASSERT(!aOrigin.IsEmpty());
MOZ_ASSERT(aURI);
MOZ_ASSERT(aPrincipal);
MOZ_ASSERT(aCallback);
}
@ -4777,12 +4730,11 @@ GetUsageOp::SendResults()
mUsageInfo.ResetUsage();
}
mCallback->OnUsageResult(mURI, mUsageInfo.TotalUsage(), mUsageInfo.FileUsage(), mAppId,
mInMozBrowserOnly);
mCallback->OnUsageResult(mPrincipal, mUsageInfo.TotalUsage(), mUsageInfo.FileUsage());
}
// Clean up.
mURI = nullptr;
mPrincipal = nullptr;
mCallback = nullptr;
}

View File

@ -306,14 +306,6 @@ public:
Client::Type aClientType,
nsACString& aDatabaseId);
static nsresult
GetInfoFromURI(nsIURI* aURI,
uint32_t aAppId,
bool aInMozBrowser,
nsACString* aGroup,
nsACString* aOrigin,
bool* aIsApp);
static nsresult
GetInfoFromPrincipal(nsIPrincipal* aPrincipal,
nsACString* aGroup,

View File

@ -7,27 +7,24 @@
#include "nsISupports.idl"
interface nsIQuotaRequest;
interface nsIURI;
interface nsIPrincipal;
interface nsIUsageCallback;
[scriptable, builtinclass, uuid(2968fcd5-1872-4ddc-8c16-62b27e357f31)]
[scriptable, builtinclass, uuid(101cf53c-e7f3-4723-9f43-a23a85c8eda0)]
interface nsIQuotaManager : nsISupports
{
/**
* Schedules an asynchronous callback that will return the total amount of
* disk space being used by storages for the given origin.
*
* @param aURI
* The URI whose usage is being queried.
* @param aPrincipal
* A principal for the origin whose usage is being queried.
* @param aCallback
* The callback that will be called when the usage is available.
*/
[optional_argc]
nsIQuotaRequest
getUsageForURI(in nsIURI aURI,
in nsIUsageCallback aCallback,
[optional] in unsigned long aAppId,
[optional] in boolean aInMozBrowserOnly);
getUsageForPrincipal(in nsIPrincipal aPrincipal,
in nsIUsageCallback aCallback);
/**
* Removes all storages. The files may not be deleted immediately depending
@ -44,15 +41,12 @@ interface nsIQuotaManager : nsISupports
* Removes all storages stored for the given URI. The files may not be
* deleted immediately depending on prohibitive concurrent operations.
*
* @param aURI
* The URI whose storages are to be cleared.
* @param aPrincipal
* A principal for the origin whose storages are to be cleared.
*/
[optional_argc]
void
clearStoragesForURI(in nsIURI aURI,
[optional] in unsigned long aAppId,
[optional] in boolean aInMozBrowserOnly,
[optional] in ACString aPersistenceType);
clearStoragesForPrincipal(in nsIPrincipal aPrincipal,
[optional] in ACString aPersistenceType);
/**
* Resets quota and storage management. This can be used to force

View File

@ -6,15 +6,12 @@
#include "nsISupports.idl"
interface nsIURI;
interface nsIPrincipal;
[scriptable, function, uuid(7b0f9928-0ddc-42c7-b9f2-6b2308b90b18)]
[scriptable, function, uuid(54b9f44f-533f-41ee-8fa8-86cc978125f0)]
interface nsIUsageCallback : nsISupports
{
void
onUsageResult(in nsIURI aURI,
in unsigned long long aUsage,
in unsigned long long aFileUsage,
in unsigned long aAppId,
in boolean aInMozBrowserOnly);
void onUsageResult(in nsIPrincipal aPrincipal,
in unsigned long long aUsage,
in unsigned long long aFileUsage);
};

View File

@ -1183,9 +1183,27 @@ MappedAttrParser::ParseMappedAttrValue(nsIAtom* aMappedAttrName,
nsCSSProps::LookupProperty(nsDependentAtomString(aMappedAttrName),
nsCSSProps::eEnabledForAllContent);
if (propertyID != eCSSProperty_UNKNOWN) {
bool changed; // outparam for ParseProperty. (ignored)
bool changed = false; // outparam for ParseProperty.
mParser.ParseProperty(propertyID, aMappedAttrValue, mDocURI, mBaseURI,
mElement->NodePrincipal(), mDecl, &changed, false, true);
if (changed) {
// The normal reporting of use counters by the nsCSSParser won't happen
// since it doesn't have a sheet.
if (nsCSSProps::IsShorthand(propertyID)) {
CSSPROPS_FOR_SHORTHAND_SUBPROPERTIES(subprop, propertyID,
nsCSSProps::eEnabledForAllContent) {
UseCounter useCounter = nsCSSProps::UseCounterFor(*subprop);
if (useCounter != eUseCounter_UNKNOWN) {
mElement->OwnerDoc()->SetDocumentAndPageUseCounter(useCounter);
}
}
} else {
UseCounter useCounter = nsCSSProps::UseCounterFor(propertyID);
if (useCounter != eUseCounter_UNKNOWN) {
mElement->OwnerDoc()->SetDocumentAndPageUseCounter(useCounter);
}
}
}
return;
}
MOZ_ASSERT(aMappedAttrName == nsGkAtoms::lang,

View File

@ -34,6 +34,7 @@ skip-if = true
[test_ril_worker_voiceprivacy.js]
[test_ril_worker_ecm.js]
[test_ril_worker_stk.js]
requesttimeoutfactor = 2
[test_ril_worker_barring_password.js]
[test_ril_worker_cdma_info_rec.js]
[test_ril_system_messenger.js]

View File

@ -33,6 +33,7 @@ interface SVGSVGElement : SVGGraphicsElement {
readonly attribute float screenPixelToMillimeterY;
readonly attribute boolean useCurrentView;
// readonly attribute SVGViewSpec currentView;
[UseCounter]
attribute float currentScale;
readonly attribute SVGPoint currentTranslate;
@ -70,6 +71,7 @@ interface SVGSVGElement : SVGGraphicsElement {
SVGTransform createSVGTransform();
[NewObject]
SVGTransform createSVGTransformFromMatrix(SVGMatrix matrix);
[UseCounter]
Element? getElementById(DOMString elementId);
};

View File

@ -1033,9 +1033,7 @@ private:
mWorkerPrivate->SetBaseURI(finalURI);
// Store the channel info if needed.
if (mWorkerPrivate->IsServiceWorker()) {
mWorkerPrivate->InitChannelInfo(channel);
}
mWorkerPrivate->InitChannelInfo(channel);
// Now to figure out which principal to give this worker.
WorkerPrivate* parent = mWorkerPrivate->GetParent();

View File

@ -503,14 +503,12 @@ public:
const ChannelInfo&
GetChannelInfo() const
{
MOZ_ASSERT(IsServiceWorker());
return mLoadInfo.mChannelInfo;
}
void
SetChannelInfo(const ChannelInfo& aChannelInfo)
{
MOZ_ASSERT(IsServiceWorker());
AssertIsOnMainThread();
MOZ_ASSERT(!mLoadInfo.mChannelInfo.IsInitialized());
MOZ_ASSERT(aChannelInfo.IsInitialized());

View File

@ -1,12 +1,21 @@
self.addEventListener("install", function(event) {
event.waitUntil(caches.open("cache").then(function(cache) {
return cache.add("index.html");
var synth = new Response('<!DOCTYPE html><script>window.parent.postMessage({status: "done-synth-sw"}, "*");</script>',
{headers:{"Content-Type": "text/html"}});
return Promise.all([
cache.add("index.html"),
cache.put("synth-sw.html", synth),
]);
}));
});
self.addEventListener("fetch", function(event) {
if (event.request.url.indexOf("index.html") >= 0) {
event.respondWith(caches.match(event.request));
} else if (event.request.url.indexOf("synth-sw.html") >= 0) {
event.respondWith(caches.match(event.request));
} else if (event.request.url.indexOf("synth-window.html") >= 0) {
event.respondWith(caches.match(event.request));
} else if (event.request.url.indexOf("synth.html") >= 0) {
event.respondWith(new Response('<!DOCTYPE html><script>window.parent.postMessage({status: "done-synth"}, "*");</script>',
{headers:{"Content-Type": "text/html"}}));

View File

@ -9,6 +9,12 @@
window.parent.postMessage({status: "registrationdone"}, "*");
}
navigator.serviceWorker.ready.then(done);
navigator.serviceWorker.ready.then(reg => {
return window.caches.open("cache").then(function(cache) {
var synth = new Response('<!DOCTYPE html><script>window.parent.postMessage({status: "done-synth-window"}, "*");</scri' + 'pt>',
{headers:{"Content-Type": "text/html"}});
return cache.put('synth-window.html', synth).then(_ => done(reg));
});
});
navigator.serviceWorker.register("https_test.js", {scope: "."});
</script>

View File

@ -31,6 +31,10 @@
ios.offline = true;
iframe.src = "https://example.com/tests/dom/workers/test/serviceworkers/fetch/https/index.html";
} else if (e.data.status == "done") {
iframe.src = "https://example.com/tests/dom/workers/test/serviceworkers/fetch/https/synth-sw.html";
} else if (e.data.status == "done-synth-sw") {
iframe.src = "https://example.com/tests/dom/workers/test/serviceworkers/fetch/https/synth-window.html";
} else if (e.data.status == "done-synth-window") {
iframe.src = "https://example.com/tests/dom/workers/test/serviceworkers/fetch/https/synth.html";
} else if (e.data.status == "done-synth") {
ios.offline = false;

View File

@ -20,7 +20,6 @@
#include "nsTArray.h"
#include "nsReadableUtils.h"
#include "nsILineInputStream.h"
#include "nsIIDNService.h"
#include "nsAppDirectoryServiceDefs.h"
#include "nsDirectoryServiceDefs.h"
#include "prprf.h"
@ -847,9 +846,7 @@ nsPermissionManager::InitDB(bool aRemoveFile)
}
rv = OpenDatabase(permissionsFile);
if (rv == NS_ERROR_UNEXPECTED) {
return rv;
} else if (rv == NS_ERROR_FILE_CORRUPTED) {
if (rv == NS_ERROR_FILE_CORRUPTED) {
LogToConsole(NS_LITERAL_STRING("permissions.sqlite is corrupted! Try again!"));
// Add telemetry probe
@ -863,6 +860,8 @@ nsPermissionManager::InitDB(bool aRemoveFile)
rv = OpenDatabase(permissionsFile);
NS_ENSURE_SUCCESS(rv, rv);
LogToConsole(NS_LITERAL_STRING("OpenDatabase to permissions.sqlite is successful!"));
} else if (NS_FAILED(rv)) {
return rv;
}
bool ready;
@ -2743,19 +2742,6 @@ nsPermissionManager::_DoImport(nsIInputStream *inputStream, mozIStorageConnectio
return NS_OK;
}
nsresult
nsPermissionManager::NormalizeToACE(nsCString &aHost)
{
// lazily init the IDN service
if (!mIDNService) {
nsresult rv;
mIDNService = do_GetService(NS_IDNSERVICE_CONTRACTID, &rv);
NS_ENSURE_SUCCESS(rv, rv);
}
return mIDNService->ConvertUTF8toACE(aHost, aHost);
}
void
nsPermissionManager::UpdateDB(OperationType aOp,
mozIStorageAsyncStatement* aStmt,

View File

@ -21,7 +21,6 @@
#include "nsDataHashtable.h"
class nsIPermission;
class nsIIDNService;
class mozIStorageConnection;
class mozIStorageAsyncStatement;
@ -239,7 +238,6 @@ private:
nsresult RemoveAllInternal(bool aNotifyObservers);
nsresult RemoveAllFromMemory();
nsresult NormalizeToACE(nsCString &aHost);
static void UpdateDB(OperationType aOp,
mozIStorageAsyncStatement* aStmt,
int64_t aID,
@ -264,8 +262,6 @@ private:
nsresult
FetchPermissions();
nsCOMPtr<nsIIDNService> mIDNService;
nsCOMPtr<mozIStorageConnection> mDBConn;
nsCOMPtr<mozIStorageAsyncStatement> mStmtInsert;
nsCOMPtr<mozIStorageAsyncStatement> mStmtDelete;

View File

@ -19,16 +19,15 @@ namespace layers {
HRESULT
D3D11ShareHandleImage::SetData(const Data& aData)
{
NS_ENSURE_TRUE(aData.mTexture, E_POINTER);
mTexture = aData.mTexture;
mPictureRect = aData.mRegion;
mSize = aData.mSize;
D3D11_TEXTURE2D_DESC frameDesc;
mTexture->GetDesc(&frameDesc);
mFormat = gfx::SurfaceFormat::B8G8R8A8;
mSize.width = frameDesc.Width;
mSize.height = frameDesc.Height;
mTextureClient =
aData.mAllocator->CreateOrRecycleClient(gfx::SurfaceFormat::B8G8R8A8,
mSize);
if (!mTextureClient) {
return E_FAIL;
}
return S_OK;
}
@ -42,29 +41,23 @@ D3D11ShareHandleImage::GetSize()
TextureClient*
D3D11ShareHandleImage::GetTextureClient(CompositableClient* aClient)
{
if (!mTextureClient) {
mTextureClient = TextureClientD3D11::Create(aClient->GetForwarder(),
mFormat,
TextureFlags::DEFAULT,
mTexture,
mSize);
}
return mTextureClient;
}
already_AddRefed<gfx::SourceSurface>
D3D11ShareHandleImage::GetAsSourceSurface()
{
if (!mTexture) {
RefPtr<ID3D11Texture2D> texture = GetTexture();
if (!texture) {
NS_WARNING("Cannot readback from shared texture because no texture is available.");
return nullptr;
}
RefPtr<ID3D11Device> device;
mTexture->GetDevice(byRef(device));
texture->GetDevice(byRef(device));
RefPtr<IDXGIKeyedMutex> keyedMutex;
if (FAILED(mTexture->QueryInterface(static_cast<IDXGIKeyedMutex**>(byRef(keyedMutex))))) {
if (FAILED(texture->QueryInterface(static_cast<IDXGIKeyedMutex**>(byRef(keyedMutex))))) {
NS_WARNING("Failed to QueryInterface for IDXGIKeyedMutex, strange.");
return nullptr;
}
@ -75,7 +68,7 @@ D3D11ShareHandleImage::GetAsSourceSurface()
}
D3D11_TEXTURE2D_DESC desc;
mTexture->GetDesc(&desc);
texture->GetDesc(&desc);
CD3D11_TEXTURE2D_DESC softDesc(desc.Format, desc.Width, desc.Height);
softDesc.CPUAccessFlags = D3D11_CPU_ACCESS_READ;
@ -102,7 +95,7 @@ D3D11ShareHandleImage::GetAsSourceSurface()
return nullptr;
}
context->CopyResource(softTexture, mTexture);
context->CopyResource(softTexture, texture);
keyedMutex->ReleaseSync(0);
RefPtr<gfx::DataSourceSurface> surface =
@ -137,8 +130,40 @@ D3D11ShareHandleImage::GetAsSourceSurface()
ID3D11Texture2D*
D3D11ShareHandleImage::GetTexture() const {
return mTexture;
return mTextureClient->GetD3D11Texture();
}
already_AddRefed<TextureClient>
D3D11RecycleAllocator::Allocate(gfx::SurfaceFormat aFormat,
gfx::IntSize aSize,
BackendSelector aSelector,
TextureFlags aTextureFlags,
TextureAllocationFlags aAllocFlags)
{
return TextureClientD3D11::Create(mSurfaceAllocator,
aFormat,
TextureFlags::DEFAULT,
mDevice,
aSize);
}
already_AddRefed<TextureClientD3D11>
D3D11RecycleAllocator::CreateOrRecycleClient(gfx::SurfaceFormat aFormat,
const gfx::IntSize& aSize)
{
RefPtr<TextureClient> textureClient =
CreateOrRecycle(aFormat,
aSize,
BackendSelector::Content,
layers::TextureFlags::DEFAULT);
if (!textureClient) {
return nullptr;
}
RefPtr<TextureClientD3D11> textureD3D11 = static_cast<TextureClientD3D11*>(textureClient.get());
return textureD3D11.forget();
}
} // namespace layers
} // namespace mozilla

View File

@ -11,10 +11,36 @@
#include "nsAutoPtr.h"
#include "d3d11.h"
#include "mozilla/layers/TextureClient.h"
#include "mozilla/layers/TextureD3D11.h"
#include "mozilla/layers/TextureClientRecycleAllocator.h"
namespace mozilla {
namespace layers {
class D3D11RecycleAllocator : public TextureClientRecycleAllocator
{
public:
explicit D3D11RecycleAllocator(ISurfaceAllocator* aAllocator,
ID3D11Device* aDevice)
: TextureClientRecycleAllocator(aAllocator)
, mDevice(aDevice)
{}
already_AddRefed<TextureClientD3D11>
CreateOrRecycleClient(gfx::SurfaceFormat aFormat,
const gfx::IntSize& aSize);
protected:
virtual already_AddRefed<TextureClient>
Allocate(gfx::SurfaceFormat aFormat,
gfx::IntSize aSize,
BackendSelector aSelector,
TextureFlags aTextureFlags,
TextureAllocationFlags aAllocFlags) override;
RefPtr<ID3D11Device> mDevice;
};
// Image class that wraps a ID3D11Texture2D. This class copies the image
// passed into SetData(), so that it can be accessed from other D3D devices.
// This class also manages the synchronization of the copy, to ensure the
@ -23,17 +49,14 @@ class D3D11ShareHandleImage : public Image {
public:
struct Data {
Data(ID3D11Texture2D* aTexture,
ID3D11Device* aDevice,
ID3D11DeviceContext* aContext,
Data(D3D11RecycleAllocator* aAllocator,
const gfx::IntSize& aSize,
const gfx::IntRect& aRegion)
: mTexture(aTexture),
mDevice(aDevice),
mContext(aContext),
mRegion(aRegion) {}
RefPtr<ID3D11Texture2D> mTexture;
RefPtr<ID3D11Device> mDevice;
RefPtr<ID3D11DeviceContext> mContext;
: mAllocator(aAllocator)
, mSize(aSize)
, mRegion(aRegion) {}
RefPtr<D3D11RecycleAllocator> mAllocator;
gfx::IntSize mSize;
gfx::IntRect mRegion;
};
@ -58,11 +81,7 @@ private:
gfx::IntSize mSize;
gfx::IntRect mPictureRect;
RefPtr<ID3D11Texture2D> mTexture;
RefPtr<TextureClient> mTextureClient;
HANDLE mShareHandle;
gfx::SurfaceFormat mFormat;
RefPtr<TextureClientD3D11> mTextureClient;
};
} // namepace layers

View File

@ -19,6 +19,7 @@ D3D9SurfaceImage::D3D9SurfaceImage()
: Image(nullptr, ImageFormat::D3D9_RGB32_TEXTURE)
, mSize(0, 0)
, mValid(false)
, mIsFirstFrame(false)
{}
D3D9SurfaceImage::~D3D9SurfaceImage()
@ -83,6 +84,7 @@ D3D9SurfaceImage::SetData(const Data& aData)
mTextureClient = textureClient;
mSize = region.Size();
mQuery = query;
mIsFirstFrame = aData.mIsFirstFrame;
return S_OK;
}
@ -103,7 +105,7 @@ D3D9SurfaceImage::EnsureSynchronized()
return;
}
int iterations = 0;
while (iterations < 10) {
while (iterations < (mIsFirstFrame ? 100 : 10)) {
HRESULT hr = query->GetData(nullptr, 0, D3DGETDATA_FLUSH);
if (hr == S_FALSE) {
Sleep(1);

View File

@ -51,15 +51,18 @@ public:
struct Data {
Data(IDirect3DSurface9* aSurface,
const gfx::IntRect& aRegion,
D3D9RecycleAllocator* aAllocator)
D3D9RecycleAllocator* aAllocator,
bool aIsFirstFrame)
: mSurface(aSurface)
, mRegion(aRegion)
, mAllocator(aAllocator)
, mIsFirstFrame(aIsFirstFrame)
{}
RefPtr<IDirect3DSurface9> mSurface;
gfx::IntRect mRegion;
RefPtr<D3D9RecycleAllocator> mAllocator;
bool mIsFirstFrame;
};
D3D9SurfaceImage();
@ -90,6 +93,7 @@ private:
RefPtr<IDirect3DQuery9> mQuery;
RefPtr<SharedTextureClientD3D9> mTextureClient;
bool mValid;
bool mIsFirstFrame;
};
} // namepace layers

View File

@ -1702,11 +1702,9 @@ Layer::PrintInfo(std::stringstream& aStream, const char* aPrefix)
}
if (GetIsFixedPosition()) {
LayerPoint anchor = GetFixedPositionAnchor();
LayerMargin margin = GetFixedPositionMargins();
aStream << nsPrintfCString(" [isFixedPosition scrollId=%d anchor=%s margin=%f,%f,%f,%f]",
aStream << nsPrintfCString(" [isFixedPosition scrollId=%d anchor=%s]",
GetFixedPositionScrollContainerId(),
ToString(anchor).c_str(),
margin.top, margin.right, margin.bottom, margin.left).get();
ToString(anchor).c_str()).get();
}
if (GetIsStickyPosition()) {
aStream << nsPrintfCString(" [isStickyPosition scrollId=%d outer=%f,%f %fx%f "

View File

@ -1151,9 +1151,8 @@ public:
/**
* CONSTRUCTION PHASE ONLY
* If a layer represents a fixed position element or elements that are on
* a document that has had fixed position element margins set on it, this
* data is stored on the layer for use by the compositor.
* If a layer represents a fixed position element, this data is stored on the
* layer for use by the compositor.
*
* - |aScrollId| identifies the scroll frame that this element is fixed
* with respect to.
@ -1162,30 +1161,19 @@ public:
* point, that is, the point which remains in the same position when
* compositing the layer tree with a transformation (such as when
* asynchronously scrolling and zooming).
*
* - |aMargins| are the fixed position margins set on the document this
* element is part of. Storing them here allows for asynchronous
* animation of the margins by reconciling the difference between this
* value and a value that is updated more frequently.
* If the left or top margins are negative, it means that the elements
* this layer represents are auto-positioned, and so fxed position
* margins should not have an effect on the corresponding axis.
*/
void SetFixedPositionData(FrameMetrics::ViewID aScrollId,
const LayerPoint& aAnchor,
const LayerMargin& aMargins)
const LayerPoint& aAnchor)
{
if (!mFixedPositionData ||
mFixedPositionData->mScrollId != aScrollId ||
mFixedPositionData->mAnchor != aAnchor ||
mFixedPositionData->mMargins != aMargins) {
mFixedPositionData->mAnchor != aAnchor) {
MOZ_LAYERS_LOG_IF_SHADOWABLE(this, ("Layer::Mutated(%p) FixedPositionData", this));
if (!mFixedPositionData) {
mFixedPositionData = MakeUnique<FixedPositionData>();
}
mFixedPositionData->mScrollId = aScrollId;
mFixedPositionData->mAnchor = aAnchor;
mFixedPositionData->mMargins = aMargins;
Mutated();
}
}
@ -1279,7 +1267,6 @@ public:
bool GetIsStickyPosition() { return mStickyPositionData; }
FrameMetrics::ViewID GetFixedPositionScrollContainerId() { return mFixedPositionData ? mFixedPositionData->mScrollId : FrameMetrics::NULL_SCROLL_ID; }
LayerPoint GetFixedPositionAnchor() { return mFixedPositionData ? mFixedPositionData->mAnchor : LayerPoint(); }
LayerMargin GetFixedPositionMargins() { return mFixedPositionData ? mFixedPositionData->mMargins : LayerMargin(); }
FrameMetrics::ViewID GetStickyScrollContainerId() { return mStickyPositionData->mScrollId; }
const LayerRect& GetStickyScrollRangeOuter() { return mStickyPositionData->mOuter; }
const LayerRect& GetStickyScrollRangeInner() { return mStickyPositionData->mInner; }
@ -1783,7 +1770,6 @@ protected:
struct FixedPositionData {
FrameMetrics::ViewID mScrollId;
LayerPoint mAnchor;
LayerMargin mMargins;
};
UniquePtr<FixedPositionData> mFixedPositionData;
struct StickyPositionData {

View File

@ -790,6 +790,12 @@ ClientLayerManager::AsyncPanZoomEnabled() const
return mWidget && mWidget->AsyncPanZoomEnabled();
}
void
ClientLayerManager::SetNextPaintSyncId(int32_t aSyncId)
{
mForwarder->SetPaintSyncId(aSyncId);
}
ClientLayer::~ClientLayer()
{
if (HasShadow()) {

View File

@ -253,6 +253,8 @@ public:
bool AsyncPanZoomEnabled() const override;
void SetNextPaintSyncId(int32_t aSyncId);
protected:
enum TransactionPhase {
PHASE_NONE, PHASE_CONSTRUCTION, PHASE_DRAWING, PHASE_FORWARD

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