mirror of
https://repo.dactyloidae.xyz/Dactyloidae/UXP.git
synced 2026-10-02 05:17:31 +09:00
Revert "Issue #21 - Remove use counters telemetry"
This reverts commit 8ca9db6b65.
This commit is contained in:
parent
bebaa470c6
commit
92a1cc3139
45 changed files with 1128 additions and 36 deletions
36
dom/base/UseCounter.h
Normal file
36
dom/base/UseCounter.h
Normal file
|
|
@ -0,0 +1,36 @@
|
||||||
|
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||||
|
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
#ifndef UseCounter_h_
|
||||||
|
#define UseCounter_h_
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
namespace mozilla {
|
||||||
|
|
||||||
|
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_##_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
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
63
dom/base/UseCounters.conf
Normal file
63
dom/base/UseCounters.conf
Normal file
|
|
@ -0,0 +1,63 @@
|
||||||
|
// This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
|
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||||
|
|
||||||
|
// This file defines a list of use counters, which are things that can
|
||||||
|
// record usage of Web platform features and then report this information
|
||||||
|
// through Telemetry.
|
||||||
|
//
|
||||||
|
// The format of this file is very strict. Each line can be:
|
||||||
|
//
|
||||||
|
// (a) a blank line
|
||||||
|
//
|
||||||
|
// (b) a comment, which is a line that begins with "//"
|
||||||
|
//
|
||||||
|
// (c) one of three possible use counter declarations:
|
||||||
|
//
|
||||||
|
// method <IDL interface name>.<IDL operation name>
|
||||||
|
// attribute <IDL interface name>.<IDL attribute 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. 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
|
||||||
|
// well. Generating things from bindings codegen and ensuring all the
|
||||||
|
// 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
|
||||||
|
|
||||||
|
// Push API
|
||||||
|
method PushManager.subscribe
|
||||||
|
method PushSubscription.unsubscribe
|
||||||
|
|
||||||
|
// window.sidebar.addSearchEngine
|
||||||
|
attribute Window.sidebar
|
||||||
|
method External.addSearchEngine
|
||||||
|
|
||||||
|
// AppCache API
|
||||||
|
method OfflineResourceList.swapCache
|
||||||
|
method OfflineResourceList.update
|
||||||
|
attribute OfflineResourceList.status
|
||||||
|
attribute OfflineResourceList.onchecking
|
||||||
|
attribute OfflineResourceList.onerror
|
||||||
|
attribute OfflineResourceList.onnoupdate
|
||||||
|
attribute OfflineResourceList.ondownloading
|
||||||
|
attribute OfflineResourceList.onprogress
|
||||||
|
attribute OfflineResourceList.onupdateready
|
||||||
|
attribute OfflineResourceList.oncached
|
||||||
|
attribute OfflineResourceList.onobsolete
|
||||||
80
dom/base/gen-usecounters.py
Normal file
80
dom/base/gen-usecounters.py
Normal file
|
|
@ -0,0 +1,80 @@
|
||||||
|
#!/usr/bin/env python
|
||||||
|
|
||||||
|
# This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
|
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||||
|
|
||||||
|
from __future__ import print_function
|
||||||
|
|
||||||
|
import json
|
||||||
|
import os
|
||||||
|
import sys
|
||||||
|
sys.path.append(os.path.dirname(__file__))
|
||||||
|
|
||||||
|
import usecounters
|
||||||
|
|
||||||
|
AUTOGENERATED_WARNING_COMMENT = "/* THIS FILE IS AUTOGENERATED BY gen-usecounters.py - DO NOT EDIT */"
|
||||||
|
|
||||||
|
def generate_list(f, counters):
|
||||||
|
def print_optional_macro_declare(name):
|
||||||
|
print('''
|
||||||
|
#ifndef %(name)s
|
||||||
|
#define %(name)s(interface_, name_) // nothing
|
||||||
|
#define DEFINED_%(name)s
|
||||||
|
#endif
|
||||||
|
''' % { 'name': name }, file=f)
|
||||||
|
|
||||||
|
def print_optional_macro_undeclare(name):
|
||||||
|
print('''
|
||||||
|
#ifdef DEFINED_%(name)s
|
||||||
|
#undef DEFINED_%(name)s
|
||||||
|
#undef %(name)s
|
||||||
|
#endif
|
||||||
|
''' % { 'name': name }, file=f)
|
||||||
|
|
||||||
|
print(AUTOGENERATED_WARNING_COMMENT, file=f)
|
||||||
|
|
||||||
|
print_optional_macro_declare('USE_COUNTER_DOM_METHOD')
|
||||||
|
print_optional_macro_declare('USE_COUNTER_DOM_ATTRIBUTE')
|
||||||
|
print_optional_macro_declare('USE_COUNTER_CSS_PROPERTY')
|
||||||
|
|
||||||
|
for counter in counters:
|
||||||
|
if counter['type'] == 'method':
|
||||||
|
print('USE_COUNTER_DOM_METHOD(%s, %s)' % (counter['interface_name'], counter['method_name']), file=f)
|
||||||
|
elif counter['type'] == 'attribute':
|
||||||
|
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), file=f)
|
||||||
|
|
||||||
|
print_optional_macro_undeclare('USE_COUNTER_DOM_METHOD')
|
||||||
|
print_optional_macro_undeclare('USE_COUNTER_DOM_ATTRIBUTE')
|
||||||
|
print_optional_macro_undeclare('USE_COUNTER_CSS_PROPERTY')
|
||||||
|
|
||||||
|
def generate_property_map(f, counters):
|
||||||
|
print(AUTOGENERATED_WARNING_COMMENT, file=f)
|
||||||
|
print('''
|
||||||
|
enum {
|
||||||
|
#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_##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']
|
||||||
|
print('#define USE_COUNTER_FOR_CSS_PROPERTY_%s eUseCounter_property_%s' % (prop, prop), file=f)
|
||||||
|
|
||||||
|
def use_counter_list(output_header, conf_filename):
|
||||||
|
counters = usecounters.read_conf(conf_filename)
|
||||||
|
generate_list(output_header, counters)
|
||||||
|
|
||||||
|
def property_map(output_map, conf_filename):
|
||||||
|
counters = usecounters.read_conf(conf_filename)
|
||||||
|
generate_property_map(output_map, counters)
|
||||||
|
|
@ -141,9 +141,11 @@ EXPORTS.mozilla += [
|
||||||
'FeedWriterEnabled.h',
|
'FeedWriterEnabled.h',
|
||||||
'TextInputProcessor.h',
|
'TextInputProcessor.h',
|
||||||
'TimerClamping.h',
|
'TimerClamping.h',
|
||||||
|
'UseCounter.h',
|
||||||
]
|
]
|
||||||
|
|
||||||
EXPORTS.mozilla.dom += [
|
EXPORTS.mozilla.dom += [
|
||||||
|
'!UseCounterList.h',
|
||||||
'AnonymousContent.h',
|
'AnonymousContent.h',
|
||||||
'Attr.h',
|
'Attr.h',
|
||||||
'BarProps.h',
|
'BarProps.h',
|
||||||
|
|
@ -469,5 +471,18 @@ if CONFIG['MOZ_PHOENIX'] or CONFIG['MOZ_XULRUNNER']:
|
||||||
if CONFIG['MOZ_X11']:
|
if CONFIG['MOZ_X11']:
|
||||||
CXXFLAGS += CONFIG['TK_CFLAGS']
|
CXXFLAGS += CONFIG['TK_CFLAGS']
|
||||||
|
|
||||||
|
GENERATED_FILES += [
|
||||||
|
'PropertyUseCounterMap.inc',
|
||||||
|
'UseCounterList.h',
|
||||||
|
]
|
||||||
|
|
||||||
|
countermap = GENERATED_FILES['PropertyUseCounterMap.inc']
|
||||||
|
countermap.script = 'gen-usecounters.py:property_map'
|
||||||
|
countermap.inputs = ['UseCounters.conf']
|
||||||
|
|
||||||
|
counterlist = GENERATED_FILES['UseCounterList.h']
|
||||||
|
counterlist.script = 'gen-usecounters.py:use_counter_list'
|
||||||
|
counterlist.inputs = ['UseCounters.conf']
|
||||||
|
|
||||||
if CONFIG['GNU_CXX']:
|
if CONFIG['GNU_CXX']:
|
||||||
CXXFLAGS += ['-Wno-error=shadow']
|
CXXFLAGS += ['-Wno-error=shadow']
|
||||||
|
|
|
||||||
|
|
@ -104,6 +104,9 @@
|
||||||
#include "nsContentPermissionHelper.h"
|
#include "nsContentPermissionHelper.h"
|
||||||
#include "nsCSSPseudoElements.h" // for CSSPseudoElementType
|
#include "nsCSSPseudoElements.h" // for CSSPseudoElementType
|
||||||
#include "nsNetUtil.h"
|
#include "nsNetUtil.h"
|
||||||
|
#include "nsDocument.h"
|
||||||
|
#include "HTMLImageElement.h"
|
||||||
|
#include "mozilla/css/ImageLoader.h"
|
||||||
#include "mozilla/layers/APZCTreeManager.h" // for layers::ZoomToRectBehavior
|
#include "mozilla/layers/APZCTreeManager.h" // for layers::ZoomToRectBehavior
|
||||||
#include "mozilla/dom/Promise.h"
|
#include "mozilla/dom/Promise.h"
|
||||||
#include "mozilla/StyleSheetInlines.h"
|
#include "mozilla/StyleSheetInlines.h"
|
||||||
|
|
@ -4022,6 +4025,27 @@ nsDOMWindowUtils::LeaveChaosMode()
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
NS_IMETHODIMP
|
||||||
|
nsDOMWindowUtils::ForceUseCounterFlush(nsIDOMNode *aNode)
|
||||||
|
{
|
||||||
|
NS_ENSURE_ARG_POINTER(aNode);
|
||||||
|
|
||||||
|
if (nsCOMPtr<nsIDocument> doc = do_QueryInterface(aNode)) {
|
||||||
|
mozilla::css::ImageLoader* loader = doc->StyleImageLoader();
|
||||||
|
loader->FlushUseCounters();
|
||||||
|
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
|
NS_IMETHODIMP
|
||||||
nsDOMWindowUtils::HasRuleProcessorUsedByMultipleStyleSets(uint32_t aSheetType,
|
nsDOMWindowUtils::HasRuleProcessorUsedByMultipleStyleSets(uint32_t aSheetType,
|
||||||
bool* aRetVal)
|
bool* aRetVal)
|
||||||
|
|
|
||||||
|
|
@ -9718,6 +9718,19 @@ static const char* kDocumentWarnings[] = {
|
||||||
};
|
};
|
||||||
#undef DOCUMENT_WARNING
|
#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
|
bool
|
||||||
nsIDocument::HasWarnedAbout(DeprecatedOperations aOperation) const
|
nsIDocument::HasWarnedAbout(DeprecatedOperations aOperation) const
|
||||||
{
|
{
|
||||||
|
|
@ -9733,6 +9746,7 @@ nsIDocument::WarnOnceAbout(DeprecatedOperations aOperation,
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
mDeprecationWarnedAbout[aOperation] = true;
|
mDeprecationWarnedAbout[aOperation] = true;
|
||||||
|
const_cast<nsIDocument*>(this)->SetDocumentAndPageUseCounter(OperationToUseCounter(aOperation));
|
||||||
uint32_t flags = asError ? nsIScriptError::errorFlag
|
uint32_t flags = asError ? nsIScriptError::errorFlag
|
||||||
: nsIScriptError::warningFlag;
|
: nsIScriptError::warningFlag;
|
||||||
nsContentUtils::ReportToConsole(flags,
|
nsContentUtils::ReportToConsole(flags,
|
||||||
|
|
@ -11983,6 +11997,69 @@ nsIDocument::GetTopLevelContentDocument()
|
||||||
return 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);
|
||||||
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
nsIDocument::HasScriptsBlockedBySandbox()
|
nsIDocument::HasScriptsBlockedBySandbox()
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -24,6 +24,7 @@
|
||||||
#include "nsTHashtable.h" // for member
|
#include "nsTHashtable.h" // for member
|
||||||
#include "mozilla/net/ReferrerPolicy.h" // for member
|
#include "mozilla/net/ReferrerPolicy.h" // for member
|
||||||
#include "nsWeakReference.h"
|
#include "nsWeakReference.h"
|
||||||
|
#include "mozilla/UseCounter.h"
|
||||||
#include "mozilla/WeakPtr.h"
|
#include "mozilla/WeakPtr.h"
|
||||||
#include "Units.h"
|
#include "Units.h"
|
||||||
#include "nsContentListDeclarations.h"
|
#include "nsContentListDeclarations.h"
|
||||||
|
|
@ -2781,6 +2782,23 @@ public:
|
||||||
|
|
||||||
bool DidFireDOMContentLoaded() const { return mDidFireDOMContentLoaded; }
|
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);
|
||||||
|
|
||||||
void SetUserHasInteracted(bool aUserHasInteracted)
|
void SetUserHasInteracted(bool aUserHasInteracted)
|
||||||
{
|
{
|
||||||
mUserHasInteracted = aUserHasInteracted;
|
mUserHasInteracted = aUserHasInteracted;
|
||||||
|
|
@ -2839,6 +2857,24 @@ public:
|
||||||
|
|
||||||
virtual void ScheduleResizeObserversNotification() const = 0;
|
virtual void ScheduleResizeObserversNotification() const = 0;
|
||||||
|
|
||||||
|
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:
|
private:
|
||||||
mutable std::bitset<eDeprecatedOperationCount> mDeprecationWarnedAbout;
|
mutable std::bitset<eDeprecatedOperationCount> mDeprecationWarnedAbout;
|
||||||
mutable std::bitset<eDocumentWarningCount> mDocWarningWarnedAbout;
|
mutable std::bitset<eDocumentWarningCount> mDocWarningWarnedAbout;
|
||||||
|
|
@ -3279,6 +3315,14 @@ protected:
|
||||||
// Our live MediaQueryLists
|
// Our live MediaQueryLists
|
||||||
PRCList mDOMMediaQueryLists;
|
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;
|
||||||
|
|
||||||
// Whether the user has interacted with the document or not:
|
// Whether the user has interacted with the document or not:
|
||||||
bool mUserHasInteracted;
|
bool mUserHasInteracted;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -198,6 +198,12 @@ nsImageLoadingContent::Notify(imgIRequest* aRequest,
|
||||||
}
|
}
|
||||||
|
|
||||||
if (aType == imgINotificationObserver::DECODE_COMPLETE) {
|
if (aType == imgINotificationObserver::DECODE_COMPLETE) {
|
||||||
|
nsCOMPtr<imgIContainer> container;
|
||||||
|
aRequest->GetImage(getter_AddRefs(container));
|
||||||
|
if (container) {
|
||||||
|
container->PropagateUseCounters(GetOurOwnerDoc());
|
||||||
|
}
|
||||||
|
|
||||||
UpdateImageState(true);
|
UpdateImageState(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,13 @@ support-files =
|
||||||
file_bug1011748_redirect.sjs
|
file_bug1011748_redirect.sjs
|
||||||
file_bug1011748_OK.sjs
|
file_bug1011748_OK.sjs
|
||||||
file_messagemanager_unload.html
|
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_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]
|
[browser_bug593387.js]
|
||||||
[browser_bug902350.js]
|
[browser_bug902350.js]
|
||||||
|
|
@ -17,4 +24,5 @@ tags = mcb
|
||||||
skip-if = e10s # this tests non-e10s behavior. it's not expected to work in e10s.
|
skip-if = e10s # this tests non-e10s behavior. it's not expected to work in e10s.
|
||||||
[browser_state_notifications.js]
|
[browser_state_notifications.js]
|
||||||
skip-if = true # Bug 1271028
|
skip-if = true # Bug 1271028
|
||||||
|
[browser_use_counters.js]
|
||||||
[browser_bug1307747.js]
|
[browser_bug1307747.js]
|
||||||
|
|
|
||||||
305
dom/base/test/browser_use_counters.js
Normal file
305
dom/base/test/browser_use_counters.js
Normal file
|
|
@ -0,0 +1,305 @@
|
||||||
|
/* -*- Mode: javascript; tab-width: 2; indent-tabs-mode: nil; js-indent-level: 2 -*- */
|
||||||
|
|
||||||
|
requestLongerTimeout(2);
|
||||||
|
|
||||||
|
var {Promise: promise} = Cu.import("resource://gre/modules/Promise.jsm", {});
|
||||||
|
Cu.import("resource://gre/modules/Services.jsm");
|
||||||
|
|
||||||
|
const gHttpTestRoot = "http://example.com/browser/dom/base/test/";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Enable local telemetry recording for the duration of the tests.
|
||||||
|
*/
|
||||||
|
var gOldContentCanRecord = false;
|
||||||
|
var gOldParentCanRecord = false;
|
||||||
|
add_task(function* test_initialize() {
|
||||||
|
let Telemetry = Cc["@mozilla.org/base/telemetry;1"].getService(Ci.nsITelemetry);
|
||||||
|
gOldParentCanRecord = Telemetry.canRecordExtended
|
||||||
|
Telemetry.canRecordExtended = true;
|
||||||
|
|
||||||
|
// Because canRecordExtended is a per-process variable, we need to make sure
|
||||||
|
// that all of the pages load in the same content process. Limit the number
|
||||||
|
// of content processes to at most 1 (or 0 if e10s is off entirely).
|
||||||
|
yield SpecialPowers.pushPrefEnv({ set: [[ "dom.ipc.processCount", 1 ]] });
|
||||||
|
|
||||||
|
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 even loads from the imglib cache update use counters. The
|
||||||
|
// 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_getElementById.svg",
|
||||||
|
"SVGSVGELEMENT_GETELEMENTBYID", false);
|
||||||
|
yield check_use_counter_iframe("file_use_counter_svg_currentScale.svg",
|
||||||
|
"SVGSVGELEMENT_CURRENTSCALE_getter", false);
|
||||||
|
yield check_use_counter_iframe("file_use_counter_svg_currentScale.svg",
|
||||||
|
"SVGSVGELEMENT_CURRENTSCALE_setter", false);
|
||||||
|
|
||||||
|
// 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");
|
||||||
|
});
|
||||||
|
|
||||||
|
add_task(function* () {
|
||||||
|
let Telemetry = Cc["@mozilla.org/base/telemetry;1"].getService(Ci.nsITelemetry);
|
||||||
|
Telemetry.canRecordExtended = gOldParentCanRecord;
|
||||||
|
|
||||||
|
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(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(use_counter_middlefix, page_before = null) {
|
||||||
|
let telemetry = Cc["@mozilla.org/base/telemetry;1"].getService(Ci.nsITelemetry);
|
||||||
|
let suffix = Services.appinfo.browserTabsRemoteAutostart ? "#content" : "";
|
||||||
|
let gather = () => [
|
||||||
|
telemetry.getHistogramById("USE_COUNTER2_" + use_counter_middlefix + "_PAGE" + suffix).snapshot().sum,
|
||||||
|
telemetry.getHistogramById("USE_COUNTER2_" + use_counter_middlefix + "_DOCUMENT" + suffix).snapshot().sum,
|
||||||
|
telemetry.getHistogramById("CONTENT_DOCUMENTS_DESTROYED" + suffix).snapshot().sum,
|
||||||
|
telemetry.getHistogramById("TOP_LEVEL_CONTENT_DOCUMENTS_DESTROYED" + suffix).snapshot().sum,
|
||||||
|
];
|
||||||
|
return BrowserTestUtils.waitForCondition(() => {
|
||||||
|
return page_before != telemetry.getHistogramById("USE_COUNTER2_" + use_counter_middlefix + "_PAGE" + suffix).snapshot().sum;
|
||||||
|
}).then(gather, gather);
|
||||||
|
}
|
||||||
|
|
||||||
|
var 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,
|
||||||
|
histogram_docs_before, histogram_toplevel_docs_before] =
|
||||||
|
yield grabHistogramsFromContent(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 content->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,
|
||||||
|
histogram_docs_after, histogram_toplevel_docs_after] =
|
||||||
|
yield grabHistogramsFromContent(use_counter_middlefix, histogram_page_before);
|
||||||
|
|
||||||
|
is(histogram_page_after, histogram_page_before + 1,
|
||||||
|
"page counts for " + use_counter_middlefix + " after are correct");
|
||||||
|
ok(histogram_toplevel_docs_after >= histogram_toplevel_docs_before + 1,
|
||||||
|
"top level document counts are correct");
|
||||||
|
if (check_documents) {
|
||||||
|
is(histogram_document_after, histogram_document_before + 1,
|
||||||
|
"document counts for " + use_counter_middlefix + " after are correct");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
var 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,
|
||||||
|
histogram_docs_before, histogram_toplevel_docs_before] =
|
||||||
|
yield grabHistogramsFromContent(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,
|
||||||
|
histogram_docs_after, histogram_toplevel_docs_after] =
|
||||||
|
yield grabHistogramsFromContent(use_counter_middlefix, histogram_page_before);
|
||||||
|
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 for " + use_counter_middlefix + " after are correct");
|
||||||
|
ok(histogram_toplevel_docs_after >= histogram_toplevel_docs_before + 1,
|
||||||
|
"top level document counts are correct");
|
||||||
|
// 2 documents: one for the outer html page containing the <img> element, and
|
||||||
|
// one for the SVG image itself.
|
||||||
|
ok(histogram_docs_after >= histogram_docs_before + 2,
|
||||||
|
"document counts are correct");
|
||||||
|
});
|
||||||
|
|
||||||
|
var 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,
|
||||||
|
histogram_docs_before, histogram_toplevel_docs_before] =
|
||||||
|
yield grabHistogramsFromContent(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,
|
||||||
|
histogram_docs_after, histogram_toplevel_docs_after] =
|
||||||
|
yield grabHistogramsFromContent(use_counter_middlefix, histogram_page_before);
|
||||||
|
if (!xfail) {
|
||||||
|
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 for " + use_counter_middlefix + " after are correct");
|
||||||
|
}
|
||||||
|
ok(histogram_toplevel_docs_after >= histogram_toplevel_docs_before + 1,
|
||||||
|
"top level document counts are correct");
|
||||||
|
ok(histogram_docs_after >= histogram_docs_before + 1,
|
||||||
|
"document counts are correct");
|
||||||
|
});
|
||||||
17
dom/base/test/file_use_counter_outer.html
Normal file
17
dom/base/test/file_use_counter_outer.html
Normal 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>
|
||||||
17
dom/base/test/file_use_counter_svg_currentScale.svg
Normal file
17
dom/base/test/file_use_counter_svg_currentScale.svg
Normal file
|
|
@ -0,0 +1,17 @@
|
||||||
|
<?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">
|
||||||
|
</image>
|
||||||
|
<circle cx="100" cy="50" r="40" stroke="black" stroke-width="2" fill="red"/>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 635 B |
15
dom/base/test/file_use_counter_svg_fill_pattern.svg
Normal file
15
dom/base/test/file_use_counter_svg_fill_pattern.svg
Normal 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 |
15
dom/base/test/file_use_counter_svg_fill_pattern_data.svg
Normal file
15
dom/base/test/file_use_counter_svg_fill_pattern_data.svg
Normal 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 |
|
|
@ -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 |
23
dom/base/test/file_use_counter_svg_fill_pattern_internal.svg
Normal file
23
dom/base/test/file_use_counter_svg_fill_pattern_internal.svg
Normal 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 |
22
dom/base/test/file_use_counter_svg_getElementById.svg
Normal file
22
dom/base/test/file_use_counter_svg_getElementById.svg
Normal file
|
|
@ -0,0 +1,22 @@
|
||||||
|
<?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">
|
||||||
|
</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: 836 B |
71
dom/base/usecounters.py
Normal file
71
dom/base/usecounters.py
Normal file
|
|
@ -0,0 +1,71 @@
|
||||||
|
# This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
|
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||||
|
|
||||||
|
import buildconfig
|
||||||
|
import collections
|
||||||
|
import re
|
||||||
|
import StringIO
|
||||||
|
import sys
|
||||||
|
|
||||||
|
def read_conf(conf_filename):
|
||||||
|
# Can't read/write from a single StringIO, so make a new one for reading.
|
||||||
|
stream = open(conf_filename, 'rU')
|
||||||
|
|
||||||
|
def parse_counters(stream):
|
||||||
|
for line_num, line in enumerate(stream):
|
||||||
|
line = line.rstrip('\n')
|
||||||
|
if not line or line.startswith('//'):
|
||||||
|
# empty line or comment
|
||||||
|
continue
|
||||||
|
m = re.match(r'method ([A-Za-z0-9]+)\.([A-Za-z0-9]+)$', line)
|
||||||
|
if m:
|
||||||
|
interface_name, method_name = m.groups()
|
||||||
|
yield { 'type': 'method',
|
||||||
|
'interface_name': interface_name,
|
||||||
|
'method_name': method_name }
|
||||||
|
continue
|
||||||
|
m = re.match(r'attribute ([A-Za-z0-9]+)\.([A-Za-z0-9]+)$', line)
|
||||||
|
if m:
|
||||||
|
interface_name, attribute_name = m.groups()
|
||||||
|
yield { 'type': 'attribute',
|
||||||
|
'interface_name': interface_name,
|
||||||
|
'attribute_name': attribute_name }
|
||||||
|
continue
|
||||||
|
m = re.match(r'property ([A-Za-z0-9]+)$', line)
|
||||||
|
if m:
|
||||||
|
property_name = m.group(1)
|
||||||
|
yield { 'type': 'property',
|
||||||
|
'property_name': property_name }
|
||||||
|
continue
|
||||||
|
raise ValueError('error parsing %s at line %d' % (conf_filename, line_num))
|
||||||
|
|
||||||
|
return parse_counters(stream)
|
||||||
|
|
||||||
|
def generate_histograms(filename):
|
||||||
|
# The mapping for use counters to telemetry histograms depends on the
|
||||||
|
# ordering of items in the dictionary.
|
||||||
|
items = collections.OrderedDict()
|
||||||
|
for counter in read_conf(filename):
|
||||||
|
def append_counter(name, desc):
|
||||||
|
items[name] = { 'expires_in_version': 'never',
|
||||||
|
'kind' : 'boolean',
|
||||||
|
'description': desc }
|
||||||
|
|
||||||
|
def append_counters(name, desc):
|
||||||
|
append_counter('USE_COUNTER2_%s_DOCUMENT' % name, 'Whether a document %s' % desc)
|
||||||
|
append_counter('USE_COUNTER2_%s_PAGE' % name, 'Whether a page %s' % desc)
|
||||||
|
|
||||||
|
if counter['type'] == 'method':
|
||||||
|
method = '%s.%s' % (counter['interface_name'], counter['method_name'])
|
||||||
|
append_counters(method.replace('.', '_').upper(), 'called %s' % method)
|
||||||
|
elif counter['type'] == 'attribute':
|
||||||
|
attr = '%s.%s' % (counter['interface_name'], counter['attribute_name'])
|
||||||
|
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)
|
||||||
|
|
||||||
|
return items
|
||||||
|
|
@ -14,6 +14,7 @@
|
||||||
#include "mozilla/Preferences.h"
|
#include "mozilla/Preferences.h"
|
||||||
#include "mozilla/SizePrintfMacros.h"
|
#include "mozilla/SizePrintfMacros.h"
|
||||||
#include "mozilla/Unused.h"
|
#include "mozilla/Unused.h"
|
||||||
|
#include "mozilla/UseCounter.h"
|
||||||
#include "mozilla/dom/DocGroup.h"
|
#include "mozilla/dom/DocGroup.h"
|
||||||
|
|
||||||
#include "AccessCheck.h"
|
#include "AccessCheck.h"
|
||||||
|
|
@ -58,6 +59,7 @@
|
||||||
#include "mozilla/jsipc/CrossProcessObjectWrappers.h"
|
#include "mozilla/jsipc/CrossProcessObjectWrappers.h"
|
||||||
#include "nsDOMClassInfo.h"
|
#include "nsDOMClassInfo.h"
|
||||||
#include "ipc/ErrorIPCUtils.h"
|
#include "ipc/ErrorIPCUtils.h"
|
||||||
|
#include "mozilla/UseCounter.h"
|
||||||
|
|
||||||
namespace mozilla {
|
namespace mozilla {
|
||||||
namespace dom {
|
namespace dom {
|
||||||
|
|
@ -3590,6 +3592,16 @@ AssertReflectorHasGivenProto(JSContext* aCx, JSObject* aReflector,
|
||||||
} // namespace binding_detail
|
} // namespace binding_detail
|
||||||
#endif // DEBUG
|
#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 {
|
namespace {
|
||||||
|
|
||||||
// This runnable is used to write a deprecation message from a worker to the
|
// This runnable is used to write a deprecation message from a worker to the
|
||||||
|
|
|
||||||
|
|
@ -46,6 +46,8 @@ class nsIJSID;
|
||||||
|
|
||||||
namespace mozilla {
|
namespace mozilla {
|
||||||
|
|
||||||
|
enum UseCounter : int16_t;
|
||||||
|
|
||||||
namespace dom {
|
namespace dom {
|
||||||
class CustomElementReactionsStack;
|
class CustomElementReactionsStack;
|
||||||
template<typename KeyType, typename ValueType> class Record;
|
template<typename KeyType, typename ValueType> class Record;
|
||||||
|
|
@ -3426,6 +3428,10 @@ already_AddRefed<nsGenericHTMLElement>
|
||||||
CreateHTMLElement(const GlobalObject& aGlobal, const JS::CallArgs& aCallArgs,
|
CreateHTMLElement(const GlobalObject& aGlobal, const JS::CallArgs& aCallArgs,
|
||||||
JS::Handle<JSObject*> aGivenProto, ErrorResult& aRv);
|
JS::Handle<JSObject*> aGivenProto, ErrorResult& aRv);
|
||||||
|
|
||||||
|
void
|
||||||
|
SetDocumentAndPageUseCounter(JSContext* aCx, JSObject* aObject,
|
||||||
|
UseCounter aUseCounter);
|
||||||
|
|
||||||
// Warnings
|
// Warnings
|
||||||
void
|
void
|
||||||
DeprecationWarning(JSContext* aCx, JSObject* aObject,
|
DeprecationWarning(JSContext* aCx, JSObject* aObject,
|
||||||
|
|
|
||||||
|
|
@ -7467,8 +7467,8 @@ class CGPerSignatureCall(CGThing):
|
||||||
|
|
||||||
def __init__(self, returnType, arguments, nativeMethodName, static,
|
def __init__(self, returnType, arguments, nativeMethodName, static,
|
||||||
descriptor, idlNode, argConversionStartsAt=0, getter=False,
|
descriptor, idlNode, argConversionStartsAt=0, getter=False,
|
||||||
setter=False, isConstructor=False, resultVar=None,
|
setter=False, isConstructor=False, useCounterName=None,
|
||||||
objectName="obj"):
|
resultVar=None, objectName="obj"):
|
||||||
assert idlNode.isMethod() == (not getter and not setter)
|
assert idlNode.isMethod() == (not getter and not setter)
|
||||||
assert idlNode.isAttr() == (getter or setter)
|
assert idlNode.isAttr() == (getter or setter)
|
||||||
# Constructors are always static
|
# Constructors are always static
|
||||||
|
|
@ -7701,6 +7701,11 @@ class CGPerSignatureCall(CGThing):
|
||||||
nativeMethodName,
|
nativeMethodName,
|
||||||
static, argsPost=argsPost, resultVar=resultVar))
|
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)
|
self.cgRoot = CGList(cgThings)
|
||||||
|
|
||||||
def getArguments(self):
|
def getArguments(self):
|
||||||
|
|
@ -7929,6 +7934,11 @@ class CGMethodCall(CGThing):
|
||||||
methodName = "%s.%s" % (descriptor.interface.identifier.name, method.identifier.name)
|
methodName = "%s.%s" % (descriptor.interface.identifier.name, method.identifier.name)
|
||||||
argDesc = "argument %d of " + methodName
|
argDesc = "argument %d of " + methodName
|
||||||
|
|
||||||
|
if method.getExtendedAttribute("UseCounter"):
|
||||||
|
useCounterName = methodName.replace(".", "_")
|
||||||
|
else:
|
||||||
|
useCounterName = None
|
||||||
|
|
||||||
if method.isStatic():
|
if method.isStatic():
|
||||||
nativeType = descriptor.nativeType
|
nativeType = descriptor.nativeType
|
||||||
staticTypeOverride = PropertyDefiner.getStringAttr(method, "StaticClassOverride")
|
staticTypeOverride = PropertyDefiner.getStringAttr(method, "StaticClassOverride")
|
||||||
|
|
@ -7950,7 +7960,8 @@ class CGMethodCall(CGThing):
|
||||||
nativeMethodName, static, descriptor,
|
nativeMethodName, static, descriptor,
|
||||||
method,
|
method,
|
||||||
argConversionStartsAt=argConversionStartsAt,
|
argConversionStartsAt=argConversionStartsAt,
|
||||||
isConstructor=isConstructor)
|
isConstructor=isConstructor,
|
||||||
|
useCounterName=useCounterName)
|
||||||
|
|
||||||
signatures = method.signatures()
|
signatures = method.signatures()
|
||||||
if len(signatures) == 1:
|
if len(signatures) == 1:
|
||||||
|
|
@ -8326,11 +8337,16 @@ class CGGetterCall(CGPerSignatureCall):
|
||||||
getter.
|
getter.
|
||||||
"""
|
"""
|
||||||
def __init__(self, returnType, nativeMethodName, descriptor, attr):
|
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
|
||||||
if attr.isStatic():
|
if attr.isStatic():
|
||||||
nativeMethodName = "%s::%s" % (descriptor.nativeType, nativeMethodName)
|
nativeMethodName = "%s::%s" % (descriptor.nativeType, nativeMethodName)
|
||||||
CGPerSignatureCall.__init__(self, returnType, [], nativeMethodName,
|
CGPerSignatureCall.__init__(self, returnType, [], nativeMethodName,
|
||||||
attr.isStatic(), descriptor, attr,
|
attr.isStatic(), descriptor, attr,
|
||||||
getter=True)
|
getter=True, useCounterName=useCounterName)
|
||||||
|
|
||||||
|
|
||||||
class CGNavigatorGetterCall(CGPerSignatureCall):
|
class CGNavigatorGetterCall(CGPerSignatureCall):
|
||||||
|
|
@ -8397,12 +8413,17 @@ class CGSetterCall(CGPerSignatureCall):
|
||||||
setter.
|
setter.
|
||||||
"""
|
"""
|
||||||
def __init__(self, argType, nativeMethodName, descriptor, attr):
|
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
|
||||||
if attr.isStatic():
|
if attr.isStatic():
|
||||||
nativeMethodName = "%s::%s" % (descriptor.nativeType, nativeMethodName)
|
nativeMethodName = "%s::%s" % (descriptor.nativeType, nativeMethodName)
|
||||||
CGPerSignatureCall.__init__(self, None,
|
CGPerSignatureCall.__init__(self, None,
|
||||||
[FakeArgument(argType, attr, allowTreatNonCallableAsNull=True)],
|
[FakeArgument(argType, attr, allowTreatNonCallableAsNull=True)],
|
||||||
nativeMethodName, attr.isStatic(),
|
nativeMethodName, attr.isStatic(),
|
||||||
descriptor, attr, setter=True)
|
descriptor, attr, setter=True, useCounterName=useCounterName)
|
||||||
|
|
||||||
def wrap_return_value(self):
|
def wrap_return_value(self):
|
||||||
attr = self.idlNode
|
attr = self.idlNode
|
||||||
|
|
@ -13911,6 +13932,12 @@ class CGBindingRoot(CGThing):
|
||||||
bindingHeaders[CGHeaders.getDeclarationFilename(enums[0])] = True
|
bindingHeaders[CGHeaders.getDeclarationFilename(enums[0])] = True
|
||||||
bindingHeaders["jsapi.h"] = True
|
bindingHeaders["jsapi.h"] = True
|
||||||
|
|
||||||
|
# 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)
|
||||||
bindingHeaders["mozilla/dom/SimpleGlobalObject.h"] = any(
|
bindingHeaders["mozilla/dom/SimpleGlobalObject.h"] = any(
|
||||||
CGDictionary.dictionarySafeToJSONify(d) for d in dictionaries)
|
CGDictionary.dictionarySafeToJSONify(d) for d in dictionaries)
|
||||||
bindingHeaders["XrayWrapper.h"] = any(
|
bindingHeaders["XrayWrapper.h"] = any(
|
||||||
|
|
|
||||||
|
|
@ -4245,6 +4245,11 @@ class IDLAttribute(IDLInterfaceMember):
|
||||||
"readonly attributes" % attr.value(),
|
"readonly attributes" % attr.value(),
|
||||||
[attr.location, self.location])
|
[attr.location, self.location])
|
||||||
self._setDependsOn(attr.value())
|
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 == "Unscopable":
|
elif identifier == "Unscopable":
|
||||||
if not attr.noArguments():
|
if not attr.noArguments():
|
||||||
raise WebIDLError("[Unscopable] must take no arguments",
|
raise WebIDLError("[Unscopable] must take no arguments",
|
||||||
|
|
@ -4974,6 +4979,11 @@ class IDLMethod(IDLInterfaceMember, IDLScope):
|
||||||
raise WebIDLError("[Alias] takes an identifier or string",
|
raise WebIDLError("[Alias] takes an identifier or string",
|
||||||
[attr.location])
|
[attr.location])
|
||||||
self._addAlias(attr.value())
|
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 == "Unscopable":
|
elif identifier == "Unscopable":
|
||||||
if not attr.noArguments():
|
if not attr.noArguments():
|
||||||
raise WebIDLError("[Unscopable] must take no arguments",
|
raise WebIDLError("[Unscopable] must take no arguments",
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,7 @@
|
||||||
#include "nsPresContext.h"
|
#include "nsPresContext.h"
|
||||||
#include "nsMappedAttributes.h"
|
#include "nsMappedAttributes.h"
|
||||||
#include "nsSize.h"
|
#include "nsSize.h"
|
||||||
|
#include "nsDocument.h"
|
||||||
#include "nsIDocument.h"
|
#include "nsIDocument.h"
|
||||||
#include "nsIDOMMutationEvent.h"
|
#include "nsIDOMMutationEvent.h"
|
||||||
#include "nsIScriptContext.h"
|
#include "nsIScriptContext.h"
|
||||||
|
|
@ -26,6 +27,7 @@
|
||||||
#include "mozilla/dom/HTMLFormElement.h"
|
#include "mozilla/dom/HTMLFormElement.h"
|
||||||
#include "nsAttrValueOrString.h"
|
#include "nsAttrValueOrString.h"
|
||||||
#include "imgLoader.h"
|
#include "imgLoader.h"
|
||||||
|
#include "Image.h"
|
||||||
|
|
||||||
// Responsive images!
|
// Responsive images!
|
||||||
#include "mozilla/dom/HTMLSourceElement.h"
|
#include "mozilla/dom/HTMLSourceElement.h"
|
||||||
|
|
@ -1360,6 +1362,16 @@ HTMLImageElement::MediaFeatureValuesChanged()
|
||||||
QueueImageLoadTask(false);
|
QueueImageLoadTask(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
HTMLImageElement::FlushUseCounters()
|
||||||
|
{
|
||||||
|
nsCOMPtr<imgIRequest> request;
|
||||||
|
GetRequest(CURRENT_REQUEST, getter_AddRefs(request));
|
||||||
|
|
||||||
|
nsCOMPtr<imgIContainer> container;
|
||||||
|
request->GetImage(getter_AddRefs(container));
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace dom
|
} // namespace dom
|
||||||
} // namespace mozilla
|
} // namespace mozilla
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -261,6 +261,12 @@ public:
|
||||||
const nsAString& aMediaAttr,
|
const nsAString& aMediaAttr,
|
||||||
nsAString& aResult);
|
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:
|
protected:
|
||||||
virtual ~HTMLImageElement();
|
virtual ~HTMLImageElement();
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -49,7 +49,7 @@ interface nsIJSRAIIHelper;
|
||||||
interface nsIContentPermissionRequest;
|
interface nsIContentPermissionRequest;
|
||||||
interface nsIObserver;
|
interface nsIObserver;
|
||||||
|
|
||||||
[scriptable, uuid(7fcc7958-77d9-45ff-8c81-277bde5f0dc8)]
|
[scriptable, uuid(c471d440-004b-4c50-a6f2-747db5f443b6)]
|
||||||
interface nsIDOMWindowUtils : nsISupports {
|
interface nsIDOMWindowUtils : nsISupports {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -1938,6 +1938,17 @@ interface nsIDOMWindowUtils : nsISupports {
|
||||||
*/
|
*/
|
||||||
bool hasRuleProcessorUsedByMultipleStyleSets(in unsigned long aSheetType);
|
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);
|
void setNextPaintSyncId(in long aSyncId);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
|
|
@ -1208,9 +1208,27 @@ MappedAttrParser::ParseMappedAttrValue(nsIAtom* aMappedAttrName,
|
||||||
nsCSSProps::LookupProperty(nsDependentAtomString(aMappedAttrName),
|
nsCSSProps::LookupProperty(nsDependentAtomString(aMappedAttrName),
|
||||||
CSSEnabledState::eForAllContent);
|
CSSEnabledState::eForAllContent);
|
||||||
if (propertyID != eCSSProperty_UNKNOWN) {
|
if (propertyID != eCSSProperty_UNKNOWN) {
|
||||||
bool changed; // outparam for ParseProperty. (ignored)
|
bool changed = false; // outparam for ParseProperty.
|
||||||
mParser.ParseProperty(propertyID, aMappedAttrValue, mDocURI, mBaseURI,
|
mParser.ParseProperty(propertyID, aMappedAttrValue, mDocURI, mBaseURI,
|
||||||
mElement->NodePrincipal(), mDecl, &changed, false, true);
|
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,
|
||||||
|
CSSEnabledState::eForAllContent) {
|
||||||
|
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;
|
return;
|
||||||
}
|
}
|
||||||
MOZ_ASSERT(aMappedAttrName == nsGkAtoms::lang,
|
MOZ_ASSERT(aMappedAttrName == nsGkAtoms::lang,
|
||||||
|
|
|
||||||
|
|
@ -13,7 +13,7 @@ interface External
|
||||||
|
|
||||||
// Mozilla extension
|
// Mozilla extension
|
||||||
partial interface External {
|
partial interface External {
|
||||||
[UnsafeInPrerendering]
|
[UnsafeInPrerendering, UseCounter]
|
||||||
void addSearchEngine(DOMString engineURL, DOMString iconURL,
|
void addSearchEngine(DOMString engineURL, DOMString iconURL,
|
||||||
DOMString suggestedTitle, DOMString suggestedCategory);
|
DOMString suggestedTitle, DOMString suggestedCategory);
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -25,30 +25,38 @@ interface OfflineResourceList : EventTarget {
|
||||||
/* The application cache group is now obsolete. */
|
/* The application cache group is now obsolete. */
|
||||||
const unsigned short OBSOLETE = 5;
|
const unsigned short OBSOLETE = 5;
|
||||||
|
|
||||||
[Throws]
|
[Throws, UseCounter]
|
||||||
readonly attribute unsigned short status;
|
readonly attribute unsigned short status;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Begin the application update process on the associated application cache.
|
* Begin the application update process on the associated application cache.
|
||||||
*/
|
*/
|
||||||
[Throws]
|
[Throws, UseCounter]
|
||||||
void update();
|
void update();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Swap in the newest version of the application cache, or disassociate
|
* Swap in the newest version of the application cache, or disassociate
|
||||||
* from the cache if the cache group is obsolete.
|
* from the cache if the cache group is obsolete.
|
||||||
*/
|
*/
|
||||||
[Throws]
|
[Throws, UseCounter]
|
||||||
void swapCache();
|
void swapCache();
|
||||||
|
|
||||||
/* Events */
|
/* Events */
|
||||||
|
[UseCounter]
|
||||||
attribute EventHandler onchecking;
|
attribute EventHandler onchecking;
|
||||||
|
[UseCounter]
|
||||||
attribute EventHandler onerror;
|
attribute EventHandler onerror;
|
||||||
|
[UseCounter]
|
||||||
attribute EventHandler onnoupdate;
|
attribute EventHandler onnoupdate;
|
||||||
|
[UseCounter]
|
||||||
attribute EventHandler ondownloading;
|
attribute EventHandler ondownloading;
|
||||||
|
[UseCounter]
|
||||||
attribute EventHandler onprogress;
|
attribute EventHandler onprogress;
|
||||||
|
[UseCounter]
|
||||||
attribute EventHandler onupdateready;
|
attribute EventHandler onupdateready;
|
||||||
|
[UseCounter]
|
||||||
attribute EventHandler oncached;
|
attribute EventHandler oncached;
|
||||||
|
[UseCounter]
|
||||||
attribute EventHandler onobsolete;
|
attribute EventHandler onobsolete;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -25,7 +25,7 @@ interface PushManagerImpl {
|
||||||
[Exposed=(Window,Worker), Func="nsContentUtils::PushEnabled",
|
[Exposed=(Window,Worker), Func="nsContentUtils::PushEnabled",
|
||||||
ChromeConstructor(DOMString scope)]
|
ChromeConstructor(DOMString scope)]
|
||||||
interface PushManager {
|
interface PushManager {
|
||||||
[Throws]
|
[Throws, UseCounter]
|
||||||
Promise<PushSubscription> subscribe(optional PushSubscriptionOptionsInit options);
|
Promise<PushSubscription> subscribe(optional PushSubscriptionOptionsInit options);
|
||||||
[Throws]
|
[Throws]
|
||||||
Promise<PushSubscription?> getSubscription();
|
Promise<PushSubscription?> getSubscription();
|
||||||
|
|
|
||||||
|
|
@ -44,7 +44,7 @@ interface PushSubscription
|
||||||
readonly attribute PushSubscriptionOptions options;
|
readonly attribute PushSubscriptionOptions options;
|
||||||
[Throws]
|
[Throws]
|
||||||
ArrayBuffer? getKey(PushEncryptionKeyName name);
|
ArrayBuffer? getKey(PushEncryptionKeyName name);
|
||||||
[Throws]
|
[Throws, UseCounter]
|
||||||
Promise<boolean> unsubscribe();
|
Promise<boolean> unsubscribe();
|
||||||
|
|
||||||
// Implements the custom serializer specified in Push API, section 9.
|
// Implements the custom serializer specified in Push API, section 9.
|
||||||
|
|
|
||||||
|
|
@ -33,6 +33,7 @@ interface SVGSVGElement : SVGGraphicsElement {
|
||||||
readonly attribute float screenPixelToMillimeterY;
|
readonly attribute float screenPixelToMillimeterY;
|
||||||
readonly attribute boolean useCurrentView;
|
readonly attribute boolean useCurrentView;
|
||||||
// readonly attribute SVGViewSpec currentView;
|
// readonly attribute SVGViewSpec currentView;
|
||||||
|
[UseCounter]
|
||||||
attribute float currentScale;
|
attribute float currentScale;
|
||||||
readonly attribute SVGPoint currentTranslate;
|
readonly attribute SVGPoint currentTranslate;
|
||||||
|
|
||||||
|
|
@ -70,6 +71,7 @@ interface SVGSVGElement : SVGGraphicsElement {
|
||||||
SVGTransform createSVGTransform();
|
SVGTransform createSVGTransform();
|
||||||
[NewObject]
|
[NewObject]
|
||||||
SVGTransform createSVGTransformFromMatrix(SVGMatrix matrix);
|
SVGTransform createSVGTransformFromMatrix(SVGMatrix matrix);
|
||||||
|
[UseCounter]
|
||||||
Element? getElementById(DOMString elementId);
|
Element? getElementById(DOMString elementId);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -368,7 +368,7 @@ Window implements OnErrorEventHandlerForWindow;
|
||||||
#ifdef HAVE_SIDEBAR
|
#ifdef HAVE_SIDEBAR
|
||||||
// Mozilla extension
|
// Mozilla extension
|
||||||
partial interface Window {
|
partial interface Window {
|
||||||
[Replaceable, Throws]
|
[Replaceable, Throws, UseCounter]
|
||||||
readonly attribute (External or WindowProxy) sidebar;
|
readonly attribute (External or WindowProxy) sidebar;
|
||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
|
|
@ -337,5 +337,11 @@ DynamicImage::Unwrap()
|
||||||
return self.forget();
|
return self.forget();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
DynamicImage::PropagateUseCounters(nsIDocument*)
|
||||||
|
{
|
||||||
|
// No use counters.
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace image
|
} // namespace image
|
||||||
} // namespace mozilla
|
} // namespace mozilla
|
||||||
|
|
|
||||||
|
|
@ -291,6 +291,12 @@ ImageWrapper::SetAnimationStartTime(const TimeStamp& aTime)
|
||||||
mInnerImage->SetAnimationStartTime(aTime);
|
mInnerImage->SetAnimationStartTime(aTime);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
ImageWrapper::PropagateUseCounters(nsIDocument* aParentDocument)
|
||||||
|
{
|
||||||
|
mInnerImage->PropagateUseCounters(aParentDocument);
|
||||||
|
}
|
||||||
|
|
||||||
nsIntSize
|
nsIntSize
|
||||||
ImageWrapper::OptimalImageSizeForDest(const gfxSize& aDest,
|
ImageWrapper::OptimalImageSizeForDest(const gfxSize& aDest,
|
||||||
uint32_t aWhichFrame,
|
uint32_t aWhichFrame,
|
||||||
|
|
|
||||||
|
|
@ -1663,6 +1663,12 @@ RasterImage::Unwrap()
|
||||||
return self.forget();
|
return self.forget();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
RasterImage::PropagateUseCounters(nsIDocument*)
|
||||||
|
{
|
||||||
|
// No use counters.
|
||||||
|
}
|
||||||
|
|
||||||
IntSize
|
IntSize
|
||||||
RasterImage::OptimalImageSizeForDest(const gfxSize& aDest, uint32_t aWhichFrame,
|
RasterImage::OptimalImageSizeForDest(const gfxSize& aDest, uint32_t aWhichFrame,
|
||||||
SamplingFilter aSamplingFilter, uint32_t aFlags)
|
SamplingFilter aSamplingFilter, uint32_t aFlags)
|
||||||
|
|
|
||||||
|
|
@ -34,6 +34,7 @@
|
||||||
#include "SVGDocumentWrapper.h"
|
#include "SVGDocumentWrapper.h"
|
||||||
#include "nsIDOMEventListener.h"
|
#include "nsIDOMEventListener.h"
|
||||||
#include "SurfaceCache.h"
|
#include "SurfaceCache.h"
|
||||||
|
#include "nsDocument.h"
|
||||||
|
|
||||||
// undef the GetCurrentTime macro defined in WinBase.h from the MS Platform SDK
|
// undef the GetCurrentTime macro defined in WinBase.h from the MS Platform SDK
|
||||||
#undef GetCurrentTime
|
#undef GetCurrentTime
|
||||||
|
|
@ -1327,6 +1328,15 @@ VectorImage::InvalidateObserversOnNextRefreshDriverTick()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
VectorImage::PropagateUseCounters(nsIDocument* aParentDocument)
|
||||||
|
{
|
||||||
|
nsIDocument* doc = mSVGDocumentWrapper->GetDocument();
|
||||||
|
if (doc) {
|
||||||
|
doc->PropagateUseCounters(aParentDocument);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
nsIntSize
|
nsIntSize
|
||||||
VectorImage::OptimalImageSizeForDest(const gfxSize& aDest,
|
VectorImage::OptimalImageSizeForDest(const gfxSize& aDest,
|
||||||
uint32_t aWhichFrame,
|
uint32_t aWhichFrame,
|
||||||
|
|
|
||||||
|
|
@ -19,6 +19,8 @@
|
||||||
#include "nsSize.h"
|
#include "nsSize.h"
|
||||||
#include "limits.h"
|
#include "limits.h"
|
||||||
|
|
||||||
|
class nsIDocument;
|
||||||
|
|
||||||
namespace mozilla {
|
namespace mozilla {
|
||||||
namespace layers {
|
namespace layers {
|
||||||
class LayerManager;
|
class LayerManager;
|
||||||
|
|
@ -65,6 +67,7 @@ native Orientation(mozilla::image::Orientation);
|
||||||
native TempRefSourceSurface(already_AddRefed<mozilla::gfx::SourceSurface>);
|
native TempRefSourceSurface(already_AddRefed<mozilla::gfx::SourceSurface>);
|
||||||
native TempRefImgIContainer(already_AddRefed<imgIContainer>);
|
native TempRefImgIContainer(already_AddRefed<imgIContainer>);
|
||||||
native nsIntSizeByVal(nsIntSize);
|
native nsIntSizeByVal(nsIntSize);
|
||||||
|
[ptr] native nsIDocument(nsIDocument);
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -74,7 +77,7 @@ native nsIntSizeByVal(nsIntSize);
|
||||||
*
|
*
|
||||||
* Internally, imgIContainer also manages animation of images.
|
* Internally, imgIContainer also manages animation of images.
|
||||||
*/
|
*/
|
||||||
[scriptable, builtinclass, uuid(7ba72242-28da-4c5f-b53f-54da8874775e)]
|
[scriptable, builtinclass, uuid(a8dbee24-ff86-4755-b40e-51175caf31af)]
|
||||||
interface imgIContainer : nsISupports
|
interface imgIContainer : nsISupports
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
|
|
@ -539,4 +542,10 @@ interface imgIContainer : nsISupports
|
||||||
* Removes any ImageWrappers and returns the unwrapped base image.
|
* Removes any ImageWrappers and returns the unwrapped base image.
|
||||||
*/
|
*/
|
||||||
[notxpcom, nostdcall] TempRefImgIContainer unwrap();
|
[notxpcom, nostdcall] TempRefImgIContainer unwrap();
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Propagate the use counters (if any) from this container to the passed in
|
||||||
|
* document.
|
||||||
|
*/
|
||||||
|
[noscript, notxpcom] void propagateUseCounters(in nsIDocument aDocument);
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -775,6 +775,16 @@ nsBulletFrame::Notify(imgIRequest *aRequest, int32_t aType, const nsIntRect* aDa
|
||||||
InvalidateFrame();
|
InvalidateFrame();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (aType == imgINotificationObserver::DECODE_COMPLETE) {
|
||||||
|
if (nsIDocument* parent = GetOurCurrentDoc()) {
|
||||||
|
nsCOMPtr<imgIContainer> container;
|
||||||
|
aRequest->GetImage(getter_AddRefs(container));
|
||||||
|
if (container) {
|
||||||
|
container->PropagateUseCounters(parent);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -15,6 +15,7 @@
|
||||||
#include "FrameLayerBuilder.h"
|
#include "FrameLayerBuilder.h"
|
||||||
#include "nsSVGEffects.h"
|
#include "nsSVGEffects.h"
|
||||||
#include "imgIContainer.h"
|
#include "imgIContainer.h"
|
||||||
|
#include "Image.h"
|
||||||
|
|
||||||
namespace mozilla {
|
namespace mozilla {
|
||||||
namespace css {
|
namespace css {
|
||||||
|
|
@ -394,6 +395,14 @@ ImageLoader::Notify(imgIRequest* aRequest, int32_t aType, const nsIntRect* aData
|
||||||
return OnFrameUpdate(aRequest);
|
return OnFrameUpdate(aRequest);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (aType == imgINotificationObserver::DECODE_COMPLETE) {
|
||||||
|
nsCOMPtr<imgIContainer> image;
|
||||||
|
aRequest->GetImage(getter_AddRefs(image));
|
||||||
|
if (image && mDocument) {
|
||||||
|
image->PropagateUseCounters(mDocument);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -499,5 +508,19 @@ ImageLoader::UnblockOnload(imgIRequest* aRequest)
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
ImageLoader::FlushUseCounters()
|
||||||
|
{
|
||||||
|
for (auto iter = mImages.Iter(); !iter.Done(); iter.Next()) {
|
||||||
|
nsPtrHashKey<Image>* key = iter.Get();
|
||||||
|
ImageLoader::Image* image = key->GetKey();
|
||||||
|
|
||||||
|
imgIRequest* request = image->mRequests.GetWeak(mDocument);
|
||||||
|
|
||||||
|
nsCOMPtr<imgIContainer> container;
|
||||||
|
request->GetImage(getter_AddRefs(container));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace css
|
} // namespace css
|
||||||
} // namespace mozilla
|
} // namespace mozilla
|
||||||
|
|
|
||||||
|
|
@ -70,6 +70,8 @@ public:
|
||||||
|
|
||||||
void DestroyRequest(imgIRequest* aRequest);
|
void DestroyRequest(imgIRequest* aRequest);
|
||||||
|
|
||||||
|
void FlushUseCounters();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
~ImageLoader() {}
|
~ImageLoader() {}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -681,12 +681,14 @@ nsCSSExpandedDataBlock::TransferFromBlock(nsCSSExpandedDataBlock& aFromBlock,
|
||||||
bool aIsImportant,
|
bool aIsImportant,
|
||||||
bool aOverrideImportant,
|
bool aOverrideImportant,
|
||||||
bool aMustCallValueAppended,
|
bool aMustCallValueAppended,
|
||||||
css::Declaration* aDeclaration)
|
css::Declaration* aDeclaration,
|
||||||
|
nsIDocument* aSheetDocument)
|
||||||
{
|
{
|
||||||
if (!nsCSSProps::IsShorthand(aPropID)) {
|
if (!nsCSSProps::IsShorthand(aPropID)) {
|
||||||
return DoTransferFromBlock(aFromBlock, aPropID,
|
return DoTransferFromBlock(aFromBlock, aPropID,
|
||||||
aIsImportant, aOverrideImportant,
|
aIsImportant, aOverrideImportant,
|
||||||
aMustCallValueAppended, aDeclaration);
|
aMustCallValueAppended, aDeclaration,
|
||||||
|
aSheetDocument);
|
||||||
}
|
}
|
||||||
|
|
||||||
// We can pass CSSEnabledState::eIgnore (here, and in ClearProperty
|
// We can pass CSSEnabledState::eIgnore (here, and in ClearProperty
|
||||||
|
|
@ -698,7 +700,8 @@ nsCSSExpandedDataBlock::TransferFromBlock(nsCSSExpandedDataBlock& aFromBlock,
|
||||||
CSSPROPS_FOR_SHORTHAND_SUBPROPERTIES(p, aPropID, aEnabledState) {
|
CSSPROPS_FOR_SHORTHAND_SUBPROPERTIES(p, aPropID, aEnabledState) {
|
||||||
changed |= DoTransferFromBlock(aFromBlock, *p,
|
changed |= DoTransferFromBlock(aFromBlock, *p,
|
||||||
aIsImportant, aOverrideImportant,
|
aIsImportant, aOverrideImportant,
|
||||||
aMustCallValueAppended, aDeclaration);
|
aMustCallValueAppended, aDeclaration,
|
||||||
|
aSheetDocument);
|
||||||
}
|
}
|
||||||
return changed;
|
return changed;
|
||||||
}
|
}
|
||||||
|
|
@ -709,7 +712,8 @@ nsCSSExpandedDataBlock::DoTransferFromBlock(nsCSSExpandedDataBlock& aFromBlock,
|
||||||
bool aIsImportant,
|
bool aIsImportant,
|
||||||
bool aOverrideImportant,
|
bool aOverrideImportant,
|
||||||
bool aMustCallValueAppended,
|
bool aMustCallValueAppended,
|
||||||
css::Declaration* aDeclaration)
|
css::Declaration* aDeclaration,
|
||||||
|
nsIDocument* aSheetDocument)
|
||||||
{
|
{
|
||||||
bool changed = false;
|
bool changed = false;
|
||||||
MOZ_ASSERT(aFromBlock.HasPropertyBit(aPropID), "oops");
|
MOZ_ASSERT(aFromBlock.HasPropertyBit(aPropID), "oops");
|
||||||
|
|
@ -737,6 +741,13 @@ nsCSSExpandedDataBlock::DoTransferFromBlock(nsCSSExpandedDataBlock& aFromBlock,
|
||||||
aDeclaration->ValueAppended(aPropID);
|
aDeclaration->ValueAppended(aPropID);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (aSheetDocument) {
|
||||||
|
UseCounter useCounter = nsCSSProps::UseCounterFor(aPropID);
|
||||||
|
if (useCounter != eUseCounter_UNKNOWN) {
|
||||||
|
aSheetDocument->SetDocumentAndPageUseCounter(useCounter);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
SetPropertyBit(aPropID);
|
SetPropertyBit(aPropID);
|
||||||
aFromBlock.ClearPropertyBit(aPropID);
|
aFromBlock.ClearPropertyBit(aPropID);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -20,6 +20,7 @@
|
||||||
|
|
||||||
struct nsRuleData;
|
struct nsRuleData;
|
||||||
class nsCSSExpandedDataBlock;
|
class nsCSSExpandedDataBlock;
|
||||||
|
class nsIDocument;
|
||||||
|
|
||||||
namespace mozilla {
|
namespace mozilla {
|
||||||
namespace css {
|
namespace css {
|
||||||
|
|
@ -257,6 +258,8 @@ public:
|
||||||
* Returns true if something changed, false otherwise. Calls
|
* Returns true if something changed, false otherwise. Calls
|
||||||
* |ValueAppended| on |aDeclaration| if the property was not
|
* |ValueAppended| on |aDeclaration| if the property was not
|
||||||
* previously set, or in any case if |aMustCallValueAppended| is true.
|
* previously set, or in any case if |aMustCallValueAppended| is true.
|
||||||
|
* Calls |SetDocumentAndPageUseCounter| on |aSheetDocument| if it is
|
||||||
|
* non-null and |aPropID| has a use counter.
|
||||||
*/
|
*/
|
||||||
bool TransferFromBlock(nsCSSExpandedDataBlock& aFromBlock,
|
bool TransferFromBlock(nsCSSExpandedDataBlock& aFromBlock,
|
||||||
nsCSSPropertyID aPropID,
|
nsCSSPropertyID aPropID,
|
||||||
|
|
@ -264,7 +267,8 @@ public:
|
||||||
bool aIsImportant,
|
bool aIsImportant,
|
||||||
bool aOverrideImportant,
|
bool aOverrideImportant,
|
||||||
bool aMustCallValueAppended,
|
bool aMustCallValueAppended,
|
||||||
mozilla::css::Declaration* aDeclaration);
|
mozilla::css::Declaration* aDeclaration,
|
||||||
|
nsIDocument* aSheetDocument);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Copies the values for aPropID into the specified aRuleData object.
|
* Copies the values for aPropID into the specified aRuleData object.
|
||||||
|
|
@ -298,7 +302,8 @@ private:
|
||||||
bool aIsImportant,
|
bool aIsImportant,
|
||||||
bool aOverrideImportant,
|
bool aOverrideImportant,
|
||||||
bool aMustCallValueAppended,
|
bool aMustCallValueAppended,
|
||||||
mozilla::css::Declaration* aDeclaration);
|
mozilla::css::Declaration* aDeclaration,
|
||||||
|
nsIDocument* aSheetDocument);
|
||||||
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
void DoAssertInitialState();
|
void DoAssertInitialState();
|
||||||
|
|
|
||||||
|
|
@ -143,6 +143,8 @@ public:
|
||||||
|
|
||||||
nsresult SetStyleSheet(CSSStyleSheet* aSheet);
|
nsresult SetStyleSheet(CSSStyleSheet* aSheet);
|
||||||
|
|
||||||
|
nsIDocument* GetDocument();
|
||||||
|
|
||||||
nsresult SetQuirkMode(bool aQuirkMode);
|
nsresult SetQuirkMode(bool aQuirkMode);
|
||||||
|
|
||||||
nsresult SetChildLoader(mozilla::css::Loader* aChildLoader);
|
nsresult SetChildLoader(mozilla::css::Loader* aChildLoader);
|
||||||
|
|
@ -1649,6 +1651,15 @@ CSSParserImpl::SetStyleSheet(CSSStyleSheet* aSheet)
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
nsIDocument*
|
||||||
|
CSSParserImpl::GetDocument()
|
||||||
|
{
|
||||||
|
if (!mSheet) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
return mSheet->GetDocument();
|
||||||
|
}
|
||||||
|
|
||||||
nsresult
|
nsresult
|
||||||
CSSParserImpl::SetQuirkMode(bool aQuirkMode)
|
CSSParserImpl::SetQuirkMode(bool aQuirkMode)
|
||||||
{
|
{
|
||||||
|
|
@ -1970,7 +1981,8 @@ CSSParserImpl::ParseTransformProperty(const nsAString& aPropValue,
|
||||||
declaration->ExpandTo(&mData);
|
declaration->ExpandTo(&mData);
|
||||||
changed = mData.TransferFromBlock(mTempData, eCSSProperty_transform,
|
changed = mData.TransferFromBlock(mTempData, eCSSProperty_transform,
|
||||||
EnabledState(), false,
|
EnabledState(), false,
|
||||||
true, false, declaration);
|
true, false, declaration,
|
||||||
|
GetDocument());
|
||||||
declaration->CompressFrom(&mData);
|
declaration->CompressFrom(&mData);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -2051,7 +2063,8 @@ CSSParserImpl::ParseProperty(const nsCSSPropertyID aPropID,
|
||||||
aDeclaration->ExpandTo(&mData);
|
aDeclaration->ExpandTo(&mData);
|
||||||
*aChanged = mData.TransferFromBlock(mTempData, aPropID,
|
*aChanged = mData.TransferFromBlock(mTempData, aPropID,
|
||||||
EnabledState(), aIsImportant,
|
EnabledState(), aIsImportant,
|
||||||
true, false, aDeclaration);
|
true, false, aDeclaration,
|
||||||
|
GetDocument());
|
||||||
aDeclaration->CompressFrom(&mData);
|
aDeclaration->CompressFrom(&mData);
|
||||||
}
|
}
|
||||||
CLEAR_ERROR();
|
CLEAR_ERROR();
|
||||||
|
|
@ -7519,7 +7532,7 @@ CSSParserImpl::ParseDeclaration(css::Declaration* aDeclaration,
|
||||||
*aChanged |= mData.TransferFromBlock(mTempData, propID, EnabledState(),
|
*aChanged |= mData.TransferFromBlock(mTempData, propID, EnabledState(),
|
||||||
status == ePriority_Important,
|
status == ePriority_Important,
|
||||||
false, aMustCallValueAppended,
|
false, aMustCallValueAppended,
|
||||||
aDeclaration);
|
aDeclaration, GetDocument());
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
|
|
||||||
|
|
@ -3423,6 +3423,21 @@ nsCSSProps::gPropertyEnabled[eCSSProperty_COUNT_with_aliases] = {
|
||||||
#undef IS_ENABLED_BY_DEFAULT
|
#undef IS_ENABLED_BY_DEFAULT
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#include "../../dom/base/PropertyUseCounterMap.inc"
|
||||||
|
|
||||||
|
/* static */ const UseCounter
|
||||||
|
nsCSSProps::gPropertyUseCounter[eCSSProperty_COUNT_no_shorthands] = {
|
||||||
|
#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_) \
|
||||||
|
static_cast<UseCounter>(USE_COUNTER_FOR_CSS_PROPERTY_##method_),
|
||||||
|
#include "nsCSSPropList.h"
|
||||||
|
#undef CSS_PROP
|
||||||
|
#undef CSS_PROP_LIST_INCLUDE_LOGICAL
|
||||||
|
#undef CSS_PROP_PUBLIC_OR_PRIVATE
|
||||||
|
};
|
||||||
|
|
||||||
// Check that all logical property flags are used appropriately.
|
// Check that all logical property flags are used appropriately.
|
||||||
#define CSS_PROP(name_, id_, method_, flags_, pref_, parsevariant_, \
|
#define CSS_PROP(name_, id_, method_, flags_, pref_, parsevariant_, \
|
||||||
kwtable_, stylestruct_, stylestructoffset_, animtype_) \
|
kwtable_, stylestruct_, stylestructoffset_, animtype_) \
|
||||||
|
|
|
||||||
|
|
@ -19,6 +19,7 @@
|
||||||
#include "nsStyleStructFwd.h"
|
#include "nsStyleStructFwd.h"
|
||||||
#include "nsCSSKeywords.h"
|
#include "nsCSSKeywords.h"
|
||||||
#include "mozilla/CSSEnabledState.h"
|
#include "mozilla/CSSEnabledState.h"
|
||||||
|
#include "mozilla/UseCounter.h"
|
||||||
#include "mozilla/EnumTypeTraits.h"
|
#include "mozilla/EnumTypeTraits.h"
|
||||||
|
|
||||||
// Length of the "--" prefix on custom names (such as custom property names,
|
// Length of the "--" prefix on custom names (such as custom property names,
|
||||||
|
|
@ -639,8 +640,19 @@ public:
|
||||||
return gPropertyEnabled[aProperty];
|
return gPropertyEnabled[aProperty];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// A table for the use counter associated with each CSS property. If a
|
||||||
|
// property does not have a use counter defined in UseCounters.conf, then
|
||||||
|
// its associated entry is |eUseCounter_UNKNOWN|.
|
||||||
|
static const mozilla::UseCounter gPropertyUseCounter[eCSSProperty_COUNT_no_shorthands];
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
|
static mozilla::UseCounter UseCounterFor(nsCSSPropertyID aProperty) {
|
||||||
|
MOZ_ASSERT(0 <= aProperty && aProperty < eCSSProperty_COUNT_no_shorthands,
|
||||||
|
"out of range");
|
||||||
|
return gPropertyUseCounter[aProperty];
|
||||||
|
}
|
||||||
|
|
||||||
static bool IsEnabled(nsCSSPropertyID aProperty, EnabledState aEnabled)
|
static bool IsEnabled(nsCSSPropertyID aProperty, EnabledState aEnabled)
|
||||||
{
|
{
|
||||||
if (IsEnabled(aProperty)) {
|
if (IsEnabled(aProperty)) {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue