Merge fx-team to m-c. a=merge
|
@ -129,14 +129,14 @@ let gEMEHandler = {
|
|||
let btnAccessKeyId = msgPrefix + "button.accesskey";
|
||||
buttons.push({
|
||||
label: gNavigatorBundle.getString(btnLabelId),
|
||||
accesskey: gNavigatorBundle.getString(btnAccessKeyId),
|
||||
accessKey: gNavigatorBundle.getString(btnAccessKeyId),
|
||||
callback: callback
|
||||
});
|
||||
|
||||
let optionsId = "emeNotifications.optionsButton";
|
||||
buttons.push({
|
||||
label: gNavigatorBundle.getString(optionsId + ".label"),
|
||||
accesskey: gNavigatorBundle.getString(optionsId + ".accesskey"),
|
||||
accessKey: gNavigatorBundle.getString(optionsId + ".accesskey"),
|
||||
popup: "emeNotificationsPopup"
|
||||
});
|
||||
}
|
||||
|
|
|
@ -520,8 +520,8 @@ let AboutReaderListener = {
|
|||
|
||||
// The loaded page may have changed while we were parsing the document.
|
||||
// Make sure we've got the current one.
|
||||
let currentURL = Services.io.newURI(content.document.documentURI, null, null).specIgnoringRef;
|
||||
if (article.url !== currentURL) {
|
||||
let url = Services.io.newURI(content.document.documentURI, null, null).spec;
|
||||
if (article.url !== url) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -931,6 +931,8 @@ const CustomizableWidgets = [
|
|||
label: "loop-call-button3.label",
|
||||
tooltiptext: "loop-call-button3.tooltiptext",
|
||||
defaultArea: CustomizableUI.AREA_NAVBAR,
|
||||
// Not in private browsing, see bug 1108187.
|
||||
showInPrivateBrowsing: false,
|
||||
introducedInVersion: 4,
|
||||
onBuild: function(aDocument) {
|
||||
// If we're not supposed to see the button, return zip.
|
||||
|
|
|
@ -1,14 +1,8 @@
|
|||
from marionette_test import MarionetteTestCase
|
||||
try:
|
||||
from by import By
|
||||
from errors import NoSuchElementException, StaleElementException
|
||||
# noinspection PyUnresolvedReferences
|
||||
from wait import Wait
|
||||
except ImportError:
|
||||
from marionette_driver.by import By
|
||||
from marionette_driver.errors import NoSuchElementException, StaleElementException
|
||||
# noinspection PyUnresolvedReferences
|
||||
from marionette_driver import Wait
|
||||
from marionette_driver.by import By
|
||||
from marionette_driver.errors import NoSuchElementException, StaleElementException
|
||||
# noinspection PyUnresolvedReferences
|
||||
from marionette_driver import Wait
|
||||
|
||||
import os
|
||||
import sys
|
||||
|
|
|
@ -620,9 +620,13 @@ DynSHOpenWithDialog(HWND hwndParent, const OPENASINFO *poainfo)
|
|||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
nsresult rv =
|
||||
SUCCEEDED(SHOpenWithDialogFn(hwndParent, poainfo)) ? NS_OK :
|
||||
NS_ERROR_FAILURE;
|
||||
nsresult rv;
|
||||
HRESULT hr = SHOpenWithDialogFn(hwndParent, poainfo);
|
||||
if (SUCCEEDED(hr) || (hr == HRESULT_FROM_WIN32(ERROR_CANCELLED))) {
|
||||
rv = NS_OK;
|
||||
} else {
|
||||
rv = NS_ERROR_FAILURE;
|
||||
}
|
||||
FreeLibrary(shellDLL);
|
||||
return rv;
|
||||
}
|
||||
|
|
|
@ -711,7 +711,7 @@ SourcesView.prototype = Heritage.extend(WidgetMethods, {
|
|||
lineTextNode.setAttribute("crop", "end");
|
||||
lineTextNode.setAttribute("flex", "1");
|
||||
|
||||
let tooltip = text.substr(0, BREAKPOINT_LINE_TOOLTIP_MAX_LENGTH);
|
||||
let tooltip = text ? text.substr(0, BREAKPOINT_LINE_TOOLTIP_MAX_LENGTH) : "";
|
||||
lineTextNode.setAttribute("tooltiptext", tooltip);
|
||||
|
||||
let container = document.createElement("hbox");
|
||||
|
@ -992,7 +992,7 @@ SourcesView.prototype = Heritage.extend(WidgetMethods, {
|
|||
let attachment = breakpointItem.attachment;
|
||||
|
||||
// Check if this is an enabled conditional breakpoint, and if so,
|
||||
// save the current conditional epression.
|
||||
// save the current conditional expression.
|
||||
let breakpointPromise = DebuggerController.Breakpoints._getAdded(attachment);
|
||||
if (breakpointPromise) {
|
||||
let { location } = yield breakpointPromise;
|
||||
|
|
|
@ -182,6 +182,8 @@ skip-if = e10s && debug
|
|||
skip-if = e10s && debug
|
||||
[browser_dbg_conditional-breakpoints-04.js]
|
||||
skip-if = e10s && debug
|
||||
[browser_dbg_conditional-breakpoints-05.js]
|
||||
skip-if = e10s && debug
|
||||
[browser_dbg_server-conditional-bp-01.js]
|
||||
skip-if = e10s && debug
|
||||
[browser_dbg_server-conditional-bp-02.js]
|
||||
|
@ -190,6 +192,8 @@ skip-if = e10s && debug
|
|||
skip-if = e10s && debug
|
||||
[browser_dbg_server-conditional-bp-04.js]
|
||||
skip-if = e10s && debug
|
||||
[browser_dbg_server-conditional-bp-05.js]
|
||||
skip-if = e10s && debug
|
||||
[browser_dbg_controller-evaluate-01.js]
|
||||
skip-if = e10s && debug
|
||||
[browser_dbg_controller-evaluate-02.js]
|
||||
|
|
|
@ -0,0 +1,141 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
/**
|
||||
* Make sure that conditional breakpoints with an exception-throwing expression
|
||||
* could pause on hit
|
||||
*/
|
||||
|
||||
const TAB_URL = EXAMPLE_URL + "doc_conditional-breakpoints.html";
|
||||
|
||||
function test() {
|
||||
let gTab, gPanel, gDebugger, gEditor;
|
||||
let gSources, gBreakpoints, gLocation;
|
||||
|
||||
initDebugger(TAB_URL).then(([aTab,, aPanel]) => {
|
||||
gTab = aTab;
|
||||
gPanel = aPanel;
|
||||
gDebugger = gPanel.panelWin;
|
||||
gEditor = gDebugger.DebuggerView.editor;
|
||||
gSources = gDebugger.DebuggerView.Sources;
|
||||
gBreakpoints = gDebugger.DebuggerController.Breakpoints;
|
||||
|
||||
// This test forces conditional breakpoints to be evaluated on the
|
||||
// client-side
|
||||
var client = gPanel.target.client;
|
||||
client.mainRoot.traits.conditionalBreakpoints = false;
|
||||
|
||||
waitForSourceAndCaretAndScopes(gPanel, ".html", 17)
|
||||
.then(addBreakpoints)
|
||||
.then(() => resumeAndTestBreakpoint(18))
|
||||
.then(() => resumeAndTestBreakpoint(19))
|
||||
.then(() => resumeAndTestBreakpoint(20))
|
||||
.then(() => resumeAndTestBreakpoint(23))
|
||||
.then(() => resumeAndTestNoBreakpoint())
|
||||
.then(() => {
|
||||
// Reset traits back to default value
|
||||
client.mainRoot.traits.conditionalBreakpoints = true;
|
||||
})
|
||||
.then(() => closeDebuggerAndFinish(gPanel))
|
||||
.then(null, aError => {
|
||||
ok(false, "Got an error: " + aError.message + "\n" + aError.stack);
|
||||
});
|
||||
|
||||
callInTab(gTab, "ermahgerd");
|
||||
});
|
||||
|
||||
function resumeAndTestBreakpoint(aLine) {
|
||||
let finished = waitForCaretUpdated(gPanel, aLine).then(() => testBreakpoint(aLine));
|
||||
|
||||
EventUtils.sendMouseEvent({ type: "mousedown" },
|
||||
gDebugger.document.getElementById("resume"),
|
||||
gDebugger);
|
||||
|
||||
return finished;
|
||||
}
|
||||
|
||||
function resumeAndTestNoBreakpoint() {
|
||||
let finished = waitForDebuggerEvents(gPanel, gDebugger.EVENTS.AFTER_FRAMES_CLEARED).then(() => {
|
||||
is(gSources.itemCount, 1,
|
||||
"Found the expected number of sources.");
|
||||
is(gEditor.getText().indexOf("ermahgerd"), 253,
|
||||
"The correct source was loaded initially.");
|
||||
is(gSources.selectedValue, gSources.values[0],
|
||||
"The correct source is selected.");
|
||||
|
||||
ok(gSources.selectedItem,
|
||||
"There should be a selected source in the sources pane.");
|
||||
ok(!gSources._selectedBreakpointItem,
|
||||
"There should be no selected breakpoint in the sources pane.");
|
||||
is(gSources._conditionalPopupVisible, false,
|
||||
"The breakpoint conditional expression popup should not be shown.");
|
||||
|
||||
is(gDebugger.document.querySelectorAll(".dbg-stackframe").length, 0,
|
||||
"There should be no visible stackframes.");
|
||||
is(gDebugger.document.querySelectorAll(".dbg-breakpoint").length, 6,
|
||||
"There should be thirteen visible breakpoints.");
|
||||
});
|
||||
|
||||
gDebugger.gThreadClient.resume();
|
||||
|
||||
return finished;
|
||||
}
|
||||
|
||||
function addBreakpoints() {
|
||||
return promise.resolve(null)
|
||||
.then(() => gPanel.addBreakpoint({ actor: gSources.selectedValue, line: 18 }))
|
||||
.then(aClient => aClient.conditionalExpression = " 1a")
|
||||
.then(() => gPanel.addBreakpoint({ actor: gSources.selectedValue, line: 19 }))
|
||||
.then(aClient => aClient.conditionalExpression = "new Error()")
|
||||
.then(() => gPanel.addBreakpoint({ actor: gSources.selectedValue, line: 20 }))
|
||||
.then(aClient => aClient.conditionalExpression = "true")
|
||||
.then(() => gPanel.addBreakpoint({ actor: gSources.selectedValue, line: 21 }))
|
||||
.then(aClient => aClient.conditionalExpression = "false")
|
||||
.then(() => gPanel.addBreakpoint({ actor: gSources.selectedValue, line: 22 }))
|
||||
.then(aClient => aClient.conditionalExpression = "0")
|
||||
.then(() => gPanel.addBreakpoint({ actor: gSources.selectedValue, line: 23 }))
|
||||
.then(aClient => aClient.conditionalExpression = "randomVar");
|
||||
}
|
||||
|
||||
function testBreakpoint(aLine, aHighlightBreakpoint) {
|
||||
// Highlight the breakpoint only if required.
|
||||
if (aHighlightBreakpoint) {
|
||||
let finished = waitForCaretUpdated(gPanel, aLine).then(() => testBreakpoint(aLine));
|
||||
gSources.highlightBreakpoint({ actor: gSources.selectedValue, line: aLine });
|
||||
return finished;
|
||||
}
|
||||
|
||||
let selectedActor = gSources.selectedValue;
|
||||
let selectedBreakpoint = gSources._selectedBreakpointItem;
|
||||
|
||||
ok(selectedActor,
|
||||
"There should be a selected item in the sources pane.");
|
||||
ok(selectedBreakpoint,
|
||||
"There should be a selected breakpoint in the sources pane.");
|
||||
|
||||
let source = gSources.selectedItem.attachment.source;
|
||||
|
||||
is(selectedBreakpoint.attachment.actor, source.actor,
|
||||
"The breakpoint on line " + aLine + " wasn't added on the correct source.");
|
||||
is(selectedBreakpoint.attachment.line, aLine,
|
||||
"The breakpoint on line " + aLine + " wasn't found.");
|
||||
is(!!selectedBreakpoint.attachment.disabled, false,
|
||||
"The breakpoint on line " + aLine + " should be enabled.");
|
||||
is(!!selectedBreakpoint.attachment.openPopup, false,
|
||||
"The breakpoint on line " + aLine + " should not have opened a popup.");
|
||||
is(gSources._conditionalPopupVisible, false,
|
||||
"The breakpoint conditional expression popup should not have been shown.");
|
||||
|
||||
return gBreakpoints._getAdded(selectedBreakpoint.attachment).then(aBreakpointClient => {
|
||||
is(aBreakpointClient.location.url, source.url,
|
||||
"The breakpoint's client url is correct");
|
||||
is(aBreakpointClient.location.line, aLine,
|
||||
"The breakpoint's client line is correct");
|
||||
isnot(aBreakpointClient.conditionalExpression, undefined,
|
||||
"The breakpoint on line " + aLine + " should have a conditional expression.");
|
||||
|
||||
ok(isCaretPos(gPanel, aLine),
|
||||
"The editor caret position is not properly set.");
|
||||
});
|
||||
}
|
||||
}
|
|
@ -36,6 +36,7 @@ function test() {
|
|||
.then(() => resumeAndTestBreakpoint(27))
|
||||
.then(() => resumeAndTestBreakpoint(28))
|
||||
.then(() => resumeAndTestBreakpoint(29))
|
||||
.then(() => resumeAndTestBreakpoint(30))
|
||||
.then(() => resumeAndTestNoBreakpoint())
|
||||
.then(() => {
|
||||
return promise.all([
|
||||
|
|
|
@ -0,0 +1,171 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
/**
|
||||
* Test conditional breakpoints throwing exceptions
|
||||
* with server support
|
||||
*/
|
||||
|
||||
const TAB_URL = EXAMPLE_URL + "doc_conditional-breakpoints.html";
|
||||
|
||||
function test() {
|
||||
// Linux debug test slaves are a bit slow at this test sometimes.
|
||||
requestLongerTimeout(2);
|
||||
|
||||
let gTab, gPanel, gDebugger;
|
||||
let gEditor, gSources, gBreakpoints, gBreakpointsAdded, gBreakpointsRemoving;
|
||||
|
||||
initDebugger(TAB_URL).then(([aTab,, aPanel]) => {
|
||||
gTab = aTab;
|
||||
gPanel = aPanel;
|
||||
gDebugger = gPanel.panelWin;
|
||||
gEditor = gDebugger.DebuggerView.editor;
|
||||
gSources = gDebugger.DebuggerView.Sources;
|
||||
gBreakpoints = gDebugger.DebuggerController.Breakpoints;
|
||||
gBreakpointsAdded = gBreakpoints._added;
|
||||
gBreakpointsRemoving = gBreakpoints._removing;
|
||||
|
||||
waitForSourceAndCaretAndScopes(gPanel, ".html", 17)
|
||||
.then(() => addBreakpoints())
|
||||
.then(() => initialChecks())
|
||||
.then(() => resumeAndTestBreakpoint(18))
|
||||
.then(() => resumeAndTestBreakpoint(19))
|
||||
.then(() => resumeAndTestBreakpoint(20))
|
||||
.then(() => resumeAndTestBreakpoint(23))
|
||||
.then(() => resumeAndTestNoBreakpoint())
|
||||
.then(() => closeDebuggerAndFinish(gPanel))
|
||||
.then(null, aError => {
|
||||
ok(false, "Got an error: " + aError.message + "\n" + aError.stack);
|
||||
});
|
||||
|
||||
callInTab(gTab, "ermahgerd");
|
||||
});
|
||||
|
||||
function addBreakpoints() {
|
||||
return promise.resolve(null)
|
||||
.then(() => gPanel.addBreakpoint({ actor: gSources.selectedValue,
|
||||
line: 18,
|
||||
condition: "1a"
|
||||
}))
|
||||
.then(() => gPanel.addBreakpoint({ actor: gSources.selectedValue,
|
||||
line: 19,
|
||||
condition: "new Error()"
|
||||
}))
|
||||
.then(() => gPanel.addBreakpoint({ actor: gSources.selectedValue,
|
||||
line: 20,
|
||||
condition: "true"
|
||||
}))
|
||||
.then(() => gPanel.addBreakpoint({ actor: gSources.selectedValue,
|
||||
line: 21,
|
||||
condition: "false"
|
||||
}))
|
||||
.then(() => gPanel.addBreakpoint({ actor: gSources.selectedValue,
|
||||
line: 22,
|
||||
condition: "undefined"
|
||||
}))
|
||||
.then(() => gPanel.addBreakpoint({ actor: gSources.selectedValue,
|
||||
line: 23,
|
||||
condition: "randomVar"
|
||||
}));
|
||||
}
|
||||
|
||||
function initialChecks() {
|
||||
is(gDebugger.gThreadClient.state, "paused",
|
||||
"Should only be getting stack frames while paused.");
|
||||
is(gSources.itemCount, 1,
|
||||
"Found the expected number of sources.");
|
||||
is(gEditor.getText().indexOf("ermahgerd"), 253,
|
||||
"The correct source was loaded initially.");
|
||||
is(gSources.selectedValue, gSources.values[0],
|
||||
"The correct source is selected.");
|
||||
|
||||
is(gBreakpointsAdded.size, 6,
|
||||
"6 breakpoints currently added.");
|
||||
is(gBreakpointsRemoving.size, 0,
|
||||
"No breakpoints currently being removed.");
|
||||
is(gEditor.getBreakpoints().length, 6,
|
||||
"6 breakpoints currently shown in the editor.");
|
||||
|
||||
ok(!gBreakpoints._getAdded({ url: "foo", line: 3 }),
|
||||
"_getAdded('foo', 3) returns falsey.");
|
||||
ok(!gBreakpoints._getRemoving({ url: "bar", line: 3 }),
|
||||
"_getRemoving('bar', 3) returns falsey.");
|
||||
}
|
||||
|
||||
function resumeAndTestBreakpoint(aLine) {
|
||||
let finished = waitForCaretUpdated(gPanel, aLine).then(() => testBreakpoint(aLine));
|
||||
|
||||
EventUtils.sendMouseEvent({ type: "mousedown" },
|
||||
gDebugger.document.getElementById("resume"),
|
||||
gDebugger);
|
||||
|
||||
return finished;
|
||||
}
|
||||
|
||||
function resumeAndTestNoBreakpoint() {
|
||||
let finished = waitForDebuggerEvents(gPanel, gDebugger.EVENTS.AFTER_FRAMES_CLEARED).then(() => {
|
||||
is(gSources.itemCount, 1,
|
||||
"Found the expected number of sources.");
|
||||
is(gEditor.getText().indexOf("ermahgerd"), 253,
|
||||
"The correct source was loaded initially.");
|
||||
is(gSources.selectedValue, gSources.values[0],
|
||||
"The correct source is selected.");
|
||||
|
||||
ok(gSources.selectedItem,
|
||||
"There should be a selected source in the sources pane.")
|
||||
ok(!gSources._selectedBreakpointItem,
|
||||
"There should be no selected breakpoint in the sources pane.")
|
||||
is(gSources._conditionalPopupVisible, false,
|
||||
"The breakpoint conditional expression popup should not be shown.");
|
||||
|
||||
is(gDebugger.document.querySelectorAll(".dbg-stackframe").length, 0,
|
||||
"There should be no visible stackframes.");
|
||||
is(gDebugger.document.querySelectorAll(".dbg-breakpoint").length, 6,
|
||||
"There should be thirteen visible breakpoints.");
|
||||
});
|
||||
|
||||
gDebugger.gThreadClient.resume();
|
||||
|
||||
return finished;
|
||||
}
|
||||
|
||||
function testBreakpoint(aLine, aHighlightBreakpoint) {
|
||||
// Highlight the breakpoint only if required.
|
||||
if (aHighlightBreakpoint) {
|
||||
let finished = waitForCaretUpdated(gPanel, aLine).then(() => testBreakpoint(aLine));
|
||||
gSources.highlightBreakpoint({ actor: gSources.selectedValue, line: aLine });
|
||||
return finished;
|
||||
}
|
||||
|
||||
let selectedActor = gSources.selectedValue;
|
||||
let selectedBreakpoint = gSources._selectedBreakpointItem;
|
||||
|
||||
ok(selectedActor,
|
||||
"There should be a selected item in the sources pane.");
|
||||
ok(selectedBreakpoint,
|
||||
"There should be a selected brekapoint in the sources pane.");
|
||||
|
||||
is(selectedBreakpoint.attachment.actor, selectedActor,
|
||||
"The breakpoint on line " + aLine + " wasn't added on the correct source.");
|
||||
is(selectedBreakpoint.attachment.line, aLine,
|
||||
"The breakpoint on line " + aLine + " wasn't found.");
|
||||
is(!!selectedBreakpoint.attachment.disabled, false,
|
||||
"The breakpoint on line " + aLine + " should be enabled.");
|
||||
is(!!selectedBreakpoint.attachment.openPopup, false,
|
||||
"The breakpoint on line " + aLine + " should not have opened a popup.");
|
||||
is(gSources._conditionalPopupVisible, false,
|
||||
"The breakpoint conditional expression popup should not have been shown.");
|
||||
|
||||
return gBreakpoints._getAdded(selectedBreakpoint.attachment).then(aBreakpointClient => {
|
||||
is(aBreakpointClient.location.actor, selectedActor,
|
||||
"The breakpoint's client url is correct");
|
||||
is(aBreakpointClient.location.line, aLine,
|
||||
"The breakpoint's client line is correct");
|
||||
isnot(aBreakpointClient.condition, undefined,
|
||||
"The breakpoint on line " + aLine + " should have a conditional expression.");
|
||||
|
||||
ok(isCaretPos(gPanel, aLine),
|
||||
"The editor caret position is not properly set.");
|
||||
});
|
||||
}
|
||||
}
|
|
@ -1395,7 +1395,7 @@ Scope.prototype = {
|
|||
|
||||
// Sort all of the properties before adding them, if preferred.
|
||||
if (aOptions.sorted && aKeysType != "just-numbers") {
|
||||
names.sort();
|
||||
names.sort(this._naturalSort);
|
||||
}
|
||||
|
||||
// Add the properties to the current scope.
|
||||
|
@ -1601,6 +1601,22 @@ Scope.prototype = {
|
|||
this._isHeaderVisible = false;
|
||||
},
|
||||
|
||||
/**
|
||||
* Sort in ascending order
|
||||
* This only needs to compare non-numbers since it is dealing with an array
|
||||
* which numeric-based indices are placed in order.
|
||||
*
|
||||
* @param string a
|
||||
* @param string b
|
||||
* @return number
|
||||
* -1 if a is less than b, 0 if no change in order, +1 if a is greater than 0
|
||||
*/
|
||||
_naturalSort: function(a,b) {
|
||||
if (isNaN(parseFloat(a)) && isNaN(parseFloat(b))) {
|
||||
return a < b ? -1 : 1;
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Shows the scope's expand/collapse arrow.
|
||||
*/
|
||||
|
@ -2232,8 +2248,9 @@ Variable.prototype = Heritage.extend(Scope.prototype, {
|
|||
|
||||
// Sort all of the properties before adding them, if preferred.
|
||||
if (aOptions.sorted) {
|
||||
propertyNames.sort();
|
||||
propertyNames.sort(this._naturalSort);
|
||||
}
|
||||
|
||||
// Add all the variable properties.
|
||||
for (let name of propertyNames) {
|
||||
let descriptor = Object.getOwnPropertyDescriptor(aObject, name);
|
||||
|
|
|
@ -63,6 +63,8 @@ function test() {
|
|||
yield testNotSorted("Array(0,1,2,3,4,5,6,7,8,9,10)");
|
||||
// NodeList
|
||||
yield testNotSorted("document.querySelectorAll('div')");
|
||||
// Object
|
||||
yield testSorted("Object({'hello':1,1:5,10:2,4:2,'abc':1})");
|
||||
|
||||
// Typed arrays.
|
||||
for (let type of typedArrayTypes) {
|
||||
|
@ -96,6 +98,35 @@ function test() {
|
|||
// If the properties are sorted, the next one will be 10.
|
||||
is(keyIterator.next().value, "2", "Third key is 2, not 10");
|
||||
}
|
||||
/**
|
||||
* A helper that ensures the properties are sorted when an object
|
||||
* specified by aObject is inspected.
|
||||
*
|
||||
* @param string aObject
|
||||
* A string that, once executed, creates and returns the object to
|
||||
* inspect.
|
||||
*/
|
||||
function testSorted(aObject) {
|
||||
info("Testing " + aObject);
|
||||
let deferred = promise.defer();
|
||||
jsterm.once("variablesview-fetched", (_, aVar) => deferred.resolve(aVar));
|
||||
jsterm.execute("inspect(" + aObject + ")");
|
||||
|
||||
let variableScope = yield deferred.promise;
|
||||
ok(variableScope, "Variables view opened");
|
||||
|
||||
// If the properties are sorted: keys = ["1", "4", "10",..., "abc", "hello"] <- correct
|
||||
// If the properties are not sorted: keys = ["1", "10", "4",...] <- incorrect
|
||||
let keyIterator = variableScope._store.keys();
|
||||
is(keyIterator.next().value, "1", "First key should be 1");
|
||||
is(keyIterator.next().value, "4", "Second key should be 4");
|
||||
|
||||
// If the properties are sorted, the next one will be 10.
|
||||
is(keyIterator.next().value, "10", "Third key is 10");
|
||||
// If sorted next properties should be "abc" then "hello"
|
||||
is(keyIterator.next().value, "abc", "Fourth key is abc");
|
||||
is(keyIterator.next().value, "hello", "Fifth key is hello");
|
||||
}
|
||||
|
||||
Task.spawn(runner).then(finishTest);
|
||||
}
|
||||
|
|
|
@ -178,8 +178,7 @@ let ReaderParent = {
|
|||
}
|
||||
|
||||
// Next, try to find a parsed article in the cache.
|
||||
let uri = Services.io.newURI(url, null, null);
|
||||
article = yield ReaderMode.getArticleFromCache(uri);
|
||||
article = yield ReaderMode.getArticleFromCache(url);
|
||||
if (article) {
|
||||
return article;
|
||||
}
|
||||
|
|
|
@ -111,6 +111,8 @@ toolbarbutton.social-provider-menuitem > .toolbarbutton-icon {
|
|||
menu.subviewbutton > .menu-right {
|
||||
-moz-appearance: none;
|
||||
list-style-image: url(chrome://browser/skin/customizableui/menu-arrow.svg#arrow);
|
||||
/* Reset the rect we inherit from the button: */
|
||||
-moz-image-region: auto;
|
||||
}
|
||||
|
||||
menu[disabled="true"].subviewbutton > .menu-right {
|
||||
|
|
|
@ -854,7 +854,7 @@ pref("media.gmp-provider.enabled", true);
|
|||
pref("reader.color_scheme", "auto");
|
||||
|
||||
// Color scheme values available in reader mode UI.
|
||||
pref("reader.color_scheme.values", "[\"light\",\"dark\",\"auto\"]");
|
||||
pref("reader.color_scheme.values", "[\"dark\",\"auto\",\"light\"]");
|
||||
|
||||
// Whether to use a vertical or horizontal toolbar.
|
||||
pref("reader.toolbar.vertical", false);
|
||||
|
|
|
@ -824,6 +824,9 @@
|
|||
<item name="android:windowNoTitle">true</item>
|
||||
<item name="android:windowIsTranslucent">true</item>
|
||||
<item name="android:backgroundDimEnabled">true</item>
|
||||
|
||||
<!-- We display the overlay on top of other Activities so show their status bar. -->
|
||||
<item name="android:statusBarColor">@android:color/transparent</item>
|
||||
</style>
|
||||
|
||||
<style name="TextAppearance.FirstrunLight"/>
|
||||
|
|
|
@ -39,8 +39,7 @@ let TEST_PAGES = [
|
|||
];
|
||||
|
||||
add_task(function* test_article_not_found() {
|
||||
let uri = Services.io.newURI(TEST_PAGES[0].url, null, null);
|
||||
let article = yield ReaderMode.getArticleFromCache(uri);
|
||||
let article = yield ReaderMode.getArticleFromCache(TEST_PAGES[0].url);
|
||||
do_check_eq(article, null);
|
||||
});
|
||||
|
||||
|
@ -55,15 +54,13 @@ add_task(function* test_store_article() {
|
|||
length: TEST_PAGES[0].expected.length
|
||||
});
|
||||
|
||||
let uri = Services.io.newURI(TEST_PAGES[0].url, null, null);
|
||||
let article = yield ReaderMode.getArticleFromCache(uri);
|
||||
let article = yield ReaderMode.getArticleFromCache(TEST_PAGES[0].url);
|
||||
checkArticle(article, TEST_PAGES[0]);
|
||||
});
|
||||
|
||||
add_task(function* test_remove_article() {
|
||||
let uri = Services.io.newURI(TEST_PAGES[0].url, null, null);
|
||||
yield ReaderMode.removeArticleFromCache(uri);
|
||||
let article = yield ReaderMode.getArticleFromCache(uri);
|
||||
yield ReaderMode.removeArticleFromCache(TEST_PAGES[0].url);
|
||||
let article = yield ReaderMode.getArticleFromCache(TEST_PAGES[0].url);
|
||||
do_check_eq(article, null);
|
||||
});
|
||||
|
||||
|
@ -110,8 +107,7 @@ add_task(function* test_migrate_cache() {
|
|||
yield Reader.migrateCache();
|
||||
|
||||
// Check to make sure the article made it into the new cache.
|
||||
let uri = Services.io.newURI(TEST_PAGES[0].url, null, null);
|
||||
let article = yield ReaderMode.getArticleFromCache(uri);
|
||||
let article = yield ReaderMode.getArticleFromCache(TEST_PAGES[0].url);
|
||||
checkArticle(article, TEST_PAGES[0]);
|
||||
});
|
||||
|
||||
|
|
|
@ -28,8 +28,7 @@ let Reader = {
|
|||
break;
|
||||
}
|
||||
case "Reader:Removed": {
|
||||
let uri = Services.io.newURI(aData, null, null);
|
||||
ReaderMode.removeArticleFromCache(uri).catch(e => Cu.reportError("Error removing article from cache: " + e));
|
||||
ReaderMode.removeArticleFromCache(aData).catch(e => Cu.reportError("Error removing article from cache: " + e));
|
||||
|
||||
let mm = window.getGroupMessageManager("browsers");
|
||||
mm.broadcastAsyncMessage("Reader:Removed", { url: aData });
|
||||
|
@ -222,8 +221,8 @@ let Reader = {
|
|||
throw new Error("Can't add tab to reading list because no tab found for ID: " + tabID);
|
||||
}
|
||||
|
||||
let urlWithoutRef = tab.browser.currentURI.specIgnoringRef;
|
||||
let article = yield this._getArticle(urlWithoutRef, tab.browser).catch(e => {
|
||||
let url = tab.browser.currentURI.spec;
|
||||
let article = yield this._getArticle(url, tab.browser).catch(e => {
|
||||
Cu.reportError("Error getting article for tab: " + e);
|
||||
return null;
|
||||
});
|
||||
|
@ -231,7 +230,7 @@ let Reader = {
|
|||
// If there was a problem getting the article, just store the
|
||||
// URL and title from the tab.
|
||||
article = {
|
||||
url: urlWithoutRef,
|
||||
url: url,
|
||||
title: tab.browser.contentDocument.title,
|
||||
length: 0,
|
||||
excerpt: "",
|
||||
|
@ -276,8 +275,7 @@ let Reader = {
|
|||
}
|
||||
|
||||
// Next, try to find a parsed article in the cache.
|
||||
let uri = Services.io.newURI(url, null, null);
|
||||
article = yield ReaderMode.getArticleFromCache(uri);
|
||||
article = yield ReaderMode.getArticleFromCache(url);
|
||||
if (article) {
|
||||
return article;
|
||||
}
|
||||
|
|
|
@ -73,8 +73,8 @@ let AboutReaderListener = {
|
|||
|
||||
// The loaded page may have changed while we were parsing the document.
|
||||
// Make sure we've got the current one.
|
||||
let currentURL = Services.io.newURI(content.document.documentURI, null, null).specIgnoringRef;
|
||||
if (article.url !== currentURL) {
|
||||
let url = Services.io.newURI(content.document.documentURI, null, null).spec;
|
||||
if (article.url !== url) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -102,22 +102,9 @@ public class SearchWidget extends AppWidgetProvider {
|
|||
|
||||
// Utility to create the view for this widget and attach any event listeners to it
|
||||
private void addView(final AppWidgetManager manager, final Context context, final int id, final Bundle options) {
|
||||
final boolean isKeyguard;
|
||||
if (options != null) {
|
||||
final int category = options.getInt(AppWidgetManager.OPTION_APPWIDGET_HOST_CATEGORY, -1);
|
||||
isKeyguard = category == AppWidgetProviderInfo.WIDGET_CATEGORY_KEYGUARD;
|
||||
} else {
|
||||
isKeyguard = false;
|
||||
}
|
||||
|
||||
final RemoteViews views;
|
||||
if (isKeyguard) {
|
||||
views = new RemoteViews(context.getPackageName(), R.layout.keyguard_widget);
|
||||
} else {
|
||||
views = new RemoteViews(context.getPackageName(), R.layout.search_widget);
|
||||
addClickIntent(context, views, R.id.search_button, ACTION_LAUNCH_SEARCH);
|
||||
}
|
||||
final RemoteViews views = new RemoteViews(context.getPackageName(), R.layout.search_widget);
|
||||
|
||||
addClickIntent(context, views, R.id.search_button, ACTION_LAUNCH_SEARCH);
|
||||
addClickIntent(context, views, R.id.new_tab_button, ACTION_LAUNCH_NEW_TAB);
|
||||
// Clicking the logo also launches the browser
|
||||
addClickIntent(context, views, R.id.logo_button, ACTION_LAUNCH_BROWSER);
|
||||
|
|
|
@ -21,7 +21,7 @@ body {
|
|||
}
|
||||
|
||||
.dark {
|
||||
background-color: #000000;
|
||||
background-color: #222222;
|
||||
color: #eeeeee;
|
||||
}
|
||||
|
||||
|
@ -284,6 +284,8 @@ body {
|
|||
list-style: decimal !important;
|
||||
}
|
||||
|
||||
/*======= Controls toolbar =======*/
|
||||
|
||||
.toolbar {
|
||||
font-family: "Clear Sans",sans-serif;
|
||||
transition-property: visibility, opacity;
|
||||
|
@ -298,7 +300,7 @@ body {
|
|||
padding: 0;
|
||||
list-style: none;
|
||||
background-color: #EBEBF0;
|
||||
-moz-user-select: none;
|
||||
border-top: 1px solid #D7D9DB;
|
||||
}
|
||||
|
||||
.toolbar-hidden {
|
||||
|
@ -314,23 +316,27 @@ body {
|
|||
}
|
||||
|
||||
.button {
|
||||
color: white;
|
||||
display: block;
|
||||
background-position: center;
|
||||
background-size: 30px 24px;
|
||||
background-size: 30px 28px;
|
||||
background-repeat: no-repeat;
|
||||
background-color: transparent;
|
||||
border: 0;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.button:active {
|
||||
background-color: #D7D7DC;
|
||||
}
|
||||
|
||||
/* Remove dotted border when button is focused */
|
||||
.button::-moz-focus-inner,
|
||||
#font-size-buttons > button::-moz-focus-inner {
|
||||
.dropdown-popup > div > button::-moz-focus-inner {
|
||||
border: 0;
|
||||
}
|
||||
|
||||
.dropdown {
|
||||
left: 0;
|
||||
text-align: center;
|
||||
display: inline-block;
|
||||
list-style: none;
|
||||
|
@ -348,135 +354,77 @@ body {
|
|||
padding: 0px;
|
||||
}
|
||||
|
||||
/*======= Font style popup =======*/
|
||||
|
||||
.dropdown-popup {
|
||||
text-align: start;
|
||||
position: absolute;
|
||||
left: 0px;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
z-index: 1000;
|
||||
float: left;
|
||||
background: #EBEBF0;
|
||||
margin-top: 12px;
|
||||
margin-bottom: 10px;
|
||||
padding-top: 4px;
|
||||
padding-bottom: 8px;
|
||||
font-size: 14px;
|
||||
box-shadow: 0px -1px 12px #333;
|
||||
border-radius: 3px;
|
||||
visibility: hidden;
|
||||
border-top: 1px solid #D7D9DB;
|
||||
}
|
||||
|
||||
.dropdown-popup > hr {
|
||||
width: 100%;
|
||||
height: 0px;
|
||||
border: 0px;
|
||||
border-top: 1px solid #B5B5B5;
|
||||
margin: 0;
|
||||
/* Only used on desktop */
|
||||
.dropdown-popup > hr,
|
||||
.dropdown-arrow,
|
||||
#font-type-buttons > button > span {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.open > .dropdown-popup {
|
||||
margin-top: 0px;
|
||||
margin-bottom: 6px;
|
||||
bottom: 100%;
|
||||
visibility: visible;
|
||||
}
|
||||
|
||||
.dropdown-arrow {
|
||||
position: absolute;
|
||||
width: 40px;
|
||||
height: 18px;
|
||||
bottom: -18px;
|
||||
background-image: url('chrome://browser/skin/images/reader-dropdown-arrow-mdpi.png');
|
||||
background-size: 40px 18px;
|
||||
background-position: center;
|
||||
display: block;
|
||||
bottom: 100%;
|
||||
}
|
||||
|
||||
#font-type-buttons,
|
||||
#font-size-buttons,
|
||||
.segmented-button {
|
||||
#color-scheme-buttons {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
list-style: none;
|
||||
padding: 10px 5px;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
#font-type-buttons > li,
|
||||
#font-size-buttons > button,
|
||||
.segmented-button > li {
|
||||
flex: 1 0 auto;
|
||||
#font-type-buttons > button,
|
||||
#color-scheme-buttons > button {
|
||||
text-align: center;
|
||||
line-height: 20px;
|
||||
}
|
||||
|
||||
#font-type-buttons > li,
|
||||
#font-type-buttons > button,
|
||||
#font-size-buttons > button {
|
||||
width: 100px; /* combined with flex, this acts as a minimum width */
|
||||
width: 50%;
|
||||
background-color: transparent;
|
||||
border: 0;
|
||||
}
|
||||
|
||||
.segmented-button > li {
|
||||
width: 50px; /* combined with flex, this acts as a minimum width */
|
||||
#font-type-buttons > button {
|
||||
font-size: 24px;
|
||||
color: #AFB1B3;
|
||||
padding: 15px 0;
|
||||
}
|
||||
|
||||
#font-type-buttons > li {
|
||||
padding: 10px 0;
|
||||
#font-type-buttons > button:active,
|
||||
#font-type-buttons > button.selected {
|
||||
color: #222222;
|
||||
}
|
||||
|
||||
.segmented-button > li {
|
||||
border-left: 1px solid #B5B5B5;
|
||||
#font-size-sample {
|
||||
flex: 0;
|
||||
font-size: 24px;
|
||||
color: #000000;
|
||||
margin-left: -20px;
|
||||
margin-right: -20px;
|
||||
}
|
||||
|
||||
#font-size-buttons > button:first-child,
|
||||
.segmented-button > li:first-child {
|
||||
border-left: 0px;
|
||||
}
|
||||
|
||||
#font-type-buttons > li > a,
|
||||
.segmented-button > li > a {
|
||||
vertical-align: middle;
|
||||
text-decoration: none;
|
||||
color: black;
|
||||
}
|
||||
|
||||
#font-type-buttons > li > a {
|
||||
display: inline-block;
|
||||
font-size: 48px;
|
||||
line-height: 50px;
|
||||
margin-bottom: 5px;
|
||||
border-bottom: 3px solid transparent;
|
||||
}
|
||||
|
||||
.segmented-button > li > a {
|
||||
display: block;
|
||||
padding: 5px 0;
|
||||
font-family: "Clear Sans",sans-serif;
|
||||
font-weight: lighter;
|
||||
}
|
||||
|
||||
#font-type-buttons > li > a:active,
|
||||
#font-type-buttons > li.selected > a {
|
||||
border-color: #ff9400;
|
||||
}
|
||||
|
||||
.segmented-button > li > a:active,
|
||||
.segmented-button > li.selected > a {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
#font-type-buttons > li > .sans-serif {
|
||||
font-weight: lighter;
|
||||
}
|
||||
|
||||
#font-type-buttons > li > div {
|
||||
color: #666;
|
||||
font-size: 12px;
|
||||
.serif-button {
|
||||
font-family: serif;
|
||||
}
|
||||
|
||||
.minus-button,
|
||||
.plus-button {
|
||||
background-color: transparent;
|
||||
border: 0;
|
||||
height: 30px;
|
||||
height: 60px;
|
||||
background-size: 18px 18px;
|
||||
background-repeat: no-repeat;
|
||||
background-position: center;
|
||||
|
@ -490,7 +438,38 @@ body {
|
|||
background-size: 24px 24px;
|
||||
}
|
||||
|
||||
/* desktop-only controls */
|
||||
#color-scheme-buttons > button {
|
||||
width: 33%;
|
||||
border-radius: 4px;
|
||||
border: 1px solid #BFBFBF;
|
||||
padding: 10px;
|
||||
margin: 15px 10px;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
#color-scheme-buttons > button:active,
|
||||
#color-scheme-buttons > button.selected {
|
||||
border: 2px solid #FF9500;
|
||||
}
|
||||
|
||||
.dark-button {
|
||||
color: #eeeeee;
|
||||
background-color: #333333;
|
||||
}
|
||||
|
||||
.auto-button {
|
||||
color: #000000;
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
.light-button {
|
||||
color: #333333;
|
||||
background-color: #ffffff;
|
||||
}
|
||||
|
||||
/*======= Toolbar icons =======*/
|
||||
|
||||
/* desktop-only controls */
|
||||
.close-button,
|
||||
.list-button {
|
||||
display: none;
|
||||
|
@ -512,6 +491,10 @@ body {
|
|||
background-image: url('chrome://browser/skin/images/reader-style-icon-mdpi.png');
|
||||
}
|
||||
|
||||
.open .style-button {
|
||||
background-image: url('chrome://browser/skin/images/reader-style-icon-active-mdpi.png');
|
||||
}
|
||||
|
||||
.minus-button {
|
||||
background-image: url('chrome://browser/skin/images/reader-minus-mdpi.png');
|
||||
}
|
||||
|
@ -521,10 +504,6 @@ body {
|
|||
}
|
||||
|
||||
@media screen and (min-resolution: 1.25dppx) {
|
||||
.dropdown-arrow {
|
||||
background-image: url('chrome://browser/skin/images/reader-dropdown-arrow-hdpi.png');
|
||||
}
|
||||
|
||||
.toggle-button.on {
|
||||
background-image: url('chrome://browser/skin/images/reader-toggle-on-icon-hdpi.png');
|
||||
}
|
||||
|
@ -541,6 +520,10 @@ body {
|
|||
background-image: url('chrome://browser/skin/images/reader-style-icon-hdpi.png');
|
||||
}
|
||||
|
||||
.open .style-button {
|
||||
background-image: url('chrome://browser/skin/images/reader-style-icon-active-hdpi.png');
|
||||
}
|
||||
|
||||
.minus-button {
|
||||
background-image: url('chrome://browser/skin/images/reader-minus-hdpi.png');
|
||||
}
|
||||
|
@ -551,10 +534,6 @@ body {
|
|||
}
|
||||
|
||||
@media screen and (min-resolution: 2dppx) {
|
||||
.dropdown-arrow {
|
||||
background-image: url('chrome://browser/skin/images/reader-dropdown-arrow-xhdpi.png');
|
||||
}
|
||||
|
||||
.toggle-button.on {
|
||||
background-image: url('chrome://browser/skin/images/reader-toggle-on-icon-xhdpi.png');
|
||||
}
|
||||
|
@ -571,6 +550,10 @@ body {
|
|||
background-image: url('chrome://browser/skin/images/reader-style-icon-xhdpi.png');
|
||||
}
|
||||
|
||||
.open .style-button {
|
||||
background-image: url('chrome://browser/skin/images/reader-style-icon-active-xhdpi.png');
|
||||
}
|
||||
|
||||
.minus-button {
|
||||
background-image: url('chrome://browser/skin/images/reader-minus-xhdpi.png');
|
||||
}
|
||||
|
@ -580,9 +563,39 @@ body {
|
|||
}
|
||||
}
|
||||
|
||||
@media screen and (min-resolution: 3dppx) {
|
||||
.toggle-button.on {
|
||||
background-image: url('chrome://browser/skin/images/reader-toggle-on-icon-xxhdpi.png');
|
||||
}
|
||||
|
||||
.toggle-button {
|
||||
background-image: url('chrome://browser/skin/images/reader-toggle-off-icon-xxhdpi.png');
|
||||
}
|
||||
|
||||
.share-button {
|
||||
background-image: url('chrome://browser/skin/images/reader-share-icon-xhdpi.png');
|
||||
}
|
||||
|
||||
.style-button {
|
||||
background-image: url('chrome://browser/skin/images/reader-style-icon-xxhdpi.png');
|
||||
}
|
||||
|
||||
.open .style-button {
|
||||
background-image: url('chrome://browser/skin/images/reader-style-icon-active-xxhdpi.png');
|
||||
}
|
||||
|
||||
.minus-button {
|
||||
background-image: url('chrome://browser/skin/images/reader-minus-xxhdpi.png');
|
||||
}
|
||||
|
||||
.plus-button {
|
||||
background-image: url('chrome://browser/skin/images/reader-plus-xxhdpi.png');
|
||||
}
|
||||
}
|
||||
|
||||
@media screen and (orientation: portrait) {
|
||||
.button {
|
||||
height: 48px;
|
||||
height: 56px;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -601,4 +614,17 @@ body {
|
|||
.toolbar > * {
|
||||
width: 56px;
|
||||
}
|
||||
|
||||
.dropdown-popup {
|
||||
position: absolute;
|
||||
width: 350px;
|
||||
left: auto;
|
||||
right: 15px;
|
||||
bottom: -12px;
|
||||
z-index: 1000;
|
||||
background: #EBEBF0;
|
||||
border: 1px solid #D7D9DB;
|
||||
border-radius: 4px;
|
||||
box-shadow: 0px 2px 4px 2px #BFBFBF;
|
||||
}
|
||||
}
|
||||
|
|
Двоичные данные
mobile/android/themes/core/images/reader-dropdown-arrow-hdpi.png
До Ширина: | Высота: | Размер: 1.0 KiB |
Двоичные данные
mobile/android/themes/core/images/reader-dropdown-arrow-mdpi.png
До Ширина: | Высота: | Размер: 661 B |
До Ширина: | Высота: | Размер: 1.4 KiB |
После Ширина: | Высота: | Размер: 214 B |
После Ширина: | Высота: | Размер: 486 B |
Двоичные данные
mobile/android/themes/core/images/reader-share-icon-hdpi.png
До Ширина: | Высота: | Размер: 577 B После Ширина: | Высота: | Размер: 542 B |
Двоичные данные
mobile/android/themes/core/images/reader-share-icon-mdpi.png
До Ширина: | Высота: | Размер: 391 B После Ширина: | Высота: | Размер: 401 B |
Двоичные данные
mobile/android/themes/core/images/reader-share-icon-xhdpi.png
До Ширина: | Высота: | Размер: 716 B После Ширина: | Высота: | Размер: 808 B |
После Ширина: | Высота: | Размер: 1011 B |
После Ширина: | Высота: | Размер: 665 B |
После Ширина: | Высота: | Размер: 501 B |
После Ширина: | Высота: | Размер: 858 B |
После Ширина: | Высота: | Размер: 1.2 KiB |
Двоичные данные
mobile/android/themes/core/images/reader-style-icon-hdpi.png
До Ширина: | Высота: | Размер: 484 B После Ширина: | Высота: | Размер: 877 B |
Двоичные данные
mobile/android/themes/core/images/reader-style-icon-mdpi.png
До Ширина: | Высота: | Размер: 352 B После Ширина: | Высота: | Размер: 660 B |
Двоичные данные
mobile/android/themes/core/images/reader-style-icon-xhdpi.png
До Ширина: | Высота: | Размер: 557 B После Ширина: | Высота: | Размер: 1.1 KiB |
После Ширина: | Высота: | Размер: 1.5 KiB |
До Ширина: | Высота: | Размер: 429 B После Ширина: | Высота: | Размер: 700 B |
До Ширина: | Высота: | Размер: 309 B После Ширина: | Высота: | Размер: 496 B |
До Ширина: | Высота: | Размер: 566 B После Ширина: | Высота: | Размер: 808 B |
После Ширина: | Высота: | Размер: 1.1 KiB |
Двоичные данные
mobile/android/themes/core/images/reader-toggle-on-icon-hdpi.png
До Ширина: | Высота: | Размер: 473 B После Ширина: | Высота: | Размер: 316 B |
Двоичные данные
mobile/android/themes/core/images/reader-toggle-on-icon-mdpi.png
До Ширина: | Высота: | Размер: 329 B После Ширина: | Высота: | Размер: 206 B |
До Ширина: | Высота: | Размер: 587 B После Ширина: | Высота: | Размер: 323 B |
После Ширина: | Высота: | Размер: 478 B |
|
@ -86,27 +86,34 @@ chrome.jar:
|
|||
skin/images/logo-hdpi.png (images/logo-hdpi.png)
|
||||
skin/images/wordmark-hdpi.png (images/wordmark-hdpi.png)
|
||||
skin/images/config-plus.png (images/config-plus.png)
|
||||
skin/images/reader-dropdown-arrow-mdpi.png (images/reader-dropdown-arrow-mdpi.png)
|
||||
skin/images/reader-dropdown-arrow-hdpi.png (images/reader-dropdown-arrow-hdpi.png)
|
||||
skin/images/reader-dropdown-arrow-xhdpi.png (images/reader-dropdown-arrow-xhdpi.png)
|
||||
skin/images/reader-minus-mdpi.png (images/reader-minus-mdpi.png)
|
||||
skin/images/reader-minus-hdpi.png (images/reader-minus-hdpi.png)
|
||||
skin/images/reader-minus-xhdpi.png (images/reader-minus-xhdpi.png)
|
||||
skin/images/reader-minus-xxhdpi.png (images/reader-minus-xxhdpi.png)
|
||||
skin/images/reader-plus-mdpi.png (images/reader-plus-mdpi.png)
|
||||
skin/images/reader-plus-hdpi.png (images/reader-plus-hdpi.png)
|
||||
skin/images/reader-plus-xhdpi.png (images/reader-plus-xhdpi.png)
|
||||
skin/images/reader-plus-xxhdpi.png (images/reader-plus-xxhdpi.png)
|
||||
skin/images/reader-toggle-on-icon-mdpi.png (images/reader-toggle-on-icon-mdpi.png)
|
||||
skin/images/reader-toggle-on-icon-hdpi.png (images/reader-toggle-on-icon-hdpi.png)
|
||||
skin/images/reader-toggle-on-icon-xhdpi.png (images/reader-toggle-on-icon-xhdpi.png)
|
||||
skin/images/reader-toggle-on-icon-xxhdpi.png (images/reader-toggle-on-icon-xxhdpi.png)
|
||||
skin/images/reader-toggle-off-icon-mdpi.png (images/reader-toggle-off-icon-mdpi.png)
|
||||
skin/images/reader-toggle-off-icon-hdpi.png (images/reader-toggle-off-icon-hdpi.png)
|
||||
skin/images/reader-toggle-off-icon-xhdpi.png (images/reader-toggle-off-icon-xhdpi.png)
|
||||
skin/images/reader-toggle-off-icon-xxhdpi.png (images/reader-toggle-off-icon-xxhdpi.png)
|
||||
skin/images/reader-share-icon-mdpi.png (images/reader-share-icon-mdpi.png)
|
||||
skin/images/reader-share-icon-hdpi.png (images/reader-share-icon-hdpi.png)
|
||||
skin/images/reader-share-icon-xhdpi.png (images/reader-share-icon-xhdpi.png)
|
||||
skin/images/reader-share-icon-xxhdpi.png (images/reader-share-icon-xxhdpi.png)
|
||||
skin/images/reader-style-icon-active-mdpi.png (images/reader-style-icon-active-mdpi.png)
|
||||
skin/images/reader-style-icon-active-hdpi.png (images/reader-style-icon-active-hdpi.png)
|
||||
skin/images/reader-style-icon-active-xhdpi.png (images/reader-style-icon-active-xhdpi.png)
|
||||
skin/images/reader-style-icon-active-xxhdpi.png (images/reader-style-icon-active-xxhdpi.png)
|
||||
skin/images/reader-style-icon-mdpi.png (images/reader-style-icon-mdpi.png)
|
||||
skin/images/reader-style-icon-hdpi.png (images/reader-style-icon-hdpi.png)
|
||||
skin/images/reader-style-icon-xhdpi.png (images/reader-style-icon-xhdpi.png)
|
||||
skin/images/reader-style-icon-xxhdpi.png (images/reader-style-icon-xxhdpi.png)
|
||||
skin/images/privatebrowsing-mask.png (images/privatebrowsing-mask.png)
|
||||
skin/images/update.png (images/update.png)
|
||||
skin/images/icon_floaty_hdpi.png (images/icon_floaty_hdpi.png)
|
||||
|
|
|
@ -49,9 +49,7 @@ let AboutReader = function(mm, win) {
|
|||
|
||||
this._scrollOffset = win.pageYOffset;
|
||||
|
||||
let body = doc.body;
|
||||
body.addEventListener("touchstart", this, false);
|
||||
body.addEventListener("click", this, false);
|
||||
doc.getElementById("container").addEventListener("click", this, false);
|
||||
|
||||
win.addEventListener("unload", this, false);
|
||||
win.addEventListener("scroll", this, false);
|
||||
|
@ -88,12 +86,12 @@ let AboutReader = function(mm, win) {
|
|||
{ name: fontTypeSample,
|
||||
description: gStrings.GetStringFromName("aboutReader.fontType.sans-serif"),
|
||||
value: "sans-serif",
|
||||
linkClass: "sans-serif"
|
||||
itemClass: "sans-serif-button"
|
||||
},
|
||||
{ name: fontTypeSample,
|
||||
description: gStrings.GetStringFromName("aboutReader.fontType.serif"),
|
||||
value: "serif",
|
||||
linkClass: "serif" },
|
||||
itemClass: "serif-button" },
|
||||
];
|
||||
|
||||
let fontType = Services.prefs.getCharPref("reader.font_type");
|
||||
|
@ -205,7 +203,6 @@ AboutReader.prototype = {
|
|||
|
||||
switch (aEvent.type) {
|
||||
case "click":
|
||||
// XXX: Don't toggle the toolbar on double click. (See the "Gesture:DoubleTap" handler in Reader.js)
|
||||
this._toggleToolbarVisibility();
|
||||
break;
|
||||
case "scroll":
|
||||
|
@ -352,6 +349,10 @@ AboutReader.prototype = {
|
|||
const FONT_SIZE_MIN = 1;
|
||||
const FONT_SIZE_MAX = 9;
|
||||
|
||||
// Sample text shown in Android UI.
|
||||
let sampleText = this._doc.getElementById("font-size-sample");
|
||||
sampleText.textContent = gStrings.GetStringFromName("aboutReader.fontTypeSample");
|
||||
|
||||
let currentSize = Services.prefs.getIntPref("reader.font_size");
|
||||
currentSize = Math.max(FONT_SIZE_MIN, Math.min(FONT_SIZE_MAX, currentSize));
|
||||
|
||||
|
@ -756,24 +757,22 @@ AboutReader.prototype = {
|
|||
for (let i = 0; i < options.length; i++) {
|
||||
let option = options[i];
|
||||
|
||||
let item = doc.createElement("li");
|
||||
let link = doc.createElement("a");
|
||||
link.textContent = option.name;
|
||||
item.appendChild(link);
|
||||
let item = doc.createElement("button");
|
||||
|
||||
// We make this extra span so that we can hide it if necessary.
|
||||
let span = doc.createElement("span");
|
||||
span.textContent = option.name;
|
||||
item.appendChild(span);
|
||||
|
||||
if (option.itemClass !== undefined)
|
||||
item.classList.add(option.itemClass);
|
||||
|
||||
if (option.linkClass !== undefined)
|
||||
link.classList.add(option.linkClass);
|
||||
|
||||
if (option.description !== undefined) {
|
||||
let description = doc.createElement("div");
|
||||
description.textContent = option.description;
|
||||
item.appendChild(description);
|
||||
}
|
||||
|
||||
link.style.MozUserSelect = 'none';
|
||||
segmentedButton.appendChild(item);
|
||||
|
||||
item.addEventListener("click", function(aEvent) {
|
||||
|
@ -831,37 +830,25 @@ AboutReader.prototype = {
|
|||
let dropdown = doc.getElementById("style-dropdown");
|
||||
let dropdownToggle = dropdown.querySelector(".dropdown-toggle");
|
||||
let dropdownPopup = dropdown.querySelector(".dropdown-popup");
|
||||
let dropdownArrow = dropdown.querySelector(".dropdown-arrow");
|
||||
|
||||
let updatePopupPosition = () => {
|
||||
if (this._isToolbarVertical) {
|
||||
let toggleHeight = dropdownToggle.offsetHeight;
|
||||
let toggleTop = dropdownToggle.offsetTop;
|
||||
let popupTop = toggleTop - toggleHeight / 2;
|
||||
dropdownPopup.style.top = popupTop + "px";
|
||||
} else {
|
||||
let popupWidth = dropdownPopup.offsetWidth + 30;
|
||||
let arrowWidth = dropdownArrow.offsetWidth;
|
||||
let toggleWidth = dropdownToggle.offsetWidth;
|
||||
let toggleLeft = dropdownToggle.offsetLeft;
|
||||
// Helper function used to position the popup on desktop,
|
||||
// where there is a vertical toolbar.
|
||||
function updatePopupPosition() {
|
||||
let toggleHeight = dropdownToggle.offsetHeight;
|
||||
let toggleTop = dropdownToggle.offsetTop;
|
||||
let popupTop = toggleTop - toggleHeight / 2;
|
||||
dropdownPopup.style.top = popupTop + "px";
|
||||
}
|
||||
|
||||
let popupShift = (toggleWidth - popupWidth) / 2;
|
||||
let popupLeft = Math.max(0, Math.min(win.innerWidth - popupWidth, toggleLeft + popupShift));
|
||||
dropdownPopup.style.left = popupLeft + "px";
|
||||
if (this._isToolbarVertical) {
|
||||
win.addEventListener("resize", event => {
|
||||
if (!event.isTrusted)
|
||||
return;
|
||||
|
||||
let arrowShift = (toggleWidth - arrowWidth) / 2;
|
||||
let arrowLeft = toggleLeft - popupLeft + arrowShift;
|
||||
dropdownArrow.style.left = arrowLeft + "px";
|
||||
}
|
||||
};
|
||||
|
||||
win.addEventListener("resize", event => {
|
||||
if (!event.isTrusted)
|
||||
return;
|
||||
|
||||
// Wait for reflow before calculating the new position of the popup.
|
||||
win.setTimeout(updatePopupPosition, 0);
|
||||
}, true);
|
||||
// Wait for reflow before calculating the new position of the popup.
|
||||
win.setTimeout(updatePopupPosition, 0);
|
||||
}, true);
|
||||
}
|
||||
|
||||
dropdownToggle.setAttribute("title", gStrings.GetStringFromName("aboutReader.toolbar.typeControls"));
|
||||
dropdownToggle.addEventListener("click", event => {
|
||||
|
@ -874,7 +861,9 @@ AboutReader.prototype = {
|
|||
dropdown.classList.remove("open");
|
||||
} else {
|
||||
dropdown.classList.add("open");
|
||||
updatePopupPosition();
|
||||
if (this._isToolbarVertical) {
|
||||
updatePopupPosition();
|
||||
}
|
||||
}
|
||||
}, true);
|
||||
},
|
||||
|
|
|
@ -128,13 +128,13 @@ this.ReaderMode = {
|
|||
/**
|
||||
* Retrieves an article from the cache given an article URI.
|
||||
*
|
||||
* @param uri The article URI.
|
||||
* @param url The article URL.
|
||||
* @return {Promise}
|
||||
* @resolves JS object representing the article, or null if no article is found.
|
||||
* @rejects OS.File.Error
|
||||
*/
|
||||
getArticleFromCache: Task.async(function* (uri) {
|
||||
let path = this._toHashedPath(uri.specIgnoringRef);
|
||||
getArticleFromCache: Task.async(function* (url) {
|
||||
let path = this._toHashedPath(url);
|
||||
try {
|
||||
let array = yield OS.File.read(path);
|
||||
return JSON.parse(new TextDecoder().decode(array));
|
||||
|
@ -161,13 +161,13 @@ this.ReaderMode = {
|
|||
/**
|
||||
* Removes an article from the cache given an article URI.
|
||||
*
|
||||
* @param uri The article URI.
|
||||
* @param url The article URL.
|
||||
* @return {Promise}
|
||||
* @resolves When the article is removed.
|
||||
* @rejects OS.File.Error
|
||||
*/
|
||||
removeArticleFromCache: Task.async(function* (uri) {
|
||||
let path = this._toHashedPath(uri.specIgnoringRef);
|
||||
removeArticleFromCache: Task.async(function* (url) {
|
||||
let path = this._toHashedPath(url);
|
||||
yield OS.File.remove(path);
|
||||
}),
|
||||
|
||||
|
@ -218,9 +218,10 @@ this.ReaderMode = {
|
|||
return;
|
||||
}
|
||||
|
||||
// Append URL to the article data. specIgnoringRef will ignore any hash
|
||||
// in the URL.
|
||||
article.url = uri.specIgnoringRef;
|
||||
// Readability returns a URI object, but we only care about the URL.
|
||||
article.url = article.uri.spec;
|
||||
delete article.uri;
|
||||
|
||||
let flags = Ci.nsIDocumentEncoder.OutputSelectionOnly | Ci.nsIDocumentEncoder.OutputAbsoluteLinks;
|
||||
article.title = Cc["@mozilla.org/parserutils;1"].getService(Ci.nsIParserUtils)
|
||||
.convertToPlainText(article.title, flags, 0);
|
||||
|
|
|
@ -11,17 +11,19 @@
|
|||
</head>
|
||||
|
||||
<body>
|
||||
<div id="reader-header" class="header">
|
||||
<a id="reader-domain" class="domain"></a>
|
||||
<div class="domain-border"></div>
|
||||
<h1 id="reader-title"></h1>
|
||||
<div id="reader-credits" class="credits"></div>
|
||||
</div>
|
||||
<div id="container">
|
||||
<div id="reader-header" class="header">
|
||||
<a id="reader-domain" class="domain"></a>
|
||||
<div class="domain-border"></div>
|
||||
<h1 id="reader-title"></h1>
|
||||
<div id="reader-credits" class="credits"></div>
|
||||
</div>
|
||||
|
||||
<div id="reader-content" class="content">
|
||||
</div>
|
||||
<div id="reader-content" class="content">
|
||||
</div>
|
||||
|
||||
<div id="reader-message" class="message">
|
||||
<div id="reader-message" class="message">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<ul id="reader-toolbar" class="toolbar toolbar-hidden">
|
||||
|
@ -30,14 +32,15 @@
|
|||
<ul id="style-dropdown" class="dropdown">
|
||||
<li><button class="dropdown-toggle button style-button"/></li>
|
||||
<li class="dropdown-popup">
|
||||
<ul id="font-type-buttons"></ul>
|
||||
<div id="font-type-buttons"></div>
|
||||
<hr></hr>
|
||||
<div id="font-size-buttons">
|
||||
<button id="font-size-minus" class="minus-button"/>
|
||||
<button id="font-size-sample"/>
|
||||
<button id="font-size-plus" class="plus-button"/>
|
||||
</div>
|
||||
<hr></hr>
|
||||
<ul id="color-scheme-buttons" class="segmented-button"></ul>
|
||||
<div id="color-scheme-buttons"></div>
|
||||
<div class="dropdown-arrow"/>
|
||||
</li>
|
||||
</ul>
|
||||
|
|
|
@ -4723,13 +4723,27 @@ BreakpointActor.prototype = {
|
|||
*
|
||||
* @param aFrame Debugger.Frame
|
||||
* The frame to evaluate the condition in
|
||||
* @returns Boolean
|
||||
* Indicates whether to pause or not, returns undefined when
|
||||
* evaluation was killed
|
||||
*/
|
||||
isValidCondition: function(aFrame) {
|
||||
if (!this.condition) {
|
||||
return true;
|
||||
checkCondition: function(aFrame) {
|
||||
let completion = aFrame.eval(this.condition);
|
||||
if (completion) {
|
||||
if (completion.throw) {
|
||||
// The evaluation failed and threw an error, currently
|
||||
// we will only return true to break on the error
|
||||
return true;
|
||||
} else if (completion.yield) {
|
||||
dbg_assert(false,
|
||||
"Shouldn't ever get yield completions from an eval");
|
||||
} else {
|
||||
return completion.return ? true : false;
|
||||
}
|
||||
} else {
|
||||
// The evaluation was killed (possibly by the slow script dialog)
|
||||
return undefined;
|
||||
}
|
||||
var res = aFrame.eval(this.condition);
|
||||
return res.return;
|
||||
},
|
||||
|
||||
/**
|
||||
|
@ -4747,18 +4761,20 @@ BreakpointActor.prototype = {
|
|||
let url = originalSourceActor.url;
|
||||
|
||||
if (this.threadActor.sources.isBlackBoxed(url)
|
||||
|| aFrame.onStep
|
||||
|| !this.isValidCondition(aFrame)) {
|
||||
|| aFrame.onStep) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
let reason = {};
|
||||
|
||||
if (this.threadActor._hiddenBreakpoints.has(this.actorID)) {
|
||||
reason.type = "pauseOnDOMEvents";
|
||||
} else {
|
||||
} else if (!this.condition || this.checkCondition(aFrame)) {
|
||||
reason.type = "breakpoint";
|
||||
// TODO: add the rest of the breakpoints on that line (bug 676602).
|
||||
reason.actors = [ this.actorID ];
|
||||
} else {
|
||||
return undefined;
|
||||
}
|
||||
return this.threadActor._pauseAndRespond(aFrame, reason);
|
||||
},
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
/**
|
||||
* Check conditional breakpoint when condition throws and make sure it is ignored
|
||||
* Check conditional breakpoint when condition throws and make sure it pauses
|
||||
*/
|
||||
|
||||
var gDebuggee;
|
||||
|
@ -33,8 +33,8 @@ function test_simple_breakpoint()
|
|||
}, function (aResponse, bpClient) {
|
||||
gThreadClient.addOneTimeListener("paused", function (aEvent, aPacket) {
|
||||
// Check the return value.
|
||||
do_check_eq(aPacket.why.type, "debuggerStatement");
|
||||
do_check_eq(aPacket.frame.where.line, 4);
|
||||
do_check_eq(aPacket.why.type, "breakpoint");
|
||||
do_check_eq(aPacket.frame.where.line, 3);
|
||||
|
||||
// Remove the breakpoint.
|
||||
bpClient.remove(function (aResponse) {
|
||||
|
@ -53,8 +53,7 @@ function test_simple_breakpoint()
|
|||
|
||||
Components.utils.evalInSandbox("debugger;\n" + // 1
|
||||
"var a = 1;\n" + // 2
|
||||
"var b = 2;\n" + // 3
|
||||
"debugger;", // 4
|
||||
"var b = 2;\n", // 3
|
||||
gDebuggee,
|
||||
"1.8",
|
||||
"test.js",
|
||||
|
|
|
@ -228,7 +228,7 @@ body {
|
|||
list-style: decimal;
|
||||
}
|
||||
|
||||
/* Toolbar */
|
||||
/*======= Controls toolbar =======*/
|
||||
|
||||
.toolbar {
|
||||
font-family: sans-serif;
|
||||
|
@ -275,18 +275,19 @@ body {
|
|||
padding: 0px;
|
||||
}
|
||||
|
||||
/*======= Font style popup =======*/
|
||||
|
||||
.dropdown-popup {
|
||||
min-width: 250px;
|
||||
text-align: start;
|
||||
position: absolute;
|
||||
left: 48px; /* offset to account for toolbar width */
|
||||
z-index: 1000;
|
||||
background-color: #FBFBFB;
|
||||
font-size: 14px;
|
||||
visibility: hidden;
|
||||
border-radius: 4px;
|
||||
border: 1px solid #B5B5B5;
|
||||
box-shadow: 0px 1px 12px #666;
|
||||
color: black;
|
||||
}
|
||||
|
||||
.dropdown-popup > hr {
|
||||
|
@ -313,81 +314,74 @@ body {
|
|||
|
||||
#font-type-buttons,
|
||||
#font-size-buttons,
|
||||
.segmented-button {
|
||||
#color-scheme-buttons {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
list-style: none;
|
||||
white-space: nowrap;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
#font-type-buttons > li,
|
||||
#font-type-buttons > button,
|
||||
#font-size-buttons > button,
|
||||
.segmented-button > li {
|
||||
flex: 1 0 auto;
|
||||
#color-scheme-buttons > button {
|
||||
text-align: center;
|
||||
border-left: 1px solid #B5B5B5;
|
||||
border-right: 0;
|
||||
border-top: 0;
|
||||
border-bottom: 0;
|
||||
padding: 10px;
|
||||
}
|
||||
|
||||
#font-type-buttons > li,
|
||||
#font-type-buttons > button,
|
||||
#font-size-buttons > button {
|
||||
width: 100px; /* combined with flex, this acts as a minimum width */
|
||||
width: 50%;
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
.segmented-button > li {
|
||||
width: 30px; /* combined with flex, this acts as a minimum width */
|
||||
line-height: 20px;
|
||||
#color-scheme-buttons > button {
|
||||
width: 33%;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
#font-type-buttons > li:first-child,
|
||||
#font-type-buttons > button:first-child,
|
||||
#font-size-buttons > button:first-child,
|
||||
.segmented-button > li:first-child {
|
||||
#color-scheme-buttons > button:first-child {
|
||||
border-left: 0px;
|
||||
}
|
||||
|
||||
#font-type-buttons > li > a,
|
||||
.segmented-button > li > a {
|
||||
vertical-align: middle;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
#font-type-buttons > li > a {
|
||||
#font-type-buttons > button {
|
||||
display: inline-block;
|
||||
font-size: 48px;
|
||||
line-height: 50px;
|
||||
border-bottom: 3px solid transparent;
|
||||
}
|
||||
|
||||
.segmented-button > li > a {
|
||||
display: block;
|
||||
font-family: sans-serif;
|
||||
font-weight: lighter;
|
||||
}
|
||||
|
||||
#font-type-buttons > li:active:hover,
|
||||
#font-type-buttons > li.selected {
|
||||
#font-type-buttons > button:active:hover,
|
||||
#font-type-buttons > button.selected {
|
||||
border-bottom: 3px solid #FC6420;
|
||||
}
|
||||
|
||||
#font-type-buttons > button > div {
|
||||
color: #666;
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.button:hover,
|
||||
#font-size-buttons > li:hover {
|
||||
#font-size-buttons > button:hover {
|
||||
background-color: #EBEBEB;
|
||||
}
|
||||
|
||||
.dropdown.open,
|
||||
.button:active,
|
||||
#font-size-buttons > li:active,
|
||||
#font-size-buttons > li.selected {
|
||||
#font-size-buttons > button:active,
|
||||
#font-size-buttons > button.selected {
|
||||
background-color: #DADADA;
|
||||
}
|
||||
|
||||
#font-type-buttons > li > .sans-serif {
|
||||
font-weight: lighter;
|
||||
/* Only used on Android */
|
||||
#font-size-sample {
|
||||
display: none;
|
||||
}
|
||||
|
||||
#font-type-buttons > li > div {
|
||||
color: #666;
|
||||
font-size: 12px;
|
||||
.serif-button {
|
||||
font-family: serif;
|
||||
}
|
||||
|
||||
.minus-button,
|
||||
|
@ -400,6 +394,8 @@ body {
|
|||
background-position: center;
|
||||
}
|
||||
|
||||
/*======= Toolbar icons =======*/
|
||||
|
||||
/* Android-only controls */
|
||||
.share-button {
|
||||
display: none;
|
||||
|
|