Merge m-c to b2g-inbound.

This commit is contained in:
Ryan VanderMeulen 2014-02-06 16:33:35 -05:00
commit d126be5783
127 changed files with 1391 additions and 640 deletions

View File

@ -3,7 +3,6 @@
- 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">
@ -17,7 +16,7 @@
<em:targetApplication>
<Description>
<em:id>{ec8030f7-c20a-464f-9b0e-13a3a9e97384}</em:id>
<em:minVersion>21.0</em:minVersion>
<em:minVersion>26.0</em:minVersion>
<em:maxVersion>29.0a1</em:maxVersion>
</Description>
</em:targetApplication>

View File

@ -34,8 +34,15 @@ const { events: stateEvents } = require('../state/events');
const { events: viewEvents } = require('./view/events');
const events = require('../../event/utils');
const { id: addonID } = require('../../self');
const { identify } = require('../id');
const buttons = new Map();
const toWidgetId = id =>
('action-button--' + addonID.toLowerCase()+ '-' + id).
replace(/[^a-z0-9_-]/g, '');
const ActionButton = Class({
extends: EventTarget,
implements: [
@ -48,32 +55,37 @@ const ActionButton = Class({
disabled: false
}, buttonContract(options));
let id = toWidgetId(options.id);
register(this, state);
// Setup listeners.
setListeners(this, options);
buttons.set(options.id, this);
buttons.set(id, this);
view.create(state);
view.create(merge({}, state, { id: id }));
},
dispose: function dispose() {
buttons.delete(this.id);
let id = toWidgetId(this.id);
buttons.delete(id);
off(this);
view.dispose(this.id);
view.dispose(id);
unregister(this);
},
get id() this.state().id,
click: function click() { view.click(this.id) }
click: function click() { view.click(toWidgetId(this.id)) }
});
exports.ActionButton = ActionButton;
identify.define(ActionButton, ({id}) => toWidgetId(id));
let actionButtonStateEvents = events.filter(stateEvents,
e => e.target instanceof ActionButton);
@ -95,7 +107,7 @@ on(updateEvents, 'data', ({target: id, window}) => {
});
on(actionButtonStateEvents, 'data', ({target, window, state}) => {
let { id } = target;
let id = toWidgetId(target.id);
view.setIcon(id, window, state.icon);
view.setLabel(id, window, state.label);
view.setDisabled(id, window, state.disabled);

View File

@ -34,8 +34,15 @@ const { events: stateEvents } = require('../state/events');
const { events: viewEvents } = require('./view/events');
const events = require('../../event/utils');
const { id: addonID } = require('../../self');
const { identify } = require('../id');
const buttons = new Map();
const toWidgetId = id =>
('toggle-button--' + addonID.toLowerCase()+ '-' + id).
replace(/[^a-z0-9_-]/g, '');
const ToggleButton = Class({
extends: EventTarget,
implements: [
@ -49,32 +56,37 @@ const ToggleButton = Class({
checked: false
}, toggleButtonContract(options));
let id = toWidgetId(options.id);
register(this, state);
// Setup listeners.
setListeners(this, options);
buttons.set(options.id, this);
buttons.set(id, this);
view.create(merge({ type: 'checkbox' }, state));
view.create(merge({ type: 'checkbox' }, state, { id: id }));
},
dispose: function dispose() {
buttons.delete(this.id);
let id = toWidgetId(this.id);
buttons.delete(id);
off(this);
view.dispose(this.id);
view.dispose(id);
unregister(this);
},
get id() this.state().id,
click: function click() view.click(this.id)
click: function click() view.click(toWidgetId(this.id))
});
exports.ToggleButton = ToggleButton;
identify.define(ToggleButton, ({id}) => toWidgetId(id));
let toggleButtonStateEvents = events.filter(stateEvents,
e => e.target instanceof ToggleButton);
@ -85,7 +97,8 @@ let clickEvents = events.filter(toggleButtonViewEvents, e => e.type === 'click')
let updateEvents = events.filter(toggleButtonViewEvents, e => e.type === 'update');
on(toggleButtonStateEvents, 'data', ({target, window, state}) => {
let { id } = target;
let id = toWidgetId(target.id);
view.setIcon(id, window, state.icon);
view.setLabel(id, window, state.label);
view.setDisabled(id, window, state.disabled);

View File

@ -13,9 +13,7 @@ module.metadata = {
const { Cu } = require('chrome');
const { on, off, emit } = require('../../event/core');
const { id: addonID, data } = require('sdk/self');
const buttonPrefix =
'button--' + addonID.toLowerCase().replace(/[^a-z0-9-_]/g, '');
const { data } = require('sdk/self');
const { isObject } = require('../../lang/type');
@ -28,9 +26,6 @@ const { events: viewEvents } = require('./view/events');
const XUL_NS = 'http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul';
const toWidgetID = id => buttonPrefix + '-' + id;
const toButtonID = id => id.substr(buttonPrefix.length + 1);
const views = new Map();
const customizedWindows = new WeakMap();
@ -47,14 +42,14 @@ const buttonListener = {
customizedWindows.delete(window);
for (let [id, ] of views) {
let placement = CustomizableUI.getPlacementOfWidget(toWidgetID(id));
let placement = CustomizableUI.getPlacementOfWidget(id);
if (placement)
emit(viewEvents, 'data', { type: 'update', target: id, window: window });
}
},
onWidgetAfterDOMChange: (node, nextNode, container) => {
let id = toButtonID(node.id);
let { id } = node;
let view = views.get(id);
let window = node.ownerDocument.defaultView;
@ -73,11 +68,11 @@ require('../../system/unload').when( _ =>
function getNode(id, window) {
return !views.has(id) || ignoreWindow(window)
? null
: CustomizableUI.getWidget(toWidgetID(id)).forWindow(window).node
: CustomizableUI.getWidget(id).forWindow(window).node
};
function isInToolbar(id) {
let placement = CustomizableUI.getPlacementOfWidget(toWidgetID(id));
let placement = CustomizableUI.getPlacementOfWidget(id);
return placement && CustomizableUI.getAreaType(placement.area) === 'toolbar';
}
@ -120,7 +115,7 @@ function create(options) {
throw new Error('The ID "' + id + '" seems already used.');
CustomizableUI.createWidget({
id: toWidgetID(id),
id: id,
type: 'custom',
removable: true,
defaultArea: AREA_NAVBAR,
@ -131,7 +126,7 @@ function create(options) {
let node = document.createElementNS(XUL_NS, 'toolbarbutton');
let image = getImage(icon, false, window.devicePixelRatio);
let image = getImage(icon, true, window.devicePixelRatio);
if (ignoreWindow(window))
node.style.display = 'none';
@ -170,7 +165,7 @@ function dispose(id) {
if (!views.has(id)) return;
views.delete(id);
CustomizableUI.destroyWidget(toWidgetID(id));
CustomizableUI.destroyWidget(id);
}
exports.dispose = dispose;

View File

@ -8,7 +8,6 @@ DEFAULT_COMMON_PREFS = {
# sets this preference)
'browser.dom.window.dump.enabled': True,
# warn about possibly incorrect code
'javascript.options.strict': True,
'javascript.options.showInConsole': True,
# Allow remote connections to the debugger

View File

@ -106,12 +106,24 @@ if not mswindows:
class Popen(subprocess.Popen):
kill_called = False
if mswindows:
def _execute_child(self, args, executable, preexec_fn, close_fds,
cwd, env, universal_newlines, startupinfo,
creationflags, shell,
p2cread, p2cwrite,
c2pread, c2pwrite,
errread, errwrite):
def _execute_child(self, *args_tuple):
# workaround for bug 958609
if sys.hexversion < 0x02070600: # prior to 2.7.6
(args, executable, preexec_fn, close_fds,
cwd, env, universal_newlines, startupinfo,
creationflags, shell,
p2cread, p2cwrite,
c2pread, c2pwrite,
errread, errwrite) = args_tuple
to_close = set()
else: # 2.7.6 and later
(args, executable, preexec_fn, close_fds,
cwd, env, universal_newlines, startupinfo,
creationflags, shell, to_close,
p2cread, p2cwrite,
c2pread, c2pwrite,
errread, errwrite) = args_tuple
if not isinstance(args, types.StringTypes):
args = subprocess.list2cmdline(args)

View File

@ -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 = {
@ -11,7 +10,7 @@ module.metadata = {
};
const { isTabOpen, activateTab, openTab,
closeTab, getURI } = require('sdk/tabs/utils');
closeTab, getTabURL, getWindowHoldingTab } = require('sdk/tabs/utils');
const windows = require('sdk/deprecated/window-utils');
const { LoaderWithHookedConsole } = require('sdk/test/loader');
const { setTimeout } = require('sdk/timers');
@ -19,10 +18,27 @@ const { is } = require('sdk/system/xul-app');
const tabs = require('sdk/tabs');
const isAustralis = "gCustomizeMode" in windows.activeBrowserWindow;
const { set: setPref } = require("sdk/preferences/service");
const { defer } = require('sdk/core/promise');
const DEPRECATE_PREF = "devtools.errorconsole.deprecation_warnings";
let uri = require('sdk/self').data.url('index.html');
function closeTabPromise(tab) {
let { promise, resolve } = defer();
let url = getTabURL(tab);
tabs.on('close', function onCloseTab(t) {
if (t.url == url) {
tabs.removeListener('close', onCloseTab);
setTimeout(_ => resolve(tab))
}
});
closeTab(tab);
return promise;
}
function isChromeVisible(window) {
let x = window.document.documentElement.getAttribute('disablechrome')
return x !== 'true';
@ -61,11 +77,12 @@ exports['test that add-on page has no chrome'] = function(assert, done) {
assert.equal(isChromeVisible(window), is('Fennec') || isAustralis,
'chrome is not visible for addon page');
closeTab(tab);
assert.ok(isChromeVisible(window), 'chrome is visible again');
loader.unload();
assert.ok(!isTabOpen(tab), 'add-on page tab is closed on unload');
done();
closeTabPromise(tab).then(function() {
assert.ok(isChromeVisible(window), 'chrome is visible again');
loader.unload();
assert.ok(!isTabOpen(tab), 'add-on page tab is closed on unload');
done();
}).then(null, assert.fail);
});
};
@ -86,11 +103,12 @@ exports['test that add-on page with hash has no chrome'] = function(assert, done
assert.equal(isChromeVisible(window), is('Fennec') || isAustralis,
'chrome is not visible for addon page');
closeTab(tab);
assert.ok(isChromeVisible(window), 'chrome is visible again');
loader.unload();
assert.ok(!isTabOpen(tab), 'add-on page tab is closed on unload');
done();
closeTabPromise(tab).then(function() {
assert.ok(isChromeVisible(window), 'chrome is visible again');
loader.unload();
assert.ok(!isTabOpen(tab), 'add-on page tab is closed on unload');
done();
}).then(null, assert.fail);
});
};
@ -111,11 +129,12 @@ exports['test that add-on page with querystring has no chrome'] = function(asser
assert.equal(isChromeVisible(window), is('Fennec') || isAustralis,
'chrome is not visible for addon page');
closeTab(tab);
assert.ok(isChromeVisible(window), 'chrome is visible again');
loader.unload();
assert.ok(!isTabOpen(tab), 'add-on page tab is closed on unload');
done();
closeTabPromise(tab).then(function() {
assert.ok(isChromeVisible(window), 'chrome is visible again');
loader.unload();
assert.ok(!isTabOpen(tab), 'add-on page tab is closed on unload');
done();
}).then(null, assert.fail);
});
};
@ -136,11 +155,12 @@ exports['test that add-on page with hash and querystring has no chrome'] = funct
assert.equal(isChromeVisible(window), is('Fennec') || isAustralis,
'chrome is not visible for addon page');
closeTab(tab);
assert.ok(isChromeVisible(window), 'chrome is visible again');
loader.unload();
assert.ok(!isTabOpen(tab), 'add-on page tab is closed on unload');
done();
closeTabPromise(tab).then(function() {
assert.ok(isChromeVisible(window), 'chrome is visible again');
loader.unload();
assert.ok(!isTabOpen(tab), 'add-on page tab is closed on unload');
done();
}).then(null, assert.fail);
});
};
@ -158,9 +178,10 @@ exports['test that malformed uri is not an addon-page'] = function(assert, done)
assert.ok(isChromeVisible(window), 'chrome is visible for malformed uri');
closeTab(tab);
loader.unload();
done();
closeTabPromise(tab).then(function() {
loader.unload();
done();
}).then(null, assert.fail);
});
};

View File

@ -25,6 +25,40 @@ 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)
});
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',
});
}
});
}
if (app.is('Firefox')) {
exports.testAOM = function(assert, done) {
tabs.open({
@ -41,7 +75,8 @@ if (app.is('Firefox')) {
'self.postMessage({\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' +
'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' +
@ -53,7 +88,8 @@ if (app.is('Firefox')) {
'pref: ele.getAttribute("pref"),\n' +
'type: ele.getAttribute("type"),\n' +
'title: ele.getAttribute("title"),\n' +
'desc: ele.getAttribute("desc")\n' +
'desc: ele.getAttribute("desc"),\n' +
'"data-jetpack-id": ele.getAttribute(\'data-jetpack-id\')\n' +
'}\n' +
'}\n' +
'}\n' +
@ -69,12 +105,14 @@ if (app.is('Firefox')) {
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 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 myHiddenInt
assert.equal(msg.myHiddenInt.type, undefined, 'myHiddenInt was not displayed');
@ -82,6 +120,9 @@ if (app.is('Firefox')) {
assert.equal(msg.myHiddenInt.title, undefined, 'myHiddenInt was not displayed');
assert.equal(msg.myHiddenInt.desc, undefined, 'myHiddenInt was not displayed');
// test sayHello
assert.equal(msg.sayHello['data-jetpack-id'], self.id, 'data-jetpack-id attribute value is correct');
tab.close(done);
}
});

View File

@ -19,5 +19,10 @@
"hidden": true,
"value": 5,
"title": "hidden-int"
}]
}, {
"name": "sayHello",
"type": "control",
"label": "Click me!",
"title": "hello"
}]
}

View File

@ -260,20 +260,22 @@ exports.testTabLocation = function(assert, done) {
// TEST: tab.close()
exports.testTabClose = function(assert, done) {
let url = "data:text/html;charset=utf-8,foo";
let testName = "testTabClose";
let url = "data:text/html;charset=utf-8," + testName;
assert.notEqual(tabs.activeTab.url, url, "tab is not the active tab");
tabs.on('ready', function onReady(tab) {
tabs.removeListener('ready', onReady);
tabs.once('ready', function onReady(tab) {
assert.equal(tabs.activeTab.url, tab.url, "tab is now the active tab");
assert.equal(url, tab.url, "tab url is the test url");
let secondOnCloseCalled = false;
// Bug 699450: Multiple calls to tab.close should not throw
tab.close(function() secondOnCloseCalled = true);
try {
tab.close(function () {
assert.notEqual(tabs.activeTab.url, url, "tab is no longer the active tab");
assert.ok(secondOnCloseCalled,
"The immediate second call to tab.close gots its callback fired");
"The immediate second call to tab.close happened");
assert.notEqual(tabs.activeTab.url, url, "tab is no longer the active tab");
done();
@ -282,7 +284,6 @@ exports.testTabClose = function(assert, done) {
catch(e) {
assert.fail("second call to tab.close() thrown an exception: " + e);
}
assert.notEqual(tabs.activeTab.url, url, "tab is no longer the active tab");
});
tabs.open(url);

View File

@ -21,7 +21,7 @@ function getWidget(buttonId, window = getMostRecentBrowserWindow()) {
const { AREA_NAVBAR } = CustomizableUI;
let widgets = CustomizableUI.getWidgetIdsInArea(AREA_NAVBAR).
filter((id) => id.startsWith('button--') && id.endsWith(buttonId));
filter((id) => id.startsWith('action-button--') && id.endsWith(buttonId));
if (widgets.length === 0)
throw new Error('Widget with id `' + id +'` not found.');
@ -594,6 +594,7 @@ exports['test button click'] = function(assert, done) {
then(done, assert.fail);
});
}).then(null, assert.fail);
}
exports['test button icon set'] = function(assert) {

View File

@ -21,7 +21,7 @@ function getWidget(buttonId, window = getMostRecentBrowserWindow()) {
const { AREA_NAVBAR } = CustomizableUI;
let widgets = CustomizableUI.getWidgetIdsInArea(AREA_NAVBAR).
filter((id) => id.startsWith('button--') && id.endsWith(buttonId));
filter((id) => id.startsWith('toggle-button--') && id.endsWith(buttonId));
if (widgets.length === 0)
throw new Error('Widget with id `' + id +'` not found.');

View File

@ -62,6 +62,13 @@ let devtoolsWidgetPanel = {
Services.obs.addObserver(this, 'remote-browser-frame-pending', false);
Services.obs.addObserver(this, 'in-process-browser-or-app-frame-shown', false);
Services.obs.addObserver(this, 'message-manager-disconnect', false);
let systemapp = document.querySelector('#systemapp').contentWindow;
let frames = systemapp.document.querySelectorAll('iframe[mozapp]');
for (let frame of frames) {
let manifestURL = frame.getAttribute("mozapp");
this.trackApp(manifestURL);
}
});
});
},

View File

@ -740,6 +740,7 @@ var PlacesMenuDNDHandler = {
_closeDelayMs: 500,
_loadTimer: null,
_closeTimer: null,
_closingTimerNode: null,
/**
* Called when the user enters the <menu> element during a drag.
@ -751,6 +752,15 @@ var PlacesMenuDNDHandler = {
if (!this._isStaticContainer(event.target))
return;
// If we re-enter the same menu or anchor before the close timer runs out,
// we should ensure that we do not close:
if (this._closeTimer && this._closingTimerNode === event.currentTarget) {
this._closeTimer.cancel();
this._closingTimerNode = null;
this._closeTimer = null;
}
PlacesControllerDragHelper.currentDropTarget = event.target;
let popup = event.target.lastChild;
if (this._loadTimer || popup.state === "showing" || popup.state === "open")
return;
@ -767,8 +777,6 @@ var PlacesMenuDNDHandler = {
/**
* Handles dragleave on the <menu> element.
* @returns true if the element is a container element (menu or
* menu-toolbarbutton), false otherwise.
*/
onDragLeave: function PMDH_onDragLeave(event) {
// Handle menu-button separate targets.
@ -781,6 +789,7 @@ var PlacesMenuDNDHandler = {
if (!this._isStaticContainer(event.target))
return;
PlacesControllerDragHelper.currentDropTarget = null;
let popup = event.target.lastChild;
if (this._loadTimer) {
@ -788,8 +797,10 @@ var PlacesMenuDNDHandler = {
this._loadTimer = null;
}
this._closeTimer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer);
this._closingTimerNode = event.currentTarget;
this._closeTimer.initWithCallback(function() {
this._closeTimer = null;
this._closingTimerNode = null;
let node = PlacesControllerDragHelper.currentDropTarget;
let inHierarchy = false;
while (node && !inHierarchy) {
@ -845,6 +856,7 @@ var PlacesMenuDNDHandler = {
PlacesUtils.bookmarks.DEFAULT_INDEX,
Ci.nsITreeView.DROP_ON);
PlacesControllerDragHelper.onDrop(ip, event.dataTransfer);
PlacesControllerDragHelper.currentDropTarget = null;
event.stopPropagation();
}
};

View File

@ -1032,6 +1032,9 @@ let SocialStatusWidgetListener = {
SocialStatus = {
populateToolbarPalette: function() {
this._toolbarHelper.populatePalette();
for (let provider of Social.providers)
this.updateButton(provider.origin);
},
removeProvider: function(origin) {

View File

@ -1049,7 +1049,7 @@
if (!this._previewMode) {
this.mCurrentTab.removeAttribute("unread");
this.selectedTab.lastAccessed = Date.now();
oldTab.lastAccessed = Date.now();
let oldFindBar = oldTab._findBar;
if (oldFindBar &&
@ -4719,10 +4719,19 @@
</getter>
</property>
<property name="lastAccessed">
<getter>
return this.selected ? Date.now() : this._lastAccessed;
</getter>
<setter>
this._lastAccessed = val;
</setter>
</property>
<field name="_lastAccessed">0</field>
<field name="mOverCloseButton">false</field>
<field name="mCorrespondingMenuitem">null</field>
<field name="closing">false</field>
<field name="lastAccessed">0</field>
<method name="_mouseenter">
<body><![CDATA[

View File

@ -1,26 +1,24 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
/**
* Test for bug 739866.
*
* 1. Adds a new tab (but doesn't select it)
* 2. Checks if timestamp on the new tab is 0
* 3. Selects the new tab, checks that the timestamp is updated (>0)
* 4. Selects the original tab & checks if new tab's timestamp has remained changed
*/
function test() {
let originalTab = gBrowser.selectedTab;
isnot(originalTab.lastAccessed, 0, "selectedTab has been selected");
ok(originalTab.lastAccessed <= Date.now(), "selectedTab has a valid timestamp");
let newTab = gBrowser.addTab("about:blank", {skipAnimation: true});
is(newTab.lastAccessed, 0, "Timestamp on the new tab is 0.");
is(newTab.lastAccessed, 0, "newTab hasn't been selected so far");
gBrowser.selectedTab = newTab;
let newTabAccessedDate = newTab.lastAccessed;
ok(newTabAccessedDate > 0, "Timestamp on the selected tab is more than 0.");
// Date.now is not guaranteed to be monotonic, so include one second of fudge.
let now = Date.now() + 1000;
ok(newTabAccessedDate <= now, "Timestamp less than or equal current Date: " + newTabAccessedDate + " <= " + now);
gBrowser.selectedTab = originalTab;
is(newTab.lastAccessed, newTabAccessedDate, "New tab's timestamp remains the same.");
isnot(newTab.lastAccessed, 0, "newTab has been selected");
ok(newTab.lastAccessed <= Date.now(), "newTab has a valid timestamp");
isnot(originalTab.lastAccessed, 0, "originalTab has been selected");
ok(originalTab.lastAccessed <= Date.now(), "originalTab has a valid timestamp");
ok(originalTab.lastAccessed <= newTab.lastAccessed,
"originalTab's timestamp must be lower than newTab's");
gBrowser.removeTab(newTab);
}

View File

@ -1188,6 +1188,12 @@ SourceScripts.prototype = {
return;
}
if (aResponse.sources.length === 0) {
DebuggerView.Sources.emptyText = L10N.getStr("noSourcesText");
window.emit(EVENTS.SOURCES_ADDED);
return;
}
// Add all the sources in the debugger view sources container.
for (let source of aResponse.sources) {
// Ignore bogus scripts, e.g. generated from 'clientEvaluate' packets.
@ -1690,11 +1696,10 @@ EventListeners.prototype = {
if (aResponse.error) {
const msg = "Error getting function definition site: " + aResponse.message;
DevToolsUtils.reportException("scheduleEventListenersFetch", msg);
deferred.reject(msg);
return;
} else {
aListener.function.url = aResponse.url;
}
aListener.function.url = aResponse.url;
deferred.resolve(aListener);
});

View File

@ -637,6 +637,8 @@ let DebuggerView = {
this.editor.clearHistory();
this._editorSource = {};
}
this.Sources.emptyText = L10N.getStr("loadingSourcesText");
},
_startup: null,

View File

@ -52,6 +52,7 @@ support-files =
doc_large-array-buffer.html
doc_minified.html
doc_minified_bogus_map.html
doc_no-page-sources.html
doc_pause-exceptions.html
doc_pretty-print.html
doc_pretty-print-2.html
@ -131,6 +132,7 @@ support-files =
[browser_dbg_location-changes-04-breakpoint.js]
[browser_dbg_multiple-windows.js]
[browser_dbg_navigation.js]
[browser_dbg_no-page-sources.js]
[browser_dbg_on-pause-highlight.js]
[browser_dbg_panel-size.js]
[browser_dbg_parser-01.js]

View File

@ -0,0 +1,50 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
/**
* Make sure the right text shows when the page has no sources.
*/
const TAB_URL = EXAMPLE_URL + "doc_no-page-sources.html";
let gTab, gDebuggee, gPanel, gDebugger;
let gEditor, gSources;
function test() {
initDebugger(TAB_URL).then(([aTab, aDebuggee, aPanel]) => {
gTab = aTab;
gDebuggee = aDebuggee;
gPanel = aPanel;
gDebugger = gPanel.panelWin;
gEditor = gDebugger.DebuggerView.editor;
gSources = gDebugger.DebuggerView.Sources;
reloadActiveTab(gPanel, gDebugger.EVENTS.SOURCES_ADDED)
.then(testSourcesEmptyText)
.then(() => closeDebuggerAndFinish(gPanel))
.then(null, aError => {
ok(false, "Got an error: " + aError.message + "\n" + aError.stack);
});
});
}
function testSourcesEmptyText() {
is(gSources.itemCount, 0,
"Found no entries in the sources widget.");
is(gEditor.getText().length, 0,
"The source editor should not have any text displayed.");
is(gDebugger.document.querySelector("#sources .side-menu-widget-empty-text").getAttribute("value"),
gDebugger.L10N.getStr("noSourcesText"),
"The sources widget should now display 'This page has no sources'.");
}
registerCleanupFunction(function() {
gTab = null;
gDebuggee = null;
gPanel = null;
gDebugger = null;
gEditor = null;
gSources = null;
});

View File

@ -0,0 +1,11 @@
<!-- Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ -->
<!doctype html>
<html>
<head>
<meta charset="utf-8"/>
<title>This page has no sources</title>
</head>
<body>
</body>
</html>

View File

@ -1103,9 +1103,7 @@ RequestsMenuView.prototype = Heritage.extend(WidgetMethods, {
// Skipping "blocked" because it doesn't work yet.
let timingsNode = $(".requests-menu-timings", target);
let startCapNode = $(".requests-menu-timings-cap.start", timingsNode);
let endCapNode = $(".requests-menu-timings-cap.end", timingsNode);
let firstBox;
let timingsTotal = $(".requests-menu-timings-total", timingsNode);
// Add a set of boxes representing timing information.
for (let key of sections) {
@ -1117,23 +1115,10 @@ RequestsMenuView.prototype = Heritage.extend(WidgetMethods, {
let timingBox = document.createElement("hbox");
timingBox.className = "requests-menu-timings-box " + key;
timingBox.setAttribute("width", width);
timingsNode.insertBefore(timingBox, endCapNode);
// Make the start cap inherit the aspect of the first timing box.
if (!firstBox) {
firstBox = timingBox;
startCapNode.classList.add(key);
}
// Same goes for the end cap, inherit the aspect of the last timing box.
endCapNode.classList.add(key);
timingsNode.insertBefore(timingBox, timingsTotal);
}
}
// Since at least one timing box should've been rendered, unhide the
// start and end timing cap nodes.
startCapNode.hidden = false;
endCapNode.hidden = false;
// Don't paint things while the waterfall view isn't even visible.
if (NetMonitorView.currentFrontendMode != "network-inspector-view") {
return;
@ -1174,8 +1159,6 @@ RequestsMenuView.prototype = Heritage.extend(WidgetMethods, {
// accurately translate and resize as needed.
for (let { target, attachment } of this) {
let timingsNode = $(".requests-menu-timings", target);
let startCapNode = $(".requests-menu-timings-cap.start", target);
let endCapNode = $(".requests-menu-timings-cap.end", target);
let totalNode = $(".requests-menu-timings-total", target);
let direction = window.isRTL ? -1 : 1;
@ -1192,8 +1175,6 @@ RequestsMenuView.prototype = Heritage.extend(WidgetMethods, {
let revScaleX = "scaleX(" + (1 / scale) + ")";
timingsNode.style.transform = scaleX + " " + translateX;
startCapNode.style.transform = revScaleX + " translateX(" + (direction * 0.5) + "px)";
endCapNode.style.transform = revScaleX + " translateX(" + (direction * -0.5) + "px)";
totalNode.style.transform = revScaleX;
}
},

View File

@ -161,8 +161,6 @@
flex="1">
<hbox class="requests-menu-timings"
align="center">
<hbox class="start requests-menu-timings-cap" hidden="true"/>
<hbox class="end requests-menu-timings-cap" hidden="true"/>
<label class="plain requests-menu-timings-total"/>
</hbox>
</hbox>

View File

@ -55,6 +55,7 @@ function StyleEditorUI(debuggee, target, panelDoc) {
this.editors = [];
this.selectedEditor = null;
this.savedLocations = {};
this._updateSourcesLabel = this._updateSourcesLabel.bind(this);
this._onStyleSheetCreated = this._onStyleSheetCreated.bind(this);
@ -104,13 +105,14 @@ StyleEditorUI.prototype = {
let toolbox = gDevTools.getToolbox(this._target);
return toolbox.initInspector().then(() => {
this._walker = toolbox.walker;
}).then(() => this.createUI())
.then(() => this._debuggee.getStyleSheets())
.then((styleSheets) => {
this._resetStyleSheetList(styleSheets);
}).then(() => {
this.createUI();
this._debuggee.getStyleSheets().then((styleSheets) => {
this._resetStyleSheetList(styleSheets);
this._target.on("will-navigate", this._clear);
this._target.on("navigate", this._onNewDocument);
this._target.on("will-navigate", this._clear);
this._target.on("navigate", this._onNewDocument);
});
});
},
@ -166,30 +168,6 @@ StyleEditorUI.prototype = {
})
},
/**
* Remove all editors and add loading indicator.
*/
_clear: function() {
// remember selected sheet and line number for next load
if (this.selectedEditor && this.selectedEditor.sourceEditor) {
let href = this.selectedEditor.styleSheet.href;
let {line, ch} = this.selectedEditor.sourceEditor.getCursor();
this._styleSheetToSelect = {
href: href,
line: line,
col: ch
};
}
this._clearStyleSheetEditors();
this._view.removeAll();
this.selectedEditor = null;
this._root.classList.add("loading");
},
/**
* Add editors for all the given stylesheets to the UI.
*
@ -208,6 +186,37 @@ StyleEditorUI.prototype = {
this.emit("stylesheets-reset");
},
/**
* Remove all editors and add loading indicator.
*/
_clear: function() {
// remember selected sheet and line number for next load
if (this.selectedEditor && this.selectedEditor.sourceEditor) {
let href = this.selectedEditor.styleSheet.href;
let {line, ch} = this.selectedEditor.sourceEditor.getCursor();
this._styleSheetToSelect = {
href: href,
line: line,
col: ch
};
}
// remember saved file locations
for (let editor of this.editors) {
if (editor.savedFile) {
this.savedLocations[editor.styleSheet.href] = editor.savedFile;
}
}
this._clearStyleSheetEditors();
this._view.removeAll();
this.selectedEditor = null;
this._root.classList.add("loading");
},
/**
* Add an editor for this stylesheet. Add editors for its original sources
* instead (e.g. Sass sources), if applicable.
@ -247,6 +256,12 @@ StyleEditorUI.prototype = {
* Optional if stylesheet is a new sheet created by user
*/
_addStyleSheetEditor: function(styleSheet, file, isNew) {
// recall location of saved file for this sheet after page reload
let savedFile = this.savedLocations[styleSheet.href];
if (savedFile && !file) {
file = savedFile;
}
let editor =
new StyleSheetEditor(styleSheet, this._window, file, isNew, this._walker);

View File

@ -77,6 +77,10 @@ noGlobalsText=No globals
# when there are no scripts.
noSourcesText=This page has no sources.
# LOCALIZATION NOTE (loadingSourcesText): The text to display in the sources menu
# when waiting for scripts to load.
loadingSourcesText=Waiting for sources...
# LOCALIZATION NOTE (noEventListenersText): The text to display in the events tab
# when there are no events.
noEventListenersText=No event listeners to display

View File

@ -185,7 +185,7 @@ browser.jar:
skin/classic/browser/devtools/breadcrumbs-divider@2x.png (../shared/devtools/images/breadcrumbs-divider@2x.png)
skin/classic/browser/devtools/breadcrumbs-scrollbutton.png (../shared/devtools/images/breadcrumbs-scrollbutton.png)
skin/classic/browser/devtools/breadcrumbs-scrollbutton@2x.png (../shared/devtools/images/breadcrumbs-scrollbutton@2x.png)
skin/classic/browser/devtools/splitview.css (../shared/devtools/splitview.css)
* skin/classic/browser/devtools/splitview.css (../shared/devtools/splitview.css)
skin/classic/browser/devtools/styleeditor.css (../shared/devtools/styleeditor.css)
* skin/classic/browser/devtools/shadereditor.css (devtools/shadereditor.css)
* skin/classic/browser/devtools/debugger.css (devtools/debugger.css)

View File

@ -295,7 +295,7 @@ browser.jar:
skin/classic/browser/devtools/breadcrumbs-divider@2x.png (../shared/devtools/images/breadcrumbs-divider@2x.png)
skin/classic/browser/devtools/breadcrumbs-scrollbutton.png (../shared/devtools/images/breadcrumbs-scrollbutton.png)
skin/classic/browser/devtools/breadcrumbs-scrollbutton@2x.png (../shared/devtools/images/breadcrumbs-scrollbutton@2x.png)
skin/classic/browser/devtools/splitview.css (../shared/devtools/splitview.css)
* skin/classic/browser/devtools/splitview.css (../shared/devtools/splitview.css)
skin/classic/browser/devtools/styleeditor.css (../shared/devtools/styleeditor.css)
* skin/classic/browser/devtools/shadereditor.css (devtools/shadereditor.css)
* skin/classic/browser/devtools/debugger.css (devtools/debugger.css)

View File

@ -5,6 +5,12 @@
%filter substitution
%define menuPanelWidth 22.35em
% XXXgijs This is the ugliest bit of code I think I've ever written for Mozilla.
% Basically, the 0.1px is there to avoid CSS rounding errors causing buttons to wrap.
% For gory details, refer to https://bugzilla.mozilla.org/show_bug.cgi?id=963365#c11
% There's no calc() here (and therefore lots of calc() where this is used) because
% we don't support nested calc(): https://bugzilla.mozilla.org/show_bug.cgi?id=968761
%define menuPanelButtonWidth (@menuPanelWidth@ / 3 - 0.1px)
%define exitSubviewGutterWidth 38px
%define buttonStateHover :not(:-moz-any([disabled],[open],[checked="true"],:active)):-moz-any(:hover,[_moz-menuactive])
%define buttonStateActive :not([disabled]):-moz-any([open],[checked="true"],:hover:active,[_moz-menuactive]:active)
@ -177,7 +183,7 @@ toolbaritem[cui-areatype="menu-panel"][sdkstylewidget="true"]:not(.panel-wide-it
.panel-customization-placeholder-child {
-moz-appearance: none;
-moz-box-orient: vertical;
width: calc(@menuPanelWidth@ / 3);
width: calc(@menuPanelButtonWidth@);
height: calc(40px + 4em);
}
@ -189,7 +195,7 @@ toolbaritem[cui-areatype="menu-panel"][sdkstylewidget="true"]:not(.panel-wide-it
.panelUI-grid .toolbarbutton-1 > .toolbarbutton-menubutton-button {
-moz-appearance: none;
-moz-box-orient: vertical;
width: calc(@menuPanelWidth@ / 3 - 2px);
width: calc(@menuPanelButtonWidth@ - 2px);
height: calc(38px + 4em);
margin-top: 3px; /* Hack needed to get type=menu-button to properly align vertically. */
border: 0;
@ -232,7 +238,7 @@ toolbaritem[cui-areatype="menu-panel"][sdkstylewidget="true"]:not(.panel-wide-it
}
toolbaritem[cui-areatype="menu-panel"][sdkstylewidget="true"] {
width: calc(@menuPanelWidth@ / 3);
width: calc(@menuPanelButtonWidth@);
margin: 0 !important;
}
@ -258,18 +264,19 @@ toolbaritem[cui-areatype="menu-panel"][sdkstylewidget="true"]:not(.panel-wide-it
.panel-customization-placeholder-child > .toolbarbutton-icon {
min-width: 32px;
min-height: 32px;
/* Explanation for calc((A / B - C) / D), simplified to calc(X / Y - Z):
A / B (@menuPanelWidth@ / 3)
Each button is @menuPanelWidth@ / 3 wide.
C (46px)
/* Explanation for the below formula (A / B - C)
A
Each button is @menuPanelButtonWidth@ wide
B
Each button has two margins.
C (46px / 2 = 23px)
The button icon is 32 pixels wide.
The button has 12px of horizontal padding (6 on each side).
The button has 2px of horizontal border (1 on each side).
Total width of button should therefore be 46px.
D (2)
Divide by 2 since each button has two horizontal margins.
Total width of button's icon + button padding should therefore be 46px,
which means each horizontal margin should be the half the button's width - (46/2) px.
*/
margin: 4px calc(@menuPanelWidth@ / 6 - 23px);
margin: 4px calc(@menuPanelButtonWidth@ / 2 - 23px);
}
toolbarpaletteitem[place="palette"] > toolbaritem > toolbarbutton {
@ -642,8 +649,8 @@ toolbarpaletteitem[place="palette"] > #search-container {
-moz-box-flex: 1;
/* reduce the width with 2px for each button to compensate for two separators
of 3px. */
min-width: calc(@menuPanelWidth@ / 3 - 2px);
max-width: calc(@menuPanelWidth@ / 3 - 2px);
min-width: calc(@menuPanelButtonWidth@ - 2px);
max-width: calc(@menuPanelButtonWidth@ - 2px);
/* We'd prefer to use height: auto here but it leads to layout bugs in the panel. Cope:
1.2em for line height + 2 * .5em padding + margin on the label (2 * 2px) */
height: calc(2.2em + 4px);

View File

@ -158,81 +158,51 @@ box.requests-menu-status {
}
.theme-dark box.requests-menu-status:not([code]) {
box-shadow:
0 0 0 1px rgba(255,255,255,0.4) inset,
0 -6px 4px 0 rgba(32,32,32,1.0) inset,
0 0 8px 0 rgba(32,0,0,0.4);
background-color: rgba(95, 115, 135, 1); /* dark grey */
}
.theme-light box.requests-menu-status:not([code]) {
box-shadow:
0 0 0 1px rgba(255,255,255,0.4) inset,
0 -6px 4px 0 rgba(32,32,32, 0.5) inset;
background-color: rgba(143, 161, 178, 1); /* grey */
}
.theme-dark box.requests-menu-status[code^="1"] {
box-shadow:
0 0 2px 1px rgba(255,255,255,0.8) inset,
0 -6px 4px 0 rgba(0,0,64,1.0) inset,
0 0 8px 0 rgba(0,0,128,1.0);
background-color: rgba(70, 175, 227, 1); /* light blue */
}
.theme-light box.requests-menu-status[code^="1"] {
box-shadow:
0 0 2px 1px rgba(255,255,255,0.8) inset,
0 -6px 4px 0 rgba(0,0,128,1) inset;
background-color: rgba(0, 136, 204, 1); /* light blue */
}
.theme-dark box.requests-menu-status[code^="2"] {
box-shadow:
0 0 2px 1px rgba(255,255,255,0.8) inset,
0 -6px 4px 0 rgba(0,64,0,1.0) inset,
0 0 8px 0 rgba(0,128,0,1.0);
background-color: rgba(112, 191, 83, 1); /* green */
}
.theme-light box.requests-menu-status[code^="2"] {
box-shadow:
0 0 2px 1px rgba(255,255,255,0.8) inset,
0 -6px 4px 0 rgba(0,128,0,1) inset;
background-color: rgba(44, 187, 15, 1); /* green */
}
.theme-dark box.requests-menu-status[code^="3"] {
box-shadow:
0 0 2px 1px rgba(255,255,255,0.8) inset,
0 -6px 4px 0 rgba(64,32,0,1.0) inset,
0 0 8px 0 rgba(128,128,0,1.0);
background-color: rgba(94, 136, 176, 1); /* grey */
}
.theme-light box.requests-menu-status[code^="3"] {
box-shadow:
0 0 2px 1px rgba(255,255,255,0.8) inset,
0 -6px 4px 0 rgba(128,64,0,1) inset;
background-color: rgba(95, 136, 176, 1); /* blue grey */
}
.theme-dark box.requests-menu-status[code^="4"] {
box-shadow:
0 0 2px 1px rgba(255,255,255,0.8) inset,
0 -6px 4px 0 rgba(64,0,0,1.0) inset,
0 0 8px 0 rgba(128,0,0,1.0);
background-color: rgba(235, 83, 104, 1); /* red */
}
.theme-light box.requests-menu-status[code^="4"] {
box-shadow:
0 0 2px 1px rgba(255,255,255,0.8) inset,
0 -6px 4px 0 rgba(128,0,0,1) inset;
background-color: rgba(237, 38, 85, 1); /* red */
}
.theme-dark box.requests-menu-status[code^="5"] {
box-shadow:
0 0 2px 1px rgba(255,255,255,0.8) inset,
0 -6px 4px 0 rgba(64,0,64,1.0) inset,
0 0 8px 0 rgba(128,0,128,1.0);
background-color: rgba(223, 128, 255, 1); /* pink? */
}
.theme-light box.requests-menu-status[code^="5"] {
box-shadow:
0 0 2px 1px rgba(255,255,255,0.8) inset,
0 -6px 4px 0 rgba(128,0,128,1.0) inset;
background-color: rgba(184, 46, 229, 1); /* pink! */
}
/* Network requests table: waterfall header */
@ -294,7 +264,7 @@ box.requests-menu-status {
/* Network requests table: waterfall items */
.requests-menu-subitem.requests-menu-waterfall {
-moz-padding-start: 4px;
-moz-padding-start: 0px;
-moz-padding-end: 4px;
background-repeat: repeat-y; /* Background created on a <canvas> in js. */
background-position: -1px center;
@ -323,129 +293,50 @@ box.requests-menu-status {
}
.requests-menu-timings-total {
-moz-padding-start: 8px;
-moz-padding-start: 4px;
font-size: 85%;
font-weight: 600;
}
.requests-menu-timings-cap {
width: 4px;
height: 8px;
box-shadow: none !important;
}
.theme-dark .requests-menu-timings-cap {
border: 1px solid #b8c8d9; /* Light content text */
}
.theme-light .requests-menu-timings-cap {
border: 1px solid #292e33; /* Dark content text */
}
.requests-menu-timings-cap.start {
-moz-border-end: none;
}
.requests-menu-timings-cap.end {
-moz-border-start: none;
}
.requests-menu-timings-cap.start:-moz-locale-dir(ltr) {
border-radius: 4px 0 0 4px;
transform-origin: right center;
}
.requests-menu-timings-cap.start:-moz-locale-dir(rtl) {
border-radius: 0 4px 4px 0;
transform-origin: left center;
}
.requests-menu-timings-cap.end:-moz-locale-dir(ltr) {
border-radius: 0 4px 4px 0;
transform-origin: left center;
}
.requests-menu-timings-cap.end:-moz-locale-dir(rtl) {
border-radius: 4px 0 0 4px;
transform-origin: right center;
}
.requests-menu-timings-box {
height: 8px;
height: 9px;
}
.theme-dark .requests-menu-timings-box {
border-top: 1px solid #b8c8d9; /* Light content text */
border-bottom: 1px solid #b8c8d9;
.requests-menu-timings-box.blocked {
background-color: rgba(235, 83, 104, 0.8); /* red */
}
.theme-light .requests-menu-timings-box {
border-top: 1px solid #292e33; /* Dark content text */
border-bottom: 1px solid #292e33;
.requests-menu-timings-box.dns {
background-color: rgba(223, 128, 255, 0.8); /* pink */
}
.requests-menu-timings-box.blocked,
.requests-menu-timings-cap.blocked {
background-color: rgba(255,32,32,0.8);
box-shadow: 0 0 2px 0 rgba(128,32,32,0.8),
0 0 1px 0 rgba(255,255,255,1.0) inset;
}
.requests-menu-timings-box.dns,
.requests-menu-timings-cap.dns {
background-color: rgba(255,128,255,0.6);
box-shadow: 0 0 2px 0 rgba(128,128,255,1.0),
0 0 1px 0 rgba(255,255,255,1.0) inset;
}
.requests-menu-timings-box.connect,
.requests-menu-timings-cap.connect {
background-color: rgba(255,128,16,0.4);
box-shadow: 0 0 2px 0 rgba(128,128,16,0.8),
0 0 1px 0 rgba(255,255,255,1.0) inset;
.requests-menu-timings-box.connect {
background-color: rgba(217, 102, 41, 0.8); /* orange */
}
/* Use custom colors for dark and light theme on remaining timing types. */
.theme-dark .requests-menu-timings-box.send,
.theme-dark .requests-menu-timings-cap.send {
background-color: rgba(255,255,128,0.4);
box-shadow: 0 0 2px 0 rgba(128,255,128,0.8),
0 0 1px 0 rgba(255,255,255,1.0) inset;
.theme-dark .requests-menu-timings-box.send {
background-color: rgba(70, 175, 227, 0.8); /* light blue */
}
.theme-light .requests-menu-timings-box.send,
.theme-light .requests-menu-timings-cap.send {
background-color: rgba(255,255,128,0.4);
box-shadow: 0 0 2px 0 rgba(128,255,128,0.8),
0 0 1px 0 rgba(255,255,255,1.0) inset;
.theme-light .requests-menu-timings-box.send {
background-color: rgba(0, 136, 204, 0.8); /* blue */
}
.theme-dark .requests-menu-timings-box.wait,
.theme-dark .requests-menu-timings-cap.wait {
background-color: rgba(255,255,255,0.2);
box-shadow: 0 0 2px 0 rgba(128,255,255,0.4),
0 0 1px 0 rgba(255,255,255,1.0) inset;
.theme-dark .requests-menu-timings-box.wait {
background-color: rgba(94, 136, 176, 0.8); /* blue grey */
}
.theme-light .requests-menu-timings-box.wait,
.theme-light .requests-menu-timings-cap.wait {
background-color: rgba(200, 200, 200, 0.8);
box-shadow: 0 0 2px 0 rgba(0, 0, 0, 0.4),
0 0 1px 0 rgba(255,255,255,1.0) inset;
.theme-light .requests-menu-timings-box.wait {
background-color: rgba(95, 136, 176, 0.8); /* blue grey */
}
.theme-dark .requests-menu-timings-box.receive,
.theme-dark .requests-menu-timings-cap.receive {
background-color: rgba(255,255,255,1.0);
box-shadow: 0 0 2px 0 rgba(128,255,255,1.0),
0 0 1px 0 rgba(255,255,255,1.0) inset;
.theme-dark .requests-menu-timings-box.receive {
background-color: rgba(112, 191, 83, 0.8); /* green */
}
.theme-light .requests-menu-timings-box.receive,
.theme-light .requests-menu-timings-cap.receive {
background-color: rgba(0, 0, 0, 0.6);
box-shadow: 0 0 2px 0 rgba(0, 0, 0, 0.8),
0 0 1px 0 rgba(0,0,0,1.0) inset;
.theme-light .requests-menu-timings-box.receive {
background-color: rgba(44, 187, 15, 0.8); /* green */
}
/* SideMenuWidget */

View File

@ -3,6 +3,14 @@
* 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/. */
%filter substitution
%define smw_marginDark #000
%define smw_marginLight #aaa
%define smw_itemDarkTopBorder rgba(0,0,0,0.2)
%define smw_itemDarkBottomBorder rgba(128,128,128,0.15)
%define smw_itemLightTopBorder rgba(128,128,128,0.15)
%define smw_itemLightBottomBorder transparent
.loading .splitview-nav-container {
background-image: url(chrome://global/skin/icons/loading_16.png);
background-repeat: no-repeat;
@ -15,67 +23,93 @@
.splitview-nav {
-moz-appearance: none;
margin: 0;
}
.theme-dark .splitview-nav {
box-shadow: inset -1px 0 0 black; /* Match the splitter. */
}
.theme-light .splitview-nav {
box-shadow: inset -1px 0 0 #aaa; /* Match the splitter color. */
}
.splitview-nav > li {
background-clip: padding-box;
border-bottom: 1px solid hsla(210,16%,76%,.1);
box-shadow: inset 0 -1px 0 hsla(210,8%,5%,.25);
-moz-padding-end: 8px;
-moz-box-align: center;
}
.splitview-nav {
list-style-image: none;
list-style: none;
padding: 0;
margin: 0;
}
.theme-dark .splitview-nav {
box-shadow: inset -1px 0 0 @smw_marginDark@;
}
.theme-dark .splitview-nav:-moz-locale-dir(rtl) {
box-shadow: inset 1px 0 0 @smw_marginDark@;
}
.theme-light .splitview-nav {
box-shadow: inset -1px 0 0 @smw_marginLight@;
}
.theme-light .splitview-nav:-moz-locale-dir(rtl) {
box-shadow: inset 1px 0 0 @smw_marginLight@;
}
.splitview-nav > li {
/* To compensate for the top and bottom borders */
margin-top: -1px;
margin-bottom: -1px;
-moz-padding-end: 8px;
-moz-box-align: center;
outline: 0;
vertical-align: bottom;
}
.theme-dark .splitview-nav > li {
border-top: 1px solid @smw_itemDarkTopBorder@;
border-bottom: 1px solid @smw_itemDarkBottomBorder@;
}
.theme-dark .splitview-nav > li:last-of-type {
box-shadow: inset 0 -1px 0 @smw_itemDarkTopBorder@;
}
.theme-light .splitview-nav > li {
border-top: 1px solid @smw_itemLightTopBorder@;
border-bottom: 1px solid @smw_itemLightBottomBorder@;
}
.theme-light .splitview-nav > li:last-of-type {
box-shadow: inset 0 -1px 0 @smw_itemLightTopBorder@;
}
.placeholder {
-moz-box-flex: 1;
text-align: center;
}
.splitview-nav > li.splitview-active {
background-image: url(itemArrow-dark-ltr.png),
linear-gradient(#1d4f73, #1d4f73);
background-repeat: no-repeat, repeat-x;
background-position: center right, top left;
background-size: auto, auto;
border-bottom: 1px solid hsla(210,8%,5%,.25);
box-shadow: inset 0 1px 0 hsla(210,40%,83%,.15),
inset 0 -1px 0 hsla(210,40%,83%,.05);
background-repeat: no-repeat, no-repeat, repeat-x;
background-position: center right, center right, top left;
background-size: auto, 1px, auto;
}
.splitview-nav > li.splitview-active:-moz-locale-dir(rtl) {
background-image: url(itemArrow-dark-rtl.png),
background-repeat: no-repeat, no-repeat, repeat-x;
background-position: center left, center left, top right;
}
.theme-dark .splitview-nav > li.splitview-active {
background-image: url(itemArrow-dark-ltr.png),
linear-gradient(@smw_marginDark@, @smw_marginDark@),
linear-gradient(#1d4f73, #1d4f73);
}
.theme-dark .splitview-nav > li.splitview-active:-moz-locale-dir(rtl) {
background-image: url(itemArrow-dark-rtl.png),
linear-gradient(@smw_marginDark@, @smw_marginDark@),
linear-gradient(#1d4f73, #1d4f73);
background-repeat: no-repeat, repeat-x;
background-position: center left, top right;
}
.theme-light .splitview-nav > li.splitview-active {
background-image: url(itemArrow-ltr.svg),
linear-gradient(@smw_marginLight@, @smw_marginLight@),
linear-gradient(#4c9ed9, #4c9ed9);
}
.theme-light .splitview-nav > li.splitview-active:-moz-locale-dir(rtl) {
background-image: url(itemArrow-rtl.png),
background-image: url(itemArrow-rtl.svg),
linear-gradient(@smw_marginLight@, @smw_marginLight@),
linear-gradient(#4c9ed9, #4c9ed9);
}
@ -88,12 +122,12 @@
.theme-dark .splitview-main > toolbar,
.theme-dark .loading .splitview-nav-container {
-moz-border-end: 1px solid black; /* Match the splitter. */
-moz-border-end: 1px solid @smw_marginDark@;
}
.theme-light .splitview-main > toolbar,
.theme-light .loading .splitview-nav-container {
-moz-border-end: 1px solid #aaa; /* Match the splitter. */
-moz-border-end: 1px solid @smw_marginLight@;
}
.splitview-main > .devtools-toolbarbutton {

View File

@ -67,8 +67,7 @@
.theme-light .devtools-toolbarbutton[open=true]:hover,
.theme-light .devtools-toolbarbutton[open=true]:hover:active,
.theme-light .devtools-toolbarbutton[checked=true],
.theme-light .devtools-toolbarbutton[checked=true]:hover,
.theme-light .devtools-toolbarbutton[checked=true]:hover:active {
.theme-light .devtools-toolbarbutton[checked=true]:hover {
background: #ddd;
}
@ -76,6 +75,11 @@
background: #eee;
}
.theme-light .devtools-toolbarbutton:hover:active,
.theme-light .devtools-toolbarbutton[checked=true]:hover:active {
background: #e8e8e8;
}
.theme-light .devtools-toolbarbutton[type=menu-button] > .toolbarbutton-menubutton-button {
color: #667380;
}
@ -203,7 +207,7 @@
.devtools-searchinput {
-moz-appearance: none;
margin: 0 3px;
border: 1px solid rgb(88, 94, 101);
border: 1px solid;
%ifdef XP_MACOSX
border-radius: 20px;
%else
@ -212,6 +216,16 @@
padding: 4px 6px;
}
.theme-dark .devtools-textinput,
.theme-dark .devtools-searchinput {
border-color: rgb(88, 94, 101);
}
.theme-light .devtools-textinput,
.theme-light .devtools-searchinput {
border-color: #aaa; /* Match the splitter color */
}
.devtools-searchinput {
padding-top: 3px;
padding-bottom: 3px;
@ -587,64 +601,87 @@
.devtools-tabbar {
-moz-appearance: none;
background: #252c33;
min-height: 28px;
border: 0px solid #000;
border: 0px solid;
border-bottom-width: 1px;
box-shadow: 0 -2px 0 rgba(0,0,0,.1) inset;
padding: 0;
}
.theme-light .devtools-tabbar {
box-shadow: 0 -2px 0 rgba(170,170,170,.1) inset;
background: #ebeced;
border-bottom-color: #aaa;
}
.theme-dark .devtools-tabbar {
box-shadow: 0 -2px 0 rgba(0,0,0,.1) inset;
background: #252c33;
border-bottom-color: #000;
}
#toolbox-tabs {
margin: 0;
}
.devtools-tab {
-moz-appearance: none;
-moz-binding: url("chrome://global/content/bindings/general.xml#control-item");
-moz-box-align: center;
}
.devtools-tab {
-moz-appearance: none;
min-width: 32px;
min-height: 28px;
max-width: 127px;
color: #b6babf;
margin: 0;
padding: 0;
-moz-border-start: 1px solid #42484f;
-moz-border-start: 1px solid;
-moz-box-align: center;
}
.theme-light .devtools-tabbar {
background: #ebeced;
border-bottom-color: #aaa;
.theme-dark .devtools-tab {
color: #b6babf;
border-color: #42484f;
}
.theme-light .devtools-tab,
.theme-light .devtools-tab:hover {
.theme-light .devtools-tab {
color: #18191a;
border-color: #aaa;
}
.theme-dark .devtools-tab:hover {
background-color: hsla(206,37%,4%,.2);
color: #ced3d9;
}
.theme-light .devtools-tab:hover {
background-color: #ddd;
box-shadow: 0 -2px 0 rgba(0,0,0,.1) inset;
background-color: rgba(170,170,170,.2);
}
.theme-dark .devtools-tab:hover:active {
background-color: hsla(206,37%,4%,.4);
color: #f5f7fa;
}
.theme-light .devtools-tab:hover:active {
background-color: rgba(170,170,170,.4);
}
.theme-dark .devtools-tab:not([selected])[highlighted] {
background-color: hsla(99,100%,14%,.2);
box-shadow: 0 2px 0 #7bc107 inset;
}
.theme-light .devtools-tab:not([selected])[highlighted] {
background-color: rgba(44, 187, 15, .2);
}
.theme-light .devtools-tab:last-child {
-moz-border-end: 1px solid #aaa;
}
.devtools-tab:first-child {
-moz-border-start-width: 0;
}
.devtools-tab:last-child {
.theme-light .devtools-tab:last-child {
-moz-border-end: 1px solid #aaa;
}
.theme-dark .devtools-tab:last-child {
-moz-border-end: 1px solid #42484f;
}
@ -674,17 +711,7 @@
opacity: 1;
}
.devtools-tab:hover {
background-color: hsla(206,37%,4%,.2);
color: #ced3d9;
}
.devtools-tab:hover:active {
background-color: hsla(206,37%,4%,.4);
color: #f5f7fa;
}
#toolbox-tabs .devtools-tab[selected] {
.theme-dark #toolbox-tabs .devtools-tab[selected] {
color: #f5f7fa;
background-color: #1a4666;
box-shadow: 0 2px 0 #d7f1ff inset,
@ -693,7 +720,11 @@
}
.theme-light #toolbox-tabs .devtools-tab[selected] {
color: #f5f7fa;
background-color: #4c9ed9;
box-shadow: 0 2px 0 #d7f1ff inset,
0 8px 3px -5px #2b82bf inset,
0 -2px 0 rgba(0,0,0,.06) inset;
}
.devtools-tab[selected]:not(:first-child),
@ -713,15 +744,6 @@
-moz-padding-start: 1px;
}
.theme-dark .devtools-tab:not([selected])[highlighted] {
background-color: hsla(99,100%,14%,.2);
box-shadow: 0 2px 0 #7bc107 inset;
}
.theme-dark #toolbox-tabs .devtools-tab[selected] {
color: #f5f7fa;
}
.devtools-tab:not([highlighted]) > .highlighted-icon,
.devtools-tab[selected] > .highlighted-icon,
.devtools-tab:not([selected])[highlighted] > .default-icon {

View File

@ -214,7 +214,7 @@ browser.jar:
skin/classic/browser/devtools/breadcrumbs-divider@2x.png (../shared/devtools/images/breadcrumbs-divider@2x.png)
skin/classic/browser/devtools/breadcrumbs-scrollbutton.png (../shared/devtools/images/breadcrumbs-scrollbutton.png)
skin/classic/browser/devtools/breadcrumbs-scrollbutton@2x.png (../shared/devtools/images/breadcrumbs-scrollbutton@2x.png)
skin/classic/browser/devtools/splitview.css (../shared/devtools/splitview.css)
* skin/classic/browser/devtools/splitview.css (../shared/devtools/splitview.css)
skin/classic/browser/devtools/styleeditor.css (../shared/devtools/styleeditor.css)
* skin/classic/browser/devtools/shadereditor.css (devtools/shadereditor.css)
* skin/classic/browser/devtools/debugger.css (devtools/debugger.css)
@ -527,7 +527,7 @@ browser.jar:
skin/classic/aero/browser/devtools/breadcrumbs-divider@2x.png (../shared/devtools/images/breadcrumbs-divider@2x.png)
skin/classic/aero/browser/devtools/breadcrumbs-scrollbutton.png (../shared/devtools/images/breadcrumbs-scrollbutton.png)
skin/classic/aero/browser/devtools/breadcrumbs-scrollbutton@2x.png (../shared/devtools/images/breadcrumbs-scrollbutton@2x.png)
skin/classic/aero/browser/devtools/splitview.css (../shared/devtools/splitview.css)
* skin/classic/aero/browser/devtools/splitview.css (../shared/devtools/splitview.css)
skin/classic/aero/browser/devtools/styleeditor.css (../shared/devtools/styleeditor.css)
* skin/classic/aero/browser/devtools/shadereditor.css (devtools/shadereditor.css)
* skin/classic/aero/browser/devtools/debugger.css (devtools/debugger.css)

View File

@ -205,3 +205,10 @@ https://www2.w3c-test.org:443
https://xn--n8j6ds53lwwkrqhv28a.w3c-test.org:443
https://xn--lve-6lad.w3c-test.org:443
http://test.w3.org:80
# Hosts for testing TLD-based fallback encoding
http://example.tw:80 privileged
http://example.cn:80 privileged
http://example.co.jp:80 privileged
http://example.fi:80 privileged

View File

@ -435,6 +435,66 @@ nsHTMLDocument::TryParentCharset(nsIDocShell* aDocShell,
}
}
void
nsHTMLDocument::TryTLD(int32_t& aCharsetSource, nsACString& aCharset)
{
if (aCharsetSource >= kCharsetFromTopLevelDomain) {
return;
}
if (!FallbackEncoding::sGuessFallbackFromTopLevelDomain) {
return;
}
if (!mDocumentURI) {
return;
}
nsAutoCString host;
mDocumentURI->GetAsciiHost(host);
if (host.IsEmpty()) {
return;
}
// First let's see if the host is DNS-absolute and ends with a dot and
// get rid of that one.
if (host.Last() == '.') {
host.SetLength(host.Length() - 1);
if (host.IsEmpty()) {
return;
}
}
// If we still have a dot, the host is weird, so let's continue only
// if we have something other than a dot now.
if (host.Last() == '.') {
return;
}
int32_t index = host.RFindChar('.');
if (index == kNotFound) {
// We have an intranet host, Gecko-internal URL or an IPv6 address.
return;
}
// Since the string didn't end with a dot and we found a dot,
// there is at least one character between the dot and the end of
// the string, so taking the substring below is safe.
nsAutoCString tld;
ToLowerCase(Substring(host, index + 1, host.Length() - (index + 1)), tld);
// Reject generic TLDs and country TLDs that need more research
if (!FallbackEncoding::IsParticipatingTopLevelDomain(tld)) {
return;
}
// Check if we have an IPv4 address
bool seenNonDigit = false;
for (size_t i = 0; i < tld.Length(); ++i) {
char c = tld.CharAt(i);
if (c < '0' || c > '9') {
seenNonDigit = true;
break;
}
}
if (!seenNonDigit) {
return;
}
aCharsetSource = kCharsetFromTopLevelDomain;
FallbackEncoding::FromTopLevelDomain(tld, aCharset);
}
void
nsHTMLDocument::TryFallback(int32_t& aCharsetSource, nsACString& aCharset)
{
@ -661,6 +721,7 @@ nsHTMLDocument::StartDocumentLoad(const char* aCommand,
TryCacheCharset(cachingChan, charsetSource, charset);
}
TryTLD(charsetSource, charset);
TryFallback(charsetSource, charset);
if (wyciwygChannel) {

View File

@ -313,6 +313,7 @@ protected:
nsACString& aCharset);
void TryParentCharset(nsIDocShell* aDocShell,
int32_t& charsetSource, nsACString& aCharset);
void TryTLD(int32_t& aCharsetSource, nsACString& aCharset);
static void TryFallback(int32_t& aCharsetSource, nsACString& aCharset);
// Override so we can munge the charset on our wyciwyg channel as needed.

View File

@ -39,7 +39,7 @@ load 878407.html
load 878478.html
load 877527.html
load 880129.html
skip-if(B2G) test-pref(media.webaudio.enabled,true) load 880202.html # load failed, bug 908306 for B2G
skip-if(B2G) load 880202.html # load failed, bug 908306 for B2G
load 880342-1.html
load 880342-2.html
load 880384.html

View File

@ -10,7 +10,6 @@
#include "nsWrapperCache.h"
#include "nsCycleCollectionParticipant.h"
#include "mozilla/Attributes.h"
#include "EnableWebAudioCheck.h"
#include "nsAutoPtr.h"
#include "nsTArray.h"
#include "AudioContext.h"
@ -31,8 +30,7 @@ class AudioContext;
* are Float32Arrays, or in mSharedChannels if the mJSChannels objects have
* been neutered.
*/
class AudioBuffer MOZ_FINAL : public nsWrapperCache,
public EnableWebAudioCheck
class AudioBuffer MOZ_FINAL : public nsWrapperCache
{
public:
AudioBuffer(AudioContext* aContext, uint32_t aLength,

View File

@ -8,7 +8,6 @@
#define AudioContext_h_
#include "mozilla/dom/AudioChannelBinding.h"
#include "EnableWebAudioCheck.h"
#include "MediaBufferDecoder.h"
#include "mozilla/Attributes.h"
#include "mozilla/dom/TypedArray.h"
@ -64,8 +63,7 @@ class WaveShaperNode;
class PeriodicWave;
class AudioContext MOZ_FINAL : public nsDOMEventTargetHelper,
public nsIMemoryReporter,
public EnableWebAudioCheck
public nsIMemoryReporter
{
AudioContext(nsPIDOMWindow* aParentWindow,
bool aIsOffline,

View File

@ -10,7 +10,6 @@
#include "nsWrapperCache.h"
#include "nsCycleCollectionParticipant.h"
#include "mozilla/Attributes.h"
#include "EnableWebAudioCheck.h"
#include "nsAutoPtr.h"
#include "ThreeDPoint.h"
#include "AudioContext.h"
@ -23,8 +22,7 @@ namespace mozilla {
namespace dom {
class AudioListener MOZ_FINAL : public nsWrapperCache,
public EnableWebAudioCheck
class AudioListener MOZ_FINAL : public nsWrapperCache
{
public:
explicit AudioListener(AudioContext* aContext);

View File

@ -10,7 +10,6 @@
#include "nsDOMEventTargetHelper.h"
#include "mozilla/dom/AudioNodeBinding.h"
#include "nsCycleCollectionParticipant.h"
#include "EnableWebAudioCheck.h"
#include "nsAutoPtr.h"
#include "nsTArray.h"
#include "AudioContext.h"
@ -82,8 +81,7 @@ private:
* still alive, and will still be alive when it receives a message from the
* engine.
*/
class AudioNode : public nsDOMEventTargetHelper,
public EnableWebAudioCheck
class AudioNode : public nsDOMEventTargetHelper
{
protected:
// You can only use refcounting to delete this object

View File

@ -10,7 +10,6 @@
#include "AudioParamTimeline.h"
#include "nsWrapperCache.h"
#include "nsCycleCollectionParticipant.h"
#include "EnableWebAudioCheck.h"
#include "nsAutoPtr.h"
#include "AudioNode.h"
#include "mozilla/dom/TypedArray.h"
@ -22,7 +21,6 @@ namespace mozilla {
namespace dom {
class AudioParam MOZ_FINAL : public nsWrapperCache,
public EnableWebAudioCheck,
public AudioParamTimeline
{
public:

View File

@ -14,8 +14,7 @@
namespace mozilla {
namespace dom {
class AudioProcessingEvent : public nsDOMEvent,
public EnableWebAudioCheck
class AudioProcessingEvent : public nsDOMEvent
{
public:
AudioProcessingEvent(ScriptProcessorNode* aOwner,

View File

@ -1,32 +0,0 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim:set ts=2 sw=2 sts=2 et cindent: */
/* 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/. */
#include "EnableWebAudioCheck.h"
#include "mozilla/Preferences.h"
namespace {
bool gPrefInitialized = false;
bool gWebAudioEnabled = false;
}
namespace mozilla {
namespace dom {
/* static */ bool
EnableWebAudioCheck::PrefEnabled()
{
if (!gPrefInitialized) {
Preferences::AddBoolVarCache(&gWebAudioEnabled, "media.webaudio.enabled");
gPrefInitialized = true;
}
return gWebAudioEnabled;
}
}
}

View File

@ -1,24 +0,0 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim:set ts=2 sw=2 sts=2 et cindent: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef EnableWebAudioCheck_h_
#define EnableWebAudioCheck_h_
namespace mozilla {
namespace dom {
// This is a helper class which enables Web Audio to be enabled or disabled
// as whole. Individual Web Audio object classes should inherit from this.
class EnableWebAudioCheck {
public:
static bool PrefEnabled();
};
}
}
#endif

View File

@ -15,8 +15,7 @@ namespace dom {
class AudioContext;
class OfflineAudioCompletionEvent : public nsDOMEvent,
public EnableWebAudioCheck
class OfflineAudioCompletionEvent : public nsDOMEvent
{
public:
OfflineAudioCompletionEvent(AudioContext* aOwner,

View File

@ -10,7 +10,6 @@
#include "nsWrapperCache.h"
#include "nsCycleCollectionParticipant.h"
#include "mozilla/Attributes.h"
#include "EnableWebAudioCheck.h"
#include "AudioContext.h"
#include "AudioNodeEngine.h"
#include "nsAutoPtr.h"
@ -19,8 +18,7 @@ namespace mozilla {
namespace dom {
class PeriodicWave MOZ_FINAL : public nsWrapperCache,
public EnableWebAudioCheck
class PeriodicWave MOZ_FINAL : public nsWrapperCache
{
public:
PeriodicWave(AudioContext* aContext,

View File

@ -36,7 +36,6 @@ EXPORTS.mozilla.dom += [
'ConvolverNode.h',
'DelayNode.h',
'DynamicsCompressorNode.h',
'EnableWebAudioCheck.h',
'GainNode.h',
'MediaElementAudioSourceNode.h',
'MediaStreamAudioDestinationNode.h',
@ -66,7 +65,6 @@ UNIFIED_SOURCES += [
'DelayNode.cpp',
'DelayProcessor.cpp',
'DynamicsCompressorNode.cpp',
'EnableWebAudioCheck.cpp',
'FFTBlock.cpp',
'GainNode.cpp',
'MediaBufferDecoder.cpp',

View File

@ -1994,6 +1994,10 @@ nsDocShell::GatherCharsetMenuTelemetry()
int32_t charsetSource = doc->GetDocumentCharacterSetSource();
switch (charsetSource) {
case kCharsetFromTopLevelDomain:
// Unlabeled doc on a domain that we map to a fallback encoding
Telemetry::Accumulate(Telemetry::CHARSET_OVERRIDE_SITUATION, 7);
break;
case kCharsetFromFallback:
case kCharsetFromDocTypeDefault:
case kCharsetFromCache:

View File

@ -17,7 +17,16 @@ static const char* localesFallbacks[][3] = {
#include "localesfallbacks.properties.h"
};
static const char* domainsFallbacks[][3] = {
#include "domainsfallbacks.properties.h"
};
static const char* nonParticipatingDomains[][3] = {
#include "nonparticipatingdomains.properties.h"
};
FallbackEncoding* FallbackEncoding::sInstance = nullptr;
bool FallbackEncoding::sGuessFallbackFromTopLevelDomain = true;
FallbackEncoding::FallbackEncoding()
{
@ -121,6 +130,8 @@ FallbackEncoding::Initialize()
Preferences::RegisterCallback(FallbackEncoding::PrefChanged,
"general.useragent.locale",
nullptr);
Preferences::AddBoolVarCache(&sGuessFallbackFromTopLevelDomain,
"intl.charset.fallback.tld");
}
void
@ -132,5 +143,26 @@ FallbackEncoding::Shutdown()
FallbackEncoding::sInstance = nullptr;
}
bool
FallbackEncoding::IsParticipatingTopLevelDomain(const nsACString& aTLD)
{
nsAutoCString dummy;
return NS_FAILED(nsUConvPropertySearch::SearchPropertyValue(
nonParticipatingDomains,
ArrayLength(nonParticipatingDomains),
aTLD,
dummy));
}
void
FallbackEncoding::FromTopLevelDomain(const nsACString& aTLD,
nsACString& aFallback)
{
if (NS_FAILED(nsUConvPropertySearch::SearchPropertyValue(
domainsFallbacks, ArrayLength(domainsFallbacks), aTLD, aFallback))) {
aFallback.AssignLiteral("windows-1252");
}
}
} // namespace dom
} // namespace mozilla

View File

@ -14,6 +14,11 @@ class FallbackEncoding
{
public:
/**
* Whether FromTopLevelDomain() should be used.
*/
static bool sGuessFallbackFromTopLevelDomain;
/**
* Gets the locale-dependent fallback encoding for legacy HTML and plain
* text content.
@ -22,6 +27,23 @@ public:
*/
static void FromLocale(nsACString& aFallback);
/**
* Checks if it is appropriate to call FromTopLevelDomain() for a given TLD.
*
* @param aTLD the top-level domain (in Punycode)
* @return true if OK to call FromTopLevelDomain()
*/
static bool IsParticipatingTopLevelDomain(const nsACString& aTLD);
/**
* Gets a top-level domain-depedendent fallback encoding for legacy HTML
* and plain text content
*
* @param aTLD the top-level domain (in Punycode)
* @param aFallback the outparam for the fallback encoding
*/
static void FromTopLevelDomain(const nsACString& aTLD, nsACString& aFallback);
// public API ends here!
/**

View File

@ -9,3 +9,7 @@ labelsencodings.properties.h: $(PROPS2ARRAYS) labelsencodings.properties
$(PYTHON) $^ $@
localesfallbacks.properties.h: $(PROPS2ARRAYS) localesfallbacks.properties
$(PYTHON) $^ $@
domainsfallbacks.properties.h: $(PROPS2ARRAYS) domainsfallbacks.properties
$(PYTHON) $^ $@
nonparticipatingdomains.properties.h: $(PROPS2ARRAYS) nonparticipatingdomains.properties
$(PYTHON) $^ $@

View File

@ -0,0 +1,167 @@
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
# This file contains educated guesses about which top-level domains are
# likely to host legacy content that assumes a non-windows-1252 encoding.
# Punycode TLDs are included on the theory that legacy content might appear
# behind those relatively new TLDs if DNS just points to a legacy server.
#
# Encodings for which a confident-enough educated guess is missing are
# listed in nonparticipatingdomains.properties. Domains that are listed
# neither there nor here get windows-1252 as the associated fallback.
#
# The list below includes Arabic-script TLDs not on IANA list but on the
# ICANN list:
# http://www.icann.org/en/resources/idn/fast-track/string-evaluation-completion
# Otherwise, the list includes non-windows-1252-affilited country TLDs from
# https://data.iana.org/TLD/tlds-alpha-by-domain.txt
#
# The guesses are assigned as follows:
# * If the country has a dominant country-affiliated language and that language
# is part of the languages to fallbacks mapping, use the encoding for that
# language from that mapping.
# * Use windows-1256 for countries that have a dominant Arabic-script
# language or whose all languages are Arabic-script languages.
# * Use windows-1251 likewise but for Cyrillic script.
ae=windows-1256
xn--mgbaam7a8h=windows-1256
af=windows-1256
bg=windows-1251
bh=windows-1256
by=windows-1251
cn=gbk
xn--fiqs8s=gbk
# Assume that Traditional Chinese TLD is meant to work if URL input happens to
# be in the traditional mode. Expect content to be simplified anyway.
xn--fiqz9s=gbk
cz=windows-1250
dz=windows-1256
xn--lgbbat1ad8j=windows-1256
ee=windows-1257
eg=windows-1256
xn--wgbh1c=windows-1256
gr=ISO-8859-7
hk=Big5-HKSCS
xn--j6w193g=Big5-HKSCS
hr=windows-1250
hu=ISO-8859-2
iq=windows-1256
ir=windows-1256
xn--mgba3a4f16a=windows-1256
jo=windows-1256
xn--mgbayh7gpa=windows-1256
jp=Shift_JIS
kg=windows-1251
kp=EUC-KR
kr=EUC-KR
xn--3e0b707e=EUC-KR
kw=windows-1256
kz=windows-1251
xn--80ao21a=windows-1251
lb=windows-1256
lt=windows-1257
lv=windows-1257
ma=windows-1256
xn--mgbc0a9azcg=windows-1256
mk=windows-1251
mn=windows-1251
xn--l1acc=windows-1251
mo=Big5
# my
xn--mgbx4cd0ab=windows-1256
om=windows-1256
xn--mgb9awbf=windows-1256
#pk
xn--mgbai9azgqp6j=windows-1256
pl=ISO-8859-2
ps=windows-1256
xn--ygbi2ammx=windows-1256
qa=windows-1256
xn--wgbl6a=windows-1256
rs=windows-1251
xn--90a3ac=windows-1251
ru=windows-1251
xn--p1ai=windows-1251
sa=windows-1256
xn--mgberp4a5d4ar=windows-1256
sd=windows-1256
xn--mgbpl2fh=windows-1256
sg=gbk
xn--yfro4i67o=gbk
si=ISO-8859-2
sk=windows-1250
su=windows-1251
sy=windows-1256
xn--mgbtf8fl=windows-1256
th=windows-874
xn--o3cw4h=windows-874
tj=windows-1251
tn=windows-1256
xn--pgbs0dh=windows-1256
tr=windows-1254
tw=Big5
# Assume that the Simplified Chinese TLD is meant to work when URL input
# happens in the simplified mode. Assume content is tradition anyway.
xn--kprw13d=Big5
xn--kpry57d=Big5
ua=windows-1251
xn--j1amh=windows-1251
uz=windows-1251
vn=windows-1258
ye=windows-1256
xn--mgb2ddes=windows-1256

View File

@ -28,6 +28,8 @@ LOCAL_INCLUDES += [
]
GENERATED_FILES += [
'domainsfallbacks.properties.h',
'labelsencodings.properties.h',
'localesfallbacks.properties.h',
'nonparticipatingdomains.properties.h',
]

View File

@ -0,0 +1,51 @@
# 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/.
# Top-level domains listed here do not participate in TLD-based guessing.
#
# We should do Web crawls to see if domains listed here can migrate to
# domainsfallbacks.properties.
#
# The value to the right of the = sign is ignored and serves as a placeholder.
# Generic
com=windows-1252
net=windows-1252
org=windows-1252
# No Firefox localization for Azeri
az=windows-1254
# windows-1251 or windows-1250?
ba=???
# ISO-8859-7 or windows-1254?
cy=???
# Is there enough unlabeled windows-1256 content for a windows-1255 to break
# too much?
il=windows-1255
# Out-of-country English use
ly=windows-1256
# Out-of-country English use
# md=windows-1250
# Out-of-country English use
# me=windows-1251
# Malaysia has an Arabic-script TLD, official script is latin, possibly Chinese-script publications
my=???
# No Firefox localization for Urdu; potential for minority-language sites
# relying on windows-1252 hacks.
pk=windows-1256
# The Romanian localization says windows-1252, even though the Windows legacy
# differs.
ro=windows-1250
tm=windows-1250

View File

@ -0,0 +1,7 @@
<!DOCTYPE html>
<script>
function report() {
window.parent.postMessage(document.characterSet, "*");
}
</script>
<body onload="report();">

View File

@ -7,6 +7,7 @@ support-files =
file_utf16_le_bom.js
file_utf16_le_bom.xhtml
file_utf16_le_nobom.xhtml
file_TLD.html
worker_helper.js
[test_BOMEncoding.js]
@ -16,4 +17,5 @@ support-files =
[test_TextEncoder.js]
[test_stringencoding.html]
[test_submit_euckr.html]
[test_TLD.html]
[test_utf16_files.html]

View File

@ -0,0 +1,57 @@
<!DOCTYPE HTML>
<html>
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=910211
-->
<head>
<meta charset="utf-8">
<title>Test for Bug 910211</title>
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
<script type="application/javascript">
/** Test for Bug 910211 **/
SimpleTest.waitForExplicitFinish();
var tlds = [
{'tld': 'tw', 'encoding': 'Big5'},
{'tld': 'cn', 'encoding': 'gbk'},
{'tld': 'co.jp', 'encoding': 'Shift_JIS'},
{'tld': 'fi', 'encoding': 'windows-1252'},
];
var iframe = null;
var current = null;
function runTest() {
iframe = document.getElementsByTagName("iframe")[0];
window.addEventListener("message", next);
next(null);
}
function next(event) {
if (event) {
is(event.data, current['encoding'], "Got bad encoding for " + current["tld"]);
}
current = tlds.shift();
if (!current) {
SimpleTest.finish();
return;
}
iframe.src = "http://example." + current["tld"] + "/tests/dom/encoding/test/file_TLD.html";
}
</script>
</head>
<body onload="runTest();">
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=910211">Mozilla Bug 910211</a>
<p id="display"></p>
<div id="content" style="display: none">
<iframe></iframe>
</div>
<pre id="test">
</pre>
</body>
</html>

View File

@ -10,7 +10,6 @@
* liability, trademark and document use rules apply.
*/
[PrefControlled]
interface AnalyserNode : AudioNode {
// Real-time frequency-domain data

View File

@ -10,7 +10,6 @@
* liability, trademark and document use rules apply.
*/
[PrefControlled]
interface AudioBuffer {
readonly attribute float sampleRate;

View File

@ -10,7 +10,6 @@
* liability, trademark and document use rules apply.
*/
[PrefControlled]
interface AudioBufferSourceNode : AudioNode {
attribute AudioBuffer? buffer;
@ -34,7 +33,6 @@ interface AudioBufferSourceNode : AudioNode {
* The origin of this IDL file is
* https://dvcs.w3.org/hg/audio/raw-file/tip/webaudio/specification.html#AlternateNames
*/
[PrefControlled]
partial interface AudioBufferSourceNode {
// Same as start()
[Throws,Pref="media.webaudio.legacy.AudioBufferSourceNode"]

View File

@ -13,7 +13,7 @@
callback DecodeSuccessCallback = void (AudioBuffer decodedData);
callback DecodeErrorCallback = void ();
[Constructor, PrefControlled]
[Constructor]
interface AudioContext : EventTarget {
readonly attribute AudioDestinationNode destination;
@ -78,7 +78,6 @@ interface AudioContext : EventTarget {
* The origin of this IDL file is
* https://dvcs.w3.org/hg/audio/raw-file/tip/webaudio/specification.html#AlternateNames
*/
[PrefControlled]
partial interface AudioContext {
[NewObject, Throws]
AudioBuffer? createBuffer(ArrayBuffer buffer, boolean mixToMono);

View File

@ -10,7 +10,6 @@
* liability, trademark and document use rules apply.
*/
[PrefControlled]
interface AudioDestinationNode : AudioNode {
readonly attribute unsigned long maxChannelCount;

View File

@ -10,7 +10,6 @@
* liability, trademark and document use rules apply.
*/
[PrefControlled]
interface AudioListener {
// same as OpenAL (default 1)

View File

@ -21,7 +21,6 @@ enum ChannelInterpretation {
"discrete"
};
[PrefControlled]
interface AudioNode : EventTarget {
[Throws]

View File

@ -10,7 +10,6 @@
* liability, trademark and document use rules apply.
*/
[PrefControlled]
interface AudioParam {
attribute float value;
@ -43,7 +42,6 @@ interface AudioParam {
* The origin of this IDL file is
* https://dvcs.w3.org/hg/audio/raw-file/tip/webaudio/specification.html#AlternateNames
*/
[PrefControlled]
partial interface AudioParam {
// Same as setTargetAtTime()
[Throws,Pref="media.webaudio.legacy.AudioParam"]

View File

@ -10,7 +10,6 @@
* liability, trademark and document use rules apply.
*/
[PrefControlled]
interface AudioProcessingEvent : Event {
readonly attribute double playbackTime;

View File

@ -24,7 +24,6 @@ enum BiquadFilterType {
"allpass"
};
[PrefControlled]
interface BiquadFilterNode : AudioNode {
attribute BiquadFilterType type;
@ -43,7 +42,6 @@ interface BiquadFilterNode : AudioNode {
* The origin of this IDL file is
* https://dvcs.w3.org/hg/audio/raw-file/tip/webaudio/specification.html#AlternateNames
*/
[PrefControlled]
partial interface BiquadFilterNode {
[Pref="media.webaudio.legacy.BiquadFilterNode"]
const unsigned short LOWPASS = 0;

View File

@ -10,7 +10,6 @@
* liability, trademark and document use rules apply.
*/
[PrefControlled]
interface ChannelMergerNode : AudioNode {
};

View File

@ -10,7 +10,6 @@
* liability, trademark and document use rules apply.
*/
[PrefControlled]
interface ChannelSplitterNode : AudioNode {
};

View File

@ -10,7 +10,6 @@
* liability, trademark and document use rules apply.
*/
[PrefControlled]
interface ConvolverNode : AudioNode {
[SetterThrows]

View File

@ -10,7 +10,6 @@
* liability, trademark and document use rules apply.
*/
[PrefControlled]
interface DelayNode : AudioNode {
readonly attribute AudioParam delayTime;

View File

@ -10,7 +10,6 @@
* liability, trademark and document use rules apply.
*/
[PrefControlled]
interface DynamicsCompressorNode : AudioNode {
readonly attribute AudioParam threshold; // in Decibels

View File

@ -10,7 +10,6 @@
* liability, trademark and document use rules apply.
*/
[PrefControlled]
interface GainNode : AudioNode {
readonly attribute AudioParam gain;

View File

@ -10,7 +10,6 @@
* liability, trademark and document use rules apply.
*/
[PrefControlled]
interface MediaElementAudioSourceNode : AudioNode {
};

View File

@ -10,9 +10,8 @@
* liability, trademark and document use rules apply.
*/
[PrefControlled]
interface MediaStreamAudioDestinationNode : AudioNode {
readonly attribute MediaStream stream;
};
};

View File

@ -10,7 +10,6 @@
* liability, trademark and document use rules apply.
*/
[PrefControlled]
interface OfflineAudioCompletionEvent : Event {
readonly attribute AudioBuffer renderedBuffer;

View File

@ -12,8 +12,7 @@
callback OfflineRenderSuccessCallback = void (AudioBuffer renderedData);
[Constructor(unsigned long numberOfChannels, unsigned long length, float sampleRate),
PrefControlled]
[Constructor(unsigned long numberOfChannels, unsigned long length, float sampleRate)]
interface OfflineAudioContext : AudioContext {
[Throws]

View File

@ -21,7 +21,6 @@ enum OscillatorType {
"custom"
};
[PrefControlled]
interface OscillatorNode : AudioNode {
[SetterThrows]

View File

@ -27,7 +27,6 @@ enum DistanceModelType {
"exponential"
};
[PrefControlled]
interface PannerNode : AudioNode {
// Default for stereo is HRTF
@ -55,7 +54,6 @@ interface PannerNode : AudioNode {
* The origin of this IDL file is
* https://dvcs.w3.org/hg/audio/raw-file/tip/webaudio/specification.html#AlternateNames
*/
[PrefControlled]
partial interface PannerNode {
[Pref="media.webaudio.legacy.PannerNode"]
const unsigned short EQUALPOWER = 0;

View File

@ -10,7 +10,6 @@
* liability, trademark and document use rules apply.
*/
[PrefControlled]
interface PeriodicWave {
};

View File

@ -10,7 +10,6 @@
* liability, trademark and document use rules apply.
*/
[PrefControlled]
interface ScriptProcessorNode : AudioNode {
attribute EventHandler onaudioprocess;

View File

@ -16,7 +16,6 @@ enum OverSampleType {
"4x"
};
[PrefControlled]
interface WaveShaperNode : AudioNode {
attribute Float32Array? curve;

View File

@ -275,6 +275,30 @@ GetWorkerPref(const nsACString& aPref,
return result;
}
// This function creates a key for a SharedWorker composed by "name|scriptSpec".
// If the name contains a '|', this will be replaced by '||'.
void
GenerateSharedWorkerKey(const nsACString& aScriptSpec, const nsACString& aName,
nsCString& aKey)
{
aKey.Truncate();
aKey.SetCapacity(aScriptSpec.Length() + aName.Length() + 1);
nsACString::const_iterator start, end;
aName.BeginReading(start);
aName.EndReading(end);
for (; start != end; ++start) {
if (*start == '|') {
aKey.AppendASCII("||");
} else {
aKey.Append(*start);
}
}
aKey.Append('|');
aKey.Append(aScriptSpec);
}
void
LoadJSContextOptions(const char* aPrefName, void* /* aClosure */)
{
@ -1257,7 +1281,7 @@ RuntimeService::RegisterWorker(JSContext* aCx, WorkerPrivate* aWorkerPrivate)
bool isSharedWorker = aWorkerPrivate->IsSharedWorker();
const nsString& sharedWorkerName = aWorkerPrivate->SharedWorkerName();
const nsCString& sharedWorkerName = aWorkerPrivate->SharedWorkerName();
nsCString sharedWorkerScriptSpec;
if (isSharedWorker) {
@ -1306,13 +1330,14 @@ RuntimeService::RegisterWorker(JSContext* aCx, WorkerPrivate* aWorkerPrivate)
}
if (isSharedWorker) {
MOZ_ASSERT(!domainInfo->mSharedWorkerInfos.Get(sharedWorkerScriptSpec));
nsAutoCString key;
GenerateSharedWorkerKey(sharedWorkerScriptSpec, sharedWorkerName, key);
MOZ_ASSERT(!domainInfo->mSharedWorkerInfos.Get(key));
SharedWorkerInfo* sharedWorkerInfo =
new SharedWorkerInfo(aWorkerPrivate, sharedWorkerScriptSpec,
sharedWorkerName);
domainInfo->mSharedWorkerInfos.Put(sharedWorkerScriptSpec,
sharedWorkerInfo);
domainInfo->mSharedWorkerInfos.Put(key, sharedWorkerInfo);
}
}
@ -1402,8 +1427,10 @@ RuntimeService::UnregisterWorker(JSContext* aCx, WorkerPrivate* aWorkerPrivate)
&match);
if (match.mSharedWorkerInfo) {
domainInfo->mSharedWorkerInfos.Remove(
match.mSharedWorkerInfo->mScriptSpec);
nsAutoCString key;
GenerateSharedWorkerKey(match.mSharedWorkerInfo->mScriptSpec,
match.mSharedWorkerInfo->mName, key);
domainInfo->mSharedWorkerInfos.Remove(key);
}
}
@ -2051,7 +2078,7 @@ RuntimeService::ResumeWorkersForWindow(nsPIDOMWindow* aWindow)
nsresult
RuntimeService::CreateSharedWorker(const GlobalObject& aGlobal,
const nsAString& aScriptURL,
const nsAString& aName,
const nsACString& aName,
SharedWorker** aSharedWorker)
{
AssertIsOnMainThread();
@ -2079,9 +2106,11 @@ RuntimeService::CreateSharedWorker(const GlobalObject& aGlobal,
WorkerDomainInfo* domainInfo;
SharedWorkerInfo* sharedWorkerInfo;
nsAutoCString key;
GenerateSharedWorkerKey(scriptSpec, aName, key);
if (mDomainMap.Get(loadInfo.mDomain, &domainInfo) &&
domainInfo->mSharedWorkerInfos.Get(scriptSpec, &sharedWorkerInfo) &&
sharedWorkerInfo->mName == aName) {
domainInfo->mSharedWorkerInfos.Get(key, &sharedWorkerInfo)) {
workerPrivate = sharedWorkerInfo->mWorkerPrivate;
}
}
@ -2144,8 +2173,10 @@ RuntimeService::ForgetSharedWorker(WorkerPrivate* aWorkerPrivate)
&match);
if (match.mSharedWorkerInfo) {
domainInfo->mSharedWorkerInfos.Remove(
match.mSharedWorkerInfo->mScriptSpec);
nsAutoCString key;
GenerateSharedWorkerKey(match.mSharedWorkerInfo->mScriptSpec,
match.mSharedWorkerInfo->mName, key);
domainInfo->mSharedWorkerInfos.Remove(key);
}
}
}

View File

@ -37,11 +37,11 @@ private:
{
WorkerPrivate* mWorkerPrivate;
nsCString mScriptSpec;
nsString mName;
nsCString mName;
SharedWorkerInfo(WorkerPrivate* aWorkerPrivate,
const nsACString& aScriptSpec,
const nsAString& aName)
const nsACString& aName)
: mWorkerPrivate(aWorkerPrivate), mScriptSpec(aScriptSpec), mName(aName)
{ }
};
@ -144,7 +144,7 @@ public:
nsresult
CreateSharedWorker(const GlobalObject& aGlobal,
const nsAString& aScriptURL,
const nsAString& aName,
const nsACString& aName,
SharedWorker** aSharedWorker);
void

View File

@ -72,9 +72,9 @@ SharedWorker::Constructor(const GlobalObject& aGlobal, JSContext* aCx,
return nullptr;
}
nsString name;
nsCString name;
if (aName.WasPassed()) {
name = aName.Value();
name = NS_ConvertUTF16toUTF8(aName.Value());
}
nsRefPtr<SharedWorker> sharedWorker;

View File

@ -2092,13 +2092,13 @@ typename WorkerPrivateParent<Derived>::cycleCollection
template <class Derived>
WorkerPrivateParent<Derived>::WorkerPrivateParent(
JSContext* aCx,
WorkerPrivate* aParent,
const nsAString& aScriptURL,
bool aIsChromeWorker,
WorkerType aWorkerType,
const nsAString& aSharedWorkerName,
LoadInfo& aLoadInfo)
JSContext* aCx,
WorkerPrivate* aParent,
const nsAString& aScriptURL,
bool aIsChromeWorker,
WorkerType aWorkerType,
const nsACString& aSharedWorkerName,
LoadInfo& aLoadInfo)
: mMutex("WorkerPrivateParent Mutex"),
mCondVar(mMutex, "WorkerPrivateParent CondVar"),
mMemoryReportCondVar(mMutex, "WorkerPrivateParent Memory Report CondVar"),
@ -3523,7 +3523,7 @@ WorkerPrivate::WorkerPrivate(JSContext* aCx,
WorkerPrivate* aParent,
const nsAString& aScriptURL,
bool aIsChromeWorker, WorkerType aWorkerType,
const nsAString& aSharedWorkerName,
const nsACString& aSharedWorkerName,
LoadInfo& aLoadInfo)
: WorkerPrivateParent<WorkerPrivate>(aCx, aParent, aScriptURL,
aIsChromeWorker, aWorkerType,
@ -3563,8 +3563,9 @@ WorkerPrivate::Constructor(const GlobalObject& aGlobal,
const nsAString& aScriptURL,
ErrorResult& aRv)
{
return WorkerPrivate::Constructor(aGlobal, aScriptURL, false, WorkerTypeDedicated,
EmptyString(), nullptr, aRv);
return WorkerPrivate::Constructor(aGlobal, aScriptURL, false,
WorkerTypeDedicated, EmptyCString(),
nullptr, aRv);
}
// static
@ -3591,8 +3592,10 @@ ChromeWorkerPrivate::Constructor(const GlobalObject& aGlobal,
const nsAString& aScriptURL,
ErrorResult& aRv)
{
return WorkerPrivate::Constructor(aGlobal, aScriptURL, true, WorkerTypeDedicated,
EmptyString(), nullptr, aRv).downcast<ChromeWorkerPrivate>();
return WorkerPrivate::Constructor(aGlobal, aScriptURL, true,
WorkerTypeDedicated, EmptyCString(),
nullptr, aRv)
.downcast<ChromeWorkerPrivate>();
}
// static
@ -3609,7 +3612,7 @@ already_AddRefed<WorkerPrivate>
WorkerPrivate::Constructor(const GlobalObject& aGlobal,
const nsAString& aScriptURL,
bool aIsChromeWorker, WorkerType aWorkerType,
const nsAString& aSharedWorkerName,
const nsACString& aSharedWorkerName,
LoadInfo* aLoadInfo, ErrorResult& aRv)
{
WorkerPrivate* parent = NS_IsMainThread() ?

View File

@ -214,7 +214,7 @@ protected:
private:
WorkerPrivate* mParent;
nsString mScriptURL;
nsString mSharedWorkerName;
nsCString mSharedWorkerName;
LocationInfo mLocationInfo;
// The lifetime of these objects within LoadInfo is managed explicitly;
// they do not need to be cycle collected.
@ -251,7 +251,8 @@ protected:
WorkerPrivateParent(JSContext* aCx, WorkerPrivate* aParent,
const nsAString& aScriptURL, bool aIsChromeWorker,
WorkerType aWorkerType,
const nsAString& aSharedWorkerName, LoadInfo& aLoadInfo);
const nsACString& aSharedWorkerName,
LoadInfo& aLoadInfo);
~WorkerPrivateParent();
@ -648,7 +649,7 @@ public:
return mWorkerType == WorkerTypeShared;
}
const nsString&
const nsCString&
SharedWorkerName() const
{
return mSharedWorkerName;
@ -788,7 +789,7 @@ public:
static already_AddRefed<WorkerPrivate>
Constructor(const GlobalObject& aGlobal, const nsAString& aScriptURL,
bool aIsChromeWorker, WorkerType aWorkerType,
const nsAString& aSharedWorkerName,
const nsACString& aSharedWorkerName,
LoadInfo* aLoadInfo, ErrorResult& aRv);
static bool
@ -1042,7 +1043,7 @@ public:
private:
WorkerPrivate(JSContext* aCx, WorkerPrivate* aParent,
const nsAString& aScriptURL, bool aIsChromeWorker,
WorkerType aWorkerType, const nsAString& aSharedWorkerName,
WorkerType aWorkerType, const nsACString& aSharedWorkerName,
LoadInfo& aLoadInfo);
void

View File

@ -311,7 +311,7 @@ DedicatedWorkerGlobalScope::PostMessage(JSContext* aCx,
}
SharedWorkerGlobalScope::SharedWorkerGlobalScope(WorkerPrivate* aWorkerPrivate,
const nsString& aName)
const nsCString& aName)
: WorkerGlobalScope(aWorkerPrivate), mName(aName)
{
}

View File

@ -138,12 +138,13 @@ public:
class SharedWorkerGlobalScope MOZ_FINAL : public WorkerGlobalScope
{
const nsString mName;
const nsCString mName;
~SharedWorkerGlobalScope() { }
public:
SharedWorkerGlobalScope(WorkerPrivate* aWorkerPrivate, const nsString& aName);
SharedWorkerGlobalScope(WorkerPrivate* aWorkerPrivate,
const nsCString& aName);
static bool
Visible(JSContext* aCx, JSObject* aObj);
@ -152,7 +153,7 @@ public:
WrapGlobalObject(JSContext* aCx) MOZ_OVERRIDE;
void GetName(DOMString& aName) const {
aName.AsAString() = mName;
aName.AsAString() = NS_ConvertUTF8toUTF16(mName);
}
IMPL_EVENT_HANDLER(connect)

View File

@ -71,6 +71,7 @@ support-files =
[test_atob.html]
[test_blobConstructor.html]
[test_blobWorkers.html]
[test_bug949946.html]
[test_chromeWorker.html]
[test_clearTimeouts.html]
[test_close.html]

View File

@ -0,0 +1,31 @@
<!--
Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/
-->
<!DOCTYPE HTML>
<html>
<head>
<title>Test for bug 949946</title>
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
</head>
<body>
<p id="display"></p>
<div id="content" style="display: none"></div>
<pre id="test"></pre>
<script class="testbody" type="text/javascript">
SpecialPowers.pushPrefEnv({ set: [["dom.workers.sharedWorkers.enabled", true]] }, function() {
new SharedWorker('sharedWorker_sharedWorker.js');
new SharedWorker('sharedWorker_sharedWorker.js', ':');
new SharedWorker('sharedWorker_sharedWorker.js', '|||');
ok(true, "3 SharedWorkers created!");
SimpleTest.finish();
});
SimpleTest.waitForExplicitFinish();
</script>
</pre>
</body>
</html>

View File

@ -293,9 +293,11 @@ ContentClientRemoteBuffer::Updated(const nsIntRegion& aRegionToDraw,
aDidSelfCopy);
MOZ_ASSERT(mTextureClient);
mForwarder->UseTexture(this, mTextureClient);
if (mTextureClientOnWhite) {
mForwarder->UseTexture(this, mTextureClientOnWhite);
mForwarder->UseComponentAlphaTextures(this, mTextureClient,
mTextureClientOnWhite);
} else {
mForwarder->UseTexture(this, mTextureClient);
}
mForwarder->UpdateTextureRegion(this,
ThebesBufferData(BufferRect(),

View File

@ -109,6 +109,7 @@ public:
// call before and after painting into this content client
virtual void BeginPaint() {}
virtual void EndPaint() {}
};
/**

View File

@ -48,6 +48,17 @@ CompositableHost::UseTextureHost(TextureHost* aTexture)
aTexture->SetCompositableBackendSpecificData(GetCompositableBackendSpecificData());
}
void
CompositableHost::UseComponentAlphaTextures(TextureHost* aTextureOnBlack,
TextureHost* aTextureOnWhite)
{
MOZ_ASSERT(aTextureOnBlack && aTextureOnWhite);
aTextureOnBlack->SetCompositor(GetCompositor());
aTextureOnBlack->SetCompositableBackendSpecificData(GetCompositableBackendSpecificData());
aTextureOnWhite->SetCompositor(GetCompositor());
aTextureOnWhite->SetCompositableBackendSpecificData(GetCompositableBackendSpecificData());
}
void
CompositableHost::SetCompositor(Compositor* aCompositor)
{

View File

@ -288,6 +288,8 @@ public:
virtual void PrintInfo(nsACString& aTo, const char* aPrefix) { }
virtual void UseTextureHost(TextureHost* aTexture);
virtual void UseComponentAlphaTextures(TextureHost* aTextureOnBlack,
TextureHost* aTextureOnWhite);
protected:
TextureInfo mTextureInfo;

View File

@ -220,13 +220,18 @@ ContentHostBase::Composite(EffectChain& aEffectChain,
void
ContentHostBase::UseTextureHost(TextureHost* aTexture)
{
if (aTexture->GetFlags() & TEXTURE_ON_WHITE) {
mTextureHostOnWhite = aTexture;
mTextureHostOnWhite->SetCompositor(GetCompositor());
} else {
mTextureHost = aTexture;
mTextureHost->SetCompositor(GetCompositor());
}
mTextureHost = aTexture;
mTextureHostOnWhite = nullptr;
mTextureHost->SetCompositor(GetCompositor());
}
void
ContentHostBase::UseComponentAlphaTextures(TextureHost* aTextureOnBlack,
TextureHost* aTextureOnWhite)
{
CompositableHost::UseComponentAlphaTextures(aTextureOnBlack, aTextureOnWhite);
mTextureHost = aTextureOnBlack;
mTextureHostOnWhite = aTextureOnWhite;
}
void

View File

@ -116,6 +116,8 @@ public:
virtual TextureHost* GetAsTextureHost() MOZ_OVERRIDE;
virtual void UseTextureHost(TextureHost* aTexture) MOZ_OVERRIDE;
virtual void UseComponentAlphaTextures(TextureHost* aTextureOnBlack,
TextureHost* aTextureOnWhite) MOZ_OVERRIDE;
virtual void SetPaintWillResample(bool aResample) { mPaintWillResample = aResample; }

View File

@ -190,6 +190,9 @@ public:
*/
virtual void UseTexture(CompositableClient* aCompositable,
TextureClient* aClient) = 0;
virtual void UseComponentAlphaTextures(CompositableClient* aCompositable,
TextureClient* aClientOnBlack,
TextureClient* aClientOnWhite) = 0;
/**
* Tell the compositor side that the shared data has been modified so that

View File

@ -233,6 +233,20 @@ CompositableParentManager::ReceiveCompositableUpdate(const CompositableOperation
}
break;
}
case CompositableOperation::TOpUseComponentAlphaTextures: {
const OpUseComponentAlphaTextures& op = aEdit.get_OpUseComponentAlphaTextures();
CompositableHost* compositable = AsCompositable(op);
RefPtr<TextureHost> texOnBlack = TextureHost::AsTextureHost(op.textureOnBlackParent());
RefPtr<TextureHost> texOnWhite = TextureHost::AsTextureHost(op.textureOnWhiteParent());
MOZ_ASSERT(texOnBlack && texOnWhite);
compositable->UseComponentAlphaTextures(texOnBlack, texOnWhite);
if (IsAsync()) {
ScheduleComposition(op);
}
break;
}
case CompositableOperation::TOpUpdateTexture: {
const OpUpdateTexture& op = aEdit.get_OpUpdateTexture();
RefPtr<TextureHost> texture = TextureHost::AsTextureHost(op.textureParent());

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