Merge mozilla-central to b2g-inbound

This commit is contained in:
Carsten "Tomcat" Book 2014-06-17 14:40:36 +02:00
Родитель 47286f9f0b 1526ee8c2b
Коммит 61dfe39e65
339 изменённых файлов: 7105 добавлений и 15949 удалений

Просмотреть файл

@ -38,6 +38,7 @@
#include "nsTableOuterFrame.h"
using namespace mozilla;
using namespace mozilla::dom;
using namespace mozilla::a11y;
////////////////////////////////////////////////////////////////////////////////
@ -869,15 +870,10 @@ HTMLTableAccessible::Description(nsString& aDescription)
bool
HTMLTableAccessible::HasDescendant(const nsAString& aTagName, bool aAllowEmpty)
{
nsCOMPtr<nsIDOMElement> tableElt(do_QueryInterface(mContent));
NS_ENSURE_TRUE(tableElt, false);
nsCOMPtr<nsIHTMLCollection> elements =
mContent->AsElement()->GetElementsByTagName(aTagName);
nsCOMPtr<nsIDOMHTMLCollection> nodeList;
tableElt->GetElementsByTagName(aTagName, getter_AddRefs(nodeList));
NS_ENSURE_TRUE(nodeList, false);
nsCOMPtr<nsIDOMNode> foundItem;
nodeList->Item(0, getter_AddRefs(foundItem));
Element* foundItem = elements->Item(0);
if (!foundItem)
return false;
@ -886,11 +882,10 @@ HTMLTableAccessible::HasDescendant(const nsAString& aTagName, bool aAllowEmpty)
// Make sure that the item we found has contents and either has multiple
// children or the found item is not a whitespace-only text node.
nsCOMPtr<nsIContent> foundItemContent = do_QueryInterface(foundItem);
if (foundItemContent->GetChildCount() > 1)
if (foundItem->GetChildCount() > 1)
return true; // Treat multiple child nodes as non-empty
nsIContent *innerItemContent = foundItemContent->GetFirstChild();
nsIContent *innerItemContent = foundItem->GetFirstChild();
if (innerItemContent && !innerItemContent->TextIsOnlyWhitespace())
return true;
@ -901,8 +896,7 @@ HTMLTableAccessible::HasDescendant(const nsAString& aTagName, bool aAllowEmpty)
// caption element only. On another hand we create accessible object for
// the first entry of caption element (see
// HTMLTableAccessible::CacheChildren).
nodeList->Item(1, getter_AddRefs(foundItem));
return !!foundItem;
return !!elements->Item(1);
}
bool

Просмотреть файл

