зеркало из https://github.com/mozilla/gecko-dev.git
Merge mozilla-central to b2g-inbound
This commit is contained in:
Коммит
61dfe39e65
|
@ -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
|
||||
|
|
|
@ -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) {};
|
|
@ -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>
|
|
@ -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>
|
Двоичный файл не отображается.
|
@ -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));
|
||||
|
|
Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше
Загрузка…
Ссылка в новой задаче