Browse Source

Issue #21 - Remove use counters telemetry

This reverts Bug 968923 - Implement some equivalent of Chrome's use counters (on top of telemetry?)

For reference: https://bugzilla.mozilla.org/show_bug.cgi?id=968923
pull/28/head
FranklinDM 4 months ago committed by roytam1
parent
commit
8a7587b401
  1. 36
      dom/base/UseCounter.h
  2. 63
      dom/base/UseCounters.conf
  3. 80
      dom/base/gen-usecounters.py
  4. 15
      dom/base/moz.build
  5. 24
      dom/base/nsDOMWindowUtils.cpp
  6. 77
      dom/base/nsDocument.cpp
  7. 46
      dom/base/nsIDocument.h
  8. 6
      dom/base/nsImageLoadingContent.cpp
  9. 8
      dom/base/test/browser.ini
  10. 238
      dom/base/test/browser_use_counters.js
  11. 17
      dom/base/test/file_use_counter_outer.html
  12. 17
      dom/base/test/file_use_counter_svg_currentScale.svg
  13. 15
      dom/base/test/file_use_counter_svg_fill_pattern.svg
  14. 15
      dom/base/test/file_use_counter_svg_fill_pattern_data.svg
  15. 14
      dom/base/test/file_use_counter_svg_fill_pattern_definition.svg
  16. 23
      dom/base/test/file_use_counter_svg_fill_pattern_internal.svg
  17. 22
      dom/base/test/file_use_counter_svg_getElementById.svg
  18. 71
      dom/base/usecounters.py
  19. 12
      dom/bindings/BindingUtils.cpp
  20. 6
      dom/bindings/BindingUtils.h
  21. 37
      dom/bindings/Codegen.py
  22. 10
      dom/bindings/parser/WebIDL.py
  23. 12
      dom/html/HTMLImageElement.cpp
  24. 6
      dom/html/HTMLImageElement.h
  25. 13
      dom/interfaces/base/nsIDOMWindowUtils.idl
  26. 20
      dom/svg/nsSVGElement.cpp
  27. 2
      dom/webidl/External.webidl
  28. 14
      dom/webidl/OfflineResourceList.webidl
  29. 2
      dom/webidl/PushManager.webidl
  30. 2
      dom/webidl/PushSubscription.webidl
  31. 2
      dom/webidl/SVGSVGElement.webidl
  32. 2
      dom/webidl/Window.webidl
  33. 6
      image/DynamicImage.cpp
  34. 6
      image/ImageWrapper.cpp
  35. 6
      image/RasterImage.cpp
  36. 10
      image/VectorImage.cpp
  37. 11
      image/imgIContainer.idl
  38. 10
      layout/generic/nsBulletFrame.cpp
  39. 23
      layout/style/ImageLoader.cpp
  40. 2
      layout/style/ImageLoader.h
  41. 19
      layout/style/nsCSSDataBlock.cpp
  42. 9
      layout/style/nsCSSDataBlock.h
  43. 19
      layout/style/nsCSSParser.cpp
  44. 15
      layout/style/nsCSSProps.cpp
  45. 12
      layout/style/nsCSSProps.h

36
dom/base/UseCounter.h