@ -15,6 +15,7 @@ const { loadReason } = require('../self');
const { rootURI, metadata } = require("@loader/options");
const globals = require('../system/globals');
const xulApp = require('../system/xul-app');
const { id } = require('sdk/self');
const appShellService = Cc['@mozilla.org/appshell/appShellService;1'].
getService(Ci.nsIAppShellService);
const { preferences } = metadata;
@ -134,7 +135,7 @@ function run(options) {
// native-options does stuff directly with preferences key from package.json
if (preferences && preferences.length > 0) {
try {
require('../preferences/native-options').enable(preferences);
require('../preferences/native-options').enable({ preferences: preferences, id: id });
}
catch (error) {
console.exception(error);

Просмотреть файл

@ -12,29 +12,41 @@ const { on } = require('../system/events');
const { id, preferencesBranch } = require('../self');
const { localizeInlineOptions } = require('../l10n/prefs');
const { AddonManager } = Cu.import("resource://gre/modules/AddonManager.jsm");
const { defer } = require("sdk/core/promise");
const DEFAULT_OPTIONS_URL = 'data:text/xml,<placeholder/>';
const VALID_PREF_TYPES = ['bool', 'boolint', 'integer', 'string', 'color',
const VALID_PREF_TYPES = ['bool', 'boolint', 'integer', 'string', 'color',
'file', 'directory', 'control', 'menulist', 'radio'];
function enable(preferences) {
function enable({ preferences, id }) {
let enabled = defer();
validate(preferences);
setDefaults(preferences, preferencesBranch);
// allow the use of custom options.xul
AddonManager.getAddonByID(id, (addon) => {
if (addon.optionsURL === DEFAULT_OPTIONS_URL)
on('addon-options-displayed', onAddonOptionsDisplayed, true);
})
on('addon-options-displayed', onAddonOptionsDisplayed, true);
enabled.resolve({ id: id });
});
function onAddonOptionsDisplayed({ subject: doc, data }) {
if (data === id) {
let parent = doc.getElementById('detail-downloads').parentNode;
injectOptions(preferences, preferencesBranch, doc, parent);
injectOptions({
preferences: preferences,
preferencesBranch: preferencesBranch,
document: doc,
parent: parent,
id: id
});
localizeInlineOptions(doc);
}
}
return enabled.promise;
}
exports.enable = enable;
@ -75,18 +87,18 @@ function setDefaults(preferences, preferencesBranch) {
const branch = Cc['@mozilla.org/preferences-service;1'].
getService(Ci.nsIPrefService).
getDefaultBranch('extensions.' + preferencesBranch + '.');
for (let {name, value} of preferences) {
for (let { name, value } of preferences) {
switch (typeof value) {
case 'boolean':
branch.setBoolPref(name, value);
break;
case 'number':
case 'number':
// must be integer, ignore otherwise
if (value % 1 === 0)
if (value % 1 === 0) {
branch.setIntPref(name, value);
}
break;
case 'string':
// ∵
let str = Cc["@mozilla.org/supports-string;1"].
createInstance(Ci.nsISupportsString);
str.data = value;
@ -98,11 +110,12 @@ function setDefaults(preferences, preferencesBranch) {
exports.setDefaults = setDefaults;
// dynamically injects inline options into about:addons page at runtime
function injectOptions(preferences, preferencesBranch, document, parent) {
function injectOptions({ preferences, preferencesBranch, document, parent, id }) {
for (let { name, type, hidden, title, description, label, options, on, off } of preferences) {
if (hidden)
if (hidden) {
continue;
}
let setting = document.createElement('setting');
setting.setAttribute('pref-name', name);
@ -114,7 +127,7 @@ function injectOptions(preferences, preferencesBranch, document, parent) {
if (type === 'file' || type === 'directory') {
setting.setAttribute('fullpath', 'true');
}
}
else if (type === 'control') {
let button = document.createElement('button');
button.setAttribute('pref-name', name);
@ -123,11 +136,11 @@ function injectOptions(preferences, preferencesBranch, document, parent) {
button.setAttribute('oncommand', "Services.obs.notifyObservers(null, '" +
id + "-cmdPressed', '" + name + "');");
setting.appendChild(button);
}
}
else if (type === 'boolint') {
setting.setAttribute('on', on);
setting.setAttribute('off', off);
}
}
else if (type === 'menulist') {
let menulist = document.createElement('menulist');
let menupopup = document.createElement('menupopup');
@ -139,7 +152,7 @@ function injectOptions(preferences, preferencesBranch, document, parent) {
}
menulist.appendChild(menupopup);
setting.appendChild(menulist);
}
}
else if (type === 'radio') {
let radiogroup = document.createElement('radiogroup');
for (let { value, label } of options) {

Просмотреть файл

@ -1,7 +1,6 @@
/* 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/. */
"use strict";
module.metadata = {

Просмотреть файл

@ -0,0 +1,50 @@
/* 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/. */
"use strict";
module.metadata = {
"stability": "unstable"
};
const { openTab, getBrowserForTab, getTabId } = require("sdk/tabs/utils");
const { defer, all } = require("sdk/core/promise");
const { on, off } = require("sdk/system/events");
const { setTimeout } = require("sdk/timers");
const { getMostRecentBrowserWindow } = require('../window/utils');
const open = function open({ id }) {
let showing = defer();
let loaded = defer();
let result = { id: id };
let tab = openTab(getMostRecentBrowserWindow(), "about:addons", {
inBackground: true
});
let browser = getBrowserForTab(tab);
browser.addEventListener("load", function onPageLoad() {
browser.removeEventListener("load", onPageLoad, true);
let window = browser.contentWindow;
// wait for the add-on's "addon-options-displayed"
on("addon-options-displayed", function onPrefDisplayed({ subject: doc, data }) {
if (data === id) {
off("addon-options-displayed", onPrefDisplayed);
result.tabId = getTabId(tab);
result.document = doc;
loaded.resolve();
}
}, true);
// display the add-on inline preferences page
window.gViewController.commands.cmd_showItemDetails.doCommand({ id: id }, true);
let { node } = window.gViewController.viewObjects.detail;
node.addEventListener("ViewChanged", function whenViewChanges() {
node.removeEventListener("ViewChanged", whenViewChanges, false);
showing.resolve();
}, false);
}, true);
return all([ showing.promise, loaded.promise ]).then(_ => result);
}
exports.open = open;

Просмотреть файл

@ -266,7 +266,7 @@ parser_groups = (
help="enable remote windows",
action="store_true",
default=False,
cmds=['test', 'run', 'testex', 'testpkgs',
cmds=['test', 'run', 'testex', 'testpkgs',
'testaddons', 'testcfx', 'testall'])),
(("", "--logfile",), dict(dest="logfile",
help="log console output to file",
@ -421,13 +421,14 @@ def test_all_testaddons(env_root, defaults):
addons.sort()
fail = False
for dirname in addons:
# apply the filter
if (not defaults['filter'].split(":")[0] in dirname):
continue
print >>sys.stderr, "Testing %s..." % dirname
sys.stderr.flush()
try:
run(arguments=["run",
run(arguments=["testrun",
"--pkgdir",
os.path.join(addons_dir, dirname)],
defaults=defaults,
@ -619,7 +620,7 @@ def run(arguments=sys.argv[1:], target_cfg=None, pkg_cfg=None,
return
test_cfx(env_root, options.verbose)
return
elif command not in ["xpi", "test", "run"]:
elif command not in ["xpi", "test", "run", "testrun"]:
print >>sys.stderr, "Unknown command: %s" % command
print >>sys.stderr, "Try using '--help' for assistance."
sys.exit(1)
@ -663,6 +664,9 @@ def run(arguments=sys.argv[1:], target_cfg=None, pkg_cfg=None,
enforce_timeouts = True
elif command == "run":
use_main = True
elif command == "testrun":
use_main = True
enforce_timeouts = True
else:
assert 0, "shouldn't get here"
@ -681,7 +685,7 @@ def run(arguments=sys.argv[1:], target_cfg=None, pkg_cfg=None,
# TODO: Consider keeping a cache of dynamic UUIDs, based
# on absolute filesystem pathname, in the root directory
# or something.
if command in ('xpi', 'run'):
if command in ('xpi', 'run', 'testrun'):
from cuddlefish.preflight import preflight_config
if target_cfg_json:
config_was_ok, modified = preflight_config(target_cfg,

Просмотреть файл

@ -37,10 +37,12 @@ import re
import os.path
def get_expanded_variables(versionfile_source):
# the code embedded in _version.py can just fetch the value of these
# variables. When used from setup.py, we don't want to import
# _version.py, so we do it with a regexp instead. This function is not
# used from _version.py.
"""
the code embedded in _version.py can just fetch the value of these
variables. When used from setup.py, we don't want to import
_version.py, so we do it with a regexp instead. This function is not
used from _version.py.
"""
variables = {}
try:
for line in open(versionfile_source,"r").readlines():
@ -81,15 +83,16 @@ def versions_from_expanded_variables(variables, tag_prefix):
"full": variables["full"].strip() }
def versions_from_vcs(tag_prefix, versionfile_source, verbose=False):
# this runs 'git' from the root of the source tree. That either means
# someone ran a setup.py command (and this code is in versioneer.py, thus
# the containing directory is the root of the source tree), or someone
# ran a project-specific entry point (and this code is in _version.py,
# thus the containing directory is somewhere deeper in the source tree).
# This only gets called if the git-archive 'subst' variables were *not*
# expanded, and _version.py hasn't already been rewritten with a short
# version string, meaning we're inside a checked out source tree.
"""
this runs 'git' from the root of the source tree. That either means
someone ran a setup.py command (and this code is in versioneer.py, thus
the containing directory is the root of the source tree), or someone
ran a project-specific entry point (and this code is in _version.py,
thus the containing directory is somewhere deeper in the source tree).
This only gets called if the git-archive 'subst' variables were *not*
expanded, and _version.py hasn't already been rewritten with a short
version string, meaning we're inside a checked out source tree.
"""
try:
here = os.path.abspath(__file__)
except NameError:

Просмотреть файл

@ -120,7 +120,9 @@ def hash_file(fn):
return hashlib.sha256(open(fn,"rb").read()).hexdigest()
def get_datafiles(datadir):
# yields pathnames relative to DATADIR, ignoring some files
"""
yields pathnames relative to DATADIR, ignoring some files
"""
for dirpath, dirnames, filenames in os.walk(datadir):
filenames = list(filter_filenames(filenames))
# this tells os.walk to prune the search
@ -193,8 +195,9 @@ class ManifestBuilder:
self.test_modules = [] # for runtime
def build(self, scan_tests, test_filter_re):
# process the top module, which recurses to process everything it
# reaches
"""
process the top module, which recurses to process everything it reaches
"""
if "main" in self.target_cfg:
top_mi = self.find_top(self.target_cfg)
top_me = self.process_module(top_mi)
@ -261,9 +264,11 @@ class ManifestBuilder:
return sorted(used)
def get_used_files(self, bundle_sdk_modules):
# returns all .js files that we reference, plus data/ files. You will
# need to add the loader, off-manifest files that it needs, and
# generated metadata.
"""
returns all .js files that we reference, plus data/ files. You will
need to add the loader, off-manifest files that it needs, and
generated metadata.
"""
for datamap in self.datamaps.values():
for (zipname, absname) in datamap.files_to_copy:
yield absname

Просмотреть файл

@ -715,7 +715,7 @@ def run_app(harness_root_dir, manifest_rdf, harness_options,
done = False
result = None
test_name = "unknown"
test_name = "Jetpack startup"
def Timeout(message, test_name, parseable):
if parseable:

Просмотреть файл

@ -25,10 +25,13 @@ UNICODE_ORG_XML_URL = "http://unicode.org/repos/cldr/trunk/common/supplemental/p
CONDITION_RE = r'n( mod \d+)? (is|in|within|(not in))( not)? ([^\s]+)'
# For a given regexp.MatchObject `g` for `CONDITION_RE`,
# returns the equivalent JS piece of code
# i.e. maps pseudo conditional language from unicode.org XML to JS code
def parseCondition(g):
"""
For a given regexp.MatchObject `g` for `CONDITION_RE`,
returns the equivalent JS piece of code
i.e. maps pseudo conditional language from unicode.org XML to JS code
"""
lvalue = "n"
if g.group(1):
lvalue = "(n %% %d)" % int(g.group(1).replace("mod ", ""))
@ -81,7 +84,9 @@ def parseCondition(g):
return "%s(%s)" % (notPrefix, " || ".join(subCondition))
def computeRules():
# Fetch plural rules data directly from unicode.org website:
"""
Fetch plural rules data directly from unicode.org website:
"""
url = UNICODE_ORG_XML_URL
f = urllib2.urlopen(url)
doc = xml.dom.minidom.parse(f)

Просмотреть файл

@ -28,9 +28,10 @@ INFINITY = float('1e66666')
FLOAT_REPR = repr
def floatstr(o, allow_nan=True):
# Check for specials. Note that this type of test is processor- and/or
# platform-specific, so do tests which don't depend on the internals.
"""
Check for specials. Note that this type of test is processor- and/or
platform-specific, so do tests which don't depend on the internals.
"""
if o != o:
text = 'NaN'
elif o == INFINITY:
@ -174,9 +175,15 @@ class JSONEncoder(object):
self.encoding = encoding
def _newline_indent(self):
"""
Indent lines by level
"""
return '\n' + (' ' * (self.indent * self.current_indent_level))
def _iterencode_list(self, lst, markers=None):
"""
Encoding lists, yielding by level
"""
if not lst:
yield '[]'
return
@ -210,6 +217,9 @@ class JSONEncoder(object):
del markers[markerid]
def _iterencode_dict(self, dct, markers=None):
"""
Encoding dictionaries, yielding by level
"""
if not dct:
yield '{}'
return

Просмотреть файл

@ -6,9 +6,10 @@
const { get: getPref } = require('sdk/preferences/service');
const { getMostRecentBrowserWindow } = require('sdk/window/utils');
const { openTab, closeTab, getBrowserForTab } = require('sdk/tabs/utils');
const tabs = require('sdk/tabs');
exports.testRemotePrefIsSet = function(assert) {
assert.ok(getPref('browser.tabs.remote.autostart'),
assert.ok(getPref('browser.tabs.remote.autostart'),
"Electrolysis remote tabs pref should be set");
}
@ -19,11 +20,12 @@ exports.testTabIsRemote = function(assert, done) {
// can't simply close a remote tab before it is loaded, bug 1006043
let mm = getBrowserForTab(tab).messageManager;
mm.addMessageListener(7, function() {
mm.addMessageListener('7', function listener() {
mm.removeMessageListener('7', listener);
tabs.once('close', done);
closeTab(tab);
done();
})
mm.loadFrameScript('data:,sendAsyncMessage(7)', false);
mm.loadFrameScript('data:,sendAsyncMessage("7")', true);
}
require('sdk/test/runner').runTestsFromModule(module);

Просмотреть файл

@ -7,8 +7,11 @@ const { Cu } = require('chrome');
const sp = require('sdk/simple-prefs');
const app = require('sdk/system/xul-app');
const self = require('sdk/self');
const tabs = require('sdk/tabs');
const { preferencesBranch } = require('sdk/self');
const { preferencesBranch } = self;
const { open } = require('sdk/preferences/utils');
const { getTabForId } = require('sdk/tabs/utils');
const { Tab } = require('sdk/tabs/tab');
require('sdk/tabs');
const { AddonManager } = Cu.import('resource://gre/modules/AddonManager.jsm', {});
@ -26,112 +29,75 @@ exports.testOptionsType = function(assert, done) {
}
exports.testButton = function(assert, done) {
tabs.open({
url: 'about:addons',
onReady: function(tab) {
sp.once('sayHello', function() {
assert.pass('The button was pressed!');
tab.close(done)
});
open(self).then(({ tabId, document }) => {
let tab = Tab({ tab: getTabForId(tabId) });
sp.once('sayHello', _ => {
assert.pass('The button was pressed!');
tab.close(done);
});
tab.attach({
contentScriptWhen: 'end',
contentScript: 'function onLoad() {\n' +
'unsafeWindow.removeEventListener("load", onLoad, false);\n' +
'AddonManager.getAddonByID("' + self.id + '", function(aAddon) {\n' +
'unsafeWindow.gViewController.viewObjects.detail.node.addEventListener("ViewChanged", function whenViewChanges() {\n' +
'unsafeWindow.gViewController.viewObjects.detail.node.removeEventListener("ViewChanged", whenViewChanges, false);\n' +
'setTimeout(function() {\n' + // TODO: figure out why this is necessary..
'unsafeWindow.document.querySelector("button[label=\'Click me!\']").click()\n' +
'}, 250);\n' +
'}, false);\n' +
'unsafeWindow.gViewController.commands.cmd_showItemDetails.doCommand(aAddon, true);\n' +
'});\n' +
'}\n' +
// Wait for the load event ?
'if (document.readyState == "complete") {\n' +
'onLoad()\n' +
'} else {\n' +
'unsafeWindow.addEventListener("load", onLoad, false);\n' +
'}\n',
});
}
tab.attach({
contentScript: 'unsafeWindow.document.querySelector("button[label=\'Click me!\']").click();'
});
});
}
if (app.is('Firefox')) {
exports.testAOM = function(assert, done) {
tabs.open({
url: 'about:addons',
onReady: function(tab) {
tab.attach({
contentScriptWhen: 'end',
contentScript: 'function onLoad() {\n' +
'unsafeWindow.removeEventListener("load", onLoad, false);\n' +
'AddonManager.getAddonByID("' + self.id + '", function(aAddon) {\n' +
'unsafeWindow.gViewController.viewObjects.detail.node.addEventListener("ViewChanged", function whenViewChanges() {\n' +
'unsafeWindow.gViewController.viewObjects.detail.node.removeEventListener("ViewChanged", whenViewChanges, false);\n' +
'setTimeout(function() {\n' + // TODO: figure out why this is necessary..
'self.postMessage({\n' +
'someCount: unsafeWindow.document.querySelectorAll("setting[title=\'some-title\']").length,\n' +
'somePreference: getAttributes(unsafeWindow.document.querySelector("setting[title=\'some-title\']")),\n' +
'myInteger: getAttributes(unsafeWindow.document.querySelector("setting[title=\'my-int\']")),\n' +
'myHiddenInt: getAttributes(unsafeWindow.document.querySelector("setting[title=\'hidden-int\']")),\n' +
'sayHello: getAttributes(unsafeWindow.document.querySelector("button[label=\'Click me!\']"))\n' +
'});\n' +
'}, 250);\n' +
'}, false);\n' +
'unsafeWindow.gViewController.commands.cmd_showItemDetails.doCommand(aAddon, true);\n' +
'});\n' +
'function getAttributes(ele) {\n' +
'if (!ele) return {};\n' +
'return {\n' +
'pref: ele.getAttribute("pref"),\n' +
'type: ele.getAttribute("type"),\n' +
'title: ele.getAttribute("title"),\n' +
'desc: ele.getAttribute("desc"),\n' +
'"data-jetpack-id": ele.getAttribute(\'data-jetpack-id\')\n' +
'}\n' +
'}\n' +
'}\n' +
// Wait for the load event ?
'if (document.readyState == "complete") {\n' +
'onLoad()\n' +
'} else {\n' +
'unsafeWindow.addEventListener("load", onLoad, false);\n' +
'}\n',
onMessage: function(msg) {
// test against doc caching
assert.equal(msg.someCount, 1, 'there is exactly one <setting> node for somePreference');
open(self).then(({ tabId }) => {
let tab = Tab({ tab: getTabForId(tabId) });
assert.pass('the add-on prefs page was opened.');
// test somePreference
assert.equal(msg.somePreference.type, 'string', 'some pref is a string');
assert.equal(msg.somePreference.pref, 'extensions.'+self.id+'.somePreference', 'somePreference path is correct');
assert.equal(msg.somePreference.title, 'some-title', 'somePreference title is correct');
assert.equal(msg.somePreference.desc, 'Some short description for the preference', 'somePreference description is correct');
assert.equal(msg.somePreference['data-jetpack-id'], self.id, 'data-jetpack-id attribute value is correct');
tab.attach({
contentScriptWhen: "end",
contentScript: 'self.postMessage({\n' +
'someCount: unsafeWindow.document.querySelectorAll("setting[title=\'some-title\']").length,\n' +
'somePreference: getAttributes(unsafeWindow.document.querySelector("setting[title=\'some-title\']")),\n' +
'myInteger: getAttributes(unsafeWindow.document.querySelector("setting[title=\'my-int\']")),\n' +
'myHiddenInt: getAttributes(unsafeWindow.document.querySelector("setting[title=\'hidden-int\']")),\n' +
'sayHello: getAttributes(unsafeWindow.document.querySelector("button[label=\'Click me!\']"))\n' +
'});\n' +
'function getAttributes(ele) {\n' +
'if (!ele) return {};\n' +
'return {\n' +
'pref: ele.getAttribute("pref"),\n' +
'type: ele.getAttribute("type"),\n' +
'title: ele.getAttribute("title"),\n' +
'desc: ele.getAttribute("desc"),\n' +
'"data-jetpack-id": ele.getAttribute(\'data-jetpack-id\')\n' +
'}\n' +
'}\n',
onMessage: msg => {
// test against doc caching
assert.equal(msg.someCount, 1, 'there is exactly one <setting> node for somePreference');
// test myInteger
assert.equal(msg.myInteger.type, 'integer', 'myInteger is a int');
assert.equal(msg.myInteger.pref, 'extensions.'+self.id+'.myInteger', 'extensions.test-simple-prefs.myInteger');
assert.equal(msg.myInteger.title, 'my-int', 'myInteger title is correct');
assert.equal(msg.myInteger.desc, 'How many of them we have.', 'myInteger desc is correct');
assert.equal(msg.myInteger['data-jetpack-id'], self.id, 'data-jetpack-id attribute value is correct');
// test somePreference
assert.equal(msg.somePreference.type, 'string', 'some pref is a string');
assert.equal(msg.somePreference.pref, 'extensions.'+self.id+'.somePreference', 'somePreference path is correct');
assert.equal(msg.somePreference.title, 'some-title', 'somePreference title is correct');
assert.equal(msg.somePreference.desc, 'Some short description for the preference', 'somePreference description is correct');
assert.equal(msg.somePreference['data-jetpack-id'], self.id, 'data-jetpack-id attribute value is correct');
// test myHiddenInt
assert.equal(msg.myHiddenInt.type, undefined, 'myHiddenInt was not displayed');
assert.equal(msg.myHiddenInt.pref, undefined, 'myHiddenInt was not displayed');
assert.equal(msg.myHiddenInt.title, undefined, 'myHiddenInt was not displayed');
assert.equal(msg.myHiddenInt.desc, undefined, 'myHiddenInt was not displayed');
// test myInteger
assert.equal(msg.myInteger.type, 'integer', 'myInteger is a int');
assert.equal(msg.myInteger.pref, 'extensions.'+self.id+'.myInteger', 'extensions.test-simple-prefs.myInteger');
assert.equal(msg.myInteger.title, 'my-int', 'myInteger title is correct');
assert.equal(msg.myInteger.desc, 'How many of them we have.', 'myInteger desc is correct');
assert.equal(msg.myInteger['data-jetpack-id'], self.id, 'data-jetpack-id attribute value is correct');
// test sayHello
assert.equal(msg.sayHello['data-jetpack-id'], self.id, 'data-jetpack-id attribute value is correct');
// test myHiddenInt
assert.equal(msg.myHiddenInt.type, undefined, 'myHiddenInt was not displayed');
assert.equal(msg.myHiddenInt.pref, undefined, 'myHiddenInt was not displayed');
assert.equal(msg.myHiddenInt.title, undefined, 'myHiddenInt was not displayed');
assert.equal(msg.myHiddenInt.desc, undefined, 'myHiddenInt was not displayed');
tab.close(done);
}
});
}
// test sayHello
assert.equal(msg.sayHello['data-jetpack-id'], self.id, 'data-jetpack-id attribute value is correct');
tab.close(done);
}
});
})
}
// run it again, to test against inline options document caching

10
addon-sdk/source/test/fixtures/bootstrap-addon/bootstrap.js поставляемый Normal file
Просмотреть файл

@ -0,0 +1,10 @@
/* 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/. */
'use strict';
function install(data, reason) {}
function uninstall(data, reason) {}
function startup(data, reasonCode) {};
function shutdown(data, reasonCode) {};

27
addon-sdk/source/test/fixtures/bootstrap-addon/install.rdf поставляемый Normal file
Просмотреть файл

@ -0,0 +1,27 @@
<?xml version="1.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/. -->
<RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:em="http://www.mozilla.org/2004/em-rdf#">
<Description about="urn:mozilla:install-manifest">
<em:id>test-bootstrap-addon@mozilla.com</em:id>
<em:name>Test Bootstrap Add-on</em:name>
<em:creator>Erik Vold</em:creator>
<em:optionsType>2</em:optionsType>
<em:version>1.0</em:version>
<em:type>2</em:type>
<em:bootstrap>true</em:bootstrap>
<em:unpack>false</em:unpack>
<!-- Firefox -->
<em:targetApplication>
<Description>
<em:id>{ec8030f7-c20a-464f-9b0e-13a3a9e97384}</em:id>
<em:minVersion>26.0</em:minVersion>
<em:maxVersion>*</em:maxVersion>
</Description>
</em:targetApplication>
</Description>
</RDF>

3
addon-sdk/source/test/fixtures/bootstrap-addon/options.xul поставляемый Normal file
Просмотреть файл

@ -0,0 +1,3 @@
<?xml version="1.0"?>
<!DOCTYPE mydialog SYSTEM "chrome://myaddon/locale/mydialog.dtd">
<vbox xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"></vbox>

Просмотреть файл

@ -1,5 +1,5 @@
{
"id": "jid1-fZHqN9JfrDBa8A",
"id": "no-prefs@jetpack",
"title": "No Prefs Test",
"author": "Erik Vold",
"loader": "lib/main.js"

Просмотреть файл

@ -1,5 +1,5 @@
{
"id": "jid1-fZHqN9JfrDBa8A",
"id": "simple-prefs@jetpack",
"title": "Simple Prefs Test",
"author": "Erik Vold",
"preferences": [{

Просмотреть файл

@ -9,7 +9,6 @@ const { on, off } = require("sdk/system/events");
const { setTimeout } = require("sdk/timers");
const tmp = require("sdk/test/tmp-file");
const system = require("sdk/system");
const fixtures = require("./fixtures");
const testFolderURL = module.uri.split('test-addon-installer.js')[0];
const ADDON_URL = testFolderURL + "fixtures/addon-install-unit-test@mozilla.com.xpi";

Просмотреть файл

@ -3,7 +3,7 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
"use strict";
const { setDefaults, injectOptions, validate } = require('sdk/preferences/native-options');
const { setDefaults, injectOptions: inject, validate } = require('sdk/preferences/native-options');
const { activeBrowserWindow: { document } } = require("sdk/deprecated/window-utils");
const { preferencesBranch, id } = require('sdk/self');
const { get } = require('sdk/preferences/service');
@ -12,6 +12,19 @@ const simple = require('sdk/simple-prefs');
const fixtures = require('./fixtures');
const { Cc, Ci } = require('chrome');
const prefsrv = Cc['@mozilla.org/preferences-service;1'].
getService(Ci.nsIPrefService);
function injectOptions(preferences, preferencesBranch, document, parent) {
inject({
id: id,
preferences: preferences,
preferencesBranch: preferencesBranch,
document: document,
parent: parent
});
}
exports.testValidate = function(assert) {
let { preferences } = packageJSON('simple-prefs');
@ -56,35 +69,45 @@ exports.testNoPrefs = function(assert, done) {
exports.testCurlyID = function(assert) {
let { preferences, id } = packageJSON('curly-id');
let branch = prefsrv.getDefaultBranch('extensions.' + id);
let parent = document.createDocumentFragment();
injectOptions(preferences, id, document, parent);
assert.equal(parent.children.length, 1, "One setting elements injected");
assert.equal(parent.firstElementChild.attributes.pref.value,
assert.equal(parent.firstElementChild.attributes.pref.value,
"extensions.{34a1eae1-c20a-464f-9b0e-000000000000}.test13",
"Setting pref attribute is set properly");
setDefaults(preferences, id);
assert.equal(get('extensions.{34a1eae1-c20a-464f-9b0e-000000000000}.test13'),
assert.equal(get('extensions.{34a1eae1-c20a-464f-9b0e-000000000000}.test13'),
26, "test13 is 26");
branch.deleteBranch('');
assert.equal(get('extensions.{34a1eae1-c20a-464f-9b0e-000000000000}.test13'),
undefined, "test13 is undefined");
}
exports.testPreferencesBranch = function(assert) {
let { preferences, 'preferences-branch': prefsBranch } = packageJSON('preferences-branch');
let branch = prefsrv.getDefaultBranch('extensions.' + prefsBranch);
let parent = document.createDocumentFragment();
injectOptions(preferences, prefsBranch, document, parent);
assert.equal(parent.children.length, 1, "One setting elements injected");
assert.equal(parent.firstElementChild.attributes.pref.value,
assert.equal(parent.firstElementChild.attributes.pref.value,
"extensions.human-readable.test42",
"Setting pref attribute is set properly");
setDefaults(preferences, prefsBranch);
assert.equal(get('extensions.human-readable.test42'), true, "test42 is true");
branch.deleteBranch('');
assert.equal(get('extensions.human-readable.test42'), undefined, "test42 is undefined");
}
exports.testSimplePrefs = function(assert) {
let { preferences } = packageJSON('simple-prefs');
let branch = prefsrv.getDefaultBranch('extensions.' + preferencesBranch);
function assertPref(setting, name, type, title) {
assert.equal(setting.getAttribute('data-jetpack-id'), id,
@ -128,13 +151,15 @@ exports.testSimplePrefs = function(assert) {
setDefaults(preferences, preferencesBranch);
assert.strictEqual(simple.prefs.test, false, "test is false");
assert.strictEqual(simple.prefs.test2, "\u00FCnic\u00F8d\u00E9", "test2 is unicode");
assert.strictEqual(simple.prefs.test2, "\u00FCnic\u00F8d\u00E9", "test2 is unicode");
assert.strictEqual(simple.prefs.test3, "1", "test3 is '1'");
assert.strictEqual(simple.prefs.test4, "red", "test4 is 'red'");
// default pref branch can't be "reset", bug 1012231
Cc['@mozilla.org/preferences-service;1'].getService(Ci.nsIPrefService).
getDefaultBranch('extensions.' + preferencesBranch).deleteBranch('');
branch.deleteBranch('');
assert.strictEqual(simple.prefs.test, undefined, "test is undefined");
assert.strictEqual(simple.prefs.test2, undefined, "test2 is undefined");
assert.strictEqual(simple.prefs.test3, undefined, "test3 is undefined");
assert.strictEqual(simple.prefs.test4, undefined, "test4 is undefined");
}
function packageJSON(dir) {

Просмотреть файл

@ -3,12 +3,29 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
"use strict";
const { Cc, Ci, Cu } = require('chrome');
const { Loader } = require("sdk/test/loader");
const { setTimeout } = require("sdk/timers");
const { emit } = require("sdk/system/events");
const { id } = require("sdk/self");
const simplePrefs = require("sdk/simple-prefs");
const { prefs: sp } = simplePrefs;
const { defer, resolve, reject, all } = require("sdk/core/promise");
const AddonInstaller = require("sdk/addon/installer");
const fixtures = require("./fixtures");
const { pathFor } = require("sdk/system");
const file = require("sdk/io/file");
const { install, uninstall } = require("sdk/addon/installer");
const { open } = require('sdk/preferences/utils');
const { toFilename } = require('sdk/url');
const { AddonManager } = Cu.import('resource://gre/modules/AddonManager.jsm', {});
const { ZipWriter } = require('./zip/utils');
const { getTabForId } = require('sdk/tabs/utils');
const { preferencesBranch, id } = require('sdk/self');
const { Tab } = require('sdk/tabs/tab');
require('sdk/tabs');
const prefsrv = Cc['@mozilla.org/preferences-service;1'].
getService(Ci.nsIPrefService);
const specialChars = "!@#$%^&*()_-=+[]{}~`\'\"<>,./?;:";
@ -230,4 +247,104 @@ exports.testPrefJSONStringification = function(assert) {
"JSON stringification should work.");
};
require('sdk/test').run(exports);
exports.testUnloadOfDynamicPrefGeneration = function(assert, done) {
let loader = Loader(module);
let branch = prefsrv.getDefaultBranch('extensions.' + preferencesBranch);
let { enable } = loader.require("sdk/preferences/native-options");
let addon_id = "test-bootstrap-addon@mozilla.com";
let xpi_path = file.join(pathFor("ProfD"), addon_id + ".xpi");
// zip the add-on
let zip = new ZipWriter(xpi_path);
assert.pass("start creating the xpi");
zip.addFile("", toFilename(fixtures.url("bootstrap-addon/"))).
then(zip.close()).
then(_ => install(xpi_path)).
// get the addon
then(id => {
let { promise, resolve } = defer();
AddonManager.getAddonByID(id, resolve);
return promise;
}).
// insatll the add-on
then(addon => {
assert.pass('installed');
assert.pass('addon id: ' + addon.id);
addon.userDisabled = false;
assert.ok(!addon.userDisabled, 'the add-on is enabled');
assert.ok(addon.isActive, 'the add-on is enabled');
// setup dynamic prefs
return enable({
id: addon.id,
preferences: [{
"name": "test",
"description": "test",
"title": "Test",
"type": "string",
"value": "default"
}, {
"name": "test-int",
"description": "test",
"type": "integer",
"value": 5,
"title": "How Many?"
}]
});
}).
then(args => {
assert.pass('enabled');
return args;
}).
// show inline prefs
then(open).
then(args => {
assert.pass('opened');
return args;
}).
// confirm dynamic pref generation did occur
then(args => {
let results = args.document.querySelectorAll("*[data-jetpack-id=\"" +args.id + "\"]");
assert.ok(results.length > 0, "the prefs were setup");
return args;
}).
// unload dynamic prefs
then(args => {
loader.unload();
assert.pass('unload');
return args;
}).
// hide and show the inline prefs
then(({ tabId, id, document }) => {
let { promise, resolve } = defer();
let tab = Tab({ tab: getTabForId(tabId) });
tab.close(_ => resolve({ id: id }));
return promise;
}).
// reopen the add-on prefs page
then(open).
// confirm dynamic pref generation did not occur
then(({ id, tabId, document }) => {
let { promise, resolve } = defer();
let tab = Tab({ tab: getTabForId(tabId) });
let results = document.querySelectorAll("*[data-jetpack-id=\"" + id + "\"]");
assert.equal(0, results.length, "the prefs were not setup after unload");
tab.close(_ => resolve({ id: id }));
return promise;
}).
// uninstall the add-on
then(({ id }) => uninstall(id)).
// delete the pref branch
then(_ => branch.deleteBranch('')).
then(done, assert.fail);
}
require("sdk/test").run(exports);

Просмотреть файл

@ -1089,41 +1089,39 @@ exports.testSidebarLeakCheckUnloadAfterAttach = function(assert, done) {
const loader = Loader(module);
const { Sidebar } = loader.require('sdk/ui/sidebar');
let testName = 'testSidebarLeakCheckUnloadAfterAttach';
let window = getMostRecentBrowserWindow();
let sidebar = Sidebar({
id: testName,
title: testName,
url: 'data:text/html;charset=utf-8,'+testName
});
sidebar.on('attach', function() {
assert.pass('the sidebar was shown');
open().then(focus).then(window => {
sidebar.on('attach', function() {
assert.pass('the sidebar was shown');
sidebar.on('show', function() {
assert.fail('the sidebar show listener should have been removed');
});
assert.pass('added a sidebar show listener');
sidebar.on('show', function() {
assert.fail('the sidebar show listener should have been removed');
});
assert.pass('added a sidebar show listener');
sidebar.on('hide', function() {
assert.fail('the sidebar hide listener should have been removed');
});
assert.pass('added a sidebar hide listener');
sidebar.on('hide', function() {
assert.fail('the sidebar hide listener should have been removed');
});
assert.pass('added a sidebar hide listener');
let panelBrowser = window.document.getElementById('sidebar').contentDocument.getElementById('web-panels-browser');
panelBrowser.contentWindow.addEventListener('unload', function onUnload() {
panelBrowser.contentWindow.removeEventListener('unload', onUnload, false);
// wait a tick..
setTimeout(function() {
let panelBrowser = window.document.getElementById('sidebar').contentDocument.getElementById('web-panels-browser');
panelBrowser.contentWindow.addEventListener('unload', function onUnload() {
panelBrowser.contentWindow.removeEventListener('unload', onUnload, false);
assert.pass('the sidebar web panel was unloaded properly');
done();
})
}, false);
close(window).then(done).catch(assert.fail);
}, false);
loader.unload();
});
loader.unload();
});
assert.pass('showing the sidebar');
sidebar.show();
assert.pass('showing the sidebar');
sidebar.show();
}).catch(assert.fail);
}
exports.testTwoSidebarsWithSameTitleAndURL = function(assert) {

Просмотреть файл

@ -0,0 +1,125 @@
/* 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/. */
"use strict";
const { Ci, Cc } = require("chrome");
const { defer, all } = require("sdk/core/promise");
const PR_RDONLY = 0x01;
const PR_WRONLY = 0x02;
const PR_RDWR = 0x04;
const PR_CREATE_FILE = 0x08;
const PR_APPEND = 0x10;
const PR_TRUNCATE = 0x20;
const PR_SYNC = 0x40;
const PR_EXCL = 0x80;
// Default compression level:
const { COMPRESSION_DEFAULT } = Ci.nsIZipWriter;
function createNsFile(path) {
let file = Cc["@mozilla.org/file/local;1"].createInstance(Ci.nsILocalFile);
try {
file.initWithPath(path);
} catch(e) {
throw new Error("This zip file path is not valid : " + path + "\n" + e);
}
return file;
}
const converter = Cc["@mozilla.org/intl/scriptableunicodeconverter"].
createInstance(Ci.nsIScriptableUnicodeConverter);
converter.charset = "UTF-8";
function streamForData(data) {
return converter.convertToInputStream(data);
}
exports.ZipWriter = function (zipPath, mode) {
mode = mode ? mode : PR_RDWR | PR_CREATE_FILE | PR_TRUNCATE;
let zw = Cc["@mozilla.org/zipwriter;1"].createInstance(Ci.nsIZipWriter);
zw.open(createNsFile(zipPath), mode);
// Create a directory entry.
// Returns true if the entry was created, or false if the entry already exists
this.mkdir = function mkdir(pathInZip) {
try {
zw.addEntryDirectory(pathInZip, 0, false);
}
catch(e) {
if (e.name === "NS_ERROR_FILE_ALREADY_EXISTS")
return false;
throw e
}
return true;
}
this.addFile = function addFile(pathInZip, filePath) {
let { promise, reject, resolve } = defer();
let nsfile = createNsFile(filePath);
if (!nsfile.exists()) {
reject(new Error("This file doesn't exists : " + nsfile.path));
return promise;
}
// Case 1/ Regular file
if (!nsfile.isDirectory()) {
try {
zw.addEntryFile(pathInZip, COMPRESSION_DEFAULT, nsfile, false);
resolve();
}
catch (e) {
reject(new Error("Unable to add following file in zip: " + nsfile.path + "\n" + e));
}
return promise;
}
// Case 2/ Directory
if (pathInZip.substr(-1) !== '/')
pathInZip += "/";
let entries = nsfile.directoryEntries;
let array = [];
zw.addEntryDirectory(pathInZip, nsfile.lastModifiedTime, false);
while(entries.hasMoreElements()) {
let file = entries.getNext().QueryInterface(Ci.nsIFile);
if (file.leafName === "." || file.leafName === "..")
continue;
let path = pathInZip + file.leafName;
if (path.substr(0, 1) == '/') {
path = path.substr(1);
}
this.addFile(path, file.path);
}
resolve();
return promise;
}
this.addData = function (pathInZip, data) {
let deferred = defer();
try {
let stream = streamForData(data);
zw.addEntryStream(pathInZip, 0, COMPRESSION_DEFAULT, stream, false);
} catch(e) {
throw new Error("Unable to add following data in zip: " +
data.substr(0, 20) + "\n" + e);
}
deferred.resolve();
return deferred.promise;
}
this.close = function close() {
let deferred = defer();
zw.close();
deferred.resolve();
return deferred.promise;
}
}

Просмотреть файл

@ -1239,7 +1239,9 @@ var gBrowserInit = {
let mpEnabled = slot &&
slot.status != Ci.nsIPKCS11Slot.SLOT_UNINITIALIZED &&
slot.status != Ci.nsIPKCS11Slot.SLOT_READY;
Services.telemetry.getHistogramById("MASTER_PASSWORD_ENABLED").add(mpEnabled);
if (mpEnabled) {
Services.telemetry.getHistogramById("MASTER_PASSWORD_ENABLED").add(mpEnabled);
}
}, 5000);
});
this.delayedStartupFinished = true;
@ -2090,10 +2092,23 @@ function BrowserViewSourceOfDocument(aDocument)
// view-source to access the cached copy of the content rather than
// refetching it from the network...
//
try{
var PageLoader = webNav.QueryInterface(Components.interfaces.nsIWebPageDescriptor);
try {
pageCookie = PageLoader.currentDescriptor;
#ifdef E10S_TESTING_ONLY
// Workaround for bug 988133, which causes a crash if we attempt to load
// the document from the cache when the document is a CPOW (which occurs
// if we're using remote tabs). This causes us to reload the document from
// the network in this case, so it's not a permanent solution, hence hiding
// it behind the E10S_TESTING_ONLY ifdef. This is just a band-aid fix until
// we can find something better - see bug 1025146.
if (!Cu.isCrossProcessWrapper(aDocument)) {
#endif
var PageLoader = webNav.QueryInterface(Components.interfaces.nsIWebPageDescriptor);
pageCookie = PageLoader.currentDescriptor;
#ifdef E10S_TESTING_ONLY
}
#endif
} catch(err) {
// If no page descriptor is available, just use the view-source URL...
}

Просмотреть файл

@ -112,6 +112,11 @@ var tests = {
iconURL: "chrome://browser/skin/Info.png",
counter: 1
};
// Disable the transition
let panel = document.getElementById("social-notification-panel");
panel.setAttribute("animate", "false");
// click on panel to open and wait for visibility
let provider = Social._getProviderFromOrigin(manifest2.origin);
let id = SocialStatus._toolbarHelper.idFromOrigin(manifest2.origin);
@ -131,8 +136,8 @@ var tests = {
case "got-social-panel-visibility":
ok(true, "got the panel message " + e.data.result);
if (e.data.result == "shown") {
let panel = document.getElementById("social-notification-panel");
panel.hidePopup();
panel.removeAttribute("animate");
} else {
port.postMessage({topic: "test-ambient-notification", data: icon});
port.close();

Просмотреть файл

@ -63,11 +63,14 @@ function checkProviderPrefsEmpty(isError) {
}
function defaultFinishChecks() {
PopupNotifications.transitionsEnabled = true;
checkProviderPrefsEmpty(true);
finish();
}
function runSocialTestWithProvider(manifest, callback, finishcallback) {
PopupNotifications.transitionsEnabled = false;
let SocialService = Cu.import("resource://gre/modules/SocialService.jsm", {}).SocialService;
let manifests = Array.isArray(manifest) ? manifest : [manifest];
@ -158,6 +161,8 @@ function runSocialTests(tests, cbPreTest, cbPostTest, cbFinish) {
let providersAtStart = Social.providers.length;
info("runSocialTests: start test run with " + providersAtStart + " providers");
PopupNotifications.transitionsEnabled = false;
if (cbPreTest === undefined) {
cbPreTest = function(cb) {cb()};
}

Просмотреть файл

@ -7,7 +7,6 @@
type="arrow"
hidden="true"
flip="slide"
animate="false"
position="bottomcenter topright"
noautofocus="true">
<panelmultiview id="PanelUI-multiView" mainViewId="PanelUI-mainView">

Просмотреть файл

@ -29,6 +29,12 @@ add_task(function() {
let newWin = yield openAndLoadWindow({}, true);
info("Waiting for panel in new window to open");
let hideTrace = function() {
info(new Error().stack);
info("Panel was hidden.");
};
newWin.PanelUI.panel.addEventListener("popuphidden", hideTrace);
yield newWin.PanelUI.show();
let newWinBookmarksToolbarPlaceholder = newWin.document.getElementById(buttonId);
ok(newWinBookmarksToolbarPlaceholder.classList.contains("toolbarbutton-1"),
@ -36,6 +42,7 @@ add_task(function() {
is(newWinBookmarksToolbarPlaceholder.getAttribute("wrap"), "true",
"Button in new window should have 'wrap' attribute");
newWin.PanelUI.panel.removeEventListener("popuphidden", hideTrace);
//XXXgijs on Linux, we're sometimes seeing the panel being hidden early
// in the newly created window, probably because something else steals focus.
if (newWin.PanelUI.panel.state != "closed") {

Просмотреть файл

@ -15,6 +15,8 @@ const promise = Cu.import("resource://gre/modules/Promise.jsm", {}).Promise;
const EventEmitter = require("devtools/toolkit/event-emitter");
const { CallWatcherFront } = require("devtools/server/actors/call-watcher");
const { CanvasFront } = require("devtools/server/actors/canvas");
const Telemetry = require("devtools/shared/telemetry");
const telemetry = new Telemetry();
XPCOMUtils.defineLazyModuleGetter(this, "Task",
"resource://gre/modules/Task.jsm");
@ -119,6 +121,7 @@ let EventsHandler = {
* Listen for events emitted by the current tab target.
*/
initialize: function() {
telemetry.toolOpened("canvasdebugger");
this._onTabNavigated = this._onTabNavigated.bind(this);
gTarget.on("will-navigate", this._onTabNavigated);
gTarget.on("navigate", this._onTabNavigated);
@ -128,6 +131,7 @@ let EventsHandler = {
* Remove events emitted by the current tab target.
*/
destroy: function() {
telemetry.toolClosed("canvasdebugger");
gTarget.off("will-navigate", this._onTabNavigated);
gTarget.off("navigate", this._onTabNavigated);
},

Просмотреть файл

@ -20,36 +20,74 @@ let test = asyncTest(function*() {
let usage = yield csscoverage.getUsage(options.target);
yield usage.oneshot();
yield navigate(usage, options);
yield checkPages(usage);
yield checkEditorReport(usage);
yield checkPageReport(usage);
yield helpers.closeToolbar(options);
yield helpers.closeTab(options);
});
/**
* Just check current page
*/
function* navigate(usage, options) {
let running = yield usage._testOnly_isRunning();
ok(!running, "csscoverage not is running");
yield usage.oneshot();
running = yield usage._testOnly_isRunning();
ok(!running, "csscoverage not is running");
}
/**
* Check the expected pages have been visited
*/
function* checkPages(usage) {
let expectedVisited = [ PAGE_3 ];
let actualVisited = yield usage._testOnly_visitedPages();
isEqualJson(actualVisited, expectedVisited, 'Visited');
}
/**
* Check that createEditorReport returns the expected JSON
*/
function* checkEditorReport(usage) {
// Page1
let expectedPage1 = { reports: [] };
let actualPage1 = yield usage.createEditorReport(PAGE_1);
let actualPage1 = yield usage.createEditorReport(PAGE_1 + " \u2192 <style> index 0");
isEqualJson(actualPage1, expectedPage1, 'Page1');
// Page2
let expectedPage2 = { reports: [] };
let actualPage2 = yield usage.createEditorReport(PAGE_2);
let actualPage2 = yield usage.createEditorReport(PAGE_2 + " \u2192 <style> index 0");
isEqualJson(actualPage2, expectedPage2, 'Page2');
// Page3
let expectedPage3 = {
// Page3a
let expectedPage3a = {
reports: [
{
selectorText: ".page3-test2",
start: { line: 9, column: 5 },
},
}
]
};
let actualPage3a = yield usage.createEditorReport(PAGE_3 + " \u2192 <style> index 0");
isEqualJson(actualPage3a, expectedPage3a, 'Page3a');
// Page3b
let expectedPage3b = {
reports: [
{
selectorText: ".page3-test3",
start: { line: 3, column: 5 },
}
]
};
let actualPage3 = yield usage.createEditorReport(PAGE_3);
isEqualJson(actualPage3, expectedPage3, 'Page3');
let actualPage3b = yield usage.createEditorReport(PAGE_3 + " \u2192 <style> index 1");
isEqualJson(actualPage3b, expectedPage3b, 'Page3b');
// SheetA
let expectedSheetA = {
@ -130,11 +168,148 @@ let test = asyncTest(function*() {
};
let actualSheetD = yield usage.createEditorReport(SHEET_D);
isEqualJson(actualSheetD, expectedSheetD, 'SheetD');
}
yield helpers.closeToolbar(options);
yield helpers.closeTab(options);
});
/**
* Check that checkPageReport returns the expected JSON
*/
function* checkPageReport(usage) {
let actualReport = yield usage.createPageReport();
// Quick check on trivial things. See doc comment for checkRuleProperties
actualReport.preload.forEach(page => page.rules.forEach(checkRuleProperties));
actualReport.unused.forEach(page => page.rules.forEach(checkRuleProperties));
// Check the summary
let expectedSummary = { "used": 23, "unused": 9, "preload": 0 };
isEqualJson(actualReport.summary, expectedSummary, 'summary');
// Check the preload header
isEqualJson(actualReport.preload.length, 0, 'preload length');
// Check the unused header
isEqualJson(actualReport.unused.length, 6, 'unused length');
// Check the unused rules
isEqualJson(actualReport.unused[0].url, PAGE_3 + " \u2192 <style> index 0", "unused url 0");
let expectedUnusedRules0 = [
{
"url": PAGE_3 + " \u2192 <style> index 0",
"start": { "line": 9, "column": 5 },
"selectorText": ".page3-test2"
}
];
isEqualJson(actualReport.unused[0].rules, expectedUnusedRules0, 'unused rules 0');
isEqualJson(actualReport.unused[1].url, PAGE_3 + " \u2192 <style> index 1", "unused url 1");
let expectedUnusedRules1 = [
{
"url": PAGE_3 + " \u2192 <style> index 1",
"start": { "line": 3, "column": 5 },
"selectorText": ".page3-test3"
}
];
isEqualJson(actualReport.unused[1].rules, expectedUnusedRules1, 'unused rules 1');
isEqualJson(actualReport.unused[2].url, SHEET_A, "unused url 2");
let expectedUnusedRules2 = [
{
"url": SHEET_A,
"start": { "line": 8, "column": 1 },
"selectorText": ".sheetA-test2"
},
{
"url": SHEET_A,
"start": { "line": 12, "column": 1 },
"selectorText": ".sheetA-test3"
},
{
"url": SHEET_A,
"start": { "line": 16, "column": 1 },
"selectorText": ".sheetA-test4"
}
];
isEqualJson(actualReport.unused[2].rules, expectedUnusedRules2, 'unused rules 2');
isEqualJson(actualReport.unused[3].url, SHEET_B, "unused url 3");
let expectedUnusedRules3 = [
{
"url": SHEET_B,
"start": { "line": 6, "column": 1 },
"selectorText": ".sheetB-test2"
},
{
"url": SHEET_B,
"start": { "line": 10, "column": 1 },
"selectorText": ".sheetB-test3"
},
{
"url": SHEET_B,
"start": { "line": 14, "column": 1 },
"selectorText": ".sheetB-test4"
}
];
isEqualJson(actualReport.unused[3].rules, expectedUnusedRules3, 'unused rules 3');
isEqualJson(actualReport.unused[4].url, SHEET_D, "unused url 4");
let expectedUnusedRules4 = [
{
"url": SHEET_D,
"start": { "line": 6, "column": 1 },
"selectorText": ".sheetD-test2"
},
{
"url": SHEET_D,
"start": { "line": 10, "column": 1 },
"selectorText": ".sheetD-test3"
},
{
"url": SHEET_D,
"start": { "line": 14, "column": 1 },
"selectorText": ".sheetD-test4"
}
];
isEqualJson(actualReport.unused[4].rules, expectedUnusedRules4, 'unused rules 4');
isEqualJson(actualReport.unused[5].url, SHEET_C, "unused url 5");
let expectedUnusedRules5 = [
{
"url": SHEET_C,
"start": { "line": 6, "column": 1 },
"selectorText": ".sheetC-test2"
},
{
"url": SHEET_C,
"start": { "line": 10, "column": 1 },
"selectorText": ".sheetC-test3"
},
{
"url": SHEET_C,
"start": { "line": 14, "column": 1 },
"selectorText": ".sheetC-test4"
}
];
isEqualJson(actualReport.unused[5].rules, expectedUnusedRules5, 'unused rules 5');
}
/**
* We do basic tests on the shortUrl and formattedCssText because they are
* very derivative, and so make for fragile tests, and having done those quick
* existence checks we remove them so the JSON check later can ignore them
*/
function checkRuleProperties(rule, index) {
is(typeof rule.shortUrl, "string", "typeof rule.shortUrl for " + index);
is(rule.shortUrl.indexOf("http://"), -1, "http not in rule.shortUrl for" + index);
delete rule.shortUrl;
is(typeof rule.formattedCssText, "string", "typeof rule.formattedCssText for " + index);
ok(rule.formattedCssText.indexOf("{") > 0, "{ in rule.formattedCssText for " + index);
delete rule.formattedCssText;
}
/**
* Utility to compare JSON structures
*/
function isEqualJson(o1, o2, msg) {
is(JSON.stringify(o1), JSON.stringify(o2), msg);
}

Просмотреть файл

@ -42,11 +42,13 @@
/* How quickly do we rush through this? */
let delay = 500;
window.addEventListener("load", () => {
dump('TEST-INFO | load from browser_cmd_csscoverage_page1.html\n');
setTimeout(() => {
dump('TEST-INFO | timeout from browser_cmd_csscoverage_page1.html\n');
/* This adds <div class=page1-test5></div> */
let parent = document.querySelector("#page1-test5-holder");
let child = document.createElement("div");
child.classList.add("class=page1-test5");
child.classList.add("page1-test5");
parent.appendChild(child);
/* Then navigate to the next step */

Просмотреть файл

@ -26,11 +26,13 @@
/* How quickly do we rush through this? */
let delay = 500;
window.addEventListener("load", () => {
dump('TEST-INFO | load from browser_cmd_csscoverage_page2.html\n');
setTimeout(() => {
dump('TEST-INFO | timeout from browser_cmd_csscoverage_page2.html\n');
/* This adds <div class=page2-test3></div> */
let parent = document.querySelector("#page2-test3-holder");
let child = document.createElement("div");
child.classList.add("class=page2-test3");
child.classList.add("page2-test3");
parent.appendChild(child);
}, delay);
});
@ -41,7 +43,6 @@
<h2>Page 2</h2>
<div class=page2-test1>.page2-test1</div>
<div class=page2-test3>.page2-test3</div>
<div id=page2-test3-holder></div>

Просмотреть файл

@ -23,6 +23,11 @@
</style>
<link rel="stylesheet" type="text/css" href="browser_cmd_csscoverage_sheetA.css">
<link rel="stylesheet" type="text/css" href="browser_cmd_csscoverage_sheetB.css">
<script type="application/javascript;version=1.8">
window.addEventListener("load", () => {
dump('TEST-INFO | load from browser_cmd_csscoverage_page3.html\n');
});
</script>
</head>
<body>

Просмотреть файл

@ -20,43 +20,100 @@ let test = asyncTest(function*() {
let usage = yield csscoverage.getUsage(options.target);
yield navigate(usage, options);
yield checkPages(usage);
yield checkEditorReport(usage);
yield checkPageReport(usage);
yield helpers.closeToolbar(options);
yield helpers.closeTab(options);
});
/**
* Visit all the pages in the test
*/
function* navigate(usage, options) {
yield usage.start();
let running = yield usage._testOnly_isRunning();
ok(running, "csscoverage is running");
yield helpers.navigate(PAGE_3, options);
yield helpers.navigate(PAGE_1, options);
// Wait for the test pages to auto-cycle
let ev = yield helpers.listenOnce(options.browser, "load", true);
is(ev.target.location.href, PAGE_1, "page 1 loaded");
ev = yield helpers.listenOnce(options.browser, "load", true);
is(ev.target.location.href, PAGE_3, "page 3 loaded");
yield usage.stop();
running = yield usage._testOnly_isRunning();
ok(!running, "csscoverage not is running");
}
/**
* Check the expected pages have been visited
*/
function* checkPages(usage) {
// 'load' event order. '' is for the initial location
let expectedVisited = [ '', PAGE_2, PAGE_1, PAGE_3 ];
let actualVisited = yield usage._testOnly_visitedPages();
isEqualJson(actualVisited, expectedVisited, 'Visited');
}
/**
* Check that createEditorReport returns the expected JSON
*/
function* checkEditorReport(usage) {
// Page1
let expectedPage1 = { reports: [] };
let actualPage1 = yield usage.createEditorReport(PAGE_1);
let expectedPage1 = {
reports: [
{
selectorText: ".page1-test2",
start: { line: 8, column: 5 },
}
]
};
let actualPage1 = yield usage.createEditorReport(PAGE_1 + " \u2192 <style> index 0");
isEqualJson(actualPage1, expectedPage1, 'Page1');
// Page2
let expectedPage2 = { reports: [] };
let actualPage2 = yield usage.createEditorReport(PAGE_2);
let expectedPage2 = {
reports: [
{
selectorText: ".page2-test2",
start: { line: 9, column: 5 },
},
]
};
let actualPage2 = yield usage.createEditorReport(PAGE_2 + " \u2192 <style> index 0");
isEqualJson(actualPage2, expectedPage2, 'Page2');
// Page3
let expectedPage3 = {
// Page3a
let expectedPage3a = {
reports: [
{
selectorText: ".page3-test2",
start: { line: 9, column: 5 },
},
}
]
};
let actualPage3a = yield usage.createEditorReport(PAGE_3 + " \u2192 <style> index 0");
isEqualJson(actualPage3a, expectedPage3a, 'Page3a');
// Page3b
let expectedPage3b = {
reports: [
{
selectorText: ".page3-test3",
start: { line: 3, column: 5 },
}
]
};
let actualPage3 = yield usage.createEditorReport(PAGE_3);
isEqualJson(actualPage3, expectedPage3, 'Page3');
let actualPage3b = yield usage.createEditorReport(PAGE_3 + " \u2192 <style> index 1");
isEqualJson(actualPage3b, expectedPage3b, 'Page3b');
// SheetA
let expectedSheetA = {
@ -64,14 +121,6 @@ let test = asyncTest(function*() {
{
selectorText: ".sheetA-test2",
start: { line: 8, column: 1 },
},
{
selectorText: ".sheetA-test3",
start: { line: 12, column: 1 },
},
{
selectorText: ".sheetA-test4",
start: { line: 16, column: 1 },
}
]
};
@ -84,14 +133,6 @@ let test = asyncTest(function*() {
{
selectorText: ".sheetB-test2",
start: { line: 6, column: 1 },
},
{
selectorText: ".sheetB-test3",
start: { line: 10, column: 1 },
},
{
selectorText: ".sheetB-test4",
start: { line: 14, column: 1 },
}
]
};
@ -104,14 +145,6 @@ let test = asyncTest(function*() {
{
selectorText: ".sheetC-test2",
start: { line: 6, column: 1 },
},
{
selectorText: ".sheetC-test3",
start: { line: 10, column: 1 },
},
{
selectorText: ".sheetC-test4",
start: { line: 14, column: 1 },
}
]
};
@ -124,24 +157,303 @@ let test = asyncTest(function*() {
{
selectorText: ".sheetD-test2",
start: { line: 6, column: 1 },
},
{
selectorText: ".sheetD-test3",
start: { line: 10, column: 1 },
},
{
selectorText: ".sheetD-test4",
start: { line: 14, column: 1 },
}
]
};
let actualSheetD = yield usage.createEditorReport(SHEET_D);
isEqualJson(actualSheetD, expectedSheetD, 'SheetD');
}
yield helpers.closeToolbar(options);
yield helpers.closeTab(options);
});
/**
* Check that checkPageReport returns the expected JSON
*/
function* checkPageReport(usage) {
let actualReport = yield usage.createPageReport();
// Quick check on trivial things. See doc comment for checkRuleProperties
actualReport.preload.forEach(page => page.rules.forEach(checkRuleProperties));
actualReport.unused.forEach(page => page.rules.forEach(checkRuleProperties));
// Check the summary
let expectedSummary = { "used": 92, "unused": 22, "preload": 28 };
isEqualJson(actualReport.summary, expectedSummary, 'summary');
checkPageReportPreload(actualReport);
checkPageReportUnused(actualReport);
}
/**
* Check that checkPageReport returns the expected preload JSON
*/
function checkPageReportPreload(actualReport) {
// Check the preload header
isEqualJson(actualReport.preload.length, 3, 'preload length');
// Check the preload rules
isEqualJson(actualReport.preload[0].url, PAGE_2, 'preload url 0');
let expectedPreloadRules0 = [
// TODO: This is already pre-loaded, we should note this
{
url: PAGE_2 + " \u2192 <style> index 0",
start: { line: 5, column: 5 },
selectorText: ".page2-test1"
},
{
url: SHEET_A,
start: { line: 4, column: 1 },
selectorText: ".sheetA-test1"
},
{
url: SHEET_A,
start: { line: 16, column: 1 },
selectorText: ".sheetA-test4"
},
{
url: SHEET_B,
start: { line: 2, column: 1 },
selectorText: ".sheetB-test1"
},
{
url: SHEET_B,
start: { line: 14, column: 1 },
selectorText: ".sheetB-test4"
},
{
url: SHEET_D,
start: { line: 2, column: 1 },
selectorText: ".sheetD-test1"
},
{
url: SHEET_D,
start: { line: 14, column: 1 },
selectorText: ".sheetD-test4"
},
{
url: SHEET_C,
start: { line: 2, column: 1 },
selectorText: ".sheetC-test1"
},
{
url: SHEET_C,
start: { line: 14, column: 1 },
selectorText: ".sheetC-test4"
}
];
isEqualJson(actualReport.preload[0].rules, expectedPreloadRules0, 'preload rules 0');
isEqualJson(actualReport.preload[1].url, PAGE_1, 'preload url 1');
let expectedPreloadRules1 = [
{
url: SHEET_A,
start: { line: 4, column: 1 },
selectorText: ".sheetA-test1"
},
{
url: SHEET_A,
start: { line: 12, column: 1 },
selectorText: ".sheetA-test3"
},
{
url: SHEET_B,
start: { line: 2, column: 1 },
selectorText: ".sheetB-test1"
},
{
url: SHEET_B,
start: { line: 10, column: 1 },
selectorText: ".sheetB-test3"
},
{
url: SHEET_D,
start: { line: 2, column: 1 },
selectorText: ".sheetD-test1"
},
{
url: SHEET_D,
start: { line: 10, column: 1 },
selectorText: ".sheetD-test3"
},
{
url: SHEET_C,
start: { line: 2, column: 1 },
selectorText: ".sheetC-test1"
},
{
url: SHEET_C,
start: { line: 10, column: 1 },
selectorText: ".sheetC-test3"
},
{
url: PAGE_1 + " \u2192 <style> index 0",
start: { line: 4, column: 5 },
selectorText: ".page1-test1"
},
{
url: PAGE_1 + " \u2192 <style> index 0",
start: { line: 12, column: 5 },
selectorText: ".page1-test3:hover"
}
];
isEqualJson(actualReport.preload[1].rules, expectedPreloadRules1, 'preload rules 1');
isEqualJson(actualReport.preload[2].url, PAGE_3, 'preload url 2');
let expectedPreloadRules2 = [
{
url: SHEET_A,
start: { line: 4, column: 1 },
selectorText: ".sheetA-test1"
},
{
url: SHEET_A,
start: { line: 20, column: 1 },
selectorText: ".sheetA-test5"
},
{
url: SHEET_B,
start: { line: 2, column: 1 },
selectorText: ".sheetB-test1"
},
{
url: SHEET_B,
start: { line: 18, column: 1 },
selectorText: ".sheetB-test5"
},
{
url: SHEET_D,
start: { line: 2, column: 1 },
selectorText: ".sheetD-test1"
},
{
url: SHEET_D,
start: { line: 18, column: 1 },
selectorText: ".sheetD-test5"
},
{
url: SHEET_C,
start: { line: 2, column: 1 },
selectorText: ".sheetC-test1"
},
{
url: SHEET_C,
start: { line: 18, column: 1 },
selectorText: ".sheetC-test5"
},
{
url: PAGE_3 + " \u2192 <style> index 0",
start: { line: 5, column: 5 },
selectorText: ".page3-test1"
},
];
isEqualJson(actualReport.preload[2].rules, expectedPreloadRules2, 'preload rules 2');
}
/**
* Check that checkPageReport returns the expected unused JSON
*/
function checkPageReportUnused(actualReport) {
// Check the unused header
isEqualJson(actualReport.unused.length, 8, 'unused length');
// Check the unused rules
isEqualJson(actualReport.unused[0].url, PAGE_2 + " \u2192 <style> index 0", "unused url 0");
let expectedUnusedRules0 = [
{
url: PAGE_2 + " \u2192 <style> index 0",
start: { line: 9, column: 5 },
selectorText: ".page2-test2"
}
];
isEqualJson(actualReport.unused[0].rules, expectedUnusedRules0, 'unused rules 0');
isEqualJson(actualReport.unused[1].url, SHEET_A, "unused url 1");
let expectedUnusedRules1 = [
{
url: SHEET_A,
start: { line: 8, column: 1 },
selectorText: ".sheetA-test2"
}
];
isEqualJson(actualReport.unused[1].rules, expectedUnusedRules1, 'unused rules 1');
isEqualJson(actualReport.unused[2].url, SHEET_B, "unused url 2");
let expectedUnusedRules2 = [
{
url: SHEET_B,
start: { line: 6, column: 1 },
selectorText: ".sheetB-test2"
}
];
isEqualJson(actualReport.unused[2].rules, expectedUnusedRules2, 'unused rules 2');
isEqualJson(actualReport.unused[3].url, SHEET_D, "unused url 3");
let expectedUnusedRules3 = [
{
url: SHEET_D,
start: { line: 6, column: 1 },
selectorText: ".sheetD-test2"
}
];
isEqualJson(actualReport.unused[3].rules, expectedUnusedRules3, 'unused rules 3');
isEqualJson(actualReport.unused[4].url, SHEET_C, "unused url 4");
let expectedUnusedRules4 = [
{
url: SHEET_C,
start: { line: 6, column: 1 },
selectorText: ".sheetC-test2"
}
];
isEqualJson(actualReport.unused[4].rules, expectedUnusedRules4, 'unused rules 4');
isEqualJson(actualReport.unused[5].url, PAGE_1 + " \u2192 <style> index 0", "unused url 5");
let expectedUnusedRules5 = [
{
url: PAGE_1 + " \u2192 <style> index 0",
start: { line: 8, column: 5 },
selectorText: ".page1-test2"
}
];
isEqualJson(actualReport.unused[5].rules, expectedUnusedRules5, 'unused rules 5');
isEqualJson(actualReport.unused[6].url, PAGE_3 + " \u2192 <style> index 0", "unused url 6");
let expectedUnusedRules6 = [
{
url: PAGE_3 + " \u2192 <style> index 0",
start: { line: 9, column: 5 },
selectorText: ".page3-test2"
}
];
isEqualJson(actualReport.unused[6].rules, expectedUnusedRules6, 'unused rules 6');
isEqualJson(actualReport.unused[7].url, PAGE_3 + " \u2192 <style> index 1", "unused url 7");
let expectedUnusedRules7 = [
{
url: PAGE_3 + " \u2192 <style> index 1",
start: { line: 3, column: 5 },
selectorText: ".page3-test3"
}
];
isEqualJson(actualReport.unused[7].rules, expectedUnusedRules7, 'unused rules 7');
}
/**
* We do basic tests on the shortUrl and formattedCssText because they are
* very derivative, and so make for fragile tests, and having done those quick
* existence checks we remove them so the JSON check later can ignore them
*/
function checkRuleProperties(rule, index) {
is(typeof rule.shortUrl, "string", "typeof rule.shortUrl for " + index);
is(rule.shortUrl.indexOf("http://"), -1, "http not in rule.shortUrl for" + index);
delete rule.shortUrl;
is(typeof rule.formattedCssText, "string", "typeof rule.formattedCssText for " + index);
ok(rule.formattedCssText.indexOf("{") > 0, "{ in rule.formattedCssText for " + index);
delete rule.formattedCssText;
}
/**
* Utility to compare JSON structures
*/
function isEqualJson(o1, o2, msg) {
is(JSON.stringify(o1), JSON.stringify(o2), msg);
}

Просмотреть файл

@ -489,9 +489,9 @@ helpers._actual = {
},
unassigned: function(options) {
return options.requisition._unassigned.map(function(assignment) {
return options.requisition._unassigned.map(assignment => {
return assignment.arg.toString();
}.bind(this));
});
},
outputState: function(options) {
@ -540,7 +540,7 @@ helpers._createDebugCheck = function(options) {
var hintsPromise = helpers._actual.hints(options);
var predictionsPromise = helpers._actual.predictions(options);
return Promise.all(hintsPromise, predictionsPromise).then(function(values) {
return Promise.all(hintsPromise, predictionsPromise).then((values) => {
var hints = values[0];
var predictions = values[1];
var output = '';
@ -610,7 +610,7 @@ helpers._createDebugCheck = function(options) {
output += ']);';
return output;
}.bind(this), util.errorHandler);
}, util.errorHandler);
};
/**
@ -933,7 +933,7 @@ helpers._exec = function(options, name, expected) {
}
try {
return requisition.exec({ hidden: true }).then(function(output) {
return requisition.exec({ hidden: true }).then((output) => {
if ('type' in expected) {
assert.is(output.type,
expected.type,
@ -993,7 +993,7 @@ helpers._exec = function(options, name, expected) {
}
return { output: output, text: textOutput };
});
}.bind(this)).then(function(data) {
}).then(function(data) {
if (expected.error) {
cli.logErrors = origLogErrors;
}

Просмотреть файл

@ -273,25 +273,25 @@ DevTools.prototype = {
this._toolboxes.set(target, toolbox);
toolbox.once("destroyed", function() {
toolbox.once("destroyed", () => {
this._toolboxes.delete(target);
this.emit("toolbox-destroyed", target);
}.bind(this));
});
// If we were asked for a specific tool then we need to wait for the
// tool to be ready, otherwise we can just wait for toolbox open
if (toolId != null) {
toolbox.once(toolId + "-ready", function(event, panel) {
toolbox.once(toolId + "-ready", (event, panel) => {
this.emit("toolbox-ready", toolbox);
deferred.resolve(toolbox);
}.bind(this));
});
toolbox.open();
}
else {
toolbox.open().then(function() {
toolbox.open().then(() => {
deferred.resolve(toolbox);
this.emit("toolbox-ready", toolbox);
}.bind(this));
});
}
}

Просмотреть файл

@ -71,14 +71,14 @@ ToolSidebar.prototype = {
let tab = this._tabbox.tabs.appendItem();
tab.setAttribute("label", ""); // Avoid showing "undefined" while the tab is loading
let onIFrameLoaded = function() {
let onIFrameLoaded = () => {
tab.setAttribute("label", iframe.contentDocument.title);
iframe.removeEventListener("load", onIFrameLoaded, true);
if ("setPanel" in iframe.contentWindow) {
iframe.contentWindow.setPanel(this._toolPanel, iframe);
}
this.emit(id + "-ready");
}.bind(this);
};
iframe.addEventListener("load", onIFrameLoaded, true);
@ -101,9 +101,9 @@ ToolSidebar.prototype = {
// For some reason I don't understand, if we call this.select in this
// event loop (after inserting the tab), the tab will never get the
// the "selected" attribute set to true.
this._panelDoc.defaultView.setTimeout(function() {
this._panelDoc.defaultView.setTimeout(() => {
this.select(id);
}.bind(this), 10);
}, 10);
}
this.emit("new-tab-registered", id);

Просмотреть файл

@ -365,7 +365,7 @@ TabTarget.prototype = {
};
this.client.addListener("tabDetached", this._onTabDetached);
this._onTabNavigated = function onRemoteTabNavigated(aType, aPacket) {
this._onTabNavigated = (aType, aPacket) => {
let event = Object.create(null);
event.url = aPacket.url;
event.title = aPacket.title;
@ -381,7 +381,7 @@ TabTarget.prototype = {
this.emit("navigate", event);
this._navWindow = null;
}
}.bind(this);
};
this.client.addListener("tabNavigated", this._onTabNavigated);
},

Просмотреть файл

@ -122,11 +122,11 @@ DevToolPanel.prototype = {
open: function() {
let deferred = promise.defer();
executeSoon(function() {
executeSoon(() => {
this._isReady = true;
this.emit("ready");
deferred.resolve(this);
}.bind(this));
});
return deferred.promise;
},

Просмотреть файл

@ -48,7 +48,7 @@ function selectAndCheckById(id) {
}
function testToggle() {
toolbox.once("destroyed", function() {
toolbox.once("destroyed", () => {
// Cannot reuse a target after it's destroyed.
target = TargetFactory.forTab(gBrowser.selectedTab);
gDevTools.showToolbox(target, "styleeditor").then(function(aToolbox) {
@ -58,7 +58,7 @@ function testToggle() {
finishUp();
});
});
}.bind(this));
});
toolbox.destroy();
}

Просмотреть файл

@ -30,7 +30,7 @@ function test() {
isTargetSupported: function() true,
build: function(iframeWindow, toolbox) {
let deferred = promise.defer();
executeSoon(function() {
executeSoon(() => {
deferred.resolve({
target: toolbox.target,
toolbox: toolbox,
@ -38,7 +38,7 @@ function test() {
destroy: function(){},
panelDoc: iframeWindow.document,
});
}.bind(this));
});
return deferred.promise;
},
};

Просмотреть файл

@ -60,10 +60,10 @@ BottomHost.prototype = {
this._nbox.appendChild(this._splitter);
this._nbox.appendChild(this.frame);
let frameLoad = function() {
let frameLoad = () => {
this.emit("ready", this.frame);
deferred.resolve(this.frame);
}.bind(this);
};
this.frame.tooltip = "aHTMLTooltip";
@ -143,10 +143,10 @@ SidebarHost.prototype = {
this._sidebar.appendChild(this._splitter);
this._sidebar.appendChild(this.frame);
let frameLoad = function() {
let frameLoad = () => {
this.emit("ready", this.frame);
deferred.resolve(this.frame);
}.bind(this);
};
this.frame.tooltip = "aHTMLTooltip";
this.frame.setAttribute("src", "about:blank");
@ -213,14 +213,14 @@ WindowHost.prototype = {
let win = Services.ww.openWindow(null, this.WINDOW_URL, "_blank",
flags, null);
let frameLoad = function(event) {
let frameLoad = (event) => {
win.removeEventListener("load", frameLoad, true);
win.focus();
this.frame = win.document.getElementById("toolbox-iframe");
this.emit("ready", this.frame);
deferred.resolve(this.frame);
}.bind(this);
};
win.addEventListener("load", frameLoad, true);
win.addEventListener("unload", this._boundUnload);

Просмотреть файл

@ -101,12 +101,12 @@ HTMLBreadcrumbs.prototype = {
this.container._scrollButtonUp.collapsed = true;
this.container._scrollButtonDown.collapsed = true;
this.onscrollboxreflow = function() {
this.onscrollboxreflow = () => {
if (this.container._scrollButtonDown.collapsed)
this.container.removeAttribute("overflows");
else
this.container.setAttribute("overflows", true);
}.bind(this);
};
this.container.addEventListener("underflow", this.onscrollboxreflow, false);
this.container.addEventListener("overflow", this.onscrollboxreflow, false);
@ -480,9 +480,9 @@ HTMLBreadcrumbs.prototype = {
button.click();
}
button.onBreadcrumbsClick = function onBreadcrumbsClick() {
button.onBreadcrumbsClick = () => {
this.selection.setNodeFront(aNode, "breadcrumbs");
}.bind(this);
};
button.onclick = (function _onBreadcrumbsRightClick(event) {
button.focus();

Просмотреть файл

@ -136,7 +136,7 @@ InspectorPanel.prototype = {
// Show a warning when the debugger is paused.
// We show the warning only when the inspector
// is selected.
this.updateDebuggerPausedWarning = function() {
this.updateDebuggerPausedWarning = () => {
let notificationBox = this._toolbox.getNotificationBox();
let notification = notificationBox.getNotificationWithValue("inspector-script-paused");
if (!notification && this._toolbox.currentToolId == "inspector" &&
@ -154,7 +154,7 @@ InspectorPanel.prototype = {
notificationBox.removeNotification(notification);
}
}.bind(this);
};
this.target.on("thread-paused", this.updateDebuggerPausedWarning);
this.target.on("thread-resumed", this.updateDebuggerPausedWarning);
this._toolbox.on("select", this.updateDebuggerPausedWarning);
@ -164,7 +164,7 @@ InspectorPanel.prototype = {
this._initMarkup();
this.isReady = false;
this.once("markuploaded", function() {
this.once("markuploaded", () => {
this.isReady = true;
// All the components are initialized. Let's select a node.
@ -174,7 +174,7 @@ InspectorPanel.prototype = {
this.emit("ready");
deferred.resolve(this);
}.bind(this));
});
this.setupSearchBox();
this.setupSidebar();
@ -281,9 +281,9 @@ InspectorPanel.prototype = {
let defaultTab = Services.prefs.getCharPref("devtools.inspector.activeSidebar");
this._setDefaultSidebar = function(event, toolId) {
this._setDefaultSidebar = (event, toolId) => {
Services.prefs.setCharPref("devtools.inspector.activeSidebar", toolId);
}.bind(this);
};
this.sidebar.on("select", this._setDefaultSidebar);
@ -850,10 +850,10 @@ InspectorPanel.prototype = {
if (this._timer) {
return null;
}
this._timer = this.panelWin.setTimeout(function() {
this._timer = this.panelWin.setTimeout(() => {
this.emit("layout-change");
this._timer = null;
}.bind(this), LAYOUT_CHANGE_TIMER);
}, LAYOUT_CHANGE_TIMER);
}
},

Просмотреть файл

@ -231,12 +231,12 @@ MarkupView.prototype = {
},
update: function() {
let updateChildren = function(node) {
let updateChildren = (node) => {
this.getContainer(node).update();
for (let child of node.treeChildren()) {
updateChildren(child);
}
}.bind(this);
};
// Start with the documentElement
let documentElement;
@ -361,11 +361,15 @@ MarkupView.prototype = {
switch(aEvent.keyCode) {
case Ci.nsIDOMKeyEvent.DOM_VK_H:
let node = this._selectedContainer.node;
if (node.hidden) {
this.walker.unhideNode(node).then(() => this.nodeChanged(node));
if (aEvent.metaKey || aEvent.shiftKey) {
handled = false;
} else {
this.walker.hideNode(node).then(() => this.nodeChanged(node));
let node = this._selectedContainer.node;
if (node.hidden) {
this.walker.unhideNode(node).then(() => this.nodeChanged(node));
} else {
this.walker.hideNode(node).then(() => this.nodeChanged(node));
}
}
break;
case Ci.nsIDOMKeyEvent.DOM_VK_DELETE:
@ -1240,10 +1244,10 @@ MarkupView.prototype = {
this._previewBar.classList.add("hide");
win.clearTimeout(this._resizePreviewTimeout);
win.setTimeout(function() {
win.setTimeout(() => {
this._updatePreview();
this._previewBar.classList.remove("hide");
}.bind(this), 1000);
}, 1000);
}
};

Просмотреть файл

@ -52,7 +52,7 @@ function Cleopatra(panel, opts) {
// or when user clicks on start/stop buttons.
doc.getElementById("profiler-report").appendChild(this.iframe);
win.addEventListener("message", function (event) {
win.addEventListener("message", (event) => {
if (parseInt(event.data.uid, 10) !== parseInt(this.uid, 10)) {
return;
}
@ -65,7 +65,7 @@ function Cleopatra(panel, opts) {
case "displaysource":
this.panel.displaySource(event.data.data);
}
}.bind(this));
});
}
Cleopatra.prototype = {
@ -163,4 +163,5 @@ Cleopatra.prototype = {
}
};
module.exports = Cleopatra;
module.exports = Cleopatra;

Просмотреть файл

@ -18,6 +18,35 @@ var AppManagerRenderer = Class({
return AppProjectEditor;
}
},
getUI: function(parent) {
let doc = parent.ownerDocument;
if (parent.childElementCount == 0) {
let image = doc.createElement("image");
let optionImage = doc.createElement("image");
let flexElement = doc.createElement("div");
let nameLabel = doc.createElement("span");
let statusElement = doc.createElement("div");
image.className = "project-image";
optionImage.className = "project-options";
optionImage.setAttribute("src", OPTION_URL);
nameLabel.className = "project-name-label";
statusElement.className = "project-status";
flexElement.className = "project-flex";
parent.appendChild(image);
parent.appendChild(nameLabel);
parent.appendChild(flexElement);
parent.appendChild(statusElement);
parent.appendChild(optionImage);
}
return {
image: parent.querySelector(".project-image"),
nameLabel: parent.querySelector(".project-name-label"),
statusElement: parent.querySelector(".project-status")
};
},
onAnnotate: function(resource, editor, elt) {
if (resource.parent || !this.isAppManagerProject()) {
return;
@ -25,33 +54,16 @@ var AppManagerRenderer = Class({
let {appManagerOpts} = this.host.project;
let doc = elt.ownerDocument;
let image = doc.createElement("image");
let optionImage = doc.createElement("image");
let flexElement = doc.createElement("div");
let nameLabel = doc.createElement("span");
let statusElement = doc.createElement("div");
image.className = "project-image";
optionImage.className = "project-options";
nameLabel.className = "project-name-label";
statusElement.className = "project-status";
flexElement.className = "project-flex";
let {image,nameLabel,statusElement} = this.getUI(elt);
let name = appManagerOpts.name || resource.basename;
let url = appManagerOpts.iconUrl || "icon-sample.png";
let status = appManagerOpts.validationStatus || "unknown";
nameLabel.textContent = name;
image.setAttribute("src", url);
optionImage.setAttribute("src", OPTION_URL);
statusElement.setAttribute("status", status)
statusElement.setAttribute("status", status);
elt.innerHTML = "";
elt.appendChild(image);
elt.appendChild(nameLabel);
elt.appendChild(flexElement);
elt.appendChild(statusElement);
elt.appendChild(optionImage);
return true;
}
});

Просмотреть файл

@ -47,12 +47,7 @@ let test = asyncTest(function*() {
validationStatus: "error"
});
ok (!nameLabel.parentNode, "The old elements have been removed");
info ("Getting ahold of and validating the project header DOM");
let image = header.querySelector(".project-image");
let nameLabel = header.querySelector(".project-name-label");
let statusElement = header.querySelector(".project-status");
is (statusElement.getAttribute("status"), "error", "The status has been set correctly.");
is (nameLabel.textContent, "Test2", "The name label has been set correctly");
is (image.getAttribute("src"), "chrome://browser/skin/devtools/tool-inspector.svg", "The icon has been set correctly");
@ -65,12 +60,7 @@ let test = asyncTest(function*() {
validationStatus: "warning"
});
ok (!nameLabel.parentNode, "The old elements have been removed");
info ("Getting ahold of and validating the project header DOM");
let image = header.querySelector(".project-image");
let nameLabel = header.querySelector(".project-name-label");
let statusElement = header.querySelector(".project-status");
is (statusElement.getAttribute("status"), "warning", "The status has been set correctly.");
is (nameLabel.textContent, "Test3", "The name label has been set correctly");
is (image.getAttribute("src"), "chrome://browser/skin/devtools/tool-webconsole.svg", "The icon has been set correctly");
@ -83,12 +73,7 @@ let test = asyncTest(function*() {
validationStatus: "valid"
});
ok (!nameLabel.parentNode, "The old elements have been removed");
info ("Getting ahold of and validating the project header DOM");
let image = header.querySelector(".project-image");
let nameLabel = header.querySelector(".project-name-label");
let statusElement = header.querySelector(".project-status");
is (statusElement.getAttribute("status"), "valid", "The status has been set correctly.");
is (nameLabel.textContent, "Test4", "The name label has been set correctly");
is (image.getAttribute("src"), "chrome://browser/skin/devtools/tool-debugger.svg", "The icon has been set correctly");

Просмотреть файл

@ -36,7 +36,7 @@ this.SplitView = function SplitView(aRoot)
this._mql = aRoot.ownerDocument.defaultView.matchMedia(LANDSCAPE_MEDIA_QUERY);
// items list focus and search-on-type handling
this._nav.addEventListener("keydown", function onKeyCatchAll(aEvent) {
this._nav.addEventListener("keydown", (aEvent) => {
function getFocusedItemWithin(nav) {
let node = nav.ownerDocument.activeElement;
while (node && node.parentNode != nav) {
@ -77,7 +77,7 @@ this.SplitView = function SplitView(aRoot)
}
return false;
}
}.bind(this), false);
}, false);
}
SplitView.prototype = {
@ -196,10 +196,10 @@ SplitView.prototype = {
this._nav.appendChild(aSummary);
aSummary.addEventListener("click", function onSummaryClick(aEvent) {
aSummary.addEventListener("click", (aEvent) => {
aEvent.stopPropagation();
this.activeSummary = aSummary;
}.bind(this), false);
}, false);
this._side.appendChild(aDetails);

Просмотреть файл

@ -125,6 +125,16 @@ Telemetry.prototype = {
userHistogram: "DEVTOOLS_SHADEREDITOR_OPENED_PER_USER_FLAG",
timerHistogram: "DEVTOOLS_SHADEREDITOR_TIME_ACTIVE_SECONDS"
},
webaudioeditor: {
histogram: "DEVTOOLS_WEBAUDIOEDITOR_OPENED_BOOLEAN",
userHistogram: "DEVTOOLS_WEBAUDIOEDITOR_OPENED_PER_USER_FLAG",
timerHistogram: "DEVTOOLS_WEBAUDIOEDITOR_TIME_ACTIVE_SECONDS"
},
canvasdebugger: {
histogram: "DEVTOOLS_CANVASDEBUGGER_OPENED_BOOLEAN",
userHistogram: "DEVTOOLS_CANVASDEBUGGER_OPENED_PER_USER_FLAG",
timerHistogram: "DEVTOOLS_CANVASDEBUGGER_TIME_ACTIVE_SECONDS"
},
jsprofiler: {
histogram: "DEVTOOLS_JSPROFILER_OPENED_BOOLEAN",
userHistogram: "DEVTOOLS_JSPROFILER_OPENED_PER_USER_FLAG",

Просмотреть файл

@ -38,6 +38,8 @@ support-files =
[browser_telemetry_sidebar.js]
[browser_telemetry_toolbox.js]
[browser_telemetry_toolboxtabs_inspector.js]
[browser_telemetry_toolboxtabs_webaudioeditor.js]
[browser_telemetry_toolboxtabs_canvasdebugger.js]
[browser_telemetry_toolboxtabs_jsdebugger.js]
[browser_telemetry_toolboxtabs_jsprofiler.js]
[browser_telemetry_toolboxtabs_netmonitor.js]

Просмотреть файл

@ -0,0 +1,117 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
const TEST_URI = "data:text/html;charset=utf-8,<p>browser_telemetry_toolboxtabs_canvasdebugger.js</p>";
// Because we need to gather stats for the period of time that a tool has been
// opened we make use of setTimeout() to create tool active times.
const TOOL_DELAY = 200;
let {Promise: promise} = Cu.import("resource://gre/modules/devtools/deprecated-sync-thenables.js", {});
let {Services} = Cu.import("resource://gre/modules/Services.jsm", {});
let require = Cu.import("resource://gre/modules/devtools/Loader.jsm", {}).devtools.require;
let Telemetry = require("devtools/shared/telemetry");
let originalPref = Services.prefs.getBoolPref("devtools.canvasdebugger.enabled");
Services.prefs.setBoolPref("devtools.canvasdebugger.enabled", true);
function init() {
Telemetry.prototype.telemetryInfo = {};
Telemetry.prototype._oldlog = Telemetry.prototype.log;
Telemetry.prototype.log = function(histogramId, value) {
if (!this.telemetryInfo) {
// Can be removed when Bug 992911 lands (see Bug 1011652 Comment 10)
return;
}
if (histogramId) {
if (!this.telemetryInfo[histogramId]) {
this.telemetryInfo[histogramId] = [];
}
this.telemetryInfo[histogramId].push(value);
}
}
openToolboxTabTwice("canvasdebugger", false);
}
function openToolboxTabTwice(id, secondPass) {
let target = TargetFactory.forTab(gBrowser.selectedTab);
gDevTools.showToolbox(target, id).then(function(toolbox) {
info("Toolbox tab " + id + " opened");
toolbox.once("destroyed", function() {
if (secondPass) {
checkResults();
} else {
openToolboxTabTwice(id, true);
}
});
// We use a timeout to check the tools active time
setTimeout(function() {
gDevTools.closeToolbox(target);
}, TOOL_DELAY);
}).then(null, reportError);
}
function checkResults() {
let result = Telemetry.prototype.telemetryInfo;
for (let [histId, value] of Iterator(result)) {
if (histId.endsWith("OPENED_PER_USER_FLAG")) {
ok(value.length === 1 && value[0] === true,
"Per user value " + histId + " has a single value of true");
} else if (histId.endsWith("OPENED_BOOLEAN")) {
ok(value.length > 1, histId + " has more than one entry");
let okay = value.every(function(element) {
return element === true;
});
ok(okay, "All " + histId + " entries are === true");
} else if (histId.endsWith("TIME_ACTIVE_SECONDS")) {
ok(value.length > 1, histId + " has more than one entry");
let okay = value.every(function(element) {
return element > 0;
});
ok(okay, "All " + histId + " entries have time > 0");
}
}
finishUp();
}
function reportError(error) {
let stack = " " + error.stack.replace(/\n?.*?@/g, "\n JS frame :: ");
ok(false, "ERROR: " + error + " at " + error.fileName + ":" +
error.lineNumber + "\n\nStack trace:" + stack);
finishUp();
}
function finishUp() {
gBrowser.removeCurrentTab();
Telemetry.prototype.log = Telemetry.prototype._oldlog;
delete Telemetry.prototype._oldlog;
delete Telemetry.prototype.telemetryInfo;
Services.prefs.setBoolPref("devtools.canvasdebugger.enabled", originalPref);
TargetFactory = Services = promise = require = null;
finish();
}
function test() {
waitForExplicitFinish();
gBrowser.selectedTab = gBrowser.addTab();
gBrowser.selectedBrowser.addEventListener("load", function() {
gBrowser.selectedBrowser.removeEventListener("load", arguments.callee, true);
waitForFocus(init, content);
}, true);
content.location = TEST_URI;
}

Просмотреть файл

@ -0,0 +1,118 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
const TEST_URI = "data:text/html;charset=utf-8,<p>browser_telemetry_toolboxtabs_webaudioeditor.js</p>";
// Because we need to gather stats for the period of time that a tool has been
// opened we make use of setTimeout() to create tool active times.
const TOOL_DELAY = 200;
let {Promise: promise} = Cu.import("resource://gre/modules/devtools/deprecated-sync-thenables.js", {});
let {Services} = Cu.import("resource://gre/modules/Services.jsm", {});
let require = Cu.import("resource://gre/modules/devtools/Loader.jsm", {}).devtools.require;
let Telemetry = require("devtools/shared/telemetry");
let originalPref = Services.prefs.getBoolPref("devtools.webaudioeditor.enabled");
Services.prefs.setBoolPref("devtools.webaudioeditor.enabled", true);
function init() {
Telemetry.prototype.telemetryInfo = {};
Telemetry.prototype._oldlog = Telemetry.prototype.log;
Telemetry.prototype.log = function(histogramId, value) {
if (!this.telemetryInfo) {
// Can be removed when Bug 992911 lands (see Bug 1011652 Comment 10)
return;
}
if (histogramId) {
if (!this.telemetryInfo[histogramId]) {
this.telemetryInfo[histogramId] = [];
}
this.telemetryInfo[histogramId].push(value);
}
}
openToolboxTabTwice("webaudioeditor", false);
}
function openToolboxTabTwice(id, secondPass) {
let target = TargetFactory.forTab(gBrowser.selectedTab);
gDevTools.showToolbox(target, id).then(function(toolbox) {
info("Toolbox tab " + id + " opened");
toolbox.once("destroyed", function() {
if (secondPass) {
checkResults();
} else {
openToolboxTabTwice(id, true);
}
});
// We use a timeout to check the tools active time
setTimeout(function() {
gDevTools.closeToolbox(target);
}, TOOL_DELAY);
}).then(null, reportError);
}
function checkResults() {
let result = Telemetry.prototype.telemetryInfo;
for (let [histId, value] of Iterator(result)) {
if (histId.endsWith("OPENED_PER_USER_FLAG")) {
ok(value.length === 1 && value[0] === true,
"Per user value " + histId + " has a single value of true");
} else if (histId.endsWith("OPENED_BOOLEAN")) {
ok(value.length > 1, histId + " has more than one entry");
let okay = value.every(function(element) {
return element === true;
});
ok(okay, "All " + histId + " entries are === true");
} else if (histId.endsWith("TIME_ACTIVE_SECONDS")) {
ok(value.length > 1, histId + " has more than one entry");
let okay = value.every(function(element) {
return element > 0;
});
ok(okay, "All " + histId + " entries have time > 0");
}
}
finishUp();
}
function reportError(error) {
let stack = " " + error.stack.replace(/\n?.*?@/g, "\n JS frame :: ");
ok(false, "ERROR: " + error + " at " + error.fileName + ":" +
error.lineNumber + "\n\nStack trace:" + stack);
finishUp();
}
function finishUp() {
gBrowser.removeCurrentTab();
Telemetry.prototype.log = Telemetry.prototype._oldlog;
delete Telemetry.prototype._oldlog;
delete Telemetry.prototype.telemetryInfo;
Services.prefs.setBoolPref("devtools.webaudioeditor.enabled", originalPref);
TargetFactory = Services = promise = require = null;
finish();
}
function test() {
waitForExplicitFinish();
gBrowser.selectedTab = gBrowser.addTab();
gBrowser.selectedBrowser.addEventListener("load", function() {
gBrowser.selectedBrowser.removeEventListener("load", arguments.callee, true);
waitForFocus(init, content);
}, true);
content.location = TEST_URI;
}

Просмотреть файл

@ -58,10 +58,10 @@ function runTest(index) {
var ais = is.bind(this);
function createTester(holder, options) {
return function() {
return () => {
ais(holder.innerHTML, options.later, options.name + ' later');
runNextTest();
}.bind(this);
};
}
executeSoon(createTester(holder, options));

Просмотреть файл

@ -134,13 +134,13 @@ StyleEditorUI.prototype = {
this._view = new SplitView(viewRoot);
wire(this._view.rootElement, ".style-editor-newButton", function onNew() {
wire(this._view.rootElement, ".style-editor-newButton", () =>{
this._debuggee.addStyleSheet(null).then(this._onStyleSheetCreated);
}.bind(this));
});
wire(this._view.rootElement, ".style-editor-importButton", function onImport() {
wire(this._view.rootElement, ".style-editor-importButton", ()=> {
this._importFromFile(this._mockImportFile || null, this._window);
}.bind(this));
});
this._optionsMenu = this._panelDoc.getElementById("style-editor-options-popup");
this._optionsMenu.addEventListener("popupshowing",
@ -300,7 +300,7 @@ StyleEditorUI.prototype = {
* Optional parent window for the file picker.
*/
_importFromFile: function(file, parentWindow) {
let onFileSelected = function(file) {
let onFileSelected = (file) => {
if (!file) {
// nothing selected
return;
@ -318,7 +318,7 @@ StyleEditorUI.prototype = {
});
});
}.bind(this);
};
showFilePicker(file, false, parentWindow, onFileSelected);
},
@ -430,11 +430,11 @@ StyleEditorUI.prototype = {
wire(summary, ".stylesheet-name", {
events: {
"keypress": function onStylesheetNameActivate(aEvent) {
"keypress": (aEvent) => {
if (aEvent.keyCode == aEvent.DOM_VK_RETURN) {
this._view.activeSummary = summary;
}
}.bind(this)
}
}
});
@ -494,7 +494,7 @@ StyleEditorUI.prototype = {
return;
}
let href = editor.styleSheet.href || editor.styleSheet.nodeHref;
let href = csscoverage.sheetToUrl(editor.styleSheet);
usage.createEditorReport(href).then(data => {
editor.removeAllUnusedRegions();

Просмотреть файл

@ -500,7 +500,7 @@ StyleSheetEditor.prototype = {
converter.charset = "UTF-8";
let istream = converter.convertToInputStream(this._state.text);
NetUtil.asyncCopy(istream, ostream, function onStreamCopied(status) {
NetUtil.asyncCopy(istream, ostream, (status) => {
if (!Components.isSuccessCode(status)) {
if (callback) {
callback(null);
@ -515,7 +515,7 @@ StyleSheetEditor.prototype = {
if (callback) {
callback(returnFile);
}
}.bind(this));
});
};
let defaultName;

Просмотреть файл

@ -429,10 +429,10 @@ CssHtmlTree.prototype = {
win.clearTimeout(this._filterChangedTimeout);
}
this._filterChangedTimeout = win.setTimeout(function() {
this._filterChangedTimeout = win.setTimeout(() => {
this.refreshPanel();
this._filterChangeTimeout = null;
}.bind(this), FILTER_CHANGED_TIMEOUT);
}, FILTER_CHANGED_TIMEOUT);
},
/**

Просмотреть файл

@ -18,6 +18,8 @@ const require = Cu.import("resource://gre/modules/devtools/Loader.jsm", {}).devt
const EventEmitter = require("devtools/toolkit/event-emitter");
const STRINGS_URI = "chrome://browser/locale/devtools/webaudioeditor.properties"
const L10N = new ViewHelpers.L10N(STRINGS_URI);
const Telemetry = require("devtools/shared/telemetry");
const telemetry = new Telemetry();
let { console } = Cu.import("resource://gre/modules/devtools/Console.jsm", {});
@ -144,6 +146,7 @@ let WebAudioEditorController = {
* Listen for events emitted by the current tab target.
*/
initialize: function() {
telemetry.toolOpened("webaudioeditor");
this._onTabNavigated = this._onTabNavigated.bind(this);
this._onThemeChange = this._onThemeChange.bind(this);
gTarget.on("will-navigate", this._onTabNavigated);
@ -169,6 +172,7 @@ let WebAudioEditorController = {
* Remove events emitted by the current tab target.
*/
destroy: function() {
telemetry.toolClosed("webaudioeditor");
gTarget.off("will-navigate", this._onTabNavigated);
gTarget.off("navigate", this._onTabNavigated);
gFront.off("start-context", this._onStartContext);

Просмотреть файл

@ -286,7 +286,7 @@ NetworkPanel.prototype =
return a.name.toLowerCase() < b.name.toLowerCase();
});
aList.forEach(function(aItem) {
aList.forEach((aItem) => {
let name = aItem.name;
if (aIgnoreCookie && (name == "Cookie" || name == "Set-Cookie")) {
return;
@ -332,7 +332,7 @@ NetworkPanel.prototype =
row.appendChild(td);
parent.appendChild(row);
}.bind(this));
});
},
/**
@ -612,7 +612,7 @@ NetworkPanel.prototype =
let content = this.httpActivity.response.content;
let longString = this.webconsole.webConsoleClient.longString(content.text);
longString.substring(longString.initial.length, longString.length,
function NP__onLongStringSubstring(aResponse)
(aResponse) =>
{
if (aResponse.error) {
Cu.reportError("NP__onLongStringSubstring error: " + aResponse.error);
@ -632,7 +632,7 @@ NetworkPanel.prototype =
this._appendTextNode("responseBody" + cached + "Content",
aResponse.substring);
}
}.bind(this));
});
},
/**
@ -779,7 +779,7 @@ NetworkPanel.prototype =
let postData = this.httpActivity.request.postData;
let longString = this.webconsole.webConsoleClient.longString(postData.text);
longString.substring(longString.initial.length, longString.length,
function NP__onLongStringSubstring(aResponse)
(aResponse) =>
{
if (aResponse.error) {
Cu.reportError("NP__onLongStringSubstring error: " + aResponse.error);
@ -788,7 +788,7 @@ NetworkPanel.prototype =
postData.text = postData.text.initial + aResponse.substring;
this._updateRequestBody();
}.bind(this));
});
},
};

Просмотреть файл

@ -1850,7 +1850,7 @@ WebConsoleFrame.prototype = {
let actor = aHttpActivity.actor;
if (actor) {
this.webConsoleClient.getRequestHeaders(actor, function(aResponse) {
this.webConsoleClient.getRequestHeaders(actor, (aResponse) => {
if (aResponse.error) {
Cu.reportError("WCF_openNetworkPanel getRequestHeaders:" +
aResponse.error);
@ -1860,10 +1860,10 @@ WebConsoleFrame.prototype = {
aHttpActivity.request.headers = aResponse.headers;
this.webConsoleClient.getRequestCookies(actor, onRequestCookies);
}.bind(this));
});
}
let onRequestCookies = function(aResponse) {
let onRequestCookies = (aResponse) => {
if (aResponse.error) {
Cu.reportError("WCF_openNetworkPanel getRequestCookies:" +
aResponse.error);
@ -1873,9 +1873,9 @@ WebConsoleFrame.prototype = {
aHttpActivity.request.cookies = aResponse.cookies;
this.webConsoleClient.getResponseHeaders(actor, onResponseHeaders);
}.bind(this);
};
let onResponseHeaders = function(aResponse) {
let onResponseHeaders = (aResponse) => {
if (aResponse.error) {
Cu.reportError("WCF_openNetworkPanel getResponseHeaders:" +
aResponse.error);
@ -1885,9 +1885,9 @@ WebConsoleFrame.prototype = {
aHttpActivity.response.headers = aResponse.headers;
this.webConsoleClient.getResponseCookies(actor, onResponseCookies);
}.bind(this);
};
let onResponseCookies = function(aResponse) {
let onResponseCookies = (aResponse) => {
if (aResponse.error) {
Cu.reportError("WCF_openNetworkPanel getResponseCookies:" +
aResponse.error);
@ -1897,9 +1897,9 @@ WebConsoleFrame.prototype = {
aHttpActivity.response.cookies = aResponse.cookies;
this.webConsoleClient.getRequestPostData(actor, onRequestPostData);
}.bind(this);
};
let onRequestPostData = function(aResponse) {
let onRequestPostData = (aResponse) => {
if (aResponse.error) {
Cu.reportError("WCF_openNetworkPanel getRequestPostData:" +
aResponse.error);
@ -1910,9 +1910,9 @@ WebConsoleFrame.prototype = {
aHttpActivity.discardRequestBody = aResponse.postDataDiscarded;
this.webConsoleClient.getResponseContent(actor, onResponseContent);
}.bind(this);
};
let onResponseContent = function(aResponse) {
let onResponseContent = (aResponse) => {
if (aResponse.error) {
Cu.reportError("WCF_openNetworkPanel getResponseContent:" +
aResponse.error);
@ -1923,9 +1923,9 @@ WebConsoleFrame.prototype = {
aHttpActivity.discardResponseBody = aResponse.contentDiscarded;
this.webConsoleClient.getEventTimings(actor, onEventTimings);
}.bind(this);
};
let onEventTimings = function(aResponse) {
let onEventTimings = (aResponse) => {
if (aResponse.error) {
Cu.reportError("WCF_openNetworkPanel getEventTimings:" +
aResponse.error);
@ -1935,9 +1935,9 @@ WebConsoleFrame.prototype = {
aHttpActivity.timings = aResponse.timings;
openPanel();
}.bind(this);
};
let openPanel = function() {
let openPanel = () => {
aNode._netPanel = netPanel;
let panel = netPanel.panel;
@ -1953,7 +1953,7 @@ WebConsoleFrame.prototype = {
});
aNode._panelOpen = true;
}.bind(this);
};
let netPanel = new NetworkPanel(this.popupset, aHttpActivity, this);
netPanel.linkNode = aNode;
@ -2911,9 +2911,9 @@ WebConsoleFrame.prototype = {
this._commandController = null;
let onDestroy = function() {
let onDestroy = () => {
this._destroyer.resolve(null);
}.bind(this);
};
if (this.proxy) {
this.proxy.disconnect().then(onDestroy);
@ -4850,12 +4850,12 @@ WebConsoleConnectionProxy.prototype = {
timeout, Ci.nsITimer.TYPE_ONE_SHOT);
let connPromise = this._connectDefer.promise;
connPromise.then(function _onSucess() {
connPromise.then(() => {
this._connectTimer.cancel();
this._connectTimer = null;
}.bind(this), function _onFailure() {
}, () => {
this._connectTimer = null;
}.bind(this));
});
let client = this.client = this.target.client;

Просмотреть файл

@ -116,6 +116,7 @@ let UI = {
this.updateTitle();
this.updateCommands();
this.updateProjectButton();
this.updateProjectEditorHeader();
break;
};
},
@ -290,6 +291,25 @@ let UI = {
return this.projecteditor.loaded;
},
updateProjectEditorHeader: function() {
let project = AppManager.selectedProject;
if (!project || !this.projecteditor) {
return;
}
let status = project.validationStatus || "unknown";
if (status == "error warning") {
status = "error";
}
this.getProjectEditor().then((projecteditor) => {
projecteditor.setProjectToAppPath(project.location, {
name: project.name,
iconUrl: project.icon,
projectOverviewURL: "chrome://webide/content/details.xhtml",
validationStatus: status
});
}, console.error);
},
isProjectEditorEnabled: function() {
return Services.prefs.getBoolPref("devtools.webide.showProjectEditor");
},
@ -333,12 +353,8 @@ let UI = {
detailsIframe.setAttribute("hidden", "true");
projecteditorIframe.removeAttribute("hidden");
this.getProjectEditor().then((projecteditor) => {
projecteditor.setProjectToAppPath(project.location, {
name: project.name,
iconUrl: project.icon,
projectOverviewURL: "chrome://webide/content/details.xhtml"
});
this.getProjectEditor().then(() => {
this.updateProjectEditorHeader();
}, console.error);
if (project.location) {

Просмотреть файл

@ -1,4 +1,4 @@
This is the pdf.js project output, https://github.com/mozilla/pdf.js
Current extension version is: 1.0.277
Current extension version is: 1.0.370

Просмотреть файл

@ -66,7 +66,12 @@ var DEFAULT_PREFERENCES = {
defaultZoomValue: '',
sidebarViewOnLoad: 0,
enableHandToolOnLoad: false,
enableWebGL: false
enableWebGL: false,
disableRange: false,
disableAutoFetch: false,
disableFontFace: false,
disableTextLayer: false,
useOnlyCssZoom: false
};

Просмотреть файл

@ -21,8 +21,8 @@ if (typeof PDFJS === 'undefined') {
(typeof window !== 'undefined' ? window : this).PDFJS = {};
}
PDFJS.version = '1.0.277';
PDFJS.build = '250d394';
PDFJS.version = '1.0.370';
PDFJS.build = '13efe84';
(function pdfjsWrapper() {
// Use strict in our context only - users might not want it
@ -883,15 +883,15 @@ function isBool(v) {
}
function isInt(v) {
return typeof v == 'number' && ((v | 0) == v);
return typeof v === 'number' && ((v | 0) === v);
}
function isNum(v) {
return typeof v == 'number';
return typeof v === 'number';
}
function isString(v) {
return typeof v == 'string';
return typeof v === 'string';
}
function isNull(v) {
@ -903,7 +903,7 @@ function isName(v) {
}
function isCmd(v, cmd) {
return v instanceof Cmd && (!cmd || v.cmd == cmd);
return v instanceof Cmd && (cmd === undefined || v.cmd === cmd);
}
function isDict(v, type) {
@ -914,7 +914,7 @@ function isDict(v, type) {
return true;
}
var dictType = v.get('Type');
return isName(dictType) && dictType.name == type;
return isName(dictType) && dictType.name === type;
}
function isArray(v) {
@ -922,13 +922,11 @@ function isArray(v) {
}
function isStream(v) {
return typeof v == 'object' && v !== null && v !== undefined &&
('getBytes' in v);
return typeof v === 'object' && v !== null && v.getBytes !== undefined;
}
function isArrayBuffer(v) {
return typeof v == 'object' && v !== null && v !== undefined &&
('byteLength' in v);
return typeof v === 'object' && v !== null && v.byteLength !== undefined;
}
function isRef(v) {
@ -1414,7 +1412,7 @@ var Annotation = (function AnnotationClosure() {
data &&
(!data.annotationFlags ||
!(data.annotationFlags & 0x22)) && // Hidden or NoView
data.rect); // rectangle is nessessary
data.rect); // rectangle is necessary
},
isPrintable: function Annotation_isPrintable() {
@ -1423,7 +1421,8 @@ var Annotation = (function AnnotationClosure() {
data &&
data.annotationFlags && // Default: not printable
data.annotationFlags & 0x4 && // Print
data.rect); // rectangle is nessessary
!(data.annotationFlags & 0x2) && // Hidden
data.rect); // rectangle is necessary
},
loadResources: function Annotation_loadResources(keys) {
@ -1548,7 +1547,9 @@ var Annotation = (function AnnotationClosure() {
if (annotation.isViewable() || annotation.isPrintable()) {
return annotation;
} else {
warn('unimplemented annotation type: ' + subtype);
if (SUPPORTED_TYPES.indexOf(subtype) === -1) {
warn('unimplemented annotation type: ' + subtype);
}
}
};
@ -2150,6 +2151,13 @@ PDFJS.disableCreateObjectURL = (PDFJS.disableCreateObjectURL === undefined ?
PDFJS.disableWebGL = (PDFJS.disableWebGL === undefined ?
true : PDFJS.disableWebGL);
/**
* Enables CSS only zooming.
* @var {boolean}
*/
PDFJS.useOnlyCssZoom = (PDFJS.useOnlyCssZoom === undefined ?
false : PDFJS.useOnlyCssZoom);
/**
* Controls the logging level.
* The constants from PDFJS.VERBOSITY_LEVELS should be used:
@ -2161,6 +2169,14 @@ PDFJS.disableWebGL = (PDFJS.disableWebGL === undefined ?
PDFJS.verbosity = (PDFJS.verbosity === undefined ?
PDFJS.VERBOSITY_LEVELS.warnings : PDFJS.verbosity);
/**
* The maximum supported canvas size in total pixels e.g. width * height.
* The default value is 4096 * 4096. Use -1 for no limit.
* @var {number}
*/
PDFJS.maxCanvasPixels = (PDFJS.maxCanvasPixels === undefined ?
16777216 : PDFJS.maxCanvasPixels);
/**
* Document initialization / loading parameters object.
*
@ -3793,6 +3809,8 @@ var CanvasGraphics = (function CanvasGraphicsClosure() {
// Defines the time the executeOperatorList is going to be executing
// before it stops and shedules a continue of execution.
var EXECUTION_TIME = 15;
// Defines the number of steps before checking the execution time
var EXECUTION_STEPS = 10;
function CanvasGraphics(canvasCtx, commonObjs, objs, imageLayer) {
this.ctx = canvasCtx;
@ -3998,49 +4016,54 @@ var CanvasGraphics = (function CanvasGraphicsClosure() {
}
}
function composeSMaskBackdrop(bytes, r0, g0, b0) {
var length = bytes.length;
for (var i = 3; i < length; i += 4) {
var alpha = bytes[i];
if (alpha === 0) {
bytes[i - 3] = r0;
bytes[i - 2] = g0;
bytes[i - 1] = b0;
} else if (alpha < 255) {
var alpha_ = 255 - alpha;
bytes[i - 3] = (bytes[i - 3] * alpha + r0 * alpha_) >> 8;
bytes[i - 2] = (bytes[i - 2] * alpha + g0 * alpha_) >> 8;
bytes[i - 1] = (bytes[i - 1] * alpha + b0 * alpha_) >> 8;
}
}
}
function composeSMaskAlpha(maskData, layerData) {
var length = maskData.length;
var scale = 1 / 255;
for (var i = 3; i < length; i += 4) {
var alpha = maskData[i];
layerData[i] = (layerData[i] * alpha * scale) | 0;
}
}
function composeSMaskLuminosity(maskData, layerData) {
var length = maskData.length;
for (var i = 3; i < length; i += 4) {
var y = ((maskData[i - 3] * 77) + // * 0.3 / 255 * 0x10000
(maskData[i - 2] * 152) + // * 0.59 ....
(maskData[i - 1] * 28)) | 0; // * 0.11 ....
layerData[i] = (layerData[i] * y) >> 16;
}
}
function genericComposeSMask(maskCtx, layerCtx, width, height,
subtype, backdrop) {
var addBackdropFn;
if (backdrop) {
addBackdropFn = function (r0, g0, b0, bytes) {
var length = bytes.length;
for (var i = 3; i < length; i += 4) {
var alpha = bytes[i] / 255;
if (alpha === 0) {
bytes[i - 3] = r0;
bytes[i - 2] = g0;
bytes[i - 1] = b0;
} else if (alpha < 1) {
var alpha_ = 1 - alpha;
bytes[i - 3] = (bytes[i - 3] * alpha + r0 * alpha_) | 0;
bytes[i - 2] = (bytes[i - 2] * alpha + g0 * alpha_) | 0;
bytes[i - 1] = (bytes[i - 1] * alpha + b0 * alpha_) | 0;
}
}
}.bind(null, backdrop[0], backdrop[1], backdrop[2]);
} else {
addBackdropFn = function () {};
}
var hasBackdrop = !!backdrop;
var r0 = hasBackdrop ? backdrop[0] : 0;
var g0 = hasBackdrop ? backdrop[1] : 0;
var b0 = hasBackdrop ? backdrop[2] : 0;
var composeFn;
if (subtype === 'Luminosity') {
composeFn = function (maskDataBytes, layerDataBytes) {
var length = maskDataBytes.length;
for (var i = 3; i < length; i += 4) {
var y = ((maskDataBytes[i - 3] * 77) + // * 0.3 / 255 * 0x10000
(maskDataBytes[i - 2] * 152) + // * 0.59 ....
(maskDataBytes[i - 1] * 28)) | 0; // * 0.11 ....
layerDataBytes[i] = (layerDataBytes[i] * y) >> 16;
}
};
composeFn = composeSMaskLuminosity;
} else {
composeFn = function (maskDataBytes, layerDataBytes) {
var length = maskDataBytes.length;
for (var i = 3; i < length; i += 4) {
var alpha = maskDataBytes[i];
layerDataBytes[i] = (layerDataBytes[i] * alpha / 255) | 0;
}
};
composeFn = composeSMaskAlpha;
}
// processing image in chunks to save memory
@ -4051,7 +4074,9 @@ var CanvasGraphics = (function CanvasGraphicsClosure() {
var maskData = maskCtx.getImageData(0, row, width, chunkHeight);
var layerData = layerCtx.getImageData(0, row, width, chunkHeight);
addBackdropFn(maskData.data);
if (hasBackdrop) {
composeSMaskBackdrop(maskData.data, r0, g0, b0);
}
composeFn(maskData.data, layerData.data);
maskCtx.putImageData(layerData, 0, row);
@ -4125,18 +4150,21 @@ var CanvasGraphics = (function CanvasGraphicsClosure() {
var argsArrayLen = argsArray.length;
// Sometimes the OperatorList to execute is empty.
if (argsArrayLen == i) {
if (argsArrayLen === i) {
return i;
}
var endTime = Date.now() + EXECUTION_TIME;
var chunkOperations = (argsArrayLen - i > EXECUTION_STEPS &&
typeof continueCallback === 'function');
var endTime = chunkOperations ? Date.now() + EXECUTION_TIME : 0;
var steps = 0;
var commonObjs = this.commonObjs;
var objs = this.objs;
var fnId;
while (true) {
if (stepper && i === stepper.nextBreakPoint) {
if (stepper !== undefined && i === stepper.nextBreakPoint) {
stepper.breakIt(i, continueCallback);
return i;
}
@ -4149,16 +4177,13 @@ var CanvasGraphics = (function CanvasGraphicsClosure() {
var deps = argsArray[i];
for (var n = 0, nn = deps.length; n < nn; n++) {
var depObjId = deps[n];
var common = depObjId.substring(0, 2) == 'g_';
var common = depObjId[0] === 'g' && depObjId[1] === '_';
var objsPool = common ? commonObjs : objs;
// If the promise isn't resolved yet, add the continueCallback
// to the promise and bail out.
if (!common && !objs.isResolved(depObjId)) {
objs.get(depObjId, continueCallback);
return i;
}
if (common && !commonObjs.isResolved(depObjId)) {
commonObjs.get(depObjId, continueCallback);
if (!objsPool.isResolved(depObjId)) {
objsPool.get(depObjId, continueCallback);
return i;
}
}
@ -4167,15 +4192,18 @@ var CanvasGraphics = (function CanvasGraphicsClosure() {
i++;
// If the entire operatorList was executed, stop as were done.
if (i == argsArrayLen) {
if (i === argsArrayLen) {
return i;
}
// If the execution took longer then a certain amount of time and
// `continueCallback` is specified, interrupt the execution.
if (continueCallback && Date.now() > endTime) {
continueCallback();
return i;
if (chunkOperations && ++steps > EXECUTION_STEPS) {
if (Date.now() > endTime) {
continueCallback();
return i;
}
steps = 0;
}
// If the operatorList isn't executed completely yet OR the execution
@ -4334,18 +4362,15 @@ var CanvasGraphics = (function CanvasGraphicsClosure() {
var old = this.current;
this.stateStack.push(old);
this.current = old.clone();
if (this.current.activeSMask) {
this.current.activeSMask = null;
}
this.current.activeSMask = null;
},
restore: function CanvasGraphics_restore() {
var prev = this.stateStack.pop();
if (prev) {
if (this.current.activeSMask) {
if (this.stateStack.length !== 0) {
if (this.current.activeSMask !== null) {
this.endSMaskGroup();
}
this.current = prev;
this.current = this.stateStack.pop();
this.ctx.restore();
}
},
@ -4901,7 +4926,7 @@ var CanvasGraphics = (function CanvasGraphicsClosure() {
// Color
getColorN_Pattern: function CanvasGraphics_getColorN_Pattern(IR) {
var pattern;
if (IR[0] == 'TilingPattern') {
if (IR[0] === 'TilingPattern') {
var color = IR[1];
pattern = new TilingPattern(IR, color, this.ctx, this.objs,
this.commonObjs, this.baseTransform);
@ -4977,13 +5002,13 @@ var CanvasGraphics = (function CanvasGraphicsClosure() {
this.save();
this.baseTransformStack.push(this.baseTransform);
if (matrix && isArray(matrix) && 6 == matrix.length) {
if (isArray(matrix) && 6 === matrix.length) {
this.transform.apply(this, matrix);
}
this.baseTransform = this.ctx.mozCurrentTransform;
if (bbox && isArray(bbox) && 4 == bbox.length) {
if (isArray(bbox) && 4 === bbox.length) {
var width = bbox[2] - bbox[0];
var height = bbox[3] - bbox[1];
this.rectangle(bbox[0], bbox[1], width, height);
@ -5135,7 +5160,7 @@ var CanvasGraphics = (function CanvasGraphicsClosure() {
matrix) {
this.save();
if (rect && isArray(rect) && 4 == rect.length) {
if (isArray(rect) && 4 === rect.length) {
var width = rect[2] - rect[0];
var height = rect[3] - rect[1];
this.rectangle(rect[0], rect[1], width, height);
@ -5453,7 +5478,7 @@ var CanvasGraphics = (function CanvasGraphicsClosure() {
consumePath: function CanvasGraphics_consumePath() {
var ctx = this.ctx;
if (this.pendingClip) {
if (this.pendingClip == EO_CLIP) {
if (this.pendingClip === EO_CLIP) {
if (ctx.mozFillRule !== undefined) {
ctx.mozFillRule = 'evenodd';
ctx.clip();

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -57,8 +57,7 @@ var NetworkManager = (function NetworkManagerClosure() {
}
function getArrayBuffer(xhr) {
var data = (xhr.mozResponseArrayBuffer || xhr.mozResponse ||
xhr.responseArrayBuffer || xhr.response);
var data = xhr.response;
if (typeof data !== 'string') {
return data;
}
@ -110,7 +109,7 @@ var NetworkManager = (function NetworkManagerClosure() {
pendingRequest.expectedStatus = 200;
}
xhr.mozResponseType = xhr.responseType = 'arraybuffer';
xhr.responseType = 'arraybuffer';
if (args.onProgress) {
xhr.onprogress = args.onProgress;

Просмотреть файл

@ -217,6 +217,8 @@ http://sourceforge.net/adobe/cmap/wiki/License/
<option title="" value="1.25">125%</option>
<option title="" value="1.5">150%</option>
<option title="" value="2">200%</option>
<option title="" value="3">300%</option>
<option title="" value="4">400%</option>
</select>
</span>
</div>

Просмотреть файл

@ -28,18 +28,17 @@ var DEFAULT_URL = 'compressed.tracemonkey-pldi-09.pdf';
var DEFAULT_SCALE = 'auto';
var DEFAULT_SCALE_DELTA = 1.1;
var UNKNOWN_SCALE = 0;
var CACHE_SIZE = 20;
var CACHE_SIZE = 10;
var CSS_UNITS = 96.0 / 72.0;
var SCROLLBAR_PADDING = 40;
var VERTICAL_PADDING = 5;
var MAX_AUTO_SCALE = 1.25;
var MIN_SCALE = 0.25;
var MAX_SCALE = 4.0;
var MAX_SCALE = 10.0;
var VIEW_HISTORY_MEMORY = 20;
var SCALE_SELECT_CONTAINER_PADDING = 8;
var SCALE_SELECT_PADDING = 22;
var THUMBNAIL_SCROLL_MARGIN = -19;
var USE_ONLY_CSS_ZOOM = false;
var CLEANUP_TIMEOUT = 30000;
var IGNORE_CURRENT_POSITION_ON_ZOOM = false;
var RenderingStates = {
@ -295,7 +294,7 @@ var Cache = function cacheCache(size) {
this.push = function cachePush(view) {
var i = data.indexOf(view);
if (i >= 0) {
data.splice(i);
data.splice(i, 1);
}
data.push(view);
if (data.length > size) {
@ -312,7 +311,12 @@ var DEFAULT_PREFERENCES = {
defaultZoomValue: '',
sidebarViewOnLoad: 0,
enableHandToolOnLoad: false,
enableWebGL: false
enableWebGL: false,
disableRange: false,
disableAutoFetch: false,
disableFontFace: false,
disableTextLayer: false,
useOnlyCssZoom: false
};
@ -2635,12 +2639,36 @@ var PDFView = {
var initializedPromise = Promise.all([
Preferences.get('enableWebGL').then(function resolved(value) {
PDFJS.disableWebGL = !value;
}, function rejected(reason) {}),
}),
Preferences.get('sidebarViewOnLoad').then(function resolved(value) {
self.preferenceSidebarViewOnLoad = value;
}, function rejected(reason) {})
}),
Preferences.get('disableTextLayer').then(function resolved(value) {
if (PDFJS.disableTextLayer === true) {
return;
}
PDFJS.disableTextLayer = value;
}),
Preferences.get('disableRange').then(function resolved(value) {
if (PDFJS.disableRange === true) {
return;
}
PDFJS.disableRange = value;
}),
Preferences.get('disableAutoFetch').then(function resolved(value) {
PDFJS.disableAutoFetch = value;
}),
Preferences.get('disableFontFace').then(function resolved(value) {
if (PDFJS.disableFontFace === true) {
return;
}
PDFJS.disableFontFace = value;
}),
Preferences.get('useOnlyCssZoom').then(function resolved(value) {
PDFJS.useOnlyCssZoom = value;
})
// TODO move more preferences and other async stuff here
]);
]).catch(function (reason) { });
return initializedPromise.then(function () {
PDFView.initialized = true;
@ -3584,6 +3612,8 @@ var PDFView = {
}
}
this.pdfDocument.cleanup();
ThumbnailView.tempImageCache = null;
},
getHighestPriority: function pdfViewGetHighestPriority(visible, views,
@ -3652,6 +3682,9 @@ var PDFView = {
},
setHash: function pdfViewSetHash(hash) {
var validFitZoomValues = ['Fit','FitB','FitH','FitBH',
'FitV','FitBV','FitR'];
if (!hash) {
return;
}
@ -3676,10 +3709,13 @@ var PDFView = {
// it should stay as it is.
var zoomArg = zoomArgs[0];
var zoomArgNumber = parseFloat(zoomArg);
var destName = 'XYZ';
if (zoomArgNumber) {
zoomArg = zoomArgNumber / 100;
} else if (validFitZoomValues.indexOf(zoomArg) >= 0) {
destName = zoomArg;
}
dest = [null, {name: 'XYZ'},
dest = [null, { name: destName },
zoomArgs.length > 1 ? (zoomArgs[1] | 0) : null,
zoomArgs.length > 2 ? (zoomArgs[2] | 0) : null,
zoomArg];
@ -3988,6 +4024,7 @@ var PageView = function pageView(container, id, scale,
this.scale = scale || 1.0;
this.viewport = defaultViewport;
this.pdfPageRotate = defaultViewport.rotation;
this.hasRestrictedScaling = false;
this.renderingState = RenderingStates.INITIAL;
this.resume = null;
@ -4058,7 +4095,13 @@ var PageView = function pageView(container, id, scale,
this.annotationLayer = null;
}
delete this.canvas;
if (this.canvas) {
// Zeroing the width and height causes Firefox to release graphics
// resources immediately, which can greatly reduce memory consumption.
this.canvas.width = 0;
this.canvas.height = 0;
delete this.canvas;
}
this.loadingIconDiv = document.createElement('div');
this.loadingIconDiv.className = 'loadingIcon';
@ -4078,8 +4121,23 @@ var PageView = function pageView(container, id, scale,
rotation: totalRotation
});
if (USE_ONLY_CSS_ZOOM && this.canvas) {
this.cssTransform(this.canvas);
var isScalingRestricted = false;
if (this.canvas && PDFJS.maxCanvasPixels > 0) {
var ctx = this.canvas.getContext('2d');
var outputScale = getOutputScale(ctx);
var pixelsInViewport = this.viewport.width * this.viewport.height;
var maxScale = Math.sqrt(PDFJS.maxCanvasPixels / pixelsInViewport);
if (((Math.floor(this.viewport.width) * outputScale.sx) | 0) *
((Math.floor(this.viewport.height) * outputScale.sy) | 0) >
PDFJS.maxCanvasPixels) {
isScalingRestricted = true;
}
}
if (this.canvas &&
(PDFJS.useOnlyCssZoom ||
(this.hasRestrictedScaling && isScalingRestricted))) {
this.cssTransform(this.canvas, true);
return;
} else if (this.canvas && !this.zoomLayer) {
this.zoomLayer = this.canvas.parentNode;
@ -4091,7 +4149,7 @@ var PageView = function pageView(container, id, scale,
this.reset(true);
};
this.cssTransform = function pageCssTransform(canvas) {
this.cssTransform = function pageCssTransform(canvas, redrawAnnotations) {
// Scale canvas, canvas wrapper, and page container.
var width = this.viewport.width;
var height = this.viewport.height;
@ -4154,7 +4212,7 @@ var PageView = function pageView(container, id, scale,
CustomStyle.setProp('transformOrigin', textLayerDiv, '0% 0%');
}
if (USE_ONLY_CSS_ZOOM && this.annotationLayer) {
if (redrawAnnotations && this.annotationLayer) {
setupAnnotations(div, this.pdfPage, this.viewport);
}
};
@ -4451,7 +4509,7 @@ var PageView = function pageView(container, id, scale,
var ctx = canvas.getContext('2d');
var outputScale = getOutputScale(ctx);
if (USE_ONLY_CSS_ZOOM) {
if (PDFJS.useOnlyCssZoom) {
var actualSizeViewport = viewport.clone({ scale: CSS_UNITS });
// Use a scale that will make the canvas be the original intended size
// of the page.
@ -4460,6 +4518,19 @@ var PageView = function pageView(container, id, scale,
outputScale.scaled = true;
}
if (PDFJS.maxCanvasPixels > 0) {
var pixelsInViewport = viewport.width * viewport.height;
var maxScale = Math.sqrt(PDFJS.maxCanvasPixels / pixelsInViewport);
if (outputScale.sx > maxScale || outputScale.sy > maxScale) {
outputScale.sx = maxScale;
outputScale.sy = maxScale;
outputScale.scaled = true;
this.hasRestrictedScaling = true;
} else {
this.hasRestrictedScaling = false;
}
}
canvas.width = (Math.floor(viewport.width) * outputScale.sx) | 0;
canvas.height = (Math.floor(viewport.height) * outputScale.sy) | 0;
canvas.style.width = Math.floor(viewport.width) + 'px';
@ -4542,8 +4613,6 @@ var PageView = function pageView(container, id, scale,
self.onAfterDraw();
}
cache.push(self);
var event = document.createEvent('CustomEvent');
event.initCustomEvent('pagerender', true, true, {
pageNumber: pdfPage.pageNumber
@ -4594,6 +4663,10 @@ var PageView = function pageView(container, id, scale,
setupAnnotations(div, pdfPage, this.viewport);
div.setAttribute('data-loaded', true);
// Add the page to the cache at the start of drawing. That way it can be
// evicted from the cache and destroyed even if we pause its rendering.
cache.push(this);
};
this.beforePrint = function pageViewBeforePrint() {
@ -4820,6 +4893,17 @@ var ThumbnailView = function thumbnailView(container, id, defaultViewport) {
this.hasImage = true;
};
function getTempCanvas(width, height) {
var tempCanvas = ThumbnailView.tempImageCache;
if (!tempCanvas) {
tempCanvas = document.createElement('canvas');
ThumbnailView.tempImageCache = tempCanvas;
}
tempCanvas.width = width;
tempCanvas.height = height;
return tempCanvas;
}
this.setImage = function thumbnailViewSetImage(img) {
if (!this.pdfPage) {
var promise = PDFView.getPage(this.id);
@ -4834,13 +4918,40 @@ var ThumbnailView = function thumbnailView(container, id, defaultViewport) {
}
this.renderingState = RenderingStates.FINISHED;
var ctx = this.getPageDrawContext();
ctx.drawImage(img, 0, 0, img.width, img.height,
var reducedImage = img;
var reducedWidth = img.width;
var reducedHeight = img.height;
// drawImage does an awful job of rescaling the image, doing it gradually
var MAX_SCALE_FACTOR = 2.0;
if (Math.max(img.width / ctx.canvas.width,
img.height / ctx.canvas.height) > MAX_SCALE_FACTOR) {
reducedWidth >>= 1;
reducedHeight >>= 1;
reducedImage = getTempCanvas(reducedWidth, reducedHeight);
var reducedImageCtx = reducedImage.getContext('2d');
reducedImageCtx.drawImage(img, 0, 0, img.width, img.height,
0, 0, reducedWidth, reducedHeight);
while (Math.max(reducedWidth / ctx.canvas.width,
reducedHeight / ctx.canvas.height) > MAX_SCALE_FACTOR) {
reducedImageCtx.drawImage(reducedImage,
0, 0, reducedWidth, reducedHeight,
0, 0, reducedWidth >> 1, reducedHeight >> 1);
reducedWidth >>= 1;
reducedHeight >>= 1;
}
}
ctx.drawImage(reducedImage, 0, 0, reducedWidth, reducedHeight,
0, 0, ctx.canvas.width, ctx.canvas.height);
this.hasImage = true;
};
};
ThumbnailView.tempImageCache = null;
var FIND_SCROLL_OFFSET_TOP = -50;
var FIND_SCROLL_OFFSET_LEFT = -400;
@ -5301,7 +5412,7 @@ function webViewerInitialized() {
}
if ('useOnlyCssZoom' in hashParams) {
USE_ONLY_CSS_ZOOM = (hashParams['useOnlyCssZoom'] === 'true');
PDFJS.useOnlyCssZoom = (hashParams['useOnlyCssZoom'] === 'true');
}
if ('verbosity' in hashParams) {
@ -5819,13 +5930,14 @@ window.addEventListener('keydown', function keydown(evt) {
break;
case 36: // home
if (PresentationMode.active) {
if (PresentationMode.active || PDFView.page > 1) {
PDFView.page = 1;
handled = true;
}
break;
case 35: // end
if (PresentationMode.active) {
if (PresentationMode.active ||
PDFView.page < PDFView.pdfDocument.numPages) {
PDFView.page = PDFView.pdfDocument.numPages;
handled = true;
}

Просмотреть файл

@ -168,8 +168,8 @@ helpManRequired=required
helpManOptional=optional
helpManDefault=optional, default=%S
# LOCALIZATION NOTE (helpIntro): This forms part of the output from the 'help'
# command. 'GCLI' is a project name and should be left untranslated.
# LOCALIZATION NOTE: This forms part of the output from the 'help' command.
# 'GCLI' is a project name and should be left untranslated.
helpIntro=GCLI is an experiment to create a highly usable command line for web developers.
# LOCALIZATION NOTE: Text shown as part of the output of the 'help' command

Просмотреть файл

@ -68,8 +68,8 @@
<!-- LOCALIZATION NOTE (options.enableChrome.label4): This is the label for the
- checkbox that toggles chrome debugging, i.e. devtools.chrome.enabled
- boolean preference in about:config, in the options panel. -->
<!ENTITY options.enableChrome.label4 "Enable chrome and addon debugging">
<!ENTITY options.enableChrome.tooltip2 "Turning this option on will allow you to use various developer tools in browser context and debug addons from the Add-On Manager">
<!ENTITY options.enableChrome.label4 "Enable chrome and add-on debugging">
<!ENTITY options.enableChrome.tooltip2 "Turning this option on will allow you to use various developer tools in browser context and debug add-ons from the Add-ons Manager">
<!-- LOCALIZATION NOTE (options.enableRemote.label3): This is the label for the
- checkbox that toggles remote debugging, i.e. devtools.debugger.remote-enabled

Просмотреть файл

@ -687,6 +687,7 @@ filefield {
border-radius: 2px;
background-color: #FBFBFB;
overflow-y: auto;
height: 500px;
}
#typeColumn,

Просмотреть файл

@ -54,6 +54,7 @@ _MOZBUILD_EXTERNAL_VARIABLES := \
JAR_MANIFEST \
JAVA_JAR_TARGETS \
JS_MODULES_PATH \
LD_VERSION_SCRIPT \
LIBRARY_NAME \
MODULE \
MSVC_ENABLE_PGO \

Просмотреть файл

@ -510,6 +510,10 @@ ifeq ($(OS_ARCH),Linux)
ifdef IS_COMPONENT
EXTRA_DSO_LDOPTS += -Wl,-Bsymbolic
endif
ifdef LD_VERSION_SCRIPT
EXTRA_DSO_LDOPTS += -Wl,--version-script,$(LD_VERSION_SCRIPT)
EXTRA_DEPS += $(LD_VERSION_SCRIPT)
endif
endif
#
@ -1020,6 +1024,10 @@ $(filter %.s,$(CPPSRCS:%.cc=%.s)): %.s: %.cc $(call mkdir_deps,$(MDDEPDIR))
$(REPORT_BUILD)
$(CCC) -S $(COMPILE_CXXFLAGS) $($(notdir $<)_FLAGS) $(TARGET_LOCAL_INCLUDES) $(_VPATH_SRCS)
$(filter %.s,$(CPPSRCS:%.cxx=%.s)): %.s: %.cpp $(call mkdir_deps,$(MDDEPDIR))
$(REPORT_BUILD)
$(CCC) -S $(COMPILE_CXXFLAGS) $($(notdir $<)_FLAGS) $(TARGET_LOCAL_INCLUDES) $(_VPATH_SRCS)
$(filter %.s,$(CSRCS:%.c=%.s)): %.s: %.c $(call mkdir_deps,$(MDDEPDIR))
$(REPORT_BUILD)
$(CC) -S $(COMPILE_CFLAGS) $($(notdir $<)_FLAGS) $(TARGET_LOCAL_INCLUDES) $(_VPATH_SRCS)
@ -1035,6 +1043,7 @@ ifneq (,$(filter %.i,$(MAKECMDGOALS)))
_group_srcs = $(sort $(patsubst %.$1,%.i,$(filter %.$1,$2 $(notdir $2))))
_PREPROCESSED_CPP_FILES := $(call _group_srcs,cpp,$(CPPSRCS))
_PREPROCESSED_CC_FILES := $(call _group_srcs,cc,$(CPPSRCS))
_PREPROCESSED_CXX_FILES := $(call _group_srcs,cxx,$(CPPSRCS))
_PREPROCESSED_C_FILES := $(call _group_srcs,c,$(CSRCS))
_PREPROCESSED_CMM_FILES := $(call _group_srcs,mm,$(CMMSRCS))
@ -1044,7 +1053,7 @@ VPATH += $(addprefix $(srcdir)/,$(sort $(dir $(CPPSRCS) $(CSRCS) $(CMMSRCS))))
# Make preprocessed files PHONY so they are always executed, since they are
# manual targets and we don't necessarily write to $@.
.PHONY: $(_PREPROCESSED_CPP_FILES) $(_PREPROCESSED_CC_FILES) $(_PREPROCESSED_C_FILES) $(_PREPROCESSED_CMM_FILES)
.PHONY: $(_PREPROCESSED_CPP_FILES) $(_PREPROCESSED_CC_FILES) $(_PREPROCESSED_CXX_FILES) $(_PREPROCESSED_C_FILES) $(_PREPROCESSED_CMM_FILES)
$(_PREPROCESSED_CPP_FILES): %.i: %.cpp $(call mkdir_deps,$(MDDEPDIR))
$(REPORT_BUILD)
@ -1056,6 +1065,11 @@ $(_PREPROCESSED_CC_FILES): %.i: %.cc $(call mkdir_deps,$(MDDEPDIR))
$(addprefix $(MKDIR) -p ,$(filter-out .,$(@D)))
$(CCC) -C $(PREPROCESS_OPTION)$@ $(COMPILE_CXXFLAGS) $($(notdir $<)_FLAGS) $(TARGET_LOCAL_INCLUDES) $(_VPATH_SRCS)
$(_PREPROCESSED_CXX_FILES): %.i: %.cxx $(call mkdir_deps,$(MDDEPDIR))
$(REPORT_BUILD)
$(addprefix $(MKDIR) -p ,$(filter-out .,$(@D)))
$(CCC) -C $(PREPROCESS_OPTION)$@ $(COMPILE_CXXFLAGS) $($(notdir $<)_FLAGS) $(TARGET_LOCAL_INCLUDES) $(_VPATH_SRCS)
$(_PREPROCESSED_C_FILES): %.i: %.c $(call mkdir_deps,$(MDDEPDIR))
$(REPORT_BUILD)
$(addprefix $(MKDIR) -p ,$(filter-out .,$(@D)))
@ -1074,7 +1088,7 @@ PP_UNIFIED ?= 1
# infinite loop if the filename doesn't exist in the unified source files.
ifndef PP_REINVOKE
MATCH_cpp = \(cpp\|cc\)
MATCH_cpp = \(cpp\|cc|cxx\)
UPPER_c = C
UPPER_cpp = CPP
UPPER_mm = CMM

Просмотреть файл

@ -2928,7 +2928,7 @@ dnl Checks for library functions.
dnl ========================================================
AC_PROG_GCC_TRADITIONAL
AC_FUNC_MEMCMP
AC_CHECK_FUNCS(stat64 lstat64 truncate64 statvfs64 statvfs statfs64 statfs getpagesize localtime_r)
AC_CHECK_FUNCS(stat64 lstat64 truncate64 statvfs64 statvfs statfs64 statfs getpagesize localtime_r arc4random arc4random_buf)
dnl check for clock_gettime(), the CLOCK_MONOTONIC clock
AC_CACHE_CHECK(for clock_gettime(CLOCK_MONOTONIC),
@ -3589,7 +3589,7 @@ MOZ_ARG_WITH_BOOL(system-nss,
_USE_SYSTEM_NSS=1 )
if test -n "$_USE_SYSTEM_NSS"; then
AM_PATH_NSS(3.16, [MOZ_NATIVE_NSS=1], [AC_MSG_ERROR([you don't have NSS installed or your version is too old])])
AM_PATH_NSS(3.16.1, [MOZ_NATIVE_NSS=1], [AC_MSG_ERROR([you don't have NSS installed or your version is too old])])
fi
if test -n "$MOZ_NATIVE_NSS"; then
@ -8803,6 +8803,7 @@ AC_SUBST(CPU_ARCH)
AC_SUBST(INTEL_ARCHITECTURE)
AC_SUBST(HAVE_TOOLCHAIN_SUPPORT_MSSSE3)
AC_SUBST(HAVE_TOOLCHAIN_SUPPORT_MSSE4_1)
AC_SUBST(GCC_USE_GNU_LD)
AC_SUBST(MOZ_CHROME_FILE_FORMAT)

Просмотреть файл

@ -1350,6 +1350,8 @@ private:
// Set if the element has a parser insertion mode other than "in body",
// per the HTML5 "Parse state" section.
ElementHasWeirdParserInsertionMode,
// Parser sets this flag if it has notified about the node.
ParserHasNotified,
// Guard value
BooleanFlagCount
};
@ -1490,6 +1492,8 @@ public:
bool IsScopedStyleRoot() { return GetBoolFlag(ElementIsScopedStyleRoot); }
bool HasRelevantHoverRules() const { return GetBoolFlag(NodeHasRelevantHoverRules); }
void SetHasRelevantHoverRules() { SetBoolFlag(NodeHasRelevantHoverRules); }
void SetParserHasNotified() { SetBoolFlag(ParserHasNotified); };
bool HasParserNotified() { return GetBoolFlag(ParserHasNotified); }
protected:
void SetParentIsContent(bool aValue) { SetBoolFlag(ParentIsContent, aValue); }
void SetInDocument() { SetBoolFlag(IsInDocument); }

Просмотреть файл

@ -559,7 +559,7 @@ WebSocket::Constructor(const GlobalObject& aGlobal,
}
nsRefPtr<WebSocket> webSocket = new WebSocket(ownerWindow);
nsresult rv = webSocket->Init(aGlobal.GetContext(), principal,
nsresult rv = webSocket->Init(aGlobal.Context(), principal,
aUrl, protocolArray);
if (NS_FAILED(rv)) {
aRv.Throw(rv);

Просмотреть файл

@ -52,8 +52,8 @@ ImageData::Constructor(const GlobalObject& aGlobal,
aRv.Throw(NS_ERROR_DOM_INDEX_SIZE_ERR);
return nullptr;
}
js::AssertSameCompartment(aGlobal.GetContext(), aGlobal.Get());
JSObject* data = Uint8ClampedArray::Create(aGlobal.GetContext(),
js::AssertSameCompartment(aGlobal.Context(), aGlobal.Get());
JSObject* data = Uint8ClampedArray::Create(aGlobal.Context(),
length.value());
if (!data) {
aRv.Throw(NS_ERROR_OUT_OF_MEMORY);

Просмотреть файл

@ -488,6 +488,26 @@ public:
mStatsShowing = aShow;
}
bool MozAllowCasting() const
{
return mAllowCasting;
}
void SetMozAllowCasting(bool aShow)
{
mAllowCasting = aShow;
}
bool MozIsCasting() const
{
return mIsCasting;
}
void SetMozIsCasting(bool aShow)
{
mIsCasting = aShow;
}
already_AddRefed<DOMMediaStream> GetMozSrcObject() const;
void SetMozSrcObject(DOMMediaStream& aValue);
@ -1093,6 +1113,14 @@ protected:
// video controls
bool mStatsShowing;
// The following two fields are here for the private storage of the builtin
// video controls, and control 'casting' of the video to external devices
// (TVs, projectors etc.)
// True if casting is currently allowed
bool mAllowCasting;
// True if currently casting this video
bool mIsCasting;
// True if the sound is being captured.
bool mAudioCaptured;

Просмотреть файл

@ -1992,6 +1992,8 @@ HTMLMediaElement::HTMLMediaElement(already_AddRefed<nsINodeInfo>& aNodeInfo)
mPaused(true),
mMuted(0),
mStatsShowing(false),
mAllowCasting(false),
mIsCasting(false),
mAudioCaptured(false),
mPlayingBeforeSeek(false),
mPausedForInactiveDocumentOrChannel(false),

Просмотреть файл

@ -13,14 +13,16 @@
#include "nsDOMSettableTokenList.h"
#include "nsFormSubmission.h"
NS_IMPL_NS_NEW_HTML_ELEMENT(Output)
NS_IMPL_NS_NEW_HTML_ELEMENT_CHECK_PARSER(Output)
namespace mozilla {
namespace dom {
HTMLOutputElement::HTMLOutputElement(already_AddRefed<nsINodeInfo>& aNodeInfo)
HTMLOutputElement::HTMLOutputElement(already_AddRefed<nsINodeInfo>& aNodeInfo,
FromParser aFromParser)
: nsGenericHTMLFormElement(aNodeInfo)
, mValueModeFlag(eModeDefault)
, mIsDoneAddingChildren(!aFromParser)
{
AddMutationObserver(this);
@ -93,6 +95,12 @@ HTMLOutputElement::ParseAttribute(int32_t aNamespaceID, nsIAtom* aAttribute,
aValue, aResult);
}
void
HTMLOutputElement::DoneAddingChildren(bool aHaveNotified)
{
mIsDoneAddingChildren = true;
}
EventStates
HTMLOutputElement::IntrinsicState() const
{
@ -170,7 +178,7 @@ HTMLOutputElement::HtmlFor()
void HTMLOutputElement::DescendantsChanged()
{
if (mValueModeFlag == eModeDefault) {
if (mIsDoneAddingChildren && mValueModeFlag == eModeDefault) {
if (!nsContentUtils::GetNodeTextContent(this, true, mDefaultValue)) {
NS_RUNTIMEABORT("OOM");
}

Просмотреть файл

@ -21,7 +21,8 @@ class HTMLOutputElement MOZ_FINAL : public nsGenericHTMLFormElement,
public:
using nsIConstraintValidation::GetValidationMessage;
HTMLOutputElement(already_AddRefed<nsINodeInfo>& aNodeInfo);
HTMLOutputElement(already_AddRefed<nsINodeInfo>& aNodeInfo,
FromParser aFromParser = NOT_FROM_PARSER);
virtual ~HTMLOutputElement();
// nsISupports
@ -39,6 +40,8 @@ public:
bool ParseAttribute(int32_t aNamespaceID, nsIAtom* aAttribute,
const nsAString& aValue, nsAttrValue& aResult) MOZ_OVERRIDE;
virtual void DoneAddingChildren(bool aHaveNotified) MOZ_OVERRIDE;
EventStates IntrinsicState() const MOZ_OVERRIDE;
virtual nsresult BindToTree(nsIDocument* aDocument, nsIContent* aParent,
@ -101,6 +104,7 @@ protected:
};
ValueModeFlag mValueModeFlag;
bool mIsDoneAddingChildren;
nsString mDefaultValue;
nsRefPtr<nsDOMSettableTokenList> mTokenList;
};

Просмотреть файл

@ -1966,6 +1966,25 @@ void MediaDecoderStateMachine::DecodeSeek()
video = mReader->FindStartTime(nextSampleStartTime);
}
if (seekTime > mediaTime &&
nextSampleStartTime < mediaTime &&
mSeekTarget.mType == SeekTarget::PrevSyncPoint) {
// We are doing a fastSeek, but we ended up *before* the previous
// playback position. This is surprising UX, so switch to an accurate
// seek and decode to the seek target. This is not conformant to the
// spec, fastSeek should always be fast, but until we get the time to
// change all Readers to seek to the keyframe after the currentTime
// in this case, we'll just decode forward. Bug 1026330.
ResetPlayback();
{
ReentrantMonitorAutoExit exitMon(mDecoder->GetReentrantMonitor());
res = mReader->DecodeToTarget(seekTime);
if (NS_SUCCEEDED(res)) {
video = mReader->FindStartTime(nextSampleStartTime);
}
}
}
// Setup timestamp state.
if (seekTime == mEndTime) {
newCurrentTime = mAudioStartTime = seekTime;

Просмотреть файл

@ -86,9 +86,9 @@ MediaKeyMessageEvent::Constructor(const GlobalObject& aGlobal,
if (aEventInitDict.mMessage.WasPassed()) {
const auto& a = aEventInitDict.mMessage.Value();
a.ComputeLengthAndData();
e->mMessage = Uint8Array::Create(aGlobal.GetContext(), owner, a.Length(), a.Data());
e->mMessage = Uint8Array::Create(aGlobal.Context(), owner, a.Length(), a.Data());
} else {
e->mMessage = Uint8Array::Create(aGlobal.GetContext(), owner, 0, nullptr);
e->mMessage = Uint8Array::Create(aGlobal.Context(), owner, 0, nullptr);
}
if (!e->mMessage) {
aRv.Throw(NS_ERROR_OUT_OF_MEMORY);

Просмотреть файл

@ -78,7 +78,7 @@ MediaKeyNeededEvent::Constructor(const GlobalObject& aGlobal,
!aEventInitDict.mInitData.Value().IsNull()) {
const auto& a = aEventInitDict.mInitData.Value().Value();
a.ComputeLengthAndData();
e->mInitData = Uint8Array::Create(aGlobal.GetContext(), owner, a.Length(), a.Data());
e->mInitData = Uint8Array::Create(aGlobal.Context(), owner, a.Length(), a.Data());
if (!e->mInitData) {
aRv.Throw(NS_ERROR_OUT_OF_MEMORY);
return nullptr;

Просмотреть файл

@ -0,0 +1,12 @@
<!DOCTYPE html>
<html class="reftest-wait">
<head>
</head>
<body>
<!-- This video file has a timescale of 0 in the mdhd atom -->
<video src="0-timescale.mp4"
onerror="document.documentElement.className=undefined"
onloadedmetadata="document.documentElement.className=undefined">
</video>
</body>
</html>

Двоичные данные
content/media/test/crashtests/0-timescale.mp4 Normal file

Двоичный файл не отображается.

Просмотреть файл

@ -1,3 +1,4 @@
skip-if(B2G) load 0-timescale.html
skip-if(B2G) load 459439-1.html # bug 888557
load 466607-1.html
load 466945-1.html

Просмотреть файл

@ -347,6 +347,7 @@ skip-if = buildapp == 'b2g' # bug 1021676
[test_error_in_video_document.html]
[test_error_on_404.html]
[test_fastSeek.html]
[test_fastSeek-forwards.html]
[test_info_leak.html]
[test_invalid_reject.html]
[test_load.html]

Просмотреть файл

@ -0,0 +1,74 @@
<!DOCTYPE HTML>
<html>
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=1022913
-->
<head>
<meta charset="utf-8">
<title>Test for Bug 1022913</title>
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
<script type="text/javascript" src="manifest.js"></script>
<script type="application/javascript">
// Test that if we're doing a fastSeek() forwards that we don't end up
// seeking backwards. This can happen if the keyframe before the seek
// target is before the current playback position. We'd prefer to seek to
// the keyframe after the seek target in this case, but we don't implement
// this yet (bug 1026330).
var manager = new MediaTestManager;
var onSecondSeekComplete = function(event) {
var v = event.target;
ok(v.currentTime >= v.firstSeekTarget, v.name + " seek never go backwards. time=" + v.currentTime + " firstSeekTarget=" + v.firstSeekTarget + " secondSeekTarget=" + v.secondSeekTarget);
manager.finished(v.token);
};
var onFirstSeekComplete = function(event) {
var v = event.target;
v.removeEventListener("seeked", onFirstSeekComplete);
// Seek to 75% of the way between the start and the first keyframe
// using fastSeek. We then test that the currentTime doesn't drop back
// to the previous keyframe, currentTime should go forwards.
v.addEventListener("seeked", onSecondSeekComplete);
v.secondSeekTarget = v.keyframes[1] * 0.75;
v.fastSeek(v.secondSeekTarget);
}
var onLoadedMetadata = function(event) {
// Seek to the mid-point between the start and the first keyframe.
var v = event.target;
v.addEventListener("seeked", onFirstSeekComplete);
v.firstSeekTarget = v.keyframes[1] * 0.5;
v.currentTime = v.firstSeekTarget;
}
function startTest(test, token) {
manager.started(token);
v = document.createElement("video");
v.src = test.name;
v.name = test.name;
v.preload = "metadata";
v.token = token;
v.target = 0;
v.keyframes = test.keyframes;
v.keyframeIndex = 0;
ok(v.keyframes.length >= 2, v.name + " - video should have at least two sync points");
v.addEventListener("loadedmetadata", onLoadedMetadata);
document.body.appendChild(v);
}
manager.runTests(gFastSeekTests, startTest);
</script>
</head>
<body>
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1022913">Mozilla Bug 1022913</a>
<p id="display"></p>
<div id="content" style="display: none">
</div>
<pre id="test">
</pre>
</body>
</html>

Просмотреть файл

@ -5,6 +5,8 @@
LIB_IS_C_ONLY = 1
include $(topsrcdir)/config/config.mk
ifeq ($(OS_ARCH),WINNT)
DEFFILE = $(CURDIR)/sqlite-processed.def
@ -20,10 +22,25 @@ sqlite-version.h: sqlite-version.py sqlite3.h
# We have to preprocess our def file because we need different symbols in debug
# builds exposed that are not built in non-debug builds.
$(DEFFILE): sqlite.def
@$(call py_action,preprocessor,$(DEFINES) \
@$(call py_action,preprocessor,$(DEFINES) $(XULPPFLAGS) \
$(srcdir)/sqlite.def -o $(DEFFILE))
export:: sqlite-version.h
else
ifndef MOZ_FOLD_LIBS
ifdef GCC_USE_GNU_LD
GARBAGE += \
$(LD_VERSION_SCRIPT) \
$(NULL)
# Convert to the format we need for ld.
$(LD_VERSION_SCRIPT): $(srcdir)/sqlite.def
@$(call py_action,convert_def_file, \
$(DEFINES) $(ACDEFINES) $(XULPPFLAGS) -o $@ $^)
endif
endif
endif
ifeq (Darwin,$(OS_TARGET))

Просмотреть файл

@ -74,6 +74,11 @@ if CONFIG['OS_ARCH'] == 'WINNT':
RCFILE = 'sqlite.rc'
RESFILE = 'sqlite.res'
if CONFIG['OS_ARCH'] == 'Linux' and \
not CONFIG['MOZ_FOLD_LIBS'] and \
CONFIG['GCC_USE_GNU_LD']:
LD_VERSION_SCRIPT = 'sqlite-processed.def'
# Suppress warnings in third-party code.
if CONFIG['GNU_CC']:
CFLAGS += [

Просмотреть файл

@ -126,6 +126,9 @@ EXPORTS
sqlite3_step
sqlite3_stmt_readonly
sqlite3_stmt_status
#ifdef XP_UNIX
sqlite3_temp_directory
#endif
sqlite3_thread_cleanup
sqlite3_total_changes
sqlite3_trace
@ -151,7 +154,7 @@ EXPORTS
sqlite3_vfs_unregister
sqlite3_vfs_register
sqlite3_vmprintf
#ifdef SQLITE_DEBUG
#ifdef DEBUG
sqlite3_mutex_held
sqlite3_mutex_notheld
#endif

Просмотреть файл

@ -25,7 +25,6 @@ public:
static already_AddRefed<Activity>
Constructor(const GlobalObject& aOwner,
JSContext* aCx,
const ActivityOptions& aOptions,
ErrorResult& aRv)
{
@ -36,7 +35,7 @@ public:
}
nsRefPtr<Activity> activity = new Activity(window);
aRv = activity->Initialize(window, aCx, aOptions);
aRv = activity->Initialize(window, aOwner.Context(), aOptions);
return activity.forget();
}

Просмотреть файл

@ -910,7 +910,7 @@ Console::Method(JSContext* aCx, MethodName aMethodName,
ErrorResult rv;
nsRefPtr<nsPerformance> performance = win->GetPerformance(rv);
if (rv.Failed()) {
if (rv.Failed() || !performance) {
return;
}

Просмотреть файл

@ -70,7 +70,7 @@ public:
// The context that this returns is not guaranteed to be in the compartment of
// the object returned from Get(), in fact it's generally in the caller's
// compartment.
JSContext* GetContext() const
JSContext* Context() const
{
return mCx;
}

Просмотреть файл

@ -1835,6 +1835,7 @@ GlobalObject::GlobalObject(JSContext* aCx, JSObject* aObject)
mCx(aCx),
mGlobalObject(nullptr)
{
MOZ_ASSERT(mCx);
JS::Rooted<JSObject*> obj(aCx, aObject);
if (js::IsWrapper(obj)) {
obj = js::CheckedUnwrap(obj, /* stopAtOuter = */ false);
@ -2437,7 +2438,7 @@ ConvertExceptionToPromise(JSContext* cx,
JS_ClearPendingException(cx);
ErrorResult rv;
nsRefPtr<Promise> promise = Promise::Reject(global, cx, exn, rv);
nsRefPtr<Promise> promise = Promise::Reject(global, exn, rv);
if (rv.Failed()) {
// We just give up. Make sure to not leak memory on the
// ErrorResult, but then just put the original exception back.

Просмотреть файл

@ -5726,8 +5726,9 @@ def isResultAlreadyAddRefed(extendedAttributes):
return 'resultNotAddRefed' not in extendedAttributes
def needCx(returnType, arguments, extendedAttributes, considerTypes):
return (considerTypes and
def needCx(returnType, arguments, extendedAttributes, considerTypes,
static=False):
return (not static and considerTypes and
(typeNeedsCx(returnType, True) or
any(typeNeedsCx(a.type) for a in arguments)) or
'implicitJSContext' in extendedAttributes)
@ -6057,10 +6058,11 @@ class CGPerSignatureCall(CGThing):
# For JS-implemented interfaces we do not want to base the
# needsCx decision on the types involved, just on our extended
# attributes.
# attributes. Also, JSContext is not needed for the static case
# since GlobalObject already contains the context.
needsCx = needCx(returnType, arguments, self.extendedAttributes,
not descriptor.interface.isJSImplemented())
if needsCx and not (static and descriptor.workers):
not descriptor.interface.isJSImplemented(), static)
if needsCx:
argsPre.append("cx")
needsUnwrap = False
@ -11708,7 +11710,7 @@ class CGNativeMember(ClassMethod):
args.insert(0, Argument("JS::Value", "aThisVal"))
# And jscontext bits.
if needCx(returnType, argList, self.extendedAttrs,
self.passJSBitsAsNeeded):
self.passJSBitsAsNeeded, self.member.isStatic()):
args.insert(0, Argument("JSContext*", "cx"))
if needScopeObject(returnType, argList, self.extendedAttrs,
self.descriptorProvider.wrapperCache,
@ -13647,7 +13649,7 @@ class CGEventMethod(CGNativeMember):
self.args.insert(0, Argument("mozilla::dom::EventTarget*", "aOwner"))
constructorForNativeCaller = CGNativeMember.declare(self, cgClass)
self.args = list(self.originalArgs)
if needCx(None, self.arguments(), [], True):
if needCx(None, self.arguments(), [], considerTypes=True, static=True):
self.args.insert(0, Argument("JSContext*", "aCx"))
self.args.insert(0, Argument("const GlobalObject&", "aGlobal"))
self.args.append(Argument('ErrorResult&', 'aRv'))
@ -13698,7 +13700,7 @@ class CGEventMethod(CGNativeMember):
""",
arg0=self.args[0].name,
arg1=self.args[1].name)
if needCx(None, self.arguments(), [], True):
if needCx(None, self.arguments(), [], considerTypes=True, static=True):
self.args.insert(0, Argument("JSContext*", "aCx"))
self.args.insert(0, Argument("const GlobalObject&", "aGlobal"))
self.args.append(Argument('ErrorResult&', 'aRv'))

Просмотреть файл

@ -151,7 +151,6 @@ public:
static
already_AddRefed<TestInterface> Test2(const GlobalObject&,
JSContext*,
const DictForConstructor&,
JS::Handle<JS::Value>,
JS::Handle<JSObject*>,
@ -682,8 +681,7 @@ public:
// Static methods and attributes
static void StaticMethod(const GlobalObject&, bool);
static void StaticMethodWithContext(const GlobalObject&, JSContext*,
JS::Value);
static void StaticMethodWithContext(const GlobalObject&, JS::Value);
static bool StaticAttribute(const GlobalObject&);
static void SetStaticAttribute(const GlobalObject&, bool);

Просмотреть файл

@ -196,7 +196,3 @@ disabled = bug 774100
# Disabled due to focus issues (no bug that I'm aware of)
[test_browserElement_oop_KeyEvents.html]
disabled =
# Disable due to certificate issue (no bug that I'm aware of)
[test_browserElement_inproc_ErrorSecurity.html]
skip-if = buildapp=='b2g'
disabled =

Просмотреть файл

@ -523,6 +523,7 @@ void
Event::SetEventType(const nsAString& aEventTypeArg)
{
if (mIsMainThreadEvent) {
mEvent->typeString.Truncate();
mEvent->userType =
nsContentUtils::GetEventIdAndAtom(aEventTypeArg, mEvent->eventStructType,
&(mEvent->message));

Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше