Merge mozilla-central to b2g-inbound

This commit is contained in:
Carsten "Tomcat" Book 2014-03-20 14:21:13 +01:00
commit a04233feb4
477 changed files with 36944 additions and 4282 deletions

View File

@ -289,6 +289,15 @@ this.EventManager.prototype = {
aEvent.accessible, { delay: 500 });
break;
}
case Events.VALUE_CHANGE:
{
let position = this.contentScope.contentControl.vc.position;
let target = aEvent.accessible;
if (position === target ||
Utils.getEmbeddedControl(position) === target) {
this.present(Presentation.valueChanged(target));
}
}
}
},

View File

@ -73,6 +73,12 @@ Presenter.prototype = {
*/
selectionChanged: function selectionChanged(aObject) {},
/**
* Value has changed.
* @param {nsIAccessible} aAccessible the object whose value has changed.
*/
valueChanged: function valueChanged(aAccessible) {},
/**
* The tab, or the tab's document state has changed.
* @param {nsIAccessible} aDocObj the tab document accessible that has had its
@ -472,6 +478,19 @@ SpeechPresenter.prototype = {
};
},
valueChanged: function SpeechPresenter_valueChanged(aAccessible) {
return {
type: this.type,
details: {
actions: [
{ method: 'speak',
data: aAccessible.value,
options: { enqueue: false } }
]
}
}
},
actionInvoked: function SpeechPresenter_actionInvoked(aObject, aActionName) {
let actions = [];
if (aActionName === 'click') {
@ -607,6 +626,10 @@ this.Presentation = {
for each (p in this.presenters)];
},
valueChanged: function valueChanged(aAccessible) {
return [ p.valueChanged(aAccessible) for (p of this.presenters) ];
},
tabStateChanged: function Presentation_tabStateChanged(aDocObj, aPageState) {
return [p.tabStateChanged(aDocObj, aPageState)
for each (p in this.presenters)];

View File

@ -8,7 +8,9 @@
'<head><title>such app</title></head>' +
'<body>' +
'<h1>wow</h1>' +
'<label><input type="checkbox">many option</label>' +
'<label><input type="checkbox">many option</label><br>' +
'<label for="r">much range</label>' +
'<input min="0" max="10" value="5" type="range" id="r">' +
'</body>' +
'</html>';

View File

@ -372,6 +372,22 @@ var ContentMessages = {
}
},
adjustRangeUp: {
name: 'AccessFu:AdjustRange',
json: {
origin: 'top',
direction: 'backward'
}
},
adjustRangeDown: {
name: 'AccessFu:AdjustRange',
json: {
origin: 'top',
direction: 'forward'
}
},
focusSelector: function focusSelector(aSelector, aBlur) {
return {
name: 'AccessFuTest:Focus',

View File

@ -46,15 +46,31 @@
speak: 'checked',
speak_checkFunc: 'todo_isnot'
}],
// uncheck checkbox
[ContentMessages.simpleMoveNext, {
speak: 'much range label'
}],
[ContentMessages.simpleMoveNext, {
speak: 'much range 5 slider'
}],
[ContentMessages.adjustRangeUp,
{ speak: '6'}],
[ContentMessages.simpleMoveNext, {
speak: 'Home button'
}],
// Simple traversal backward
[ContentMessages.simpleMovePrevious, {
speak: 'many option checked check button such app'
speak: 'much range 6 slider such app'
}],
[ContentMessages.adjustRangeDown,
{ speak: '5'}],
[ContentMessages.simpleMovePrevious, {
speak: 'much range label'
}],
[ContentMessages.simpleMovePrevious, {
speak: 'many option checked check button'
}],
// uncheck checkbox
[ContentMessages.activateCurrent(), {
speak: 'unchecked'
}],

View File

@ -679,19 +679,6 @@ pref("hal.processPriorityManager.gonk.BACKGROUND.Nice", 18);
// Processes get this niceness when they have low CPU priority.
pref("hal.processPriorityManager.gonk.LowCPUNice", 18);
// By default the compositor thread on gonk runs without real-time priority. RT
// priority can be enabled by setting this pref to a value between 1 and 99.
// Note that audio processing currently runs at RT priority 2 or 3 at most.
//
// If RT priority is disabled, then the compositor nice value is used. The
// code will default to ANDROID_PRIORITY_URGENT_DISPLAY which is -8. Per gfx
// request we are keeping the compositor at nice level 0 until we can complete
// the investigation in bug 982972.
//
// Do not change these values without gfx team review.
pref("hal.gonk.compositor.rt_priority", 0);
pref("hal.gonk.compositor.nice", 0);
// Fire a memory pressure event when the system has less than Xmb of memory
// remaining. You should probably set this just above Y.KillUnderKB for
// the highest priority class Y that you want to make an effort to keep alive.

View File

@ -543,7 +543,6 @@
@BINPATH@/components/SystemMessageManager.manifest
@BINPATH@/components/Activities.manifest
@BINPATH@/components/ActivityOptions.js
@BINPATH@/components/ActivityProxy.js
@BINPATH@/components/ActivityRequestHandler.js
@BINPATH@/components/ActivityWrapper.js

View File

@ -1303,10 +1303,16 @@ let BookmarkingUI = {
if (this._itemIds.length > 0) {
this.button.setAttribute("starred", "true");
this.button.setAttribute("buttontooltiptext", this._starredTooltip);
if (this.button.getAttribute("overflowedItem") == "true") {
this.button.setAttribute("label", this._starButtonOverflowedStarredLabel);
}
}
else {
this.button.removeAttribute("starred");
this.button.setAttribute("buttontooltiptext", this._unstarredTooltip);
if (this.button.getAttribute("overflowedItem") == "true") {
this.button.setAttribute("label", this._starButtonOverflowedLabel);
}
}
},

View File

@ -4440,7 +4440,8 @@ var TabsInTitlebar = {
let tabsToolbar = $("TabsToolbar");
let fullTabsHeight = rect(tabsToolbar).height;
// Buttons first:
let captionButtonsBoxWidth = rect($("titlebar-buttonbox")).width;
let captionButtonsBoxWidth = rect($("titlebar-buttonbox-container")).width;
#ifdef XP_MACOSX
let fullscreenButtonWidth = rect($("titlebar-fullscreen-button")).width;
// No need to look up the menubar stuff on OS X:

View File

@ -483,6 +483,11 @@
<hbox id="titlebar-content">
<spacer id="titlebar-spacer" flex="1"/>
<hbox id="titlebar-buttonbox-container">
#ifdef XP_WIN
<hbox id="private-browsing-indicator-titlebar">
<hbox class="private-browsing-indicator"/>
</hbox>
#endif
<hbox id="titlebar-buttonbox">
<toolbarbutton class="titlebar-button" id="titlebar-min" oncommand="window.minimize();"/>
<toolbarbutton class="titlebar-button" id="titlebar-max" oncommand="onTitlebarMaxClick();"/>
@ -595,7 +600,7 @@
tooltiptext="&closeTab.label;"/>
#ifdef XP_WIN
<hbox id="private-browsing-indicator" skipintoolbarset="true" ordinal="1000"/>
<hbox class="private-browsing-indicator" skipintoolbarset="true" ordinal="1000"/>
#endif
#ifdef CAN_DRAW_IN_TITLEBAR
<hbox class="titlebar-placeholder" type="caption-buttons"

View File

@ -42,4 +42,3 @@
!define OPTIONS_BKGRD_COLOR 0x0F1B26
!define INSTALL_BLURB_TEXT_COLOR 0xFFFFFF
!define INSTALL_PROGRESS_TEXT_COLOR_NORMAL 0xFFFFFF
!define INSTALL_PROGRESS_TEXT_COLOR_FADED 0xA1AAB3

View File

@ -42,4 +42,3 @@
!define OPTIONS_BKGRD_COLOR 0x0F1B26
!define INSTALL_BLURB_TEXT_COLOR 0xFFFFFF
!define INSTALL_PROGRESS_TEXT_COLOR_NORMAL 0xFFFFFF
!define INSTALL_PROGRESS_TEXT_COLOR_FADED 0xA1AAB3

View File

@ -46,4 +46,3 @@
!define OPTIONS_BKGRD_COLOR 0xF0F0F0
!define INSTALL_BLURB_TEXT_COLOR 0x666666
!define INSTALL_PROGRESS_TEXT_COLOR_NORMAL 0x666666
!define INSTALL_PROGRESS_TEXT_COLOR_FADED 0x999999

View File

@ -42,4 +42,3 @@
!define OPTIONS_BKGRD_COLOR 0x0F1B26
!define INSTALL_BLURB_TEXT_COLOR 0xFFFFFF
!define INSTALL_PROGRESS_TEXT_COLOR_NORMAL 0xFFFFFF
!define INSTALL_PROGRESS_TEXT_COLOR_FADED 0xA1AAB3

View File

@ -81,6 +81,18 @@ function updateCombinedWidgetStyle(aNode, aArea, aModifyCloseMenu) {
}
}
function addShortcut(aNode, aDocument, aItem) {
let shortcutId = aNode.getAttribute("key");
if (!shortcutId) {
return;
}
let shortcut = aDocument.getElementById(shortcutId);
if (!shortcut) {
return;
}
aItem.setAttribute("shortcut", ShortcutUtils.prettifyShortcut(shortcut));
}
const CustomizableWidgets = [{
id: "history-panelmenu",
type: "view",
@ -292,6 +304,7 @@ const CustomizableWidgets = [{
} else if (node.localName == "menuitem") {
item = doc.createElementNS(kNSXUL, "toolbarbutton");
item.setAttribute("class", "subviewbutton");
addShortcut(node, doc, item);
} else {
continue;
}
@ -367,8 +380,10 @@ const CustomizableWidgets = [{
if (attrVal)
item.setAttribute(attr, attrVal);
}
if (node.localName == "menuitem")
if (node.localName == "menuitem") {
item.classList.add("subviewbutton");
addShortcut(node, doc, item);
}
fragment.appendChild(item);
}
@ -750,6 +765,7 @@ const CustomizableWidgets = [{
elem.section = aSection;
elem.value = item.value;
elem.setAttribute("class", "subviewbutton");
addShortcut(item, doc, elem);
containerElem.appendChild(elem);
}
},

View File

@ -11,7 +11,6 @@ var SubscribeHandler = {
init: function SH_init() {
this._feedWriter = new BrowserFeedWriter();
this._feedWriter.init(window);
},
writeContent: function SH_writeContent() {
@ -20,9 +19,5 @@ var SubscribeHandler = {
uninit: function SH_uninit() {
this._feedWriter.close();
},
subscribe: function SH_subscribe() {
this._feedWriter.subscribe();
}
};

View File

@ -6,7 +6,6 @@
XPIDL_SOURCES += [
'nsIFeedResultService.idl',
'nsIFeedWriter.idl',
'nsIWebContentConverterRegistrar.idl',
]

View File

@ -1,35 +0,0 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "nsISupports.idl"
interface nsIDOMWindow;
/**
* Instances of this component write UI into the display page. This component
* is trusted so can access preferences etc, but page content isn't and so
* cannot.
*/
[scriptable, uuid(67003393-018c-4e96-af10-c6c51a049fad)]
interface nsIFeedWriter : nsISupports
{
/**
* Initializes the feed writer and loads the feed subscription UI.
* @param aWindow
* The DOMWindow of the preview page.
* window.location.href == the URI of the feed.
*/
void init(in nsIDOMWindow aWindow);
/**
* Writes the feed content, assumes that the feed writer is initialized.
*/
void writeContent();
/**
* Uninitialize the feed writer.
*/
void close();
};

View File

@ -23,7 +23,6 @@ component {1c31ed79-accd-4b94-b517-06e0c81999d5} FeedConverter.js
contract @mozilla.org/network/protocol;1?name=pcast {1c31ed79-accd-4b94-b517-06e0c81999d5}
component {49bb6593-3aff-4eb3-a068-2712c28bd58e} FeedWriter.js
contract @mozilla.org/browser/feeds/result-writer;1 {49bb6593-3aff-4eb3-a068-2712c28bd58e}
category JavaScript-global-constructor BrowserFeedWriter @mozilla.org/browser/feeds/result-writer;1
component {792a7e82-06a0-437c-af63-b2d12e808acc} WebContentConverter.js
contract @mozilla.org/embeddor.implemented/web-content-handler-registrar;1 {792a7e82-06a0-437c-af63-b2d12e808acc}
category app-startup WebContentConverter service,@mozilla.org/embeddor.implemented/web-content-handler-registrar;1 application={3c2e2abc-06d4-11e1-ac3b-374f68613e61} application={ec8030f7-c20a-464f-9b0e-13a3a9e97384} application={aa3c5121-dab2-40e2-81ca-7ea25febc110} application={a23983c0-fd0e-11dc-95ff-0800200c9a66}

View File

@ -1123,7 +1123,7 @@ FeedWriter.prototype = {
_feedPrincipal: null,
_handlersMenuList: null,
// nsIFeedWriter
// BrowserFeedWriter WebIDL methods
init: function FW_init(aWindow) {
var window = aWindow;
this._feedURI = this._getOriginalURI(window);
@ -1376,13 +1376,9 @@ FeedWriter.prototype = {
},
classID: FEEDWRITER_CID,
classInfo: XPCOMUtils.generateCI({classID: FEEDWRITER_CID,
contractID: FEEDWRITER_CONTRACTID,
interfaces: [Ci.nsIFeedWriter],
flags: Ci.nsIClassInfo.DOM_OBJECT}),
QueryInterface: XPCOMUtils.generateQI([Ci.nsIFeedWriter,
Ci.nsIDOMEventListener, Ci.nsIObserver,
Ci.nsINavHistoryObserver])
QueryInterface: XPCOMUtils.generateQI([Ci.nsIDOMEventListener, Ci.nsIObserver,
Ci.nsINavHistoryObserver,
Ci.nsIDOMGlobalPropertyInitializer])
};
this.NSGetFactory = XPCOMUtils.generateNSGetFactory([FeedWriter]);

View File

@ -0,0 +1,47 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "js/TypeDecls.h"
#include "nsGlobalWindow.h"
#include "nsIPrincipal.h"
#include "nsIURI.h"
#include "nsString.h"
#include "xpcpublic.h"
namespace mozilla {
struct FeedWriterEnabled {
static bool IsEnabled(JSContext* cx, JSObject* aGlobal)
{
// Make sure the global is a window
nsGlobalWindow* win = xpc::WindowGlobalOrNull(aGlobal);
if (!win) {
return false;
}
// Make sure that the principal is about:feeds.
nsCOMPtr<nsIPrincipal> principal = win->GetPrincipal();
NS_ENSURE_TRUE(principal, false);
nsCOMPtr<nsIURI> uri;
principal->GetURI(getter_AddRefs(uri));
if (!uri) {
return false;
}
// First check the scheme to avoid getting long specs in the common case.
bool isAbout = false;
uri->SchemeIs("about", &isAbout);
if (!isAbout) {
return false;
}
// Now check the spec itself
nsAutoCString spec;
uri->GetSpec(spec);
return spec.Equals("about:feeds");
}
};
}

View File

@ -8,6 +8,10 @@ SOURCES += [
'nsFeedSniffer.cpp',
]
EXPORTS.mozilla += [
'FeedWriterEnabled.h',
]
EXTRA_COMPONENTS += [
'BrowserFeeds.manifest',
'FeedConverter.js',

View File

@ -21,22 +21,27 @@ let Prefs = new ViewHelpers.Prefs("devtools.debugger", {
chromeDebuggingPort: ["Int", "chrome-debugging-port"]
});
// Initiate the connection
let transport = debuggerSocketConnect(
Prefs.chromeDebuggingHost,
Prefs.chromeDebuggingPort
);
let client = new DebuggerClient(transport);
client.connect(() => {
client.listTabs(openToolbox);
});
let gToolbox, gClient;
let gToolbox;
function connect() {
window.removeEventListener("load", connect);
// Initiate the connection
let transport = debuggerSocketConnect(
Prefs.chromeDebuggingHost,
Prefs.chromeDebuggingPort
);
gClient = new DebuggerClient(transport);
gClient.connect(() => {
gClient.listTabs(openToolbox);
});
}
window.addEventListener("load", connect);
function openToolbox(form) {
let options = {
form: form,
client: client,
client: gClient,
chrome: true
};
devtools.TargetFactory.forRemoteTab(options).then(target => {

View File

@ -75,12 +75,14 @@ function selectDiv() {
}
function testTransformDimension() {
let deferred = promise.defer();
info("Testing css transform tooltip dimensions");
return Task.spawn(function*() {
let tooltip = ruleView.previewTooltip;
let panel = tooltip.panel;
let {valueSpan} = getRuleViewProperty("transform");
showTooltipOn(ruleView.previewTooltip, valueSpan, () => {
let panel = ruleView.previewTooltip.panel;
info("Testing css transform tooltip dimensions");
let {valueSpan} = getRuleViewProperty("transform");
yield assertTooltipShownOn(tooltip, valueSpan);
// Let's not test for a specific size, but instead let's make sure it's at
// least as big as the preview canvas
@ -92,22 +94,23 @@ function testTransformDimension() {
ok(panelRect.width >= w, "The panel is wide enough to show the canvas");
ok(panelRect.height >= h, "The panel is high enough to show the canvas");
ruleView.previewTooltip.hide();
deferred.resolve();
let onHidden = tooltip.once("hidden");
tooltip.hide();
yield onHidden;
});
return deferred.promise;
}
function testImageDimension() {
let deferred = promise.defer();
info("Testing background-image tooltip dimensions");
return Task.spawn(function*() {
info("Testing background-image tooltip dimensions");
let {valueSpan} = getRuleViewProperty("background");
let uriSpan = valueSpan.querySelector(".theme-link");
let tooltip = ruleView.previewTooltip;
let panel = tooltip.panel;
showTooltipOn(ruleView.previewTooltip, uriSpan, () => {
let panel = ruleView.previewTooltip.panel;
let {valueSpan} = getRuleViewProperty("background");
let uriSpan = valueSpan.querySelector(".theme-link");
yield assertTooltipShownOn(tooltip, uriSpan);
// Let's not test for a specific size, but instead let's make sure it's at
// least as big as the image
@ -119,22 +122,24 @@ function testImageDimension() {
ok(panelRect.height >= imageRect.height,
"The panel is high enough to show the image");
ruleView.previewTooltip.hide();
deferred.resolve();
let onHidden = tooltip.once("hidden");
tooltip.hide();
yield onHidden;
});
return deferred.promise;
}
function testPickerDimension() {
let deferred = promise.defer();
info("Testing color-picker tooltip dimensions");
return Task.spawn(function*() {
info("Testing color-picker tooltip dimensions");
let {valueSpan} = getRuleViewProperty("background");
let swatch = valueSpan.querySelector(".ruleview-colorswatch");
let cPicker = ruleView.colorPicker;
let {valueSpan} = getRuleViewProperty("background");
let swatch = valueSpan.querySelector(".ruleview-colorswatch");
let cPicker = ruleView.colorPicker;
let onShown = cPicker.tooltip.once("shown");
swatch.click();
yield onShown;
cPicker.tooltip.once("shown", () => {
// The colorpicker spectrum's iframe has a fixed width height, so let's
// make sure the tooltip is at least as big as that
let w = cPicker.tooltip.panel.querySelector("iframe").width;
@ -144,21 +149,43 @@ function testPickerDimension() {
ok(panelRect.width >= w, "The panel is wide enough to show the picker");
ok(panelRect.height >= h, "The panel is high enough to show the picker");
let onHidden = cPicker.tooltip.once("hidden");
cPicker.hide();
deferred.resolve();
yield onHidden;
});
swatch.click();
return deferred.promise;
}
function showTooltipOn(tooltip, element, cb) {
// If there is indeed a show-on-hover on element, the xul panel will be shown
tooltip.panel.addEventListener("popupshown", function shown() {
tooltip.panel.removeEventListener("popupshown", shown, true);
cb();
}, true);
tooltip._showOnHover(element);
/**
* @return a promise that resolves when the tooltip is shown
*/
function assertTooltipShownOn(tooltip, element) {
return Task.spawn(function*() {
let isTarget = yield isHoverTooltipTarget(tooltip, element);
ok(isTarget, "The element is a tooltip target and content has been inserted");
info("Showing the tooltip now that content has been inserted by isValidHoverTarget");
let onShown = tooltip.once("shown");
tooltip.show();
yield onShown;
});
}
/**
* Given a tooltip object instance (see Tooltip.js), checks if it is set to
* toggle and hover and if so, checks if the given target is a valid hover target.
* This won't actually show the tooltip (the less we interact with XUL panels
* during test runs, the better).
* @return a promise that resolves when the answer is known. Also, this will
* delete to a function in the rule-view which will insert content into the
* tooltip
*/
function isHoverTooltipTarget(tooltip, target) {
if (!tooltip._basedNode || !tooltip.panel) {
return promise.reject(new Error("The tooltip passed isn't set to toggle on hover or is not a tooltip"));
}
// The tooltip delegates to a user defined cb that inserts content in the tooltip
// when calling isValidHoverTarget
return tooltip.isValidHoverTarget(target);
}
function getRuleViewProperty(name) {

View File

@ -110,7 +110,7 @@ MarkupView.prototype = {
_initTooltips: function() {
this.tooltip = new Tooltip(this._inspector.panelDoc);
this.tooltip.startTogglingOnHover(this._elt,
this._buildTooltipContent.bind(this));
this._isImagePreviewTarget.bind(this));
},
_initHighlighter: function() {
@ -232,7 +232,15 @@ MarkupView.prototype = {
updateChildren(documentElement);
},
_buildTooltipContent: function(target) {
/**
* Executed when the mouse hovers over a target in the markup-view and is used
* to decide whether this target should be used to display an image preview
* tooltip.
* Delegates the actual decision to the corresponding MarkupContainer instance
* if one is found.
* @return the promise returned by MarkupContainer._isImagePreviewTarget
*/
_isImagePreviewTarget: function(target) {
// From the target passed here, let's find the parent MarkupContainer
// and ask it if the tooltip should be shown
let parent = target, container;
@ -247,7 +255,7 @@ MarkupView.prototype = {
if (container) {
// With the newly found container, delegate the tooltip content creation
// and decision to show or not the tooltip
return container._buildTooltipContent(target, this.tooltip);
return container._isImagePreviewTarget(target, this.tooltip);
}
},
@ -1271,6 +1279,13 @@ MarkupContainer.prototype = {
}
},
/**
* If the node is an image or canvas (@see isPreviewable), then get the
* image data uri from the server so that it can then later be previewed in
* a tooltip if needed.
* Stores a promise in this.tooltipData.data that resolves when the data has
* been retrieved
*/
_prepareImagePreview: function() {
if (this.isPreviewable()) {
// Get the image data for later so that when the user actually hovers over
@ -1297,6 +1312,27 @@ MarkupContainer.prototype = {
}
},
/**
* Executed by MarkupView._isImagePreviewTarget which is itself called when the
* mouse hovers over a target in the markup-view.
* Checks if the target is indeed something we want to have an image tooltip
* preview over and, if so, inserts content into the tooltip.
* @return a promise that resolves when the content has been inserted or
* rejects if no preview is required. This promise is then used by Tooltip.js
* to decide if/when to show the tooltip
*/
_isImagePreviewTarget: function(target, tooltip) {
if (!this.tooltipData || this.tooltipData.target !== target) {
return promise.reject();
}
return this.tooltipData.data.then(({data, size}) => {
tooltip.setImageContent(data, size);
}, () => {
tooltip.setBrokenImageContent();
});
},
copyImageDataUri: function() {
// We need to send again a request to gettooltipData even if one was sent for
// the tooltip, because we want the full-size image
@ -1307,17 +1343,6 @@ MarkupContainer.prototype = {
});
},
_buildTooltipContent: function(target, tooltip) {
if (this.tooltipData && target === this.tooltipData.target) {
this.tooltipData.data.then(({data, size}) => {
tooltip.setImageContent(data, size);
}, () => {
tooltip.setBrokenImageContent();
});
return true;
}
},
/**
* True if the current node has children. The MarkupView
* will set this attribute for the MarkupContainer.

View File

@ -88,7 +88,7 @@ function testImageTooltip(index) {
target = container.editor.getAttributeElement("src");
}
assertTooltipShownOn(target, () => {
assertTooltipShownOn(target).then(() => {
let images = markup.tooltip.panel.getElementsByTagName("image");
is(images.length, 1,
"Tooltip for [" + TEST_NODES[index].selector + "] contains an image");
@ -97,7 +97,6 @@ function testImageTooltip(index) {
is(label.textContent, TEST_NODES[index].size,
"Tooltip label for [" + TEST_NODES[index].selector + "] displays the right image size")
markup.tooltip.hide();
testImageTooltip(index + 1);
});
}
@ -117,22 +116,10 @@ function compareImageData(img, imgData) {
}
function assertTooltipShownOn(element, cb) {
// If there is indeed a show-on-hover on element, the xul panel will be shown
markup.tooltip.panel.addEventListener("popupshown", function shown() {
markup.tooltip.panel.removeEventListener("popupshown", shown, true);
return Task.spawn(function*() {
info("Is the element a valid hover target");
// Poll until the image gets loaded in the tooltip. This is required because
// markup containers only load images in their associated tooltips when
// the image data comes back from the server. However, this test is executed
// synchronously as soon as "inspector-updated" is fired, which is before
// the data for images is known.
let hasImage = () => markup.tooltip.panel.getElementsByTagName("image").length;
let poll = setInterval(() => {
if (hasImage()) {
clearInterval(poll);
cb();
}
}, 200);
}, true);
markup.tooltip._showOnHover(element);
let isValid = yield markup.tooltip.isValidHoverTarget(element);
ok(isValid, "The element is a valid hover target for the image tooltip");
});
}

View File

@ -59,16 +59,17 @@ function test() {
});
}
function showTooltipOn(aTooltip, aTarget) {
let deferred = promise.defer();
aTooltip.panel.addEventListener("popupshown", function onEvent() {
aTooltip.panel.removeEventListener("popupshown", onEvent, true);
deferred.resolve(aTooltip);
}, true);
aTooltip._showOnHover(aTarget);
return deferred.promise;
/**
* @return a promise that resolves when the tooltip is shown
*/
function showTooltipOn(tooltip, element) {
return Task.spawn(function*() {
let isTarget = yield tooltip.isValidHoverTarget(element);
let onShown = tooltip.once("shown");
tooltip.show();
yield onShown;
return tooltip;
});
}
aDebuggee.performRequests();

View File

@ -392,19 +392,34 @@ Tooltip.prototype = {
this.hide();
this._lastHovered = event.target;
setNamedTimeout(this.uid, this._showDelay, () => {
this._showOnHover(event.target);
this.isValidHoverTarget(event.target).then(target => {
this.show(target);
});
});
}
},
_showOnHover: function(target) {
/**
* Is the given target DOMNode a valid node for toggling the tooltip on hover.
* This delegates to the user-defined _targetNodeCb callback.
* @return a promise that resolves or rejects depending if the tooltip should
* be shown or not. If it resolves, it does to the actual anchor to be used
*/
isValidHoverTarget: function(target) {
// Execute the user-defined callback which should return either true/false
// or a promise that resolves or rejects
let res = this._targetNodeCb(target, this);
let show = arg => this.show(arg instanceof Ci.nsIDOMNode ? arg : target);
// The callback can additionally return a DOMNode to replace the anchor of
// the tooltip when shown
if (res && res.then) {
res.then(show);
} else if (res) {
show(res);
return res.then(arg => {
return arg instanceof Ci.nsIDOMNode ? arg : target;
}, () => {
return false;
});
} else {
return res ? promise.resolve(res) : promise.reject(false);
}
},
@ -620,42 +635,44 @@ Tooltip.prototype = {
* a number here
*/
setImageContent: function(imageUrl, options={}) {
if (imageUrl) {
// Main container
let vbox = this.doc.createElement("vbox");
vbox.setAttribute("align", "center");
// Display the image
let image = this.doc.createElement("image");
image.setAttribute("src", imageUrl);
if (options.maxDim) {
image.style.maxWidth = options.maxDim + "px";
image.style.maxHeight = options.maxDim + "px";
}
vbox.appendChild(image);
// Dimension label
let label = this.doc.createElement("label");
label.classList.add("devtools-tooltip-caption");
label.classList.add("theme-comment");
if (options.naturalWidth && options.naturalHeight) {
label.textContent = this._getImageDimensionLabel(options.naturalWidth,
options.naturalHeight);
} else {
// If no dimensions were provided, load the image to get them
label.textContent = l10n.strings.GetStringFromName("previewTooltip.image.brokenImage");
let imgObj = new this.doc.defaultView.Image();
imgObj.src = imageUrl;
imgObj.onload = () => {
imgObj.onload = null;
label.textContent = this._getImageDimensionLabel(imgObj.naturalWidth,
imgObj.naturalHeight);
}
}
vbox.appendChild(label);
this.content = vbox;
if (!imageUrl) {
return;
}
// Main container
let vbox = this.doc.createElement("vbox");
vbox.setAttribute("align", "center");
// Display the image
let image = this.doc.createElement("image");
image.setAttribute("src", imageUrl);
if (options.maxDim) {
image.style.maxWidth = options.maxDim + "px";
image.style.maxHeight = options.maxDim + "px";
}
vbox.appendChild(image);
// Dimension label
let label = this.doc.createElement("label");
label.classList.add("devtools-tooltip-caption");
label.classList.add("theme-comment");
if (options.naturalWidth && options.naturalHeight) {
label.textContent = this._getImageDimensionLabel(options.naturalWidth,
options.naturalHeight);
} else {
// If no dimensions were provided, load the image to get them
label.textContent = l10n.strings.GetStringFromName("previewTooltip.image.brokenImage");
let imgObj = new this.doc.defaultView.Image();
imgObj.src = imageUrl;
imgObj.onload = () => {
imgObj.onload = null;
label.textContent = this._getImageDimensionLabel(imgObj.naturalWidth,
imgObj.naturalHeight);
}
}
vbox.appendChild(label);
this.content = vbox;
},
_getImageDimensionLabel: (w, h) => w + " x " + h,

View File

@ -91,7 +91,7 @@ function autoComplete({ ed, cm }) {
let cur = ed.getCursor();
completer.complete(cm.getRange({line: 0, ch: 0}, cur), cur)
.then(suggestions => {
if (!suggestions || !suggestions.length || !suggestions[0].preLabel) {
if (!suggestions || !suggestions.length || suggestions[0].preLabel == null) {
private.suggestionInsertedOnce = false;
popup.hidePopup();
ed.emit("after-suggest");

View File

@ -648,6 +648,11 @@ CSSCompleter.prototype = {
} else {
this.completing = "";
}
// Special case the situation when the user just entered ":" after typing a
// property name.
if (this.completing == ":" && _state == CSS_STATES.value)
this.completing = "";
// Special check for !important; case.
if (tokens[cursor - 2] && tokens[cursor - 2].value == "!" &&
this.completing == "important".slice(0, this.completing.length)) {
@ -760,6 +765,9 @@ CSSCompleter.prototype = {
*/
completeProperties: function(startProp) {
let finalList = [];
if (!startProp)
return finalList;
let length = propertyNames.length;
let i = 0, count = 0;
for (; i < length && count < this.maxEntries; i++) {
@ -787,6 +795,11 @@ CSSCompleter.prototype = {
completeValues: function(propName, startValue) {
let finalList = [];
let list = ["!important;", ...(properties[propName] || [])];
// If there is no character being completed, we are showing an initial list
// of possible values. Skipping '!important' in this case.
if (!startValue)
list.splice(0, 1);
let length = list.length;
let i = 0, count = 0;
for (; i < length && count < this.maxEntries; i++) {

View File

@ -18,6 +18,7 @@
[[12, 20], ['none', 'number-input']],
[[12, 22], ['none']],
[[17, 22], ['hsl', 'hsla']],
[[21, 9], ["-moz-calc", "auto", "calc", "inherit", "initial","unset"]],
[[22, 5], ['color', 'color-interpolation', 'color-interpolation-filters']],
[[25, 26], ['.devtools-toolbarbutton > tab',
'.devtools-toolbarbutton > .toolbarbutton-menubutton-button',

View File

@ -135,6 +135,8 @@ StyleEditorPanel.prototype = {
this._target = null;
this._toolbox = null;
this._panelDoc = null;
this._debuggee.destroy();
this._debuggee = null;
this.UI.destroy();
}

View File

@ -37,7 +37,7 @@ let TEST_CASES = [
['a', getSuggestionNumberFor("ba"), 0],
['VK_DOWN', getSuggestionNumberFor("ba"), 0, 1],
['VK_TAB', getSuggestionNumberFor("ba"), 1, 1],
[':', -1],
[':', getSuggestionNumberFor("background", ""), 0],
['b', getSuggestionNumberFor("background", "b"), 0],
['l', getSuggestionNumberFor("background", "bl"), 0],
['VK_TAB', getSuggestionNumberFor("background", "bl"), 0, 1],
@ -223,7 +223,7 @@ function getCSSKeywords() {
* Returns the number of properties starting with `property` otherwise.
*/
function getSuggestionNumberFor(property, value) {
if (!value) {
if (value == null) {
return CSSProperties.filter(prop => prop.startsWith(property))
.slice(0, MAX_SUGGESTIONS).length;
}

View File

@ -1122,7 +1122,7 @@ CssRuleView.prototype = {
// Test for css transform
if (property && property.name === "transform") {
this.previewTooltip.setCssTransformContent(property.value, this.pageStyle,
this._viewedElement).then(def.resolve);
this._viewedElement).then(def.resolve, def.reject);
hasTooltip = true;
}
@ -1163,11 +1163,11 @@ CssRuleView.prototype = {
hasTooltip = true;
}
if (hasTooltip) {
if (!hasTooltip) {
def.reject();
} else if (this.colorPicker.tooltip.isShown()) {
this.colorPicker.revert();
this.colorPicker.hide();
} else {
def.reject();
}
return def.promise;

View File

@ -52,56 +52,43 @@ function endTests() {
finish();
}
function assertTooltipShownOn(tooltip, element, cb) {
// If there is indeed a show-on-hover on element, the xul panel will be shown
tooltip.panel.addEventListener("popupshown", function shown() {
tooltip.panel.removeEventListener("popupshown", shown, true);
cb();
}, true);
tooltip._showOnHover(element);
}
function testRuleView() {
info("Testing font-family tooltips in the rule view");
Task.spawn(function*() {
info("Testing font-family tooltips in the rule view");
let panel = ruleView.previewTooltip.panel;
let panel = ruleView.previewTooltip.panel;
// Check that the rule view has a tooltip and that a XUL panel has been created
ok(ruleView.previewTooltip, "Tooltip instance exists");
ok(panel, "XUL panel exists");
// Check that the rule view has a tooltip and that a XUL panel has been created
ok(ruleView.previewTooltip, "Tooltip instance exists");
ok(panel, "XUL panel exists");
// Get the font family property inside the rule view
let {valueSpan} = getRuleViewProperty("font-family");
// Get the font family property inside the rule view
let {valueSpan} = getRuleViewProperty("font-family");
// And verify that the tooltip gets shown on this property
assertTooltipShownOn(ruleView.previewTooltip, valueSpan);
// And verify that the tooltip gets shown on this property
assertTooltipShownOn(ruleView.previewTooltip, valueSpan, () => {
let description = panel.getElementsByTagName("description")[0];
is(description.style.fontFamily, "cursive", "Tooltips contains correct font-family style");
ruleView.previewTooltip.hide();
testComputedView();
});
}).then(testComputedView);
}
function testComputedView() {
info("Testing font-family tooltips in the computed view");
Task.spawn(function*() {
info("Testing font-family tooltips in the computed view");
inspector.sidebar.select("computedview");
computedView = inspector.sidebar.getWindowForTab("computedview").computedview.view;
let doc = computedView.styleDocument;
inspector.sidebar.select("computedview");
computedView = inspector.sidebar.getWindowForTab("computedview").computedview.view;
let doc = computedView.styleDocument;
let panel = computedView.tooltip.panel;
let {valueSpan} = getComputedViewProperty("font-family");
let panel = computedView.tooltip.panel;
let {valueSpan} = getComputedViewProperty("font-family");
assertTooltipShownOn(computedView.tooltip, valueSpan);
assertTooltipShownOn(computedView.tooltip, valueSpan, () => {
let description = panel.getElementsByTagName("description")[0];
is(description.style.fontFamily, "cursive", "Tooltips contains correct font-family style");
computedView.tooltip.hide();
endTests();
});
}).then(endTests);
}
function getRuleViewProperty(name) {

View File

@ -50,60 +50,48 @@ function endTests() {
finish();
}
function assertTooltipShownOn(tooltip, element, cb) {
// If there is indeed a show-on-hover on element, the xul panel will be shown
tooltip.panel.addEventListener("popupshown", function shown() {
tooltip.panel.removeEventListener("popupshown", shown, true);
cb();
}, true);
tooltip._showOnHover(element);
}
function testRuleView() {
info("Testing font-family tooltips in the rule view");
Task.spawn(function*() {
info("Testing font-family tooltips in the rule view");
let panel = ruleView.previewTooltip.panel;
let panel = ruleView.previewTooltip.panel;
// Check that the rule view has a tooltip and that a XUL panel has been created
ok(ruleView.previewTooltip, "Tooltip instance exists");
ok(panel, "XUL panel exists");
// Check that the rule view has a tooltip and that a XUL panel has been created
ok(ruleView.previewTooltip, "Tooltip instance exists");
ok(panel, "XUL panel exists");
// Get the computed font family property inside the font rule view
let propertyList = ruleView.element.querySelectorAll(".ruleview-propertylist");
let fontExpander = propertyList[1].querySelectorAll(".ruleview-expander")[0];
fontExpander.click();
// Get the computed font family property inside the font rule view
let propertyList = ruleView.element.querySelectorAll(".ruleview-propertylist");
let fontExpander = propertyList[1].querySelectorAll(".ruleview-expander")[0];
fontExpander.click();
let {valueSpan} = getRuleViewProperty("font-family");
let {valueSpan} = getRuleViewProperty("font-family");
// And verify that the tooltip gets shown on this property
assertTooltipShownOn(ruleView.previewTooltip, valueSpan, () => {
// And verify that the tooltip gets shown on this property
yield assertTooltipShownOn(ruleView.previewTooltip, valueSpan);
// And that it has the right content
let description = panel.getElementsByTagName("description")[0];
is(description.style.fontFamily, "Arial", "Tooltips contains correct font-family style");
ruleView.previewTooltip.hide();
testComputedView();
});
}).then(testComputedView);
}
function testComputedView() {
info("Testing font-family tooltips in the computed view");
Task.spawn(function*() {
info("Testing font-family tooltips in the computed view");
inspector.sidebar.select("computedview");
computedView = inspector.sidebar.getWindowForTab("computedview").computedview.view;
let doc = computedView.styleDocument;
inspector.sidebar.select("computedview");
computedView = inspector.sidebar.getWindowForTab("computedview").computedview.view;
let doc = computedView.styleDocument;
let panel = computedView.tooltip.panel;
let {valueSpan} = getComputedViewProperty("font-family");
let panel = computedView.tooltip.panel;
let {valueSpan} = getComputedViewProperty("font-family");
yield assertTooltipShownOn(computedView.tooltip, valueSpan);
assertTooltipShownOn(computedView.tooltip, valueSpan, () => {
let description = panel.getElementsByTagName("description")[0];
is(description.style.fontFamily, "Arial", "Tooltips contains correct font-family style");
computedView.tooltip.hide();
endTests();
});
}).then(endTests);
}
function getRuleViewProperty(name) {

View File

@ -64,106 +64,82 @@ function endTests() {
}
function testTransformTooltipOnIDSelector() {
info("Testing that a transform tooltip appears on the #ID rule");
Task.spawn(function*() {
info("Testing that a transform tooltip appears on the #ID rule");
let panel = ruleView.previewTooltip.panel;
ok(panel, "The XUL panel exists for the rule-view preview tooltips");
let panel = ruleView.previewTooltip.panel;
ok(panel, "The XUL panel exists for the rule-view preview tooltips");
let {valueSpan} = getRuleViewProperty("#testElement", "transform");
yield assertTooltipShownOn(ruleView.previewTooltip, valueSpan);
let {valueSpan} = getRuleViewProperty("#testElement", "transform");
assertTooltipShownOn(ruleView.previewTooltip, valueSpan, () => {
// The transform preview is canvas, so there's not much we can test, so for
// now, let's just be happy with the fact that the tooltips is shown!
ok(true, "Tooltip shown on the transform property of the #ID rule");
ruleView.previewTooltip.hide();
executeSoon(testTransformTooltipOnClassSelector);
});
}).then(testTransformTooltipOnClassSelector);
}
function testTransformTooltipOnClassSelector() {
info("Testing that a transform tooltip appears on the .class rule");
Task.spawn(function*() {
info("Testing that a transform tooltip appears on the .class rule");
let {valueSpan} = getRuleViewProperty(".test-element", "transform");
yield assertTooltipShownOn(ruleView.previewTooltip, valueSpan);
let {valueSpan} = getRuleViewProperty(".test-element", "transform");
assertTooltipShownOn(ruleView.previewTooltip, valueSpan, () => {
// The transform preview is canvas, so there's not much we can test, so for
// now, let's just be happy with the fact that the tooltips is shown!
ok(true, "Tooltip shown on the transform property of the .class rule");
ruleView.previewTooltip.hide();
executeSoon(testTransformTooltipOnTagSelector);
});
}).then(testTransformTooltipOnTagSelector);
}
function testTransformTooltipOnTagSelector() {
info("Testing that a transform tooltip appears on the tag rule");
Task.spawn(function*() {
info("Testing that a transform tooltip appears on the tag rule");
let {valueSpan} = getRuleViewProperty("div", "transform");
yield assertTooltipShownOn(ruleView.previewTooltip, valueSpan);
let {valueSpan} = getRuleViewProperty("div", "transform");
assertTooltipShownOn(ruleView.previewTooltip, valueSpan, () => {
// The transform preview is canvas, so there's not much we can test, so for
// now, let's just be happy with the fact that the tooltips is shown!
ok(true, "Tooltip shown on the transform property of the tag rule");
ruleView.previewTooltip.hide();
executeSoon(testTransformTooltipNotShownOnInvalidTransform);
});
}).then(testTransformTooltipNotShownOnInvalidTransform);
}
function testTransformTooltipNotShownOnInvalidTransform() {
info("Testing that a transform tooltip does not appear for invalid values");
Task.spawn(function*() {
info("Testing that a transform tooltip does not appear for invalid values");
let ruleEditor;
for (let rule of ruleView._elementStyle.rules) {
if (rule.matchedSelectors[0] === "[attr]") {
ruleEditor = rule.editor;
let ruleEditor;
for (let rule of ruleView._elementStyle.rules) {
if (rule.matchedSelectors[0] === "[attr]") {
ruleEditor = rule.editor;
}
}
}
ruleEditor.addProperty("transform", "muchTransform(suchAngle)", "");
ruleEditor.addProperty("transform", "muchTransform(suchAngle)", "");
let {valueSpan} = getRuleViewProperty("[attr]", "transform");
assertTooltipNotShownOn(ruleView.previewTooltip, valueSpan, () => {
executeSoon(testTransformTooltipOnComputedView);
});
let {valueSpan} = getRuleViewProperty("[attr]", "transform");
let isValid = yield isHoverTooltipTarget(ruleView.previewTooltip, valueSpan);
ok(!isValid, "The tooltip did not appear on hover of an invalid transform value");
}).then(testTransformTooltipOnComputedView);
}
function testTransformTooltipOnComputedView() {
info("Testing that a transform tooltip appears in the computed view too");
Task.spawn(function*() {
info("Testing that a transform tooltip appears in the computed view too");
inspector.sidebar.select("computedview");
computedView = inspector.sidebar.getWindowForTab("computedview").computedview.view;
let doc = computedView.styleDocument;
inspector.sidebar.select("computedview");
computedView = inspector.sidebar.getWindowForTab("computedview").computedview.view;
let doc = computedView.styleDocument;
let panel = computedView.tooltip.panel;
let {valueSpan} = getComputedViewProperty("transform");
let panel = computedView.tooltip.panel;
let {valueSpan} = getComputedViewProperty("transform");
yield assertTooltipShownOn(computedView.tooltip, valueSpan);
assertTooltipShownOn(computedView.tooltip, valueSpan, () => {
// The transform preview is canvas, so there's not much we can test, so for
// now, let's just be happy with the fact that the tooltips is shown!
ok(true, "Tooltip shown on the computed transform property");
computedView.tooltip.hide();
executeSoon(endTests);
});
}
function assertTooltipShownOn(tooltip, element, cb) {
// If there is indeed a show-on-hover on element, the xul panel will be shown
tooltip.panel.addEventListener("popupshown", function shown() {
tooltip.panel.removeEventListener("popupshown", shown, true);
cb();
}, true);
// Run _showOnHover at stable state after the next refresh driver tick.
// This way nothing during reflow or painting should be able to
// cancel showing the popup.
element.ownerDocument.defaultView.requestAnimationFrame(() => {
executeSoon(() => { tooltip._showOnHover(element); });
});
}
function assertTooltipNotShownOn(tooltip, element, cb) {
// The only way to make sure the tooltip is not shown is try and show it, wait
// for a given amount of time, and then check if it's shown or not
tooltip._showOnHover(element);
setTimeout(() => {
ok(!tooltip.isShown(), "The tooltip did not appear on hover of the element");
cb();
}, tooltip.defaultShowDelay + 100);
}).then(endTests);
}
function getRule(selectorText) {

View File

@ -59,100 +59,92 @@ function endTests() {
finish();
}
function assertTooltipShownOn(tooltip, element, cb) {
// If there is indeed a show-on-hover on element, the xul panel will be shown
tooltip.panel.addEventListener("popupshown", function shown() {
tooltip.panel.removeEventListener("popupshown", shown, true);
cb();
}, true);
tooltip._showOnHover(element);
}
function testBodyRuleView() {
info("Testing tooltips in the rule view");
Task.spawn(function*() {
info("Testing tooltips in the rule view");
let panel = ruleView.previewTooltip.panel;
let panel = ruleView.previewTooltip.panel;
// Check that the rule view has a tooltip and that a XUL panel has been created
ok(ruleView.previewTooltip, "Tooltip instance exists");
ok(panel, "XUL panel exists");
// Check that the rule view has a tooltip and that a XUL panel has been created
ok(ruleView.previewTooltip, "Tooltip instance exists");
ok(panel, "XUL panel exists");
// Get the background-image property inside the rule view
let {valueSpan} = getRuleViewProperty("background-image");
let uriSpan = valueSpan.querySelector(".theme-link");
yield assertTooltipShownOn(ruleView.previewTooltip, uriSpan);
// Get the background-image property inside the rule view
let {valueSpan} = getRuleViewProperty("background-image");
let uriSpan = valueSpan.querySelector(".theme-link");
// And verify that the tooltip gets shown on this property
assertTooltipShownOn(ruleView.previewTooltip, uriSpan, () => {
let images = panel.getElementsByTagName("image");
is(images.length, 1, "Tooltip contains an image");
ok(images[0].src.indexOf("iVBORw0KGgoAAAANSUhEUgAAAEAAAABACAYAAACqaXHe") !== -1, "The image URL seems fine");
ruleView.previewTooltip.hide();
ok(images[0].getAttribute("src").indexOf("iVBORw0KGgoAAAANSUhEUgAAAEAAAABACAYAAACqaXHe") !== -1,
"The image URL seems fine");
let onUpdated = inspector.once("inspector-updated");
inspector.selection.setNode(contentDoc.querySelector(".test-element"));
inspector.once("inspector-updated", testDivRuleView);
});
yield onUpdated;
}).then(testDivRuleView);
}
function testDivRuleView() {
let panel = ruleView.previewTooltip.panel;
Task.spawn(function*() {
let panel = ruleView.previewTooltip.panel;
// Get the background property inside the rule view
let {valueSpan} = getRuleViewProperty("background");
let uriSpan = valueSpan.querySelector(".theme-link");
// Get the background property inside the rule view
let {valueSpan} = getRuleViewProperty("background");
let uriSpan = valueSpan.querySelector(".theme-link");
yield assertTooltipShownOn(ruleView.previewTooltip, uriSpan);
// And verify that the tooltip gets shown on this property
assertTooltipShownOn(ruleView.previewTooltip, uriSpan, () => {
let images = panel.getElementsByTagName("image");
is(images.length, 1, "Tooltip contains an image");
ok(images[0].src.startsWith("data:"), "Tooltip contains a data-uri image as expected");
ruleView.previewTooltip.hide();
testTooltipAppearsEvenInEditMode();
});
ok(images[0].getAttribute("src").startsWith("data:"), "Tooltip contains a data-uri image as expected");
}).then(testTooltipAppearsEvenInEditMode);
}
function testTooltipAppearsEvenInEditMode() {
let panel = ruleView.previewTooltip.panel;
Task.spawn(function*() {
let panel = ruleView.previewTooltip.panel;
// Switch one field to edit mode
let brace = ruleView.doc.querySelector(".ruleview-ruleclose");
waitForEditorFocus(brace.parentNode, editor => {
// Now try to show the tooltip
info("Switching to edit mode in the rule view");
let editor = yield turnToEditMode(ruleView);
info("Now trying to show the preview tooltip");
let {valueSpan} = getRuleViewProperty("background");
let uriSpan = valueSpan.querySelector(".theme-link");
assertTooltipShownOn(ruleView.previewTooltip, uriSpan, () => {
is(ruleView.doc.activeElement, editor.input,
"Tooltip was shown in edit mode, and inplace-editor still focused");
yield assertTooltipShownOn(ruleView.previewTooltip, uriSpan);
ruleView.previewTooltip.hide();
is(ruleView.doc.activeElement, editor.input,
"Tooltip was shown in edit mode, and inplace-editor still focused");
}).then(testComputedView);
}
testComputedView();
});
});
function turnToEditMode(ruleView) {
let def = promise.defer();
let brace = ruleView.doc.querySelector(".ruleview-ruleclose");
waitForEditorFocus(brace.parentNode, def.resolve);
brace.click();
return def.promise;
}
function testComputedView() {
info("Testing tooltips in the computed view");
Task.spawn(function*() {
info("Testing tooltips in the computed view");
inspector.sidebar.select("computedview");
computedView = inspector.sidebar.getWindowForTab("computedview").computedview.view;
let doc = computedView.styleDocument;
inspector.sidebar.select("computedview");
computedView = inspector.sidebar.getWindowForTab("computedview").computedview.view;
let doc = computedView.styleDocument;
let panel = computedView.tooltip.panel;
let {valueSpan} = getComputedViewProperty("background-image");
let uriSpan = valueSpan.querySelector(".theme-link");
let panel = computedView.tooltip.panel;
let {valueSpan} = getComputedViewProperty("background-image");
let uriSpan = valueSpan.querySelector(".theme-link");
yield assertTooltipShownOn(computedView.tooltip, uriSpan);
assertTooltipShownOn(computedView.tooltip, uriSpan, () => {
let images = panel.getElementsByTagName("image");
is(images.length, 1, "Tooltip contains an image");
ok(images[0].src.startsWith("data:"), "Tooltip contains a data-uri in the computed-view too");
computedView.tooltip.hide();
endTests();
});
ok(images[0].getAttribute("src").startsWith("data:"), "Tooltip contains a data-uri in the computed-view too");
}).then(endTests);
}
function getRuleViewProperty(name) {

View File

@ -105,24 +105,24 @@ function testColorPickerAppearsOnColorSwatchClick() {
}
function testColorPickerHidesWhenImageTooltipAppears() {
let swatch = swatches[0];
let bgImageSpan = getRuleViewProperty("background-image").valueSpan;
let uriSpan = bgImageSpan.querySelector(".theme-link");
Task.spawn(function*() {
let swatch = swatches[0];
let bgImageSpan = getRuleViewProperty("background-image").valueSpan;
let uriSpan = bgImageSpan.querySelector(".theme-link");
let tooltip = ruleView.colorPicker.tooltip;
info("Showing the color picker tooltip by clicking on the color swatch");
let onShown = tooltip.once("shown");
swatch.click();
yield onShown;
info("Now showing the image preview tooltip to hide the color picker");
let onHidden = tooltip.once("hidden");
yield assertTooltipShownOn(ruleView.previewTooltip, uriSpan);
yield onHidden;
ruleView.colorPicker.tooltip.once("shown", () => {
info("The color picker is shown, now display an image tooltip to hide it");
ruleView.previewTooltip._showOnHover(uriSpan);
});
ruleView.colorPicker.tooltip.once("hidden", () => {
ok(true, "The color picker closed when the image preview tooltip appeared");
executeSoon(() => {
ruleView.previewTooltip.hide();
testPressingEscapeRevertsChanges();
});
});
swatch.click();
}).then(testPressingEscapeRevertsChanges);
}
function testPressingEscapeRevertsChanges() {

View File

@ -290,3 +290,30 @@ registerCleanupFunction(tearDown);
waitForExplicitFinish();
/**
* @return a promise that resolves when the tooltip is shown
*/
function assertTooltipShownOn(tooltip, element) {
return Task.spawn(function*() {
let isTarget = yield isHoverTooltipTarget(tooltip, element);
ok(isTarget, "The element is a tooltip target");
});
}
/**
* Given a tooltip object instance (see Tooltip.js), checks if it is set to
* toggle and hover and if so, checks if the given target is a valid hover target.
* This won't actually show the tooltip (the less we interact with XUL panels
* during test runs, the better).
* @return a promise that resolves when the answer is known. Also, this will
* delegate to a function in the rule-view which will insert content into the
* tooltip
*/
function isHoverTooltipTarget(tooltip, target) {
if (!tooltip._basedNode || !tooltip.panel) {
return promise.reject(new Error("The tooltip passed isn't set to toggle on hover or is not a tooltip"));
}
// The tooltip delegates to a user defined cb that inserts content in the tooltip
// when calling isValidHoverTarget
return tooltip.isValidHoverTarget(target);
}

View File

@ -2183,7 +2183,7 @@ Widgets.ObjectRenderers.add({
tagName.appendChild(this.el("span.cm-attribute", "#" + attributes.id));
}
if (attributes.class) {
tagName.appendChild(this.el("span.cm-attribute", "." + attributes.class.split(" ").join(".")));
tagName.appendChild(this.el("span.cm-attribute", "." + attributes.class.split(/\s+/g).join(".")));
}
} else {
for (let name of Object.keys(attributes)) {

View File

@ -46,7 +46,7 @@ let inputTests = [
{
input: "testNodeList()",
output: 'NodeList [ <html>, <head>, <meta>, <title>, <body#body-id.body-class>, <p>, <iframe>, <script> ]',
output: 'NodeList [ <html>, <head>, <meta>, <title>, <body#body-id.body-class>, <p>, <iframe>, <div.some.classname.here.with.more.classnames.here>, <script> ]',
printOutput: "[object NodeList]",
inspectable: true,
noClick: true,

View File

@ -11,6 +11,7 @@
<body class="body-class" id="body-id">
<p some-attribute="some-value">hello world!</p>
<iframe src="data:text/html,<p>hello from iframe</p>"></iframe>
<div class="some classname here with more classnames here"></div>
<script type="text/javascript">
function testBodyNode() {
return document.body;

View File

@ -0,0 +1,13 @@
=====================
Telemetry Experiments
=====================
Telemetry Experiments is a feature of Firefox that allows the installation
of add-ons called experiments to a subset of the Firefox population for
the purposes of experimenting with changes and collecting data on specific
aspects of application usage.
.. toctree::
:maxdepth: 1
manifest

View File

@ -0,0 +1,429 @@
.. _experiments_manifests:
=====================
Experiments Manifests
=====================
*Experiments Manifests* are documents that describe the set of active
experiments a client may run.
*Experiments Manifests* are fetched periodically by clients. When
fetched, clients look at the experiments within the manifest and
determine which experiments are applicable. If an experiment is
applicable, the client may download and start the experiment.
Manifest Format
===============
Manifests are JSON documents where the main element is an object.
The *schema* of the object is versioned and defined by the presence
of a top-level ``version`` property, whose integer value is the
schema version used by that manifest. Each version is documented
in the sections below.
Version 1
---------
Version 1 is the original manifest format.
The following properties may exist in the root object:
experiments
An array of objects describing candidate experiments. The format of
these objects is documented below.
An array is used to create an explicit priority of experiments.
Experiments listed at the beginning of the array take priority over
experiments that follow.
Experiments Objects
^^^^^^^^^^^^^^^^^^^
Each object in the ``experiments`` array may contain the following
properties:
id
(required) String identifier of this experiment. The identifier should
be treated as opaque by clients. It is used to uniquely identify an
experiment for all of time.
xpiURL
(required) String URL of the XPI that implements this experiment.
If the experiment is activated, the client will download and install this
XPI.
xpiHash
(required) String hash of the XPI that implements this experiment.
The value is composed of a hash identifier followed by a colon
followed by the hash value. e.g.
`sha1:f677428b9172e22e9911039aef03f3736e7f78a7`. `sha1` and `sha256`
are the two supported hashing mechanisms. The hash value is the hex
encoding of the binary hash.
When the client downloads the XPI for the experiment, it should compare
the hash of that XPI against this value. If the hashes don't match,
the client should not install the XPI.
Clients may also use this hash as a means of determining when an
experiment's XPI has changed and should be refreshed.
startTime
Integer seconds since UNIX epoch that this experiment should
start. Clients should not start an experiment if *now()* is less than
this value.
maxStartTime
(optional) Integer seconds since UNIX epoch after which this experiment
should no longer start.
Some experiments may wish to impose hard deadlines after which no new
clients should activate the experiment. This property may be used to
facilitate that.
endTime
Integer seconds since UNIX epoch after which this experiment
should no longer run. Clients should cease an experiment when the current
time is beyond this value.
maxActiveSeconds
Integer seconds defining the max wall time this experiment should be
active for.
The client should deactivate the experiment this many seconds after
initial activation.
This value only involves wall time, not browser activity or session time.
appName
Array of application names this experiment should run on.
An application name comes from ``nsIXULAppInfo.name``. It is a value
like ``Firefox``, ``Fennec``, or `B2G`.
The client should compare its application name against the members of
this array. If a match is found, the experiment is applicable.
minVersion
(optional) String version number of the minimum application version this
experiment should run on.
A version number is something like ``27.0.0`` or ``28``.
The client should compare its version number to this value. If the client's
version is greater or equal to this version (using a version-aware comparison
function), the experiment is applicable.
If this is not specified, there is no lower bound to versions this
experiment should run on.
maxVersion
(optional) String version number of the maximum application version this
experiment should run on.
This is similar to ``minVersion`` except it sets the upper bound for
application versions.
If the client's version is less than or equal to this version, the
experiment is applicable.
If this is not specified, there is no upper bound to versions this
experiment should run on.
version
(optional) Array of application versions this experiment should run on.
This is similar to ``minVersion`` and ``maxVersion`` except only a
whitelisted set of specific versions are allowed.
The client should compare its version to members of this array. If a match
is found, the experiment is applicable.
minBuildID
(optional) String minimum Build ID this experiment should run on.
Build IDs are values like ``201402261424``.
The client should perform a string comparison of its Build ID against this
value. If its value is greater than or equal to this value, the experiment
is applicable.
maxBuildID
(optional) String maximum Build ID this experiment should run on.
This is similar to ``minBuildID`` except it sets the upper bound
for Build IDs.
The client should perform a string comparison of its Build ID against
this value. If its value is less than or equal to this value, the
experiment is applicable.
buildIDs
(optional) Array of Build IDs this experiment should run on.
This is similar to ``minBuildID`` and ``maxBuildID`` except only a
whitelisted set of Build IDs are considered.
The client should compare its Build ID to members of this array. If a
match is found, the experiment is applicable.
os
(optional) Array of operating system identifiers this experiment should
run on.
Values for this array come from ``nsIXULRuntime.OS``.
The client will compare its operating system identifier to members
of this array. If a match is found, the experiment is applicable to the
client.
channel
(optional) Array of release channel identifiers this experiment should run
on.
The client will compare its channel to members of this array. If a match
is found, the experiment is applicable.
If this property is not defined, the client should assume the experiment
is to run on all channels.
locale
(optional) Array of locale identifiers this experiment should run on.
A locale identifier is a string like ``en-US`` or ``zh-CN`` and is
obtained by looking at
``nsIXULChromeRegistry.getSelectedLocale("global")``.
The client should compare its locale identifier to members of this array.
If a match is found, the experiment is applicable.
If this property is not defined, the client should assume the experiment
is to run on all locales.
sample
(optional) Decimal number indicating the sampling rate for this experiment.
This will contain a value between ``0.0`` and ``1.0``. The client should
generate a random decimal between ``0.0`` and ``1.0``. If the randomly
generated number is less than or equal to the value of this field, the
experiment is applicable.
disabled
(optional) Boolean value indicating whether an experiment is disabled.
Normally, experiments are deactivated after a certain time has passed or
after the experiment itself determines it no longer needs to run (perhaps
it collected sufficient data already).
This property serves as a backup mechanism to remotely disable an
experiment before it was scheduled to be disabled. It can be used to
kill experiments that are found to be doing wrong or bad things or that
aren't useful.
If this property is not defined or is false, the client should assume
the experiment is active and a candidate for activation.
frozen
(optional) Boolean value indicating this experiment is frozen and no
longer accepting new enrollments.
If a client sees a true value in this field, it should not attempt to
activate an experiment.
jsfilter
(optional) JavaScript code that will be evaluated to determine experiment
applicability.
This property contains the string representation of JavaScript code that
will be evaluated in a sandboxed environment using JavaScript's
``eval()``.
The string is expected to contain the definition of a JavaScript function
``filter(context)``. This function receives as its argument an object
holding application state. See the section below for the definition of
this object.
The purpose of this property is to allow experiments to define complex
rules and logic for evaluating experiment applicability in a manner
that is privacy conscious and doesn't require the transmission of
excessive data.
The return value of this filter indicates whether the experiment is
applicable. Functions should return true if the experiment is
applicable.
If an experiment is not applicable, they should throw an Error whose
message contains the reason the experiment is not applicable. This
message may be logged and sent to remote servers, so it should not
contain private or otherwise sensitive data that wouldn't normally
be submitted.
If a falsey (or undefined) value is returned, the client should
assume the experiment is not applicable.
If this property is not defined, the client does not consider a custom
JavaScript filter function when determining whether an experiment is
applicable.
JavaScript Filter Context Objects
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
The object passed to a ``jsfilter`` ``filter()`` function contains the
following properties:
healthReportSubmissionEnabled
This property contains a boolean indicating whether Firefox Health
Report has its data submission flag enabled (whether Firefox Health
Report is sending data to remote servers).
healthReportPayload
This property contains the current Firefox Health Report payload.
The payload format is documented at :ref:`healthreport_dataformat`.
telemetryPayload
This property contains the current Telemetry payload.
The evaluation sandbox for the JavaScript filters may be destroyed
immediately after ``filter()`` returns. This function should not assume
async code will finish.
Experiment Applicability and Client Behavior
============================================
The point of an experiment manifest is to define which experiments are
available and where and how to run them. This section explains those
rules in more detail.
Many of the properties in *Experiment Objects* are related to determining
whether an experiment should run on a given client. This evaluation is
performed client side.
1. Multiple conditions in an experiment
---------------------------------------
If multiple conditions are defined for an experiment, the client should
combine each condition with a logical *AND*: all conditions must be
satisfied for an experiment to run. If one condition fails, the experiment
is not applicable.
2. Active experiment disappears from manifest
---------------------------------------------
If a specific experiment disappears from the manifest, the client should
continue conducting an already-active experiment. Furthermore, the
client should remember what the expiration events were for an experiment
and honor them.
The rationale here is that we want to prevent an accidental deletion
or temporary failure on the server to inadvertantly deactivate
supposed-to-be-active experiments. We also don't want premature deletion
of an experiment from the manifest to result in indefinite activation
periods.
3. Inactive experiment disappears from manifest
-----------------------------------------------
If an inactive but scheduled-to-be-active experiment disappears from the
manifest, the client should not activate the experiment.
If that experiment reappears in the manifest, the client should not
treat that experiment any differently than any other new experiment. Put
another way, the fact an inactive experiment disappears and then
reappears should not be significant.
The rationale here is that server operators should have complete
control of an inactive experiment up to it's go-live date.
4. Re-evaluating applicability on manifest refresh
--------------------------------------------------
When an experiment manifest is refreshed or updated, the client should
re-evaluate the applicability of each experiment therein.
The rationale here is that the server may change the parameters of an
experiment and want clients to pick those up.
5. Activating a previously non-applicable experiment
----------------------------------------------------
If the conditions of an experiment change or the state of the client
changes to allow an experiment to transition from previously
non-applicable to applicable, the experiment should be activated.
For example, if a client is running version 28 and the experiment
initially requires version 29 or above, the client will not mark the
experiment as applicable. But if the client upgrades to version 29 or if
the manifest is updated to require 28 or above, the experiment will
become applicable.
6. Deactivating a previously active experiment
----------------------------------------------
If the conditions of an experiment change or the state of the client
changes and an active experiment is no longer applicable, that
experiment should be deactivated.
7. Calculation of sampling-based applicability
----------------------------------------------
For calculating sampling-based applicability, the client will associate
a random value between ``0.0`` and ``1.0`` for each observed experiment
ID. This random value will be generated the first time sampling
applicability is evaluated. This random value will be persisted and used
in future applicability evaluations for this experiment.
By saving and re-using the value, the client is able to reliably and
consistently evaluate applicability, even if the sampling threshold
in the manifest changes.
Clients should retain the randomly-generated sampling value for
experiments that no longer appear in a manifest for a period of at least
30 days. The rationale is that if an experiment disappears and reappears
from a manifest, the client will not have multiple opportunities to
generate a random value that satisfies the sampling criteria.
8. Incompatible version numbers
-------------------------------
If a client receives a manifest with a version number that it doesn't
recognize, it should ignore the manifest.
9. Usage of old manifests
-------------------------
If a client experiences an error fetching a manifest (server not
available) or if the manifest is corrupt, not readable, or compatible,
the client may use a previously-fetched (cached) manifest.
10. Updating XPIs
-----------------
If the URL or hash of an active experiment's XPI changes, the client
should fetch the new XPI, uninstall the old XPI, and install the new
XPI.
Examples
========
Here is an example manifest::
{
"version": 1,
"experiments": [
{
"id": "da9d7f4f-f3f9-4f81-bacd-6f0626ffa360",
"xpiURL": "https://experiments.mozilla.org/foo.xpi",
"xpiHash": "sha1:cb1eb32b89d86d78b7326f416cf404548c5e0099",
"startTime": 1393000000,
"endTime": 1394000000,
"appName": ["Firefox", "Fennec"],
"minVersion": "28",
"maxVersion": "30",
"os": ["windows", "linux", "osx"],
"jsfilter": "function filter(context) { return context.healthReportEnabled; }"
}
]
}

View File

@ -14,3 +14,5 @@ EXTRA_JS_MODULES += [
]
XPCSHELL_TESTS_MANIFESTS += ['test/xpcshell/xpcshell.ini']
SPHINX_TREES['experiments'] = 'docs'

View File

@ -544,7 +544,6 @@
@BINPATH@/components/SystemMessageManager.manifest
@BINPATH@/components/Activities.manifest
@BINPATH@/components/ActivityOptions.js
@BINPATH@/components/ActivityProxy.js
@BINPATH@/components/ActivityRequestHandler.js
@BINPATH@/components/ActivityWrapper.js

View File

@ -21,12 +21,9 @@ RequestExecutionLevel user
!addplugindir ./
Var Dialog
Var ProgressbarDownload
Var ProgressbarInstall
Var LabelDownloadingDown
Var LabelDownloadingInProgress
Var LabelInstallingInProgress
Var LabelInstallingToBeDone
Var Progressbar
Var LabelDownloading
Var LabelInstalling
Var LabelFreeSpace
Var CheckboxSetAsDefault
Var CheckboxShortcutOnBar ; Used for Quicklaunch or Taskbar as appropriate
@ -63,6 +60,8 @@ Var InitialInstallDir
Var HandleDownload
Var CanSetAsDefault
Var InstallCounterStep
Var InstallStepSize
Var InstallTotalSteps
Var TmpVal
Var ExitCode
@ -90,8 +89,6 @@ Var EndPreInstallPhaseTickCount
Var EndInstallPhaseTickCount
Var EndFinishPhaseTickCount
Var IntroPageShownCount
Var OptionsPageShownCount
Var InitialInstallRequirementsCode
Var ExistingProfile
Var ExistingVersion
@ -108,7 +105,7 @@ Var ControlRightPX
; the stub installer
;!define STUB_DEBUG
!define StubURLVersion "v5"
!define StubURLVersion "v6"
; Successful install exit code
!define ERR_SUCCESS 0
@ -144,7 +141,7 @@ Var ControlRightPX
* The following errors prefixed with ERR_INSTALL apply to the install phase.
*/
; The installation timed out. The installation timeout is defined by the number
; of progress steps defined in InstallProgresSteps and the install timer
; of progress steps defined in InstallTotalSteps and the install timer
; interval defined in InstallIntervalMS
!define ERR_INSTALL_TIMEOUT 30
@ -168,18 +165,25 @@ Var ControlRightPX
; Interval for the install timer
!define InstallIntervalMS 100
; Number of steps for the install progress.
; This is 120 seconds with a 100 millisecond timer and a first step of 20 as
; defined by InstallProgressFirstStep. This might not be enough when installing
; on a slow network drive so it will fallback to downloading the full installer
; if it reaches this number. The size of the install progress step increases
; when the full installer finishes instead of waiting the entire 120 seconds.
!define InstallProgresSteps 1220
; The first step for the install progress bar. By starting with a large step
; immediate feedback is given to the user.
!define InstallProgressFirstStep 20
; Number of steps for the install progress.
; This might not be enough when installing on a slow network drive so it will
; fallback to downloading the full installer if it reaches this number. The size
; of the install progress step is increased when the full installer finishes
; instead of waiting.
; Approximately 150 seconds with a 100 millisecond timer and a first step of 20
; as defined by InstallProgressFirstStep.
!define /math InstallCleanTotalSteps ${InstallProgressFirstStep} + 1500
; Approximately 165 seconds (minus 0.2 seconds for each file that is removed)
; with a 100 millisecond timer and a first step of 20 as defined by
; InstallProgressFirstStep .
!define /math InstallPaveOverTotalSteps ${InstallProgressFirstStep} + 1800
; The interval in MS used for the progress bars set as marquee.
!define ProgressbarMarqueeIntervalMS 10
@ -189,12 +193,18 @@ Var ControlRightPX
!define CONFIG_INI "config.ini"
!define MAX_PATH 260
!define FILE_SHARE_READ 1
!define GENERIC_READ 0x80000000
!define OPEN_EXISTING 3
!define INVALID_HANDLE_VALUE -1
!ifndef FILE_SHARE_READ
!define FILE_SHARE_READ 1
!endif
!ifndef GENERIC_READ
!define GENERIC_READ 0x80000000
!endif
!ifndef OPEN_EXISTING
!define OPEN_EXISTING 3
!endif
!ifndef INVALID_HANDLE_VALUE
!define INVALID_HANDLE_VALUE -1
!endif
!include "nsDialogs.nsh"
!include "LogicLib.nsh"
@ -230,6 +240,7 @@ Var ControlRightPX
!insertmacro ElevateUAC
!insertmacro GetLongPath
!insertmacro GetPathFromString
!insertmacro GetParent
!insertmacro GetSingleInstallPath
!insertmacro GetTextWidthHeight
!insertmacro IsUserAdmin
@ -340,39 +351,6 @@ Function .onInit
System::Call 'user32::SetProcessDPIAware()'
${EndIf}
; Create a mutex to prevent multiple launches of the same stub installer in
; the same location on the file system. This intentionally won't handle the
; case where someone runs multiple copies of the stub on the file system but
; it does handle the important case which is a user launching the same stub
; multiple times.
StrCpy $1 "$EXEPATH"
; Backslashes are illegal in a mutex name so replace all occurences of a
; backslash with a forward slash.
${WordReplace} "$1" "\" "/" "+" $1
StrLen $2 "$1"
; The lpName parameter for CreateMutexW is limited to MAX_PATH characters so
; use the characters at the end since they are more likely to be unique.
${If} $2 > ${MAX_PATH}
StrCpy $1 "$1" ${MAX_PATH} -${MAX_PATH}
${EndIf}
System::Call "kernel32::CreateMutexW(i 0, i 0, w '$1') i .r0 ?e"
Pop $0
${Unless} $0 == 0
; The mutex is specific to this executable's path so we should be able to
; find the Window with the same caption as this executable's and bring that
; window to the front. This could find another instance of the same
; executable but that is an uninteresting edge case.
FindWindow $1 "#32770" "$(WIN_CAPTION)" 0
${If} $1 != 0
; Restore the window if it is minimized and make it the foreground window
System::Call "user32::ShowWindow(i r1, i ${SW_RESTORE}) i."
System::Call "user32::SetForegroundWindow(i r1) i."
${EndIf}
Abort
${EndUnless}
SetShellVarContext all ; Set SHCTX to HKLM
${GetSingleInstallPath} "Software\Mozilla\${BrandFullNameInternal}" $R9
@ -392,6 +370,8 @@ Function .onInit
WriteRegStr HKLM "Software\Mozilla" "${BrandShortName}InstallerTest" \
"Write Test"
; Only display set as default when there is write access to HKLM and on Win7
; and below.
${If} ${Errors}
${OrIf} ${AtLeastWin8}
StrCpy $CanSetAsDefault "false"
@ -407,8 +387,6 @@ Function .onInit
StrCpy $OptionsPhaseSeconds "0"
StrCpy $EndPreInstallPhaseTickCount "0"
StrCpy $EndInstallPhaseTickCount "0"
StrCpy $IntroPageShownCount "0"
StrCpy $OptionsPageShownCount "0"
StrCpy $InitialInstallRequirementsCode ""
StrCpy $IsDownloadFinished ""
StrCpy $FirefoxLaunchCode "0"
@ -560,9 +538,17 @@ Function SendPing
StrCpy $R1 "0"
${EndIf}
${WinVerGetMajor} $R2
${WinVerGetMinor} $R3
${WinVerGetBuild} $R4
; Though these values are sometimes incorrect due to bug 444664 it happens
; so rarely it isn't worth working around it by reading the registry values.
${WinVerGetMajor} $5
${WinVerGetMinor} $6
${WinVerGetBuild} $7
${WinVerGetServicePackLevel} $8
${If} ${IsServerOS}
StrCpy $9 "1"
${Else}
StrCpy $9 "0"
${EndIf}
${If} "$ExitCode" == "${ERR_SUCCESS}"
ReadINIStr $R5 "$INSTDIR\application.ini" "App" "Version"
@ -595,6 +581,74 @@ Function SendPing
StrCpy $DownloadServerIP "Unknown"
${EndIf}
StrCpy $R2 ""
SetShellVarContext current ; Set SHCTX to the current user
ReadRegStr $R2 HKCU "Software\Classes\http\shell\open\command" ""
${If} $R2 != ""
${GetPathFromString} "$R2" $R2
${GetParent} "$R2" $R3
${GetLongPath} "$R3" $R3
${If} $R3 == $INSTDIR
StrCpy $R2 "1" ; This Firefox install is set as default.
${Else}
StrCpy $R2 "$R2" "" -11 # length of firefox.exe
${If} "$R2" == "${FileMainEXE}"
StrCpy $R2 "2" ; Another Firefox install is set as default.
${Else}
StrCpy $R2 "0"
${EndIf}
${EndIf}
${Else}
StrCpy $R2 "0" ; Firefox is not set as default.
${EndIf}
${If} "$R2" == "0"
${AndIf} ${AtLeastWinVista}
; Check to see if this install location is currently set as the default
; browser by Default Programs which is only available on Vista and above.
ClearErrors
ReadRegStr $R3 HKLM "Software\RegisteredApplications" "${AppRegName}"
${Unless} ${Errors}
AppAssocReg::QueryAppIsDefaultAll "${AppRegName}" "effective"
Pop $R3
${If} $R3 == "1"
StrCpy $R3 ""
ReadRegStr $R2 HKLM "Software\Classes\http\shell\open\command" ""
${If} $R2 != ""
${GetPathFromString} "$R2" $R2
${GetParent} "$R2" $R3
${GetLongPath} "$R3" $R3
${If} $R3 == $INSTDIR
StrCpy $R2 "1" ; This Firefox install is set as default.
${Else}
StrCpy $R2 "$R2" "" -11 # length of firefox.exe
${If} "$R2" == "${FileMainEXE}"
StrCpy $R2 "2" ; Another Firefox install is set as default.
${Else}
StrCpy $R2 "0"
${EndIf}
${EndIf}
${Else}
StrCpy $R2 "0" ; Firefox is not set as default.
${EndIf}
${EndIf}
${EndUnless}
${EndIf}
${If} $CanSetAsDefault == "true"
${If} $CheckboxSetAsDefault == "1"
StrCpy $R3 "2"
${Else}
StrCpy $R3 "3"
${EndIf}
${Else}
${If} ${AtLeastWin8}
StrCpy $R3 "1"
${Else}
StrCpy $R3 "0"
${EndIf}
${EndIf}
!ifdef STUB_DEBUG
MessageBox MB_OK "${BaseURLStubPing} \
$\nStub URL Version = ${StubURLVersion}${StubURLVersionAppend} \
@ -603,13 +657,16 @@ Function SendPing
$\nLocale = ${AB_CD} \
$\nFirefox x64 = $R0 \
$\nRunning x64 Windows = $R1 \
$\nMajor = $R2 \
$\nMinor = $R3 \
$\nBuild = $R4 \
$\nMajor = $5 \
$\nMinor = $6 \
$\nBuild = $7 \
$\nServicePack = $8 \
$\nIsServer = $9 \
$\nExit Code = $ExitCode \
$\nFirefox Launch Code = $FirefoxLaunchCode \
$\nDownload Retry Count = $DownloadRetryCount \
$\nDownloaded Bytes = $DownloadedBytes \
$\nDownload Size Bytes = $DownloadSizeBytes \
$\nIntroduction Phase Seconds = $IntroPhaseSeconds \
$\nOptions Phase Seconds = $OptionsPhaseSeconds \
$\nDownload Phase Seconds = $0 \
@ -618,8 +675,6 @@ Function SendPing
$\nPreinstall Phase Seconds = $2 \
$\nInstall Phase Seconds = $3 \
$\nFinish Phase Seconds = $4 \
$\nIntro Page Shown Count = $IntroPageShownCount \
$\nOptions Page Shown Count = $OptionsPageShownCount \
$\nInitial Install Requirements Code = $InitialInstallRequirementsCode \
$\nOpened Download Page = $OpenedDownloadPage \
$\nExisting Profile = $ExistingProfile \
@ -629,6 +684,8 @@ Function SendPing
$\nNew Build ID = $R6 \
$\nDefault Install Dir = $R7 \
$\nHas Admin = $R8 \
$\nDefault Status = $R2 \
$\nSet As Sefault Status = $R3 \
$\nDownload Server IP = $DownloadServerIP"
; The following will exit the installer
SetAutoClose true
@ -636,7 +693,7 @@ Function SendPing
Call RelativeGotoPage
!else
${NSD_CreateTimer} OnPing ${DownloadIntervalMS}
InetBgDL::Get "${BaseURLStubPing}/${StubURLVersion}${StubURLVersionAppend}/${Channel}/${UpdateChannel}/${AB_CD}/$R0/$R1/$R2/$R3/$R4/$ExitCode/$FirefoxLaunchCode/$DownloadRetryCount/$DownloadedBytes/$IntroPhaseSeconds/$OptionsPhaseSeconds/$0/$1/$DownloadFirstTransferSeconds/$2/$3/$4/$IntroPageShownCount/$OptionsPageShownCount/$InitialInstallRequirementsCode/$OpenedDownloadPage/$ExistingProfile/$ExistingVersion/$ExistingBuildID/$R5/$R6/$R7/$R8/$DownloadServerIP" \
InetBgDL::Get "${BaseURLStubPing}/${StubURLVersion}/${Channel}/${UpdateChannel}/${AB_CD}/$R0/$R1/$5/$6/$7/$8/$9/$ExitCode/$FirefoxLaunchCode/$DownloadRetryCount/$DownloadedBytes/$DownloadSizeBytes/$IntroPhaseSeconds/$OptionsPhaseSeconds/$0/$1/$DownloadFirstTransferSeconds/$2/$3/$4/$InitialInstallRequirementsCode/$OpenedDownloadPage/$ExistingProfile/$ExistingVersion/$ExistingBuildID/$R5/$R6/$R7/$R8/$R2/$R3/$DownloadServerIP" \
"$PLUGINSDIR\_temp" /END
!endif
${Else}
@ -675,8 +732,6 @@ Function createIntro
SetCtlColors $HWNDPARENT ${FOOTER_CONTROL_TEXT_COLOR_NORMAL} ${FOOTER_BKGRD_COLOR}
GetDlgItem $0 $HWNDPARENT 10 ; Default browser checkbox
; Set as default is not supported in the installer for Win8 and above so
; only display it on Windows 7 and below
${If} "$CanSetAsDefault" == "true"
; The uxtheme must be disabled on checkboxes in order to override the
; system font color.
@ -714,8 +769,6 @@ Function createIntro
GetDlgItem $0 $HWNDPARENT 3 ; Back button used for Options
SendMessage $0 ${WM_SETTEXT} 0 "STR:$(OPTIONS_BUTTON)"
IntOp $IntroPageShownCount $IntroPageShownCount + 1
System::Call "kernel32::GetTickCount()l .s"
Pop $StartIntroPhaseTickCount
@ -731,10 +784,12 @@ Function leaveIntro
System::Call "kernel32::GetTickCount()l .s"
Pop $0
${GetSecondsElapsed} "$StartIntroPhaseTickCount" "$0" $1
; This is added to the previous value of $IntroPhaseSeconds because the
; introduction page can be displayed multiple times.
IntOp $IntroPhaseSeconds $IntroPhaseSeconds + $1
${GetSecondsElapsed} "$StartIntroPhaseTickCount" "$0" $IntroPhaseSeconds
; It is possible for this value to be 0 if the user clicks fast enough so
; increment the value by 1 if it is 0.
${If} $IntroPhaseSeconds == 0
IntOp $IntroPhaseSeconds $IntroPhaseSeconds + 1
${EndIf}
SetShellVarContext all ; Set SHCTX to All Users
; If the user doesn't have write access to the installation directory set
@ -980,8 +1035,6 @@ Function createOptions
${EndIf}
${EndIf}
StrCpy $OptionsPageShownCount "1"
System::Call "kernel32::GetTickCount()l .s"
Pop $StartOptionsPhaseTickCount
@ -1017,10 +1070,12 @@ Function leaveOptions
System::Call "kernel32::GetTickCount()l .s"
Pop $0
${GetSecondsElapsed} "$StartOptionsPhaseTickCount" "$0" $1
; This is added to the previous value of $OptionsPhaseSeconds because the
; options page can be displayed multiple times.
IntOp $OptionsPhaseSeconds $OptionsPhaseSeconds + $1
${GetSecondsElapsed} "$StartOptionsPhaseTickCount" "$0" $OptionsPhaseSeconds
; It is possible for this value to be 0 if the user clicks fast enough so
; increment the value by 1 if it is 0.
${If} $OptionsPhaseSeconds == 0
IntOp $OptionsPhaseSeconds $OptionsPhaseSeconds + 1
${EndIf}
${NSD_GetState} $CheckboxShortcutOnBar $CheckboxShortcutOnBar
${NSD_GetState} $CheckboxShortcutInStartMenu $CheckboxShortcutInStartMenu
@ -1101,40 +1156,26 @@ Function createInstall
ShowWindow $BitmapBlurb3 ${SW_HIDE}
ShowWindow $LabelBlurb3 ${SW_HIDE}
nsDialogs::CreateControl /NOUNLOAD STATIC ${DEFAULT_STYLES}|${SS_SUNKEN} 0 260u 166u 1u 30u ""
Pop $0
${NSD_CreateLabelCenter} 103u 180u 157u 20u "$(DOWNLOADING_IN_PROGRESS)"
Pop $LabelDownloadingInProgress
SendMessage $LabelDownloadingInProgress ${WM_SETFONT} $FontNormal 0
SetCtlColors $LabelDownloadingInProgress ${INSTALL_PROGRESS_TEXT_COLOR_NORMAL} transparent
${NSD_CreateLabelCenter} 103u 180u 157u 20u "$(DOWNLOADING_DONE)"
Pop $LabelDownloadingDown
SendMessage $LabelDownloadingDown ${WM_SETFONT} $FontItalic 0
SetCtlColors $LabelDownloadingDown ${INSTALL_PROGRESS_TEXT_COLOR_FADED} transparent
ShowWindow $LabelDownloadingDown ${SW_HIDE}
${NSD_CreateLabelCenter} 260uu 180u 84u 20u "$(INSTALLING_TO_BE_DONE)"
Pop $LabelInstallingToBeDone
SendMessage $LabelInstallingToBeDone ${WM_SETFONT} $FontItalic 0
SetCtlColors $LabelInstallingToBeDone ${INSTALL_PROGRESS_TEXT_COLOR_FADED} transparent
${NSD_CreateLabelCenter} 260uu 180u 84u 20u "$(INSTALLING_IN_PROGRESS)"
Pop $LabelInstallingInProgress
SendMessage $LabelInstallingInProgress ${WM_SETFONT} $FontNormal 0
SetCtlColors $LabelInstallingInProgress ${INSTALL_PROGRESS_TEXT_COLOR_NORMAL} transparent
ShowWindow $LabelInstallingInProgress ${SW_HIDE}
${NSD_CreateProgressBar} 103u 166u 157u 9u ""
Pop $ProgressbarDownload
${NSD_AddStyle} $ProgressbarDownload ${PBS_MARQUEE}
SendMessage $ProgressbarDownload ${PBM_SETMARQUEE} 1 \
${NSD_CreateProgressBar} 103u 166u 241u 9u ""
Pop $Progressbar
${NSD_AddStyle} $Progressbar ${PBS_MARQUEE}
SendMessage $Progressbar ${PBM_SETMARQUEE} 1 \
${ProgressbarMarqueeIntervalMS} ; start=1|stop=0 interval(ms)=+N
${NSD_CreateProgressBar} 260u 166u 84u 9u ""
Pop $ProgressbarInstall
SendMessage $ProgressbarInstall ${PBM_SETRANGE32} 0 ${InstallProgresSteps}
${NSD_CreateLabelCenter} 103u 180u 241u 20u "$(DOWNLOADING_LABEL)"
Pop $LabelDownloading
SendMessage $LabelDownloading ${WM_SETFONT} $FontNormal 0
SetCtlColors $LabelDownloading ${INSTALL_PROGRESS_TEXT_COLOR_NORMAL} transparent
${If} ${FileExists} "$INSTDIR\${FileMainEXE}"
${NSD_CreateLabelCenter} 103u 180u 241u 20u "$(UPGRADING_LABEL)"
${Else}
${NSD_CreateLabelCenter} 103u 180u 241u 20u "$(INSTALLING_LABEL)"
${EndIf}
Pop $LabelInstalling
SendMessage $LabelInstalling ${WM_SETFONT} $FontNormal 0
SetCtlColors $LabelInstalling ${INSTALL_PROGRESS_TEXT_COLOR_NORMAL} transparent
ShowWindow $LabelInstalling ${SW_HIDE}
${NSD_CreateBitmap} ${APPNAME_BMP_EDGE_DU} ${APPNAME_BMP_TOP_DU} \
${APPNAME_BMP_WIDTH_DU} ${APPNAME_BMP_HEIGHT_DU} ""
@ -1161,7 +1202,6 @@ Function createInstall
; Kill the Cancel button's focus so pressing enter won't cancel the install.
SendMessage $0 ${WM_KILLFOCUS} 0 0
; Set as default is not supported in the installer for Win8 and above
${If} "$CanSetAsDefault" == "true"
GetDlgItem $0 $HWNDPARENT 10 ; Default browser checkbox
SendMessage $0 ${BM_GETCHECK} 0 0 $CheckboxSetAsDefault
@ -1170,7 +1210,11 @@ Function createInstall
${EndIf}
GetDlgItem $0 $HWNDPARENT 11
SendMessage $0 ${WM_SETTEXT} 0 "STR:$(ONE_MOMENT)"
${If} ${FileExists} "$INSTDIR\${FileMainEXE}"
SendMessage $0 ${WM_SETTEXT} 0 "STR:$(ONE_MOMENT_UPGRADE)"
${Else}
SendMessage $0 ${WM_SETTEXT} 0 "STR:$(ONE_MOMENT_INSTALL)"
${EndIf}
SendMessage $0 ${WM_SETFONT} $FontNormal 0
SetCtlColors $0 ${FOOTER_CONTROL_TEXT_COLOR_FADED} ${FOOTER_BKGRD_COLOR}
ShowWindow $0 ${SW_SHOW}
@ -1209,6 +1253,12 @@ Function createInstall
System::Call "kernel32::GetTickCount()l .s"
Pop $StartDownloadPhaseTickCount
${If} ${FileExists} "$INSTDIR\uninstall\uninstall.log"
StrCpy $InstallTotalSteps ${InstallPaveOverTotalSteps}
${Else}
StrCpy $InstallTotalSteps ${InstallCleanTotalSteps}
${EndIf}
${NSD_CreateTimer} StartDownload ${DownloadIntervalMS}
LockWindow off
@ -1247,8 +1297,8 @@ Function OnDownload
IntOp $DownloadRetryCount $DownloadRetryCount + 1
${If} "$DownloadReset" != "true"
StrCpy $DownloadedBytes "0"
${NSD_AddStyle} $ProgressbarDownload ${PBS_MARQUEE}
SendMessage $ProgressbarDownload ${PBM_SETMARQUEE} 1 \
${NSD_AddStyle} $Progressbar ${PBS_MARQUEE}
SendMessage $Progressbar ${PBM_SETMARQUEE} 1 \
${ProgressbarMarqueeIntervalMS} ; start=1|stop=0 interval(ms)=+N
${EndIf}
InetBgDL::Get /RESET /END
@ -1302,9 +1352,13 @@ Function OnDownload
StrCpy $DownloadSizeBytes "$4"
System::Int64Op $4 / 2
Pop $HalfOfDownload
SendMessage $ProgressbarDownload ${PBM_SETMARQUEE} 0 0 ; start=1|stop=0 interval(ms)=+N
${RemoveStyle} $ProgressbarDownload ${PBS_MARQUEE}
SendMessage $ProgressbarDownload ${PBM_SETRANGE32} 0 $DownloadSizeBytes
System::Int64Op $HalfOfDownload / $InstallTotalSteps
Pop $InstallStepSize
SendMessage $Progressbar ${PBM_SETMARQUEE} 0 0 ; start=1|stop=0 interval(ms)=+N
${RemoveStyle} $Progressbar ${PBS_MARQUEE}
System::Int64Op $HalfOfDownload + $DownloadSizeBytes
Pop $R9
SendMessage $Progressbar ${PBM_SETRANGE32} 0 $R9
${EndIf}
; Don't update the status until after the download starts
@ -1361,12 +1415,14 @@ Function OnDownload
LockWindow on
; Update the progress bars first in the UI change so they take affect
; before other UI changes.
SendMessage $ProgressbarDownload ${PBM_SETPOS} $DownloadSizeBytes 0
SendMessage $ProgressbarInstall ${PBM_SETPOS} $InstallCounterStep 0
ShowWindow $LabelDownloadingInProgress ${SW_HIDE}
ShowWindow $LabelInstallingToBeDone ${SW_HIDE}
ShowWindow $LabelInstallingInProgress ${SW_SHOW}
ShowWindow $LabelDownloadingDown ${SW_SHOW}
SendMessage $Progressbar ${PBM_SETPOS} $DownloadSizeBytes 0
System::Int64Op $InstallStepSize * ${InstallProgressFirstStep}
Pop $R9
SendMessage $Progressbar ${PBM_SETSTEP} $R9 0
SendMessage $Progressbar ${PBM_STEPIT} 0 0
SendMessage $Progressbar ${PBM_SETSTEP} $InstallStepSize 0
ShowWindow $LabelDownloading ${SW_HIDE}
ShowWindow $LabelInstalling ${SW_SHOW}
ShowWindow $LabelBlurb2 ${SW_HIDE}
ShowWindow $BitmapBlurb2 ${SW_HIDE}
ShowWindow $LabelBlurb3 ${SW_SHOW}
@ -1451,7 +1507,7 @@ Function OnDownload
WriteIniStr "$0" "TASKBAR" "Migrated" "true"
${EndIf}
${OnStubInstallUninstall}
${OnStubInstallUninstall} $Progressbar $InstallCounterStep
; Delete the install.log and let the full installer create it. When the
; installer closes it we can detect that it has completed.
@ -1476,7 +1532,7 @@ Function OnDownload
LockWindow off
${EndIf}
StrCpy $DownloadedBytes "$3"
SendMessage $ProgressbarDownload ${PBM_SETPOS} $3 0
SendMessage $Progressbar ${PBM_SETPOS} $3 0
${EndIf}
${EndIf}
FunctionEnd
@ -1511,7 +1567,7 @@ Function StartInstall
IntOp $InstallCounterStep $InstallCounterStep + 1
LockWindow on
SendMessage $ProgressbarInstall ${PBM_SETPOS} $InstallCounterStep 0
SendMessage $Progressbar ${PBM_STEPIT} 0 0
LockWindow off
Exec "$\"$PLUGINSDIR\download.exe$\" /INI=$PLUGINSDIR\${CONFIG_INI}"
@ -1520,7 +1576,7 @@ FunctionEnd
Function CheckInstall
IntOp $InstallCounterStep $InstallCounterStep + 1
${If} $InstallCounterStep >= ${InstallProgresSteps}
${If} $InstallCounterStep >= $InstallTotalSteps
${NSD_KillTimer} CheckInstall
; Close the handle that prevents modification of the full installer
System::Call 'kernel32::CloseHandle(i $HandleDownload)'
@ -1530,7 +1586,7 @@ Function CheckInstall
Return
${EndIf}
SendMessage $ProgressbarInstall ${PBM_SETPOS} $InstallCounterStep 0
SendMessage $Progressbar ${PBM_STEPIT} 0 0
${If} ${FileExists} "$INSTDIR\install.log"
Delete "$INSTDIR\install.tmp"
@ -1549,26 +1605,32 @@ Function CheckInstall
Delete "$PLUGINSDIR\${CONFIG_INI}"
System::Call "kernel32::GetTickCount()l .s"
Pop $EndInstallPhaseTickCount
System::Int64Op $InstallStepSize * 20
Pop $InstallStepSize
SendMessage $Progressbar ${PBM_SETSTEP} $InstallStepSize 0
${NSD_CreateTimer} FinishInstall ${InstallIntervalMS}
${EndUnless}
${EndIf}
FunctionEnd
Function FinishInstall
; The full installer has complete but we still need to finish the progress
; bar so increase the size of the step
IntOp $InstallCounterStep $InstallCounterStep + 20
${If} ${InstallProgresSteps} < $InstallCounterStep
StrCpy $InstallCounterStep "${InstallProgresSteps}"
; The full installer has completed but the progress bar still needs to finish
; so increase the size of the step.
IntOp $InstallCounterStep $InstallCounterStep + 40
${If} $InstallTotalSteps < $InstallCounterStep
StrCpy $InstallCounterStep "$InstallTotalSteps"
${EndIf}
SendMessage $ProgressbarInstall ${PBM_SETPOS} $InstallCounterStep 0
${If} ${InstallProgresSteps} != $InstallCounterStep
${If} $InstallTotalSteps != $InstallCounterStep
SendMessage $Progressbar ${PBM_STEPIT} 0 0
Return
${EndIf}
${NSD_KillTimer} FinishInstall
SendMessage $Progressbar ${PBM_GETRANGE} 0 0 $R9
SendMessage $Progressbar ${PBM_SETPOS} $R9 0
${If} "$CheckboxSetAsDefault" == "1"
${GetParameters} $0
ClearErrors
@ -1603,6 +1665,19 @@ Function FinishInstall
StrCpy $ExitCode "${ERR_SUCCESS}"
StrCpy $InstallCounterStep 0
${NSD_CreateTimer} FinishProgressBar ${InstallIntervalMS}
FunctionEnd
Function FinishProgressBar
IntOp $InstallCounterStep $InstallCounterStep + 1
${If} $InstallCounterStep < 10
Return
${EndIf}
${NSD_KillTimer} FinishProgressBar
Call LaunchApp
Call SendPing

View File

@ -46,16 +46,16 @@ ADD_CheckboxShortcutInStartMenu=In my &Start Menu Programs Folder
ADD_CheckboxShortcutOnDesktop=On my &Desktop
SPACE_REQUIRED=Space Required:
SPACE_AVAILABLE=Space Available:
ONE_MOMENT=One moment, $BrandShortName will launch as soon as the install is complete…
ONE_MOMENT_INSTALL=One moment, $BrandShortName will launch as soon as the install is complete…
ONE_MOMENT_UPGRADE=One moment, $BrandShortName will launch as soon as the upgrade is complete…
INSTALL_MAINT_SERVICE=&Install the $BrandShortName background update service
SEND_PING=S&end information about this installation to Mozilla
BROWSE_BUTTON=B&rowse…
DEST_FOLDER=Destination Folder
DOWNLOADING_IN_PROGRESS=Downloading…
DOWNLOADING_DONE=Downloaded
INSTALLING_TO_BE_DONE=Installing
INSTALLING_IN_PROGRESS=Installing…
DOWNLOADING_LABEL=Downloading $BrandShortName…
INSTALLING_LABEL=Installing $BrandShortName…
UPGRADING_LABEL=Upgrading $BrandShortName…
SELECT_FOLDER_TEXT=Select the folder to install $BrandShortName in.

View File

@ -568,6 +568,7 @@ menuitem:not([type]):not(.menuitem-tooltip):not(.menuitem-iconic-tooltip) {
:-moz-any(#TabsToolbar, #nav-bar) .toolbarbutton-1 > .toolbarbutton-menubutton-button > .toolbarbutton-icon,
:-moz-any(#TabsToolbar, #nav-bar) .toolbarbutton-1 > .toolbarbutton-menubutton-dropmarker > .dropmarker-icon,
:-moz-any(#TabsToolbar, #nav-bar) .toolbarbutton-1 > .toolbarbutton-badge-container > .toolbarbutton-icon,
:-moz-any(#TabsToolbar, #nav-bar) .toolbarbutton-1 > .toolbarbutton-icon {
-moz-margin-end: 0;
padding: 2px 6px;
@ -578,10 +579,16 @@ menuitem:not([type]):not(.menuitem-tooltip):not(.menuitem-iconic-tooltip) {
}
:-moz-any(#TabsToolbar, #nav-bar) .toolbarbutton-1:not(:-moz-any(@primaryToolbarButtons@)) > .toolbarbutton-icon,
:-moz-any(#TabsToolbar, #nav-bar) .toolbarbutton-1:not(:-moz-any(@primaryToolbarButtons@)) > .toolbarbutton-badge-container > .toolbarbutton-icon,
:-moz-any(#TabsToolbar, #nav-bar) .toolbarbutton-1:not(:-moz-any(@primaryToolbarButtons@)) > .toolbarbutton-menubutton-button > .toolbarbutton-icon {
padding: 3px 7px;
}
toolbarbutton[type="badged"] > .toolbarbutton-badge-container > .toolbarbutton-icon,
toolbarbutton[type="socialmark"] > .toolbarbutton-icon {
max-width: 32px !important;
}
/* Help SDK icons fit: */
toolbarbutton[sdk-button="true"][cui-areatype="toolbar"] > .toolbarbutton-icon {
width: 16px;
@ -599,6 +606,7 @@ toolbarbutton[sdk-button="true"][cui-areatype="toolbar"] > .toolbarbutton-icon {
:-moz-any(#TabsToolbar, #nav-bar) .toolbarbutton-1:not([disabled=true]):hover > .toolbarbutton-menubutton-button > .toolbarbutton-icon,
:-moz-any(#TabsToolbar, #nav-bar) .toolbarbutton-1:not([disabled=true]):hover > .toolbarbutton-menubutton-dropmarker > .dropmarker-icon,
:-moz-any(#TabsToolbar, #nav-bar) .toolbarbutton-1:not([disabled=true]):hover > .toolbarbutton-badge-container > .toolbarbutton-icon,
:-moz-any(#TabsToolbar, #nav-bar) .toolbarbutton-1:not([disabled=true]):hover > .toolbarbutton-icon {
background-color: hsla(0,0%,100%,.3);
background-image: linear-gradient(hsla(0,0%,100%,.7), hsla(0,0%,100%,.2));
@ -616,6 +624,7 @@ toolbarbutton[sdk-button="true"][cui-areatype="toolbar"] > .toolbarbutton-icon {
:-moz-any(#TabsToolbar, #nav-bar) .toolbarbutton-1 > .toolbarbutton-menubutton-button:not([disabled=true]):hover:active > .toolbarbutton-icon,
:-moz-any(#TabsToolbar, #nav-bar) .toolbarbutton-1[open="true"] > .toolbarbutton-menubutton-dropmarker:not([disabled=true]) > .dropmarker-icon,
:-moz-any(#TabsToolbar, #nav-bar) .toolbarbutton-1:not([disabled=true]):-moz-any([open],[checked],:hover:active) > .toolbarbutton-badge-container > .toolbarbutton-icon,
:-moz-any(#TabsToolbar, #nav-bar) .toolbarbutton-1:not([disabled=true]):-moz-any([open],[checked],:hover:active) > .toolbarbutton-icon {
background-color: rgba(154,154,154,.5);
background-image: linear-gradient(hsla(0,0%,100%,.7), hsla(0,0%,100%,.4));

View File

@ -2738,18 +2738,26 @@ toolbarbutton.chevron > .toolbarbutton-menu-dropmarker {
min-height: @tabHeight@;
}
#main-window:not(:-moz-any([privatebrowsingmode=temporary],[customizing])) #navigator-toolbox[inFullscreen]:not(:-moz-lwtheme)::before,
#main-window:not(:-moz-any([privatebrowsingmode=temporary],[customizing],[tabsintitlebar])) #navigator-toolbox:not(:-moz-lwtheme)::before {
/* We want the titlebar to be unified, but we still want to be able
* to give #TabsToolbar a background. So we can't set -moz-appearance:
* toolbar on #TabsToolbar itself. Instead, we set it on a box of the
* right size which is put underneath #TabsToolbar.
*/
/* We want the titlebar to be unified, but we still want to be able
* to give #TabsToolbar a background. So we can't set -moz-appearance:
* toolbar on #TabsToolbar itself. Instead, we set it on a box of the
* right size which is put underneath #TabsToolbar.
*
* Because of Bug 941309, we make sure this pseudoelement always exists,
* but we only make it visible when we need it.
*/
#navigator-toolbox::before {
content: '';
display: block;
-moz-appearance: toolbar;
height: calc(@tabHeight@ + 1px);
margin-bottom: calc(-1px - @tabHeight@);
visibility: hidden;
}
#main-window:not(:-moz-any([privatebrowsingmode=temporary],[customizing])) #navigator-toolbox[inFullscreen]:not(:-moz-lwtheme)::before,
#main-window:not(:-moz-any([privatebrowsingmode=temporary],[customizing],[tabsintitlebar])) #navigator-toolbox:not(:-moz-lwtheme)::before {
visibility: visible;
}
#TabsToolbar {
@ -2764,11 +2772,11 @@ toolbarbutton.chevron > .toolbarbutton-menu-dropmarker {
}
/*
* Draw the bottom border of the tabstrip when core doesn't do it for us:
* Draw the bottom border of the tabstrip when core doesn't do it for us.
* Because of Bug 941309, we make sure this pseudoelement always exists,
* but we only make it visible when we need it.
*/
#main-window:-moz-any([privatebrowsingmode=temporary],[sizemode="fullscreen"],[customize-entered]) #TabsToolbar::after,
#main-window:not([tabsintitlebar]) #TabsToolbar::after,
#TabsToolbar:-moz-lwtheme::after {
#TabsToolbar::after {
content: '';
/* Because we use placeholders for window controls etc. in the tabstrip,
* and position those with ordinal attributes, and because our layout code
@ -2782,6 +2790,13 @@ toolbarbutton.chevron > .toolbarbutton-menu-dropmarker {
right: 0;
z-index: 0;
border-bottom: 1px solid hsla(0,0%,0%,.3);
visibility: hidden;
}
#main-window:-moz-any([privatebrowsingmode=temporary],[sizemode="fullscreen"],[customize-entered]) #TabsToolbar::after,
#main-window:not([tabsintitlebar]) #TabsToolbar::after,
#TabsToolbar:-moz-lwtheme::after {
visibility: visible;
}
#tabbrowser-tabs {
@ -4014,9 +4029,6 @@ toolbarbutton.chevron > .toolbarbutton-menu-dropmarker {
padding: 0;
position: relative;
}
.toolbarbutton-badge-container > .toolbarbutton-icon {
margin: 4px 2px;
}
.toolbarbutton-badge[badge]:not([badge=""]) {
/* The |content| property is set in the content stylesheet. */

View File

@ -613,11 +613,26 @@ panelview .toolbarbutton-1,
border: none;
}
.subviewbutton.panel-subview-footer > .toolbarbutton-text,
.subviewbutton.panel-subview-footer > .menu-text {
-moz-padding-start: 0;
-moz-padding-end: 12px;
-moz-appearance: none;
-moz-margin-start: 0px !important;
-moz-padding-start: 6px;
-moz-padding-end: 6px;
-moz-box-flex: 0;
text-align: center;
}
.subviewbutton.panel-subview-footer > .toolbarbutton-icon {
margin: 0;
}
.subviewbutton.panel-subview-footer > .toolbarbutton-text {
text-align: center;
padding: 0;
}
.subviewbutton.panel-subview-footer > .menu-accel-container {
-moz-padding-start: 6px;
}
.subviewbutton:not(.panel-subview-footer) {
@ -631,6 +646,16 @@ panelview .toolbarbutton-1,
font: menu;
}
.PanelUI-subView .subviewbutton[shortcut]::after {
content: attr(shortcut);
float: right;
color: hsl(0,0%,50%);
}
.PanelUI-subView.cui-widget-panelview .subviewbutton[shortcut]::after {
-moz-margin-start: 10px;
}
/* This is a <label> but it should fit in with the menu font- and colorwise. */
#PanelUI-characterEncodingView-autodetect-label {
font: menu;
@ -680,14 +705,16 @@ menuitem.subviewbutton@menuStateActive@,
color: hsl(0,0%,25%)
}
menuitem.panel-subview-footer@menuStateHover@,
.subviewbutton.panel-subview-footer@buttonStateHover@ {
background-color: hsla(210,4%,10%,.1);
border-top: 1px solid hsla(210,4%,10%,.12);
background-color: hsla(210,4%,10%,.15);
border-top: 1px solid hsla(210,4%,10%,.14);
}
menuitem.panel-subview-footer@menuStateActive@,
.subviewbutton.panel-subview-footer@buttonStateActive@ {
background-color: hsla(210,4%,10%,.15);
border-top: 1px solid hsla(210,4%,10%,.12);
background-color: hsla(210,4%,10%,.19);
border-top: 1px solid hsla(210,4%,10%,.14);
box-shadow: 0 1px 0 hsla(210,4%,10%,.05) inset;
}

View File

@ -376,3 +376,38 @@
#close-button:-moz-locale-dir(rtl) {
transform: scaleX(-1);
}
/* ::::: private browsing indicator ::::: */
@media (-moz-os-version: windows-vista),
(-moz-os-version: windows-win7) {
#TabsToolbar > .private-browsing-indicator {
background-image: url("chrome://browser/skin/privatebrowsing-mask-tabstrip-XPVista7.png");
}
#private-browsing-indicator-titlebar > .private-browsing-indicator {
background-image: url("chrome://browser/skin/privatebrowsing-mask-titlebar-XPVista7.png");
}
}
@media (-moz-windows-glass) {
#main-window[sizemode="normal"] > #titlebar > #titlebar-content > #titlebar-buttonbox-container > #private-browsing-indicator-titlebar > .private-browsing-indicator {
top: 1px;
}
#main-window[sizemode="maximized"] > #titlebar > #titlebar-content > #titlebar-buttonbox-container > #private-browsing-indicator-titlebar > .private-browsing-indicator {
top: -1px;
}
}
/**
* This next block targets Aero Basic, which has different positioning for the
* window caption buttons, and therefore needs to be special-cased.
*/
@media (-moz-windows-default-theme) {
@media not all and (-moz-windows-compositor) {
#main-window[sizemode="normal"] > #titlebar > #titlebar-content > #titlebar-buttonbox-container > #private-browsing-indicator-titlebar > .private-browsing-indicator {
background-image: url("chrome://browser/skin/privatebrowsing-mask-titlebar-XPVista7-tall.png");
height: 28px;
}
}
}

View File

@ -48,14 +48,6 @@
-moz-binding: url("chrome://browser/content/customizableui/toolbar.xml#toolbar-drag");
}
#main-window[tabsintitlebar] #main-menubar > menu:not(:-moz-lwtheme) {
color: CaptionText;
}
#main-window[tabsintitlebar] #main-menubar > menu:not(:-moz-lwtheme):-moz-window-inactive {
color: InactiveCaptionText;
}
#main-window[customize-entered][tabsintitlebar]:not([inFullscreen]) #toolbar-menubar[customizing-dragovertarget].customization-target::before,
#main-window[customize-entered][tabsintitlebar]:not([inFullscreen]) #TabsToolbar[customizing-dragovertarget].customization-target::before,
#main-window[customize-entered][tabsintitlebar]:not([inFullscreen]) #toolbar-menubar.customization-target:hover::before,
@ -90,10 +82,12 @@
background-color: transparent !important;
}
#main-window[tabsintitlebar]:not([inFullscreen]) #toolbar-menubar:not(:-moz-lwtheme),
#main-window[tabsintitlebar]:not([inFullscreen]) #TabsToolbar:not(:-moz-lwtheme) {
color: CaptionText;
}
#main-window[tabsintitlebar]:not([inFullscreen]) #toolbar-menubar:not(:-moz-lwtheme):-moz-window-inactive,
#main-window[tabsintitlebar]:not([inFullscreen]) #TabsToolbar:not(:-moz-lwtheme):-moz-window-inactive {
color: InactiveCaptionText;
}
@ -114,6 +108,13 @@
}
%endif
/* Make the menu inherit the toolbar's color. On non-compositor (Aero Basic, XP modern, classic)
* this is defined above. Otherwise (Aero Glass, Windows 8), this is hardcoded to black in
* browser-aero.css. */
#main-menubar > menu:not(:-moz-lwtheme) {
color: inherit;
}
/**
* In the classic themes, the titlebar has a horizontal gradient, which is
* problematic for reading the text of background tabs when they're in the
@ -2755,11 +2756,83 @@ chatbox {
/* End customization mode */
#main-window[privatebrowsingmode=temporary] #private-browsing-indicator {
width: 40px;
background: url("chrome://browser/skin/privatebrowsing-indicator.png") no-repeat center center;
/* Private browsing indicators */
/**
* Currently, we have two places where we put private browsing indicators on
* Windows. When tabsintitlebar is enabled, we draw the indicator in the titlebar.
* When tabsintitlebar is disabled, we draw the indicator at the end of the
* tabstrip. The titlebar indicator is the fiddliest of the bunch, since we
* want the bottom border of the image to line up with the bottom of the window
* caption buttons. That's why there's so much special-casing going on in here.
*/
.private-browsing-indicator {
display: none;
pointer-events: none;
}
#private-browsing-indicator-titlebar {
display: block;
position: absolute;
}
#main-window[privatebrowsingmode=temporary][tabsintitlebar] #private-browsing-indicator-titlebar > .private-browsing-indicator {
display: block;
}
#main-window[privatebrowsingmode=temporary]:not([tabsintitlebar]) #TabsToolbar > .private-browsing-indicator {
display: -moz-box;
}
#TabsToolbar > .private-browsing-indicator {
background: url("chrome://browser/skin/privatebrowsing-mask-tabstrip.png") no-repeat center -3px;
-moz-margin-start: 4px;
width: 48px;
}
#private-browsing-indicator-titlebar > .private-browsing-indicator {
background: url("chrome://browser/skin/privatebrowsing-mask-titlebar.png") no-repeat center 0px;
-moz-margin-end: 4px;
width: 40px;
height: 20px;
position: relative;
}
%ifndef WINDOWS_AERO
#TabsToolbar > .private-browsing-indicator {
background-image: url("chrome://browser/skin/privatebrowsing-mask-tabstrip-XPVista7.png");
}
@media not all and (-moz-windows-classic) {
#private-browsing-indicator-titlebar > .private-browsing-indicator {
background-image: url("chrome://browser/skin/privatebrowsing-mask-titlebar-XPVista7-tall.png");
height: 28px;
}
#main-window[sizemode="maximized"] > #titlebar > #titlebar-content > #titlebar-buttonbox-container > #private-browsing-indicator-titlebar > .private-browsing-indicator {
top: -5px;
}
#main-window[sizemode="normal"] > #titlebar > #titlebar-content > #titlebar-buttonbox-container > #private-browsing-indicator-titlebar > .private-browsing-indicator {
top: -1px;
}
}
%endif
@media (-moz-windows-classic) {
#private-browsing-indicator-titlebar > .private-browsing-indicator {
background-image: url("chrome://browser/skin/privatebrowsing-mask-titlebar-XPVista7.png");
}
/**
* We have to use top instead of background-position in this case, otherwise
* the bottom of the indicator would get cut off by the bounds of the
* private-browsing-indicator element.
*/
#main-window[sizemode="normal"] > #titlebar > #titlebar-content > #titlebar-buttonbox-container > #private-browsing-indicator-titlebar > .private-browsing-indicator {
top: 4px;
}
}
/* End private browsing indicators */
%include ../shared/UITour.inc.css
#UITourTooltipButtons {

View File

@ -65,7 +65,9 @@ browser.jar:
skin/classic/browser/Privacy-16.png
skin/classic/browser/Privacy-32.png
skin/classic/browser/Privacy-48.png
skin/classic/browser/privatebrowsing-indicator.png
skin/classic/browser/privatebrowsing-mask-tabstrip-XPVista7.png
skin/classic/browser/privatebrowsing-mask-titlebar-XPVista7.png
skin/classic/browser/privatebrowsing-mask-titlebar-XPVista7-tall.png
skin/classic/browser/reload-stop-go.png
skin/classic/browser/searchbar.css
skin/classic/browser/searchbar-dropdown-arrow.png
@ -397,7 +399,11 @@ browser.jar:
skin/classic/aero/browser/Privacy-16.png (Privacy-16-aero.png)
skin/classic/aero/browser/Privacy-32.png (Privacy-32-aero.png)
skin/classic/aero/browser/Privacy-48.png (Privacy-48-aero.png)
skin/classic/aero/browser/privatebrowsing-indicator.png
skin/classic/aero/browser/privatebrowsing-mask-tabstrip.png
skin/classic/aero/browser/privatebrowsing-mask-tabstrip-XPVista7.png
skin/classic/aero/browser/privatebrowsing-mask-titlebar.png
skin/classic/aero/browser/privatebrowsing-mask-titlebar-XPVista7.png
skin/classic/aero/browser/privatebrowsing-mask-titlebar-XPVista7-tall.png
skin/classic/aero/browser/reload-stop-go.png
skin/classic/aero/browser/searchbar.css
skin/classic/aero/browser/searchbar-dropdown-arrow.png (searchbar-dropdown-arrow-aero.png)

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 950 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 403 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 942 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 860 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 370 B

View File

@ -11,24 +11,39 @@ dnl can mess around with things like:
dnl AC_SOMETHING(foo,AC_SUBST(),bar)
define([AC_SUBST],
[ifdef([AC_SUBST_SET_$1], [m4_fatal([Cannot use AC_SUBST and AC_SUBST_SET on the same variable ($1)])],
[ifdef([AC_SUBST_LIST_$1], [m4_fatal([Cannot use AC_SUBST and AC_SUBST_LIST on the same variable ($1)])],
[ifdef([AC_SUBST_$1], ,
[define([AC_SUBST_$1], )dnl
AC_DIVERT_PUSH(MOZ_DIVERSION_SUBST)dnl
(''' $1 ''', r''' [$]$1 ''')
AC_DIVERT_POP()dnl
])])])
])])])])
dnl Like AC_SUBST, but makes the value available as a set in python,
dnl with values got from the value of the environment variable, split on
dnl whitespaces.
define([AC_SUBST_SET],
[ifdef([AC_SUBST_$1], [m4_fatal([Cannot use AC_SUBST and AC_SUBST_SET on the same variable ($1)])],
[ifdef([AC_SUBST_LIST$1], [m4_fatal([Cannot use AC_SUBST_LIST and AC_SUBST_SET on the same variable ($1)])],
[ifdef([AC_SUBST_SET_$1], ,
[define([AC_SUBST_SET_$1], )dnl
AC_DIVERT_PUSH(MOZ_DIVERSION_SUBST)dnl
(''' $1 ''', set(r''' [$]$1 '''.split()))
AC_DIVERT_POP()dnl
])])])
])])])])
dnl Like AC_SUBST, but makes the value available as a list in python,
dnl with values got from the value of the environment variable, split on
dnl whitespaces.
define([AC_SUBST_LIST],
[ifdef([AC_SUBST_$1], [m4_fatal([Cannot use AC_SUBST and AC_SUBST_LIST on the same variable ($1)])],
[ifdef([AC_SUBST_SET_$1], [m4_fatal([Cannot use AC_SUBST_SET and AC_SUBST_LIST on the same variable ($1)])],
[ifdef([AC_SUBST_LIST_$1], ,
[define([AC_SUBST_LIST_$1], )dnl
AC_DIVERT_PUSH(MOZ_DIVERSION_SUBST)dnl
(''' $1 ''', list(r''' [$]$1 '''.split()))
AC_DIVERT_POP()dnl
])])])])
dnl Wrap AC_DEFINE to store values in a format suitable for python.
dnl autoconf's AC_DEFINE still needs to be used to fill confdefs.h,

View File

@ -1916,6 +1916,9 @@ case "$target" in
fi
TARGET_NSPR_MDCPUCFG='\"md/_darwin.cfg\"'
MMX_FLAGS="-mmmx"
SSE_FLAGS="-msse"
SSE2_FLAGS="-msse2"
if test "x$lto_is_enabled" = "xyes"; then
echo "Skipping -dead_strip because lto is enabled."
@ -2008,6 +2011,10 @@ ia64*-hpux*)
fi
TARGET_NSPR_MDCPUCFG='\"md/_linux.cfg\"'
MMX_FLAGS="-mmmx"
SSE_FLAGS="-msse"
SSE2_FLAGS="-msse2"
MOZ_GFX_OPTIMIZE_MOBILE=1
MOZ_OPTIMIZE_FLAGS="-Os -freorder-blocks -fno-reorder-functions"
;;
@ -2029,6 +2036,10 @@ ia64*-hpux*)
MOZ_OPTIMIZE_FLAGS="-Os -freorder-blocks $MOZ_OPTIMIZE_SIZE_TWEAK"
fi
MMX_FLAGS="-mmmx"
SSE_FLAGS="-msse"
SSE2_FLAGS="-msse2"
TARGET_NSPR_MDCPUCFG='\"md/_linux.cfg\"'
MOZ_MEMORY=1
@ -2074,6 +2085,10 @@ ia64*-hpux*)
DLL_PREFIX=
IMPORT_LIB_SUFFIX=dll.a
MMX_FLAGS="-mmmx"
SSE_FLAGS="-msse"
SSE2_FLAGS="-msse2"
# We use mix of both POSIX and Win32 printf format across the tree, so format
# warnings are useless on mingw.
MOZ_C_SUPPORTS_WARNING(-Wno-, format, ac_c_has_wno_format)
@ -2275,6 +2290,9 @@ ia64*-hpux*)
fi
MKSHLIB='$(CXX) $(CXXFLAGS) $(DSO_PIC_CFLAGS) $(DSO_LDOPTS) -Wl,-soname,$(notdir $@) -o $@'
MKCSHLIB='$(CC) $(CFLAGS) $(DSO_PIC_CFLAGS) $(DSO_LDOPTS) -Wl,-soname,$(notdir $@)) -o $@'
MMX_FLAGS="-mmmx"
SSE_FLAGS="-msse"
SSE2_FLAGS="-msse2"
;;
*-openbsd*)
@ -2290,6 +2308,9 @@ ia64*-hpux*)
if test "$LIBRUNPATH"; then
DSO_LDOPTS="-R$LIBRUNPATH $DSO_LDOPTS"
fi
MMX_FLAGS="-mmmx"
SSE_FLAGS="-msse"
SSE2_FLAGS="-msse2"
;;
*-solaris*)
@ -2305,6 +2326,9 @@ ia64*-hpux*)
CFLAGS="$CFLAGS -xlibmieee -xstrconst -xbuiltin=%all -D__FUNCTION__=__func__"
CXXFLAGS="$CXXFLAGS -xlibmieee -xbuiltin=%all -features=tmplife,tmplrefstatic,extensions,no%except -norunpath -D__FUNCTION__=__func__ -template=no%extdef"
LDFLAGS="-xildoff $LDFLAGS"
MMX_FLAGS="-xarch=mmx -xO4"
SSE_FLAGS="-xarch=sse"
SSE2_FLAGS="-xarch=ssei2 -xO4"
if test -z "$CROSS_COMPILE" -a -f /usr/lib/ld/map.noexstk; then
_SAVE_LDFLAGS=$LDFLAGS
LDFLAGS="-M /usr/lib/ld/map.noexstk $LDFLAGS"
@ -2368,6 +2392,9 @@ ia64*-hpux*)
if test "$OS_RELEASE" = "5.3"; then
AC_DEFINE(MUST_UNDEF_HAVE_BOOLEAN_AFTER_INCLUDES)
fi
MMX_FLAGS="-mmmx"
SSE_FLAGS="-msse"
SSE2_FLAGS="-msse2"
fi
if test "$OS_RELEASE" = "5.5.1"; then
AC_DEFINE(NEED_USLEEP_PROTOTYPE)
@ -2389,6 +2416,10 @@ ia64*-hpux*)
esac
AC_SUBST_LIST(MMX_FLAGS)
AC_SUBST_LIST(SSE_FLAGS)
AC_SUBST_LIST(SSE2_FLAGS)
case "$target" in
*-*linux*)
# Includes linux-android

View File

@ -2650,4 +2650,10 @@ nsINode::OwnerDocAsNode() const
return OwnerDoc();
}
inline mozilla::dom::ParentObject
nsINode::GetParentObject() const
{
return GetParentObjectInternal(OwnerDoc());
}
#endif /* nsIDocument_h___ */

View File

@ -20,6 +20,7 @@
#include "mozilla/dom/EventTarget.h" // for base class
#include "js/TypeDecls.h" // for Handle, Value, JSObject, JSContext
#include "mozilla/dom/DOMString.h"
#include "mozilla/dom/BindingDeclarations.h"
// Including 'windows.h' will #define GetClassInfo to something else.
#ifdef XP_WIN
@ -392,18 +393,18 @@ protected:
return nullptr;
}
public:
nsIDocument* GetParentObject() const
{
// Make sure that we get the owner document of the content node, in case
// we're in document teardown. If we are, it's important to *not* use
// globalObj as the node's parent since that would give the node the
// principal of globalObj (i.e. the principal of the document that's being
// loaded) and not the principal of the document that's being unloaded.
// See http://bugzilla.mozilla.org/show_bug.cgi?id=227417
return OwnerDoc();
// Subclasses that wish to override the parent behavior should return the
// result of GetParentObjectIntenral, which handles the XBL scope stuff.
//
mozilla::dom::ParentObject GetParentObjectInternal(nsINode* aNativeParent) const {
mozilla::dom::ParentObject p(aNativeParent);
p.mUseXBLScope = ChromeOnlyAccess();
return p;
}
public:
mozilla::dom::ParentObject GetParentObject() const; // Implemented in nsIDocument.h
/**
* Return whether the node is an Element node
*/

View File

@ -572,24 +572,20 @@ Link::SizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf) const
}
URLSearchParams*
Link::GetSearchParams()
Link::SearchParams()
{
CreateSearchParamsIfNeeded();
return mSearchParams;
}
void
Link::SetSearchParams(URLSearchParams* aSearchParams)
Link::SetSearchParams(URLSearchParams& aSearchParams)
{
if (!aSearchParams) {
return;
}
if (mSearchParams) {
mSearchParams->RemoveObserver(this);
}
mSearchParams = aSearchParams;
mSearchParams = &aSearchParams;
mSearchParams->AddObserver(this);
nsAutoString search;

View File

@ -62,7 +62,7 @@ public:
void SetHostname(const nsAString &aHostname);
void SetPathname(const nsAString &aPathname);
void SetSearch(const nsAString &aSearch);
void SetSearchParams(mozilla::dom::URLSearchParams* aSearchParams);
void SetSearchParams(mozilla::dom::URLSearchParams& aSearchParams);
void SetPort(const nsAString &aPort);
void SetHash(const nsAString &aHash);
void GetOrigin(nsAString &aOrigin);
@ -73,7 +73,7 @@ public:
void GetHostname(nsAString &_hostname);
void GetPathname(nsAString &_pathname);
void GetSearch(nsAString &_search);
URLSearchParams* GetSearchParams();
URLSearchParams* SearchParams();
void GetPort(nsAString &_port);
void GetHash(nsAString &_hash);

View File

@ -51,12 +51,7 @@ if CONFIG['MOZ_WEBRTC']:
# nsTextFragment.cpp
if CONFIG['INTEL_ARCHITECTURE']:
SOURCES += ['nsTextFragmentSSE2.cpp']
if CONFIG['GNU_CC']:
# gcc requires -msse2 for this file since it uses SSE2 intrinsics. (See bug
# 585538 comment 12.)
SOURCES['nsTextFragmentSSE2.cpp'].flags += ['-msse2']
if CONFIG['SOLARIS_SUNPRO_CXX']:
SOURCES['nsTextFragmentSSE2.cpp'].flags += ['-xarch=sse2', '-xO4']
SOURCES['nsTextFragmentSSE2.cpp'].flags += CONFIG['SSE2_FLAGS']
EXPORTS.mozilla.dom += [
'Attr.h',

View File

@ -2594,19 +2594,8 @@ nsINode::WrapObject(JSContext *aCx, JS::Handle<JSObject*> aScope)
}
JS::Rooted<JSObject*> obj(aCx, WrapNode(aCx, aScope));
if (obj && ChromeOnlyAccess() &&
!nsContentUtils::IsSystemPrincipal(NodePrincipal()) &&
xpc::AllowXBLScope(js::GetObjectCompartment(obj)))
{
// Create a new wrapper and cache it.
JSAutoCompartment ac(aCx, obj);
JSObject* wrapper = xpc::WrapperFactory::WrapSOWObject(aCx, obj);
if (!wrapper) {
ClearWrapper();
return nullptr;
}
dom::SetSystemOnlyWrapper(obj, this, *wrapper);
}
MOZ_ASSERT_IF(ChromeOnlyAccess(),
xpc::IsInXBLScope(obj) || !xpc::UseXBLScope(js::GetObjectCompartment(obj)));
return obj;
}

View File

@ -1537,11 +1537,11 @@ nsXMLHttpRequest::Open(const nsACString& method, const nsACString& url,
}
nsresult
nsXMLHttpRequest::Open(const nsACString& method, const nsACString& url,
nsXMLHttpRequest::Open(const nsACString& inMethod, const nsACString& url,
bool async, const Optional<nsAString>& user,
const Optional<nsAString>& password)
{
NS_ENSURE_ARG(!method.IsEmpty());
NS_ENSURE_ARG(!inMethod.IsEmpty());
if (!async && !DontWarnAboutSyncXHR() && GetOwner() &&
GetOwner()->GetExtantDoc()) {
@ -1555,9 +1555,29 @@ nsXMLHttpRequest::Open(const nsACString& method, const nsACString& url,
// Disallow HTTP/1.1 TRACE method (see bug 302489)
// and MS IIS equivalent TRACK (see bug 381264)
if (method.LowerCaseEqualsLiteral("trace") ||
method.LowerCaseEqualsLiteral("track")) {
return NS_ERROR_INVALID_ARG;
// and CONNECT
if (inMethod.LowerCaseEqualsLiteral("trace") ||
inMethod.LowerCaseEqualsLiteral("connect") ||
inMethod.LowerCaseEqualsLiteral("track")) {
return NS_ERROR_DOM_SECURITY_ERR;
}
nsAutoCString method;
// GET, POST, DELETE, HEAD, OPTIONS, PUT methods normalized to upper case
if (inMethod.LowerCaseEqualsLiteral("get")) {
method.Assign(NS_LITERAL_CSTRING("GET"));
} else if (inMethod.LowerCaseEqualsLiteral("post")) {
method.Assign(NS_LITERAL_CSTRING("POST"));
} else if (inMethod.LowerCaseEqualsLiteral("delete")) {
method.Assign(NS_LITERAL_CSTRING("DELETE"));
} else if (inMethod.LowerCaseEqualsLiteral("head")) {
method.Assign(NS_LITERAL_CSTRING("HEAD"));
} else if (inMethod.LowerCaseEqualsLiteral("options")) {
method.Assign(NS_LITERAL_CSTRING("OPTIONS"));
} else if (inMethod.LowerCaseEqualsLiteral("put")) {
method.Assign(NS_LITERAL_CSTRING("PUT"));
} else {
method = inMethod; // other methods are not normalized
}
// sync request is not allowed using withCredential or responseType

View File

@ -3130,6 +3130,18 @@ CanvasRenderingContext2D::IsPointInPath(double x, double y, const CanvasWindingR
return mPath->ContainsPoint(Point(x, y), mTarget->GetTransform());
}
bool CanvasRenderingContext2D::IsPointInPath(const CanvasPath& mPath, double x, double y, const CanvasWindingRule& mWinding)
{
if (!FloatValidate(x,y)) {
return false;
}
EnsureTarget();
RefPtr<gfx::Path> tempPath = mPath.GetPath(mWinding, mTarget);
return tempPath->ContainsPoint(Point(x, y), mTarget->GetTransform());
}
bool
CanvasRenderingContext2D::IsPointInStroke(double x, double y)
{
@ -3158,6 +3170,28 @@ CanvasRenderingContext2D::IsPointInStroke(double x, double y)
return mPath->StrokeContainsPoint(strokeOptions, Point(x, y), mTarget->GetTransform());
}
bool CanvasRenderingContext2D::IsPointInStroke(const CanvasPath& mPath, double x, double y)
{
if (!FloatValidate(x,y)) {
return false;
}
EnsureTarget();
RefPtr<gfx::Path> tempPath = mPath.GetPath(CanvasWindingRule::Nonzero, mTarget);
const ContextState &state = CurrentState();
StrokeOptions strokeOptions(state.lineWidth,
state.lineJoin,
state.lineCap,
state.miterLimit,
state.dash.Length(),
state.dash.Elements(),
state.dashOffset);
return tempPath->StrokeContainsPoint(strokeOptions, Point(x, y), mTarget->GetTransform());
}
//
// image
//

View File

@ -231,7 +231,9 @@ public:
void Clip(const CanvasWindingRule& winding);
void Clip(const CanvasPath& path, const CanvasWindingRule& winding);
bool IsPointInPath(double x, double y, const CanvasWindingRule& winding);
bool IsPointInPath(const CanvasPath& path, double x, double y, const CanvasWindingRule& winding);
bool IsPointInStroke(double x, double y);
bool IsPointInStroke(const CanvasPath& path, double x, double y);
void FillText(const nsAString& text, double x, double y,
const Optional<double>& maxWidth,
mozilla::ErrorResult& error);

View File

@ -162,6 +162,159 @@ function test_large_canvas() {
}
</script>
<p>Canvas test: test_isPointInPath_canvas</p>
<canvas id="c5" class="output" width="100" height="100">+
</canvas>
<script type="text/javascript">
function shouldThrow(ctx, s) {
var _ok = false;
try {
eval(s);
} catch(e) {
_ok = true;
}
ok(_ok, s);
}
function shouldBeTrue(ctx, path, s) {
var _ok = eval(s);
ok(_ok, s);
}
function shouldBeFalse(ctx, path, s) {
var _ok = !eval(s);
ok(_ok, s);
}
function test_isPointInPath_canvas() {
var c = document.getElementById("c5");
var ctx = c.getContext("2d");
var path = new Path2D();
path.rect(0, 0, 100, 100);
path.rect(25, 25, 50, 50);
shouldBeTrue(ctx, path, "ctx.isPointInPath(path, 50, 50)");
shouldBeFalse(ctx, path, "ctx.isPointInPath(path, NaN, 50)");
shouldBeFalse(ctx, path, "ctx.isPointInPath(path, 50, NaN)");
path = new Path2D();
path.rect(0, 0, 100, 100);
path.rect(25, 25, 50, 50);
shouldBeTrue(ctx, path, "ctx.isPointInPath(path, 50, 50, 'nonzero')");
path = new Path2D();
path.rect(0, 0, 100, 100);
path.rect(25, 25, 50, 50);
shouldBeFalse(ctx, path, "ctx.isPointInPath(path, 50, 50, 'evenodd')");
shouldThrow(ctx, "ctx.isPointInPath(null, 50, 50)");
shouldThrow(ctx, "ctx.isPointInPath(null, 50, 50, 'nonzero')");
shouldThrow(ctx, "ctx.isPointInPath(null, 50, 50, 'evenodd')");
shouldThrow(ctx, "ctx.isPointInPath(path, 50, 50)");
shouldThrow(ctx, "ctx.isPointInPath(path, 50, 50, 'nonzero')");
shouldThrow(ctx, "ctx.isPointInPath(path, 50, 50, 'evenodd')");
shouldThrow(ctx, "ctx.isPointInPath([], 50, 50)");
shouldThrow(ctx, "ctx.isPointInPath([], 50, 50, 'nonzero')");
shouldThrow(ctx, "ctx.isPointInPath([], 50, 50, 'evenodd')");
shouldThrow(ctx, "ctx.isPointInPath({}, 50, 50)");
shouldThrow(ctx, "ctx.isPointInPath({}, 50, 50, 'nonzero')");
shouldThrow(ctx, "ctx.isPointInPath({}, 50, 50, 'evenodd')");
}
</script>
<p>Canvas test: test_isPointInStroke_canvas</p>
<canvas id="c6" class="output" width="100" height="100">+
</canvas>
<script type="text/javascript">
function test_isPointInStroke_canvas() {
var c = document.getElementById("c6");
var ctx = c.getContext("2d");
ctx.strokeStyle = '#0ff';
var path = new Path2D();
path.rect(20,20,100,100);
shouldBeTrue(ctx, path, "ctx.isPointInStroke(path,20,20)");
shouldBeTrue(ctx, path, "ctx.isPointInStroke(path,120,20)");
shouldBeTrue(ctx, path, "ctx.isPointInStroke(path,20,120)");
shouldBeTrue(ctx, path, "ctx.isPointInStroke(path,120,120)");
shouldBeTrue(ctx, path, "ctx.isPointInStroke(path,70,20)");
shouldBeTrue(ctx, path, "ctx.isPointInStroke(path,20,70)");
shouldBeTrue(ctx, path, "ctx.isPointInStroke(path,120,70)");
shouldBeTrue(ctx, path, "ctx.isPointInStroke(path,70,120)");
shouldBeFalse(ctx, path, "ctx.isPointInStroke(path,22,22)");
shouldBeFalse(ctx, path, "ctx.isPointInStroke(path,118,22)");
shouldBeFalse(ctx, path, "ctx.isPointInStroke(path,22,118)");
shouldBeFalse(ctx, path, "ctx.isPointInStroke(path,118,118)");
shouldBeFalse(ctx, path, "ctx.isPointInStroke(path,70,18)");
shouldBeFalse(ctx, path, "ctx.isPointInStroke(path,122,70)");
shouldBeFalse(ctx, path, "ctx.isPointInStroke(path,70,122)");
shouldBeFalse(ctx, path, "ctx.isPointInStroke(path,18,70)");
shouldBeFalse(ctx, path, "ctx.isPointInStroke(path,NaN,122)");
shouldBeFalse(ctx, path, "ctx.isPointInStroke(path,18,NaN)");
shouldThrow(ctx, "ctx.isPointInStroke(null,70,20)");
shouldThrow(ctx, "ctx.isPointInStroke([],20,70)");
shouldThrow(ctx, "ctx.isPointInStroke({},120,70)");
ctx.lineWidth = 10;
shouldBeTrue(ctx, path, "ctx.isPointInStroke(path,22,22)");
shouldBeTrue(ctx, path, "ctx.isPointInStroke(path,118,22)");
shouldBeTrue(ctx, path, "ctx.isPointInStroke(path,22,118)");
shouldBeTrue(ctx, path, "ctx.isPointInStroke(path,118,118)");
shouldBeTrue(ctx, path, "ctx.isPointInStroke(path,70,18)");
shouldBeTrue(ctx, path, "ctx.isPointInStroke(path,122,70)");
shouldBeTrue(ctx, path, "ctx.isPointInStroke(path,70,122)");
shouldBeTrue(ctx, path, "ctx.isPointInStroke(path,18,70)");
shouldBeFalse(ctx, path, "ctx.isPointInStroke(path,26,70)");
shouldBeFalse(ctx, path, "ctx.isPointInStroke(path,70,26)");
shouldBeFalse(ctx, path, "ctx.isPointInStroke(path,70,114)");
shouldBeFalse(ctx, path, "ctx.isPointInStroke(path,114,70)");
path = new Path2D();
path.moveTo(10,10);
path.lineTo(110,20);
path.lineTo(10,30);
ctx.lineJoin = "bevel";
shouldBeFalse(ctx, path, "ctx.isPointInStroke(path,113,20)");
ctx.miterLimit = 40.0;
ctx.lineJoin = "miter";
shouldBeTrue(ctx, path, "ctx.isPointInStroke(path,113,20)");
ctx.miterLimit = 2.0;
shouldBeFalse(ctx, path, "ctx.isPointInStroke(path,113,20)");
path = new Path2D();
path.moveTo(10,10);
path.lineTo(110,10);
ctx.lineCap = "butt";
shouldBeFalse(ctx, path, "ctx.isPointInStroke(path,112,10)");
ctx.lineCap = "round";
shouldBeTrue(ctx, path, "ctx.isPointInStroke(path,112,10)");
shouldBeFalse(ctx, path, "ctx.isPointInStroke(path,117,10)");
ctx.lineCap = "square";
shouldBeTrue(ctx, path, "ctx.isPointInStroke(path,112,10)");
shouldBeFalse(ctx, path, "ctx.isPointInStroke(path,117,10)");
ctx.lineCap = "butt";
ctx.setLineDash([10,10]);
shouldBeTrue(ctx, path, "ctx.isPointInStroke(path,15,10)");
shouldBeFalse(ctx, path, "ctx.isPointInStroke(path,25,10)");
shouldBeTrue(ctx, path, "ctx.isPointInStroke(path,35,10)");
ctx.lineDashOffset = 10;
shouldBeFalse(ctx, path, "ctx.isPointInStroke(path,15,10)");
shouldBeTrue(ctx, path, "ctx.isPointInStroke(path,25,10)");
shouldBeFalse(ctx, path, "ctx.isPointInStroke(path,35,10)");
}
</script>
<script>
function runTests() {
@ -189,7 +342,18 @@ function runTests() {
throw e;
ok(false, "unexpected exception thrown in: test_large_canvas");
}
try {
test_isPointInPath_canvas();
} catch(e) {
throw e;
ok(false, "unexpected exception thrown in: test_isPointInPath_canvas");
}
try {
test_isPointInStroke_canvas();
} catch(e) {
throw e;
ok(false, "unexpected exception thrown in: test_isPointInStroke_canvas");
}
SpecialPowers.setBoolPref("canvas.path.enabled", false);
SimpleTest.finish();
}

View File

@ -78,9 +78,9 @@ public:
SetHTMLAttr(nsGkAtoms::align, aAlign, aError);
}
nsINode* GetParentObject() {
ParentObject GetParentObject() {
Element* form = GetFormElement();
return form ? static_cast<nsINode*>(form)
return form ? GetParentObjectInternal(form)
: nsGenericHTMLElement::GetParentObject();
}

View File

@ -3951,6 +3951,7 @@ HTMLMediaElement::AddTextTrack(TextTrackKind aKind,
if (mTextTrackManager) {
return mTextTrackManager->AddTextTrack(aKind, aLabel, aLanguage,
TextTrackMode::Hidden,
TextTrackReadyState::Loaded,
TextTrackSource::AddTextTrack);
}
return nullptr;

View File

@ -154,7 +154,9 @@ HTMLTrackElement::CreateTextTrack()
}
mTrack = new TextTrack(OwnerDoc()->GetParentObject(), kind, label, srcLang,
TextTrackMode::Disabled, TextTrackSource::Track);
TextTrackMode::Disabled,
TextTrackReadyState::NotLoaded,
TextTrackSource::Track);
mTrack->SetTrackElement(this);
if (mMediaParent) {
@ -317,7 +319,7 @@ uint16_t
HTMLTrackElement::ReadyState() const
{
if (!mTrack) {
return READY_STATE_NONE;
return TextTrackReadyState::NotLoaded;
}
return mTrack->ReadyState();

View File

@ -85,13 +85,6 @@ public:
SetHTMLBoolAttr(nsGkAtoms::_default, aDefault, aError);
}
// Constants for numeric readyState property values.
enum {
READY_STATE_NONE = 0U,
READY_STATE_LOADING = 1U,
READY_STATE_LOADED = 2U,
READY_STATE_ERROR = 3U
};
uint16_t ReadyState() const;
TextTrack* Track();

View File

@ -113,15 +113,15 @@ already_AddRefed<TextTrack>
TextTrackManager::AddTextTrack(TextTrackKind aKind, const nsAString& aLabel,
const nsAString& aLanguage,
TextTrackMode aMode,
TextTrackReadyState aReadyState,
TextTrackSource aTextTrackSource)
{
if (!mMediaElement) {
return nullptr;
}
nsRefPtr<TextTrack> ttrack =
mTextTracks->AddTextTrack(aKind, aLabel, aLanguage, aMode, aTextTrackSource,
CompareTextTracks(mMediaElement));
ttrack->SetReadyState(HTMLTrackElement::READY_STATE_LOADED);
mTextTracks->AddTextTrack(aKind, aLabel, aLanguage, aMode, aReadyState,
aTextTrackSource, CompareTextTracks(mMediaElement));
AddCues(ttrack);
return ttrack.forget();
}
@ -218,7 +218,7 @@ TextTrackManager::PopulatePendingList()
for (uint32_t index = 0; index < len; ++index) {
TextTrack* ttrack = mTextTracks->IndexedGetter(index, dummy);
if (ttrack && ttrack->Mode() != TextTrackMode::Disabled &&
ttrack->ReadyState() == HTMLTrackElement::READY_STATE_LOADING) {
ttrack->ReadyState() == TextTrackReadyState::Loading) {
mPendingTextTracks->AddTextTrack(ttrack,
CompareTextTracks(mMediaElement));
}

View File

@ -47,6 +47,7 @@ public:
const nsAString& aLabel,
const nsAString& aLanguage,
TextTrackMode aMode,
TextTrackReadyState aReadyState,
TextTrackSource aTextTrackSource);
void AddTextTrack(TextTrack* aTextTrack);
void RemoveTextTrack(TextTrack* aTextTrack, bool aPendingListOnly);

View File

@ -106,64 +106,6 @@
using namespace mozilla;
using namespace mozilla::dom;
class nsINodeInfo;
class nsIDOMNodeList;
class nsRuleWalker;
// XXX todo: add in missing out-of-memory checks
//----------------------------------------------------------------------
#ifdef GATHER_ELEMENT_USEAGE_STATISTICS
// static objects that have constructors are kinda bad, but we don't
// care here, this is only debugging code!
static nsHashtable sGEUS_ElementCounts;
void GEUS_ElementCreated(nsINodeInfo *aNodeInfo)
{
nsAutoString name;
aNodeInfo->GetName(name);
nsStringKey key(name);
int32_t count = (int32_t)sGEUS_ElementCounts.Get(&key);
count++;
sGEUS_ElementCounts.Put(&key, (void *)count);
}
bool GEUS_enum_func(nsHashKey *aKey, void *aData, void *aClosure)
{
const char16_t *name_chars = ((nsStringKey *)aKey)->GetString();
NS_ConvertUTF16toUTF8 name(name_chars);
printf ("%s %d\n", name.get(), aData);
return true;
}
void GEUS_DumpElementCounts()
{
printf ("Element count statistics:\n");
sGEUS_ElementCounts.Enumerate(GEUS_enum_func, nullptr);
printf ("End of element count statistics:\n");
}
nsresult
nsGenericHTMLElement::Init(nsINodeInfo *aNodeInfo)
{
GEUS_ElementCreated(aNodeInfo);
return nsGenericHTMLElementBase::Init(aNodeInfo);
}
#endif
/**
* nsAutoFocusEvent is used to dispatch a focus event when a
* nsGenericHTMLFormElement is binded to the tree with the autofocus attribute
@ -1985,12 +1927,14 @@ NS_IMPL_ISUPPORTS_INHERITED1(nsGenericHTMLFormElement,
nsGenericHTMLElement,
nsIFormControl)
nsINode*
mozilla::dom::ParentObject
nsGenericHTMLFormElement::GetParentObject() const
{
// We use the parent chain to implement the scope for event handlers.
return mForm ? static_cast<nsINode*>(mForm)
: static_cast<nsINode*>(OwnerDoc());
if (mForm) {
return GetParentObjectInternal(mForm);
}
return nsGenericHTMLElement::GetParentObject();
}
bool

View File

@ -19,25 +19,15 @@
#include "mozilla/dom/ValidityState.h"
#include "mozilla/dom/ElementInlines.h"
class nsIDOMAttr;
class nsIDOMEventListener;
class nsIDOMNodeList;
class nsIFrame;
class nsIStyleRule;
class nsChildContentList;
class nsDOMCSSDeclaration;
class nsIDOMCSSStyleDeclaration;
class nsIURI;
class nsIFormControlFrame;
class nsIForm;
class nsPresState;
class nsILayoutHistoryState;
class nsIEditor;
struct nsRect;
struct nsSize;
class nsIDOMHTMLMenuElement;
class nsIDOMHTMLCollection;
class nsDOMSettableTokenList;
class nsIDOMHTMLMenuElement;
class nsIEditor;
class nsIFormControlFrame;
class nsIFrame;
class nsILayoutHistoryState;
class nsIURI;
class nsPresState;
struct nsSize;
namespace mozilla {
class EventChainPostVisitor;
@ -1290,7 +1280,7 @@ public:
NS_DECL_ISUPPORTS_INHERITED
nsINode* GetParentObject() const;
mozilla::dom::ParentObject GetParentObject() const;
virtual bool IsNodeOfType(uint32_t aFlags) const MOZ_OVERRIDE;
virtual void SaveSubtreeState() MOZ_OVERRIDE;

View File

@ -29,28 +29,22 @@ NS_IMPL_RELEASE_INHERITED(TextTrack, nsDOMEventTargetHelper)
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(TextTrack)
NS_INTERFACE_MAP_END_INHERITING(nsDOMEventTargetHelper)
TextTrack::TextTrack(nsISupports* aParent, TextTrackSource aTextTrackSource)
: mParent(aParent)
, mTextTrackSource(aTextTrackSource)
{
SetDefaultSettings();
SetIsDOMBinding();
}
TextTrack::TextTrack(nsISupports* aParent,
TextTrackKind aKind,
const nsAString& aLabel,
const nsAString& aLanguage,
TextTrackMode aMode,
TextTrackReadyState aReadyState,
TextTrackSource aTextTrackSource)
: mParent(aParent)
, mKind(aKind)
, mLabel(aLabel)
, mLanguage(aLanguage)
, mMode(aMode)
, mReadyState(aReadyState)
, mTextTrackSource(aTextTrackSource)
{
SetDefaultSettings();
mKind = aKind;
mLabel = aLabel;
mLanguage = aLanguage;
mMode = aMode;
SetIsDOMBinding();
}
@ -60,29 +54,28 @@ TextTrack::TextTrack(nsISupports* aParent,
const nsAString& aLabel,
const nsAString& aLanguage,
TextTrackMode aMode,
TextTrackReadyState aReadyState,
TextTrackSource aTextTrackSource)
: mParent(aParent)
, mTextTrackList(aTextTrackList)
, mKind(aKind)
, mLabel(aLabel)
, mLanguage(aLanguage)
, mMode(aMode)
, mReadyState(aReadyState)
, mTextTrackSource(aTextTrackSource)
{
SetDefaultSettings();
mKind = aKind;
mLabel = aLabel;
mLanguage = aLanguage;
mMode = aMode;
SetIsDOMBinding();
}
void
TextTrack::SetDefaultSettings()
{
mKind = TextTrackKind::Subtitles;
mMode = TextTrackMode::Hidden;
mCueList = new TextTrackCueList(mParent);
mActiveCueList = new TextTrackCueList(mParent);
mCuePos = 0;
mDirty = false;
mReadyState = HTMLTrackElement::READY_STATE_NONE;
}
JSObject*
@ -187,14 +180,14 @@ TextTrack::GetActiveCueArray(nsTArray<nsRefPtr<TextTrackCue> >& aCues)
}
}
uint16_t
TextTrackReadyState
TextTrack::ReadyState() const
{
return mReadyState;
}
void
TextTrack::SetReadyState(uint16_t aState)
TextTrack::SetReadyState(TextTrackReadyState aState)
{
mReadyState = aState;
@ -203,8 +196,8 @@ TextTrack::SetReadyState(uint16_t aState)
}
HTMLMediaElement* mediaElement = mTextTrackList->GetMediaElement();
if (mediaElement && (mReadyState == HTMLTrackElement::READY_STATE_LOADED ||
mReadyState == HTMLTrackElement::READY_STATE_ERROR)) {
if (mediaElement && (mReadyState == TextTrackReadyState::Loaded||
mReadyState == TextTrackReadyState::FailedToLoad)) {
mediaElement->RemoveTextTrack(this, true);
}
}

View File

@ -28,19 +28,26 @@ enum TextTrackSource {
MediaResourceSpecific
};
// Constants for numeric readyState property values.
enum TextTrackReadyState {
NotLoaded = 0U,
Loading = 1U,
Loaded = 2U,
FailedToLoad = 3U
};
class TextTrack MOZ_FINAL : public nsDOMEventTargetHelper
{
public:
NS_DECL_ISUPPORTS_INHERITED
NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(TextTrack, nsDOMEventTargetHelper)
TextTrack(nsISupports* aParent,
TextTrackSource aTextTrackSource);
TextTrack(nsISupports* aParent,
TextTrackKind aKind,
const nsAString& aLabel,
const nsAString& aLanguage,
TextTrackMode aMode,
TextTrackReadyState aReadyState,
TextTrackSource aTextTrackSource);
TextTrack(nsISupports* aParent,
TextTrackList* aTextTrackList,
@ -48,6 +55,7 @@ public:
const nsAString& aLabel,
const nsAString& aLanguage,
TextTrackMode aMode,
TextTrackReadyState aReadyState,
TextTrackSource aTextTrackSource);
void SetDefaultSettings();
@ -98,8 +106,8 @@ public:
TextTrackCueList* GetActiveCues();
void GetActiveCueArray(nsTArray<nsRefPtr<TextTrackCue> >& aCues);
uint16_t ReadyState() const;
void SetReadyState(uint16_t aState);
TextTrackReadyState ReadyState() const;
void SetReadyState(TextTrackReadyState aState);
void AddCue(TextTrackCue& aCue);
void RemoveCue(TextTrackCue& aCue, ErrorResult& aRv);
@ -136,7 +144,7 @@ private:
nsRefPtr<HTMLTrackElement> mTrackElement;
uint32_t mCuePos;
uint16_t mReadyState;
TextTrackReadyState mReadyState;
bool mDirty;
// An enum that represents where the track was sourced from.

View File

@ -66,11 +66,13 @@ TextTrackList::AddTextTrack(TextTrackKind aKind,
const nsAString& aLabel,
const nsAString& aLanguage,
TextTrackMode aMode,
TextTrackReadyState aReadyState,
TextTrackSource aTextTrackSource,
const CompareTextTracks& aCompareTT)
{
nsRefPtr<TextTrack> track = new TextTrack(mGlobal, this, aKind, aLabel, aLanguage,
aMode, aTextTrackSource);
nsRefPtr<TextTrack> track = new TextTrack(mGlobal, this, aKind, aLabel,
aLanguage, aMode, aReadyState,
aTextTrackSource);
AddTextTrack(track, aCompareTT);
return track.forget();
}

View File

@ -51,6 +51,7 @@ public:
const nsAString& aLabel,
const nsAString& aLanguage,
TextTrackMode aMode,
TextTrackReadyState aReadyState,
TextTrackSource aTextTrackSource,
const CompareTextTracks& aCompareTT);
TextTrack* GetTrackById(const nsAString& aId);

View File

@ -78,7 +78,7 @@ WebVTTListener::LoadResource()
rv = mParserWrapper->Watch(this);
NS_ENSURE_SUCCESS(rv, rv);
mElement->mTrack->SetReadyState(HTMLTrackElement::READY_STATE_LOADING);
mElement->mTrack->SetReadyState(TextTrackReadyState::Loading);
return NS_OK;
}
@ -106,9 +106,9 @@ WebVTTListener::OnStopRequest(nsIRequest* aRequest,
nsISupports* aContext,
nsresult aStatus)
{
if (mElement->ReadyState() != HTMLTrackElement::READY_STATE_ERROR) {
if (mElement->ReadyState() != TextTrackReadyState::FailedToLoad) {
TextTrack* track = mElement->Track();
track->SetReadyState(HTMLTrackElement::READY_STATE_LOADED);
track->SetReadyState(TextTrackReadyState::Loaded);
}
// Attempt to parse any final data the parser might still have.
mParserWrapper->Flush();

View File

@ -71,14 +71,13 @@ class GetCameraNameRunnable;
*
* MediaThread:
* mState, mImage, mWidth, mHeight, mCapability, mPrefs, mDeviceName, mUniqueId, mInitDone,
* mSources, mImageContainer, mSources, mState, mImage, mLastCapture
* mImageContainer, mSources, mState, mImage
*
* MainThread:
* mCaptureIndex, mWindowId,
* mNativeCameraControl, mPreviewStream, mState, mLastCapture, mWidth, mHeight
* mCaptureIndex, mLastCapture, mState, mWidth, mHeight,
*
* Where mWidth, mHeight, mImage are protected by mMonitor
* mState, mLastCapture is protected by mCallbackMonitor
* mState is protected by mCallbackMonitor
* Other variable is accessed only from single thread
*/
class MediaEngineWebRTCVideoSource : public MediaEngineVideoSource

View File

@ -643,7 +643,6 @@ MediaEngineWebRTCVideoSource::OnError(CameraErrorContext aContext, CameraError a
void
MediaEngineWebRTCVideoSource::OnTakePictureComplete(uint8_t* aData, uint32_t aLength, const nsAString& aMimeType)
{
ReentrantMonitorAutoEnter sync(mCallbackMonitor);
mLastCapture =
static_cast<nsIDOMFile*>(new nsDOMMemoryFile(static_cast<void*>(aData),
static_cast<uint64_t>(aLength),
@ -715,10 +714,14 @@ MediaEngineWebRTCVideoSource::RotateImage(layers::Image* aImage, uint32_t aWidth
bool
MediaEngineWebRTCVideoSource::OnNewPreviewFrame(layers::Image* aImage, uint32_t aWidth, uint32_t aHeight) {
MonitorAutoLock enter(mMonitor);
if (mState == kStopped) {
return false;
{
ReentrantMonitorAutoEnter sync(mCallbackMonitor);
if (mState == kStopped) {
return false;
}
}
MonitorAutoLock enter(mMonitor);
// Bug XXX we'd prefer to avoid converting if mRotation == 0, but that causes problems in UpdateImage()
RotateImage(aImage, aWidth, aHeight);
if (mRotation != 0 && mRotation != 180) {

View File

@ -77,7 +77,7 @@ SVGFEBlendElement::GetPrimitiveDescription(nsSVGFilterInstance* aInstance,
nsTArray<RefPtr<SourceSurface>>& aInputImages)
{
uint32_t mode = mEnumAttributes[MODE].GetAnimValue();
FilterPrimitiveDescription descr(FilterPrimitiveDescription::eBlend);
FilterPrimitiveDescription descr(PrimitiveType::Blend);
descr.Attributes().Set(eBlendBlendmode, mode);
return descr;
}

View File

@ -93,7 +93,7 @@ SVGFEColorMatrixElement::GetPrimitiveDescription(nsSVGFilterInstance* aInstance,
uint32_t type = mEnumAttributes[TYPE].GetAnimValue();
const SVGNumberList &values = mNumberListAttributes[VALUES].GetAnimValue();
FilterPrimitiveDescription descr(FilterPrimitiveDescription::eColorMatrix);
FilterPrimitiveDescription descr(PrimitiveType::ColorMatrix);
if (!mNumberListAttributes[VALUES].IsExplicitlySet() &&
(type == SVG_FECOLORMATRIX_TYPE_MATRIX ||
type == SVG_FECOLORMATRIX_TYPE_SATURATE ||

View File

@ -78,7 +78,7 @@ SVGFEComponentTransferElement::GetPrimitiveDescription(nsSVGFilterInstance* aIns
eComponentTransferFunctionA
};
FilterPrimitiveDescription descr(FilterPrimitiveDescription::eComponentTransfer);
FilterPrimitiveDescription descr(PrimitiveType::ComponentTransfer);
for (int32_t i = 0; i < 4; i++) {
if (childForChannel[i]) {
descr.Attributes().Set(attributeNames[i], childForChannel[i]->ComputeAttributes());

View File

@ -114,7 +114,7 @@ SVGFECompositeElement::GetPrimitiveDescription(nsSVGFilterInstance* aInstance,
const nsTArray<bool>& aInputsAreTainted,
nsTArray<RefPtr<SourceSurface>>& aInputImages)
{
FilterPrimitiveDescription descr(FilterPrimitiveDescription::eComposite);
FilterPrimitiveDescription descr(PrimitiveType::Composite);
uint32_t op = mEnumAttributes[OPERATOR].GetAnimValue();
descr.Attributes().Set(eCompositeOperator, op);

View File

@ -169,7 +169,7 @@ SVGFEConvolveMatrixElement::GetPrimitiveDescription(nsSVGFilterInstance* aInstan
const nsTArray<bool>& aInputsAreTainted,
nsTArray<RefPtr<SourceSurface>>& aInputImages)
{
const FilterPrimitiveDescription failureDescription(FilterPrimitiveDescription::eNone);
const FilterPrimitiveDescription failureDescription(PrimitiveType::Empty);
const SVGNumberList &kernelMatrix =
mNumberListAttributes[KERNELMATRIX].GetAnimValue();
@ -230,7 +230,7 @@ SVGFEConvolveMatrixElement::GetPrimitiveDescription(nsSVGFilterInstance* aInstan
Size kernelUnitLength =
GetKernelUnitLength(aInstance, &mNumberPairAttributes[KERNEL_UNIT_LENGTH]);
FilterPrimitiveDescription descr(FilterPrimitiveDescription::eConvolveMatrix);
FilterPrimitiveDescription descr(PrimitiveType::ConvolveMatrix);
AttributeMap& atts = descr.Attributes();
atts.Set(eConvolveMatrixKernelSize, IntSize(orderX, orderY));
atts.Set(eConvolveMatrixKernelMatrix, &kernelMatrix[0], kmLength);

View File

@ -68,7 +68,7 @@ SVGFEDiffuseLightingElement::GetPrimitiveDescription(nsSVGFilterInstance* aInsta
{
float diffuseConstant = mNumberAttributes[DIFFUSE_CONSTANT].GetAnimValue();
FilterPrimitiveDescription descr(FilterPrimitiveDescription::eDiffuseLighting);
FilterPrimitiveDescription descr(PrimitiveType::DiffuseLighting);
descr.Attributes().Set(eDiffuseLightingDiffuseConstant, diffuseConstant);
return AddLightingAttributes(descr, aInstance);
}

View File

@ -99,7 +99,7 @@ SVGFEDisplacementMapElement::GetPrimitiveDescription(nsSVGFilterInstance* aInsta
if (aInputsAreTainted[1]) {
// If the map is tainted, refuse to apply the effect and act as a
// pass-through filter instead, as required by the spec.
FilterPrimitiveDescription descr(FilterPrimitiveDescription::eOffset);
FilterPrimitiveDescription descr(PrimitiveType::Offset);
descr.Attributes().Set(eOffsetOffset, IntPoint(0, 0));
return descr;
}
@ -108,7 +108,7 @@ SVGFEDisplacementMapElement::GetPrimitiveDescription(nsSVGFilterInstance* aInsta
&mNumberAttributes[SCALE]);
uint32_t xChannel = mEnumAttributes[CHANNEL_X].GetAnimValue();
uint32_t yChannel = mEnumAttributes[CHANNEL_Y].GetAnimValue();
FilterPrimitiveDescription descr(FilterPrimitiveDescription::eDisplacementMap);
FilterPrimitiveDescription descr(PrimitiveType::DisplacementMap);
descr.Attributes().Set(eDisplacementMapScale, scale);
descr.Attributes().Set(eDisplacementMapXChannel, xChannel);
descr.Attributes().Set(eDisplacementMapYChannel, yChannel);

View File

@ -93,7 +93,7 @@ SVGFEDropShadowElement::GetPrimitiveDescription(nsSVGFilterInstance* aInstance,
&mNumberPairAttributes[STD_DEV],
nsSVGNumberPair::eSecond);
if (stdX < 0 || stdY < 0) {
return FilterPrimitiveDescription(FilterPrimitiveDescription::eNone);
return FilterPrimitiveDescription(PrimitiveType::Empty);
}
IntPoint offset(int32_t(aInstance->GetPrimitiveNumber(
@ -101,7 +101,7 @@ SVGFEDropShadowElement::GetPrimitiveDescription(nsSVGFilterInstance* aInstance,
int32_t(aInstance->GetPrimitiveNumber(
SVGContentUtils::Y, &mNumberAttributes[DY])));
FilterPrimitiveDescription descr(FilterPrimitiveDescription::eDropShadow);
FilterPrimitiveDescription descr(PrimitiveType::DropShadow);
descr.Attributes().Set(eDropShadowStdDeviation, Size(stdX, stdY));
descr.Attributes().Set(eDropShadowOffset, offset);

View File

@ -39,7 +39,7 @@ SVGFEFloodElement::GetPrimitiveDescription(nsSVGFilterInstance* aInstance,
const nsTArray<bool>& aInputsAreTainted,
nsTArray<RefPtr<SourceSurface>>& aInputImages)
{
FilterPrimitiveDescription descr(FilterPrimitiveDescription::eFlood);
FilterPrimitiveDescription descr(PrimitiveType::Flood);
nsIFrame* frame = GetPrimaryFrame();
if (frame) {
nsStyleContext* style = frame->StyleContext();

View File

@ -76,10 +76,10 @@ SVGFEGaussianBlurElement::GetPrimitiveDescription(nsSVGFilterInstance* aInstance
&mNumberPairAttributes[STD_DEV],
nsSVGNumberPair::eSecond);
if (stdX < 0 || stdY < 0) {
return FilterPrimitiveDescription(FilterPrimitiveDescription::eNone);
return FilterPrimitiveDescription(PrimitiveType::Empty);
}
FilterPrimitiveDescription descr(FilterPrimitiveDescription::eGaussianBlur);
FilterPrimitiveDescription descr(PrimitiveType::GaussianBlur);
descr.Attributes().Set(eGaussianBlurStdDeviation, Size(stdX, stdY));
return descr;
}

View File

@ -198,7 +198,7 @@ SVGFEImageElement::GetPrimitiveDescription(nsSVGFilterInstance* aInstance,
{
nsIFrame* frame = GetPrimaryFrame();
if (!frame) {
return FilterPrimitiveDescription(FilterPrimitiveDescription::eNone);
return FilterPrimitiveDescription(PrimitiveType::Empty);
}
nsCOMPtr<imgIRequest> currentRequest;
@ -218,7 +218,7 @@ SVGFEImageElement::GetPrimitiveDescription(nsSVGFilterInstance* aInstance,
}
if (!currentFrame) {
return FilterPrimitiveDescription(FilterPrimitiveDescription::eNone);
return FilterPrimitiveDescription(PrimitiveType::Empty);
}
gfxPlatform* platform = gfxPlatform::GetPlatform();
@ -239,7 +239,7 @@ SVGFEImageElement::GetPrimitiveDescription(nsSVGFilterInstance* aInstance,
Filter filter = ToFilter(nsLayoutUtils::GetGraphicsFilterForFrame(frame));
FilterPrimitiveDescription descr(FilterPrimitiveDescription::eImage);
FilterPrimitiveDescription descr(PrimitiveType::Image);
descr.Attributes().Set(eImageFilter, (uint32_t)filter);
descr.Attributes().Set(eImageTransform, TM);

View File

@ -33,7 +33,7 @@ SVGFEMergeElement::GetPrimitiveDescription(nsSVGFilterInstance* aInstance,
const nsTArray<bool>& aInputsAreTainted,
nsTArray<RefPtr<SourceSurface>>& aInputImages)
{
return FilterPrimitiveDescription(FilterPrimitiveDescription::eMerge);
return FilterPrimitiveDescription(PrimitiveType::Merge);
}
void

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