@ -1,36 +0,0 @@
/* -*- 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

@ -1,63 +0,0 @@
// 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

@ -1,80 +0,0 @@
#!/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)

15
dom/base/moz.build

@ -141,11 +141,9 @@ EXPORTS.mozilla += [
'FeedWriterEnabled.h',
'TextInputProcessor.h',
'TimerClamping.h',
'UseCounter.h',
]
EXPORTS.mozilla.dom += [
'!UseCounterList.h',
'AnonymousContent.h',
'Attr.h',
'BarProps.h',
@ -471,18 +469,5 @@ if CONFIG['MOZ_PHOENIX'] or CONFIG['MOZ_XULRUNNER']:
if CONFIG['MOZ_X11']:
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']:
CXXFLAGS += ['-Wno-error=shadow']

24
dom/base/nsDOMWindowUtils.cpp

@ -104,9 +104,6 @@
#include "nsContentPermissionHelper.h"
#include "nsCSSPseudoElements.h" // for CSSPseudoElementType
#include "nsNetUtil.h"
#include "nsDocument.h"
#include "HTMLImageElement.h"
#include "mozilla/css/ImageLoader.h"
#include "mozilla/layers/APZCTreeManager.h" // for layers::ZoomToRectBehavior
#include "mozilla/dom/Promise.h"
#include "mozilla/StyleSheetInlines.h"
@ -4025,27 +4022,6 @@ nsDOMWindowUtils::LeaveChaosMode()
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
nsDOMWindowUtils::HasRuleProcessorUsedByMultipleStyleSets(uint32_t aSheetType,
bool* aRetVal)

77
dom/base/nsDocument.cpp

@ -9718,19 +9718,6 @@ 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
{
@ -9746,7 +9733,6 @@ 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,
@ -11997,69 +11983,6 @@ nsIDocument::GetTopLevelContentDocument()
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
nsIDocument::HasScriptsBlockedBySandbox()
{

46
dom/base/nsIDocument.h

@ -24,7 +24,6 @@
#include "nsTHashtable.h" // for member
#include "mozilla/net/ReferrerPolicy.h" // for member
#include "nsWeakReference.h"
#include "mozilla/UseCounter.h"
#include "mozilla/WeakPtr.h"
#include "Units.h"
#include "nsContentListDeclarations.h"
@ -2782,23 +2781,6 @@ 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);
void SetUserHasInteracted(bool aUserHasInteracted)
{
mUserHasInteracted = aUserHasInteracted;
@ -2857,24 +2839,6 @@ public:
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:
mutable std::bitset<eDeprecatedOperationCount> mDeprecationWarnedAbout;
mutable std::bitset<eDocumentWarningCount> mDocWarningWarnedAbout;
@ -3315,15 +3279,7 @@ 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;
// Whether the user has interacted with the document or not:
// Whether the user has interacted with the document or not:
bool mUserHasInteracted;
mozilla::TimeStamp mPageUnloadingEventTimeStamp;

6
dom/base/nsImageLoadingContent.cpp

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

8
dom/base/test/browser.ini

@ -4,13 +4,6 @@ support-files =
file_bug1011748_redirect.sjs
file_bug1011748_OK.sjs
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_bug902350.js]
@ -24,5 +17,4 @@ tags = mcb
skip-if = e10s # this tests non-e10s behavior. it's not expected to work in e10s.
[browser_state_notifications.js]
skip-if = true # Bug 1271028
[browser_use_counters.js]
[browser_bug1307747.js]

238
dom/base/test/browser_use_counters.js

@ -1,238 +0,0 @@
/* -*- 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/";
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");
});
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) {
}
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();
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.
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();
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();
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

@ -1,17 +0,0 @@
<!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

@ -1,17 +0,0 @@
<?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>

Before

Width:  |  Height:  |  Size: 635 B

15
dom/base/test/file_use_counter_svg_fill_pattern.svg

@ -1,15 +0,0 @@
<?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>

Before

Width:  |  Height:  |  Size: 763 B

15
dom/base/test/file_use_counter_svg_fill_pattern_data.svg

@ -1,15 +0,0 @@
<?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>

Before

Width:  |  Height:  |  Size: 1.5 KiB

14
dom/base/test/file_use_counter_svg_fill_pattern_definition.svg

@ -1,14 +0,0 @@
<?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>

Before

Width:  |  Height:  |  Size: 591 B

23
dom/base/test/file_use_counter_svg_fill_pattern_internal.svg

@ -1,23 +0,0 @@
<?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>

Before

Width:  |  Height:  |  Size: 944 B

22
dom/base/test/file_use_counter_svg_getElementById.svg

@ -1,22 +0,0 @@
<?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>

Before

Width:  |  Height:  |  Size: 836 B

71
dom/base/usecounters.py

@ -1,71 +0,0 @@
# 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

12
dom/bindings/BindingUtils.cpp

@ -14,7 +14,6 @@
#include "mozilla/Preferences.h"
#include "mozilla/SizePrintfMacros.h"
#include "mozilla/Unused.h"
#include "mozilla/UseCounter.h"
#include "mozilla/dom/DocGroup.h"
#include "AccessCheck.h"
@ -59,7 +58,6 @@
#include "mozilla/jsipc/CrossProcessObjectWrappers.h"
#include "nsDOMClassInfo.h"
#include "ipc/ErrorIPCUtils.h"
#include "mozilla/UseCounter.h"
namespace mozilla {
namespace dom {
@ -3592,16 +3590,6 @@ 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 {
// This runnable is used to write a deprecation message from a worker to the

6
dom/bindings/BindingUtils.h

@ -46,8 +46,6 @@ class nsIJSID;
namespace mozilla {
enum UseCounter : int16_t;
namespace dom {
class CustomElementReactionsStack;
template<typename KeyType, typename ValueType> class Record;
@ -3428,10 +3426,6 @@ already_AddRefed<nsGenericHTMLElement>
CreateHTMLElement(const GlobalObject& aGlobal, const JS::CallArgs& aCallArgs,
JS::Handle<JSObject*> aGivenProto, ErrorResult& aRv);
void
SetDocumentAndPageUseCounter(JSContext* aCx, JSObject* aObject,
UseCounter aUseCounter);
// Warnings
void
DeprecationWarning(JSContext* aCx, JSObject* aObject,

37
dom/bindings/Codegen.py

@ -7467,8 +7467,8 @@ class CGPerSignatureCall(CGThing):
def __init__(self, returnType, arguments, nativeMethodName, static,
descriptor, idlNode, argConversionStartsAt=0, getter=False,
setter=False, isConstructor=False, useCounterName=None,
resultVar=None, objectName="obj"):
setter=False, isConstructor=False, resultVar=None,
objectName="obj"):
assert idlNode.isMethod() == (not getter and not setter)
assert idlNode.isAttr() == (getter or setter)
# Constructors are always static
@ -7701,11 +7701,6 @@ class CGPerSignatureCall(CGThing):
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):
@ -7934,11 +7929,6 @@ 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
if method.isStatic():
nativeType = descriptor.nativeType
staticTypeOverride = PropertyDefiner.getStringAttr(method, "StaticClassOverride")
@ -7960,8 +7950,7 @@ class CGMethodCall(CGThing):
nativeMethodName, static, descriptor,
method,
argConversionStartsAt=argConversionStartsAt,
isConstructor=isConstructor,
useCounterName=useCounterName)
isConstructor=isConstructor)
signatures = method.signatures()
if len(signatures) == 1:
@ -8337,16 +8326,11 @@ 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
if attr.isStatic():
nativeMethodName = "%s::%s" % (descriptor.nativeType, nativeMethodName)
CGPerSignatureCall.__init__(self, returnType, [], nativeMethodName,
attr.isStatic(), descriptor, attr,
getter=True, useCounterName=useCounterName)
getter=True)
class CGNavigatorGetterCall(CGPerSignatureCall):
@ -8413,17 +8397,12 @@ 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
if attr.isStatic():
nativeMethodName = "%s::%s" % (descriptor.nativeType, nativeMethodName)
CGPerSignatureCall.__init__(self, None,
[FakeArgument(argType, attr, allowTreatNonCallableAsNull=True)],
nativeMethodName, attr.isStatic(),
descriptor, attr, setter=True, useCounterName=useCounterName)
descriptor, attr, setter=True)
def wrap_return_value(self):
attr = self.idlNode
@ -13932,12 +13911,6 @@ class CGBindingRoot(CGThing):
bindingHeaders[CGHeaders.getDeclarationFilename(enums[0])] = 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(
CGDictionary.dictionarySafeToJSONify(d) for d in dictionaries)
bindingHeaders["XrayWrapper.h"] = any(

10
dom/bindings/parser/WebIDL.py

@ -4245,11 +4245,6 @@ 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 == "Unscopable":
if not attr.noArguments():
raise WebIDLError("[Unscopable] must take no arguments",
@ -4979,11 +4974,6 @@ 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 == "Unscopable":
if not attr.noArguments():
raise WebIDLError("[Unscopable] must take no arguments",

12
dom/html/HTMLImageElement.cpp

@ -10,7 +10,6 @@
#include "nsPresContext.h"
#include "nsMappedAttributes.h"
#include "nsSize.h"
#include "nsDocument.h"
#include "nsIDocument.h"
#include "nsIDOMMutationEvent.h"
#include "nsIScriptContext.h"
@ -27,7 +26,6 @@
#include "mozilla/dom/HTMLFormElement.h"
#include "nsAttrValueOrString.h"
#include "imgLoader.h"
#include "Image.h"
// Responsive images!
#include "mozilla/dom/HTMLSourceElement.h"
@ -1362,16 +1360,6 @@ HTMLImageElement::MediaFeatureValuesChanged()
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 mozilla

6
dom/html/HTMLImageElement.h

@ -261,12 +261,6 @@ 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();

13
dom/interfaces/base/nsIDOMWindowUtils.idl

@ -49,7 +49,7 @@ interface nsIJSRAIIHelper;
interface nsIContentPermissionRequest;
interface nsIObserver;
[scriptable, uuid(c471d440-004b-4c50-a6f2-747db5f443b6)]
[scriptable, uuid(7fcc7958-77d9-45ff-8c81-277bde5f0dc8)]
interface nsIDOMWindowUtils : nsISupports {
/**
@ -1938,17 +1938,6 @@ interface nsIDOMWindowUtils : nsISupports {
*/
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);
/**

20
dom/svg/nsSVGElement.cpp

@ -1208,27 +1208,9 @@ MappedAttrParser::ParseMappedAttrValue(nsIAtom* aMappedAttrName,
nsCSSProps::LookupProperty(nsDependentAtomString(aMappedAttrName),
CSSEnabledState::eForAllContent);
if (propertyID != eCSSProperty_UNKNOWN) {
bool changed = false; // outparam for ParseProperty.
bool changed; // outparam for ParseProperty. (ignored)
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,
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;
}
MOZ_ASSERT(aMappedAttrName == nsGkAtoms::lang,

2
dom/webidl/External.webidl

@ -13,7 +13,7 @@ interface External
// Mozilla extension
partial interface External {
[UnsafeInPrerendering, UseCounter]
[UnsafeInPrerendering]
void addSearchEngine(DOMString engineURL, DOMString iconURL,
DOMString suggestedTitle, DOMString suggestedCategory);
};

14
dom/webidl/OfflineResourceList.webidl

@ -25,38 +25,30 @@ interface OfflineResourceList : EventTarget {
/* The application cache group is now obsolete. */
const unsigned short OBSOLETE = 5;
[Throws, UseCounter]
[Throws]
readonly attribute unsigned short status;
/**
* Begin the application update process on the associated application cache.
*/
[Throws, UseCounter]
[Throws]
void update();
/**
* Swap in the newest version of the application cache, or disassociate
* from the cache if the cache group is obsolete.
*/
[Throws, UseCounter]
[Throws]
void swapCache();
/* Events */
[UseCounter]
attribute EventHandler onchecking;
[UseCounter]
attribute EventHandler onerror;
[UseCounter]
attribute EventHandler onnoupdate;
[UseCounter]
attribute EventHandler ondownloading;
[UseCounter]
attribute EventHandler onprogress;
[UseCounter]
attribute EventHandler onupdateready;
[UseCounter]
attribute EventHandler oncached;
[UseCounter]
attribute EventHandler onobsolete;
};

2
dom/webidl/PushManager.webidl

@ -25,7 +25,7 @@ interface PushManagerImpl {
[Exposed=(Window,Worker), Func="nsContentUtils::PushEnabled",