mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-10 11:55:49 +00:00
Merge mozilla-central to b2g-inbound
This commit is contained in:
commit
a04233feb4
@ -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));
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
|
@ -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)];
|
||||
|
@ -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>';
|
||||
|
||||
|
@ -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',
|
||||
|
@ -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'
|
||||
}],
|
||||
|
@ -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.
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
|
@ -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:
|
||||
|
@ -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"
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
}
|
||||
},
|
||||
|
@ -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();
|
||||
}
|
||||
};
|
||||
|
@ -6,7 +6,6 @@
|
||||
|
||||
XPIDL_SOURCES += [
|
||||
'nsIFeedResultService.idl',
|
||||
'nsIFeedWriter.idl',
|
||||
'nsIWebContentConverterRegistrar.idl',
|
||||
]
|
||||
|
||||
|
@ -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();
|
||||
};
|
@ -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}
|
||||
|
@ -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]);
|
||||
|
47
browser/components/feeds/src/FeedWriterEnabled.h
Normal file
47
browser/components/feeds/src/FeedWriterEnabled.h
Normal 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");
|
||||
}
|
||||
};
|
||||
|
||||
}
|
@ -8,6 +8,10 @@ SOURCES += [
|
||||
'nsFeedSniffer.cpp',
|
||||
]
|
||||
|
||||
EXPORTS.mozilla += [
|
||||
'FeedWriterEnabled.h',
|
||||
]
|
||||
|
||||
EXTRA_COMPONENTS += [
|
||||
'BrowserFeeds.manifest',
|
||||
'FeedConverter.js',
|
||||
|
@ -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 => {
|
||||
|
@ -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) {
|
||||
|
@ -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.
|
||||
|
@ -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");
|
||||
});
|
||||
}
|
||||
|
@ -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();
|
||||
|
@ -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,
|
||||
|
@ -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");
|
||||
|
@ -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++) {
|
||||
|
@ -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',
|
||||
|
@ -135,6 +135,8 @@ StyleEditorPanel.prototype = {
|
||||
this._target = null;
|
||||
this._toolbox = null;
|
||||
this._panelDoc = null;
|
||||
this._debuggee.destroy();
|
||||
this._debuggee = null;
|
||||
|
||||
this.UI.destroy();
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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) {
|
||||
|
@ -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) {
|
||||
|
@ -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) {
|
||||
|
@ -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) {
|
||||
|
@ -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() {
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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)) {
|
||||
|
@ -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,
|
||||
|
@ -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;
|
||||
|
13
browser/experiments/docs/index.rst
Normal file
13
browser/experiments/docs/index.rst
Normal 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
|
429
browser/experiments/docs/manifest.rst
Normal file
429
browser/experiments/docs/manifest.rst
Normal 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; }"
|
||||
}
|
||||
]
|
||||
}
|
@ -14,3 +14,5 @@ EXTRA_JS_MODULES += [
|
||||
]
|
||||
|
||||
XPCSHELL_TESTS_MANIFESTS += ['test/xpcshell/xpcshell.ini']
|
||||
|
||||
SPHINX_TREES['experiments'] = 'docs'
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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.
|
||||
|
||||
|
@ -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));
|
||||
|
@ -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. */
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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 {
|
||||
|
@ -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 |
BIN
browser/themes/windows/privatebrowsing-mask-tabstrip.png
Normal file
BIN
browser/themes/windows/privatebrowsing-mask-tabstrip.png
Normal file
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 |
BIN
browser/themes/windows/privatebrowsing-mask-titlebar.png
Normal file
BIN
browser/themes/windows/privatebrowsing-mask-titlebar.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 370 B |
@ -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,
|
||||
|
31
configure.in
31
configure.in
@ -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
|
||||
|
@ -2650,4 +2650,10 @@ nsINode::OwnerDocAsNode() const
|
||||
return OwnerDoc();
|
||||
}
|
||||
|
||||
inline mozilla::dom::ParentObject
|
||||
nsINode::GetParentObject() const
|
||||
{
|
||||
return GetParentObjectInternal(OwnerDoc());
|
||||
}
|
||||
|
||||
#endif /* nsIDocument_h___ */
|
||||
|
@ -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
|
||||
*/
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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',
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
//
|
||||
|
@ -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);
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -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();
|
||||
}
|
||||
|
||||
|
@ -3951,6 +3951,7 @@ HTMLMediaElement::AddTextTrack(TextTrackKind aKind,
|
||||
if (mTextTrackManager) {
|
||||
return mTextTrackManager->AddTextTrack(aKind, aLabel, aLanguage,
|
||||
TextTrackMode::Hidden,
|
||||
TextTrackReadyState::Loaded,
|
||||
TextTrackSource::AddTextTrack);
|
||||
}
|
||||
return nullptr;
|
||||
|
@ -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();
|
||||
|
@ -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();
|
||||
|
@ -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));
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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.
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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();
|
||||
|
@ -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
|
||||
|
@ -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) {
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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 ||
|
||||
|
@ -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());
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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();
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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
Loading…
Reference in New Issue
Block a user