merge fx-team to mozilla-central a=merge
|
@ -1386,6 +1386,8 @@ pref("devtools.timeline.enabled", false);
|
|||
pref("devtools.performance_dev.enabled", false);
|
||||
#endif
|
||||
|
||||
pref("devtools.performance.ui.show-timeline-memory", false);
|
||||
|
||||
// The default Profiler UI settings
|
||||
pref("devtools.profiler.ui.show-platform-data", false);
|
||||
|
||||
|
|
|
@ -385,7 +385,7 @@ Tools.webAudioEditor = {
|
|||
tooltip: l10n("ToolboxWebAudioEditor1.tooltip", webAudioEditorStrings),
|
||||
|
||||
isTargetSupported: function(target) {
|
||||
return !target.isAddon && !target.chrome;
|
||||
return !target.isAddon && !target.chrome && target.hasActor("webaudio");
|
||||
},
|
||||
|
||||
build: function(iframeWindow, toolbox) {
|
||||
|
|
|
@ -0,0 +1,322 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
"use strict";
|
||||
|
||||
const { Cc, Ci, Cu, Cr } = require("chrome");
|
||||
const { extend } = require("sdk/util/object");
|
||||
const { Task } = require("resource://gre/modules/Task.jsm");
|
||||
|
||||
loader.lazyRequireGetter(this, "Services");
|
||||
loader.lazyRequireGetter(this, "promise");
|
||||
loader.lazyRequireGetter(this, "EventEmitter",
|
||||
"devtools/toolkit/event-emitter");
|
||||
loader.lazyRequireGetter(this, "TimelineFront",
|
||||
"devtools/server/actors/timeline", true);
|
||||
loader.lazyRequireGetter(this, "DevToolsUtils",
|
||||
"devtools/toolkit/DevToolsUtils");
|
||||
|
||||
loader.lazyImporter(this, "gDevTools",
|
||||
"resource:///modules/devtools/gDevTools.jsm");
|
||||
|
||||
let showTimelineMemory = () => Services.prefs.getBoolPref("devtools.performance.ui.show-timeline-memory");
|
||||
|
||||
/**
|
||||
* A cache of all PerformanceActorsConnection instances. The keys are Target objects.
|
||||
*/
|
||||
let SharedPerformanceActors = new WeakMap();
|
||||
|
||||
/**
|
||||
* Instantiates a shared PerformanceActorsConnection for the specified target.
|
||||
* Consumers must yield on `open` to make sure the connection is established.
|
||||
*
|
||||
* @param Target target
|
||||
* The target owning this connection.
|
||||
*/
|
||||
SharedPerformanceActors.forTarget = function(target) {
|
||||
if (this.has(target)) {
|
||||
return this.get(target);
|
||||
}
|
||||
|
||||
let instance = new PerformanceActorsConnection(target);
|
||||
this.set(target, instance);
|
||||
return instance;
|
||||
};
|
||||
|
||||
/**
|
||||
* A connection to underlying actors (profiler, memory, framerate, etc)
|
||||
* shared by all tools in a target.
|
||||
*
|
||||
* Use `SharedPerformanceActors.forTarget` to make sure you get the same
|
||||
* instance every time, and the `PerformanceFront` to start/stop recordings.
|
||||
*
|
||||
* @param Target target
|
||||
* The target owning this connection.
|
||||
*/
|
||||
function PerformanceActorsConnection(target) {
|
||||
EventEmitter.decorate(this);
|
||||
|
||||
this._target = target;
|
||||
this._client = this._target.client;
|
||||
this._request = this._request.bind(this);
|
||||
|
||||
Services.obs.notifyObservers(null, "performance-actors-connection-created", null);
|
||||
}
|
||||
|
||||
PerformanceActorsConnection.prototype = {
|
||||
|
||||
/**
|
||||
* Initializes a connection to the profiler and other miscellaneous actors.
|
||||
* If already open, nothing happens.
|
||||
*
|
||||
* @return object
|
||||
* A promise that is resolved once the connection is established.
|
||||
*/
|
||||
open: Task.async(function*() {
|
||||
if (this._connected) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Local debugging needs to make the target remote.
|
||||
yield this._target.makeRemote();
|
||||
|
||||
// Sets `this._profiler`
|
||||
yield this._connectProfilerActor();
|
||||
|
||||
// Sets or shims `this._timeline`
|
||||
yield this._connectTimelineActor();
|
||||
|
||||
this._connected = true;
|
||||
|
||||
Services.obs.notifyObservers(null, "performance-actors-connection-opened", null);
|
||||
}),
|
||||
|
||||
/**
|
||||
* Destroys this connection.
|
||||
*/
|
||||
destroy: function () {
|
||||
this._disconnectActors();
|
||||
this._connected = false;
|
||||
},
|
||||
|
||||
/**
|
||||
* Initializes a connection to the profiler actor.
|
||||
*/
|
||||
_connectProfilerActor: Task.async(function*() {
|
||||
// Chrome debugging targets have already obtained a reference
|
||||
// to the profiler actor.
|
||||
if (this._target.chrome) {
|
||||
this._profiler = this._target.form.profilerActor;
|
||||
}
|
||||
// Or when we are debugging content processes, we already have the tab
|
||||
// specific one. Use it immediately.
|
||||
else if (this._target.form && this._target.form.profilerActor) {
|
||||
this._profiler = this._target.form.profilerActor;
|
||||
}
|
||||
// Check if we already have a grip to the `listTabs` response object
|
||||
// and, if we do, use it to get to the profiler actor.
|
||||
else if (this._target.root && this._target.root.profilerActor) {
|
||||
this._profiler = this._target.root.profilerActor;
|
||||
}
|
||||
// Otherwise, call `listTabs`.
|
||||
else {
|
||||
this._profiler = (yield listTabs(this._client)).profilerActor;
|
||||
}
|
||||
}),
|
||||
|
||||
/**
|
||||
* Initializes a connection to a timeline actor.
|
||||
*/
|
||||
_connectTimelineActor: function() {
|
||||
// Only initialize the timeline front if the respective actor is available.
|
||||
// Older Gecko versions don't have an existing implementation, in which case
|
||||
// all the methods we need can be easily mocked.
|
||||
//
|
||||
// If the timeline actor exists, all underlying actors (memory, framerate) exist,
|
||||
// with the expected methods and behaviour. If using the Performance tool,
|
||||
// and timeline actor does not exist (FxOS devices < Gecko 35),
|
||||
// then just use the mocked actor and do not display timeline data.
|
||||
//
|
||||
// TODO use framework level feature detection from bug 1069673
|
||||
if (this._target.form && this._target.form.timelineActor) {
|
||||
this._timeline = new TimelineFront(this._target.client, this._target.form);
|
||||
} else {
|
||||
this._timeline = {
|
||||
start: () => {},
|
||||
stop: () => {},
|
||||
isRecording: () => false,
|
||||
on: () => {},
|
||||
off: () => {},
|
||||
destroy: () => {}
|
||||
};
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Closes the connections to non-profiler actors.
|
||||
*/
|
||||
_disconnectActors: function () {
|
||||
this._timeline.destroy();
|
||||
},
|
||||
|
||||
/**
|
||||
* Sends the request over the remote debugging protocol to the
|
||||
* specified actor.
|
||||
*
|
||||
* @param string actor
|
||||
* The designated actor. Currently supported: "profiler", "timeline".
|
||||
* @param string method
|
||||
* Method to call on the backend.
|
||||
* @param any args [optional]
|
||||
* Additional data or arguments to send with the request.
|
||||
* @return object
|
||||
* A promise resolved with the response once the request finishes.
|
||||
*/
|
||||
_request: function(actor, method, ...args) {
|
||||
// Handle requests to the profiler actor.
|
||||
if (actor == "profiler") {
|
||||
let deferred = promise.defer();
|
||||
let data = args[0] || {};
|
||||
data.to = this._profiler;
|
||||
data.type = method;
|
||||
this._client.request(data, deferred.resolve);
|
||||
return deferred.promise;
|
||||
}
|
||||
|
||||
// Handle requests to the timeline actor.
|
||||
if (actor == "timeline") {
|
||||
return this._timeline[method].apply(this._timeline, args);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* A thin wrapper around a shared PerformanceActorsConnection for the parent target.
|
||||
* Handles manually starting and stopping a recording.
|
||||
*
|
||||
* @param PerformanceActorsConnection connection
|
||||
* The shared instance for the parent target.
|
||||
*/
|
||||
function PerformanceFront(connection) {
|
||||
EventEmitter.decorate(this);
|
||||
|
||||
this._request = connection._request;
|
||||
|
||||
// Pipe events from TimelineActor to the PerformanceFront
|
||||
connection._timeline.on("markers", markers => this.emit("markers", markers));
|
||||
connection._timeline.on("memory", (delta, measurement) => this.emit("memory", delta, measurement));
|
||||
connection._timeline.on("ticks", (delta, timestamps) => this.emit("ticks", delta, timestamps));
|
||||
}
|
||||
|
||||
PerformanceFront.prototype = {
|
||||
/**
|
||||
* Manually begins a recording session.
|
||||
*
|
||||
* @return object
|
||||
* A promise that is resolved once recording has started.
|
||||
*/
|
||||
startRecording: Task.async(function*() {
|
||||
let { isActive, currentTime } = yield this._request("profiler", "isActive");
|
||||
|
||||
// Start the profiler only if it wasn't already active. The built-in
|
||||
// nsIPerformance module will be kept recording, because it's the same instance
|
||||
// for all targets and interacts with the whole platform, so we don't want
|
||||
// to affect other clients by stopping (or restarting) it.
|
||||
if (!isActive) {
|
||||
// Extend the options so that protocol.js doesn't modify
|
||||
// the source object.
|
||||
let options = extend({}, this._customPerformanceOptions);
|
||||
yield this._request("profiler", "startProfiler", options);
|
||||
this._profilingStartTime = 0;
|
||||
this.emit("profiler-activated");
|
||||
} else {
|
||||
this._profilingStartTime = currentTime;
|
||||
this.emit("profiler-already-active");
|
||||
}
|
||||
|
||||
// The timeline actor is target-dependent, so just make sure
|
||||
// it's recording.
|
||||
let withMemory = showTimelineMemory();
|
||||
yield this._request("timeline", "start", { withTicks: true, withMemory: withMemory });
|
||||
}),
|
||||
|
||||
/**
|
||||
* Manually ends the current recording session.
|
||||
*
|
||||
* @return object
|
||||
* A promise that is resolved once recording has stopped,
|
||||
* with the profiler and timeline data.
|
||||
*/
|
||||
stopRecording: Task.async(function*() {
|
||||
// We'll need to filter out all samples that fall out of current profile's
|
||||
// range. This is necessary because the profiler is continuously running.
|
||||
let profilerData = yield this._request("profiler", "getProfile");
|
||||
filterSamples(profilerData, this._profilingStartTime);
|
||||
offsetSampleTimes(profilerData, this._profilingStartTime);
|
||||
|
||||
yield this._request("timeline", "stop");
|
||||
|
||||
// Join all the acquired data and return it for outside consumers.
|
||||
return {
|
||||
recordingDuration: profilerData.currentTime - this._profilingStartTime,
|
||||
profilerData: profilerData
|
||||
};
|
||||
}),
|
||||
|
||||
/**
|
||||
* Overrides the options sent to the built-in profiler module when activating,
|
||||
* such as the maximum entries count, the sampling interval etc.
|
||||
*
|
||||
* Used in tests and for older backend implementations.
|
||||
*/
|
||||
_customPerformanceOptions: {
|
||||
entries: 1000000,
|
||||
interval: 1,
|
||||
features: ["js"]
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Filters all the samples in the provided profiler data to be more recent
|
||||
* than the specified start time.
|
||||
*
|
||||
* @param object profilerData
|
||||
* The profiler data received from the backend.
|
||||
* @param number profilingStartTime
|
||||
* The earliest acceptable sample time (in milliseconds).
|
||||
*/
|
||||
function filterSamples(profilerData, profilingStartTime) {
|
||||
let firstThread = profilerData.profile.threads[0];
|
||||
|
||||
firstThread.samples = firstThread.samples.filter(e => {
|
||||
return e.time >= profilingStartTime;
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Offsets all the samples in the provided profiler data by the specified time.
|
||||
*
|
||||
* @param object profilerData
|
||||
* The profiler data received from the backend.
|
||||
* @param number timeOffset
|
||||
* The amount of time to offset by (in milliseconds).
|
||||
*/
|
||||
function offsetSampleTimes(profilerData, timeOffset) {
|
||||
let firstThreadSamples = profilerData.profile.threads[0].samples;
|
||||
|
||||
for (let sample of firstThreadSamples) {
|
||||
sample.time -= timeOffset;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A collection of small wrappers promisifying functions invoking callbacks.
|
||||
*/
|
||||
function listTabs(client) {
|
||||
let deferred = promise.defer();
|
||||
client.listTabs(deferred.resolve);
|
||||
return deferred.promise;
|
||||
}
|
||||
|
||||
exports.getPerformanceActorsConnection = target => SharedPerformanceActors.forTarget(target);
|
||||
exports.PerformanceFront = PerformanceFront;
|
|
@ -4,5 +4,8 @@
|
|||
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
EXTRA_JS_MODULES.devtools.performance += [
|
||||
'modules/front.js',
|
||||
'panel.js'
|
||||
]
|
||||
|
||||
BROWSER_CHROME_MANIFESTS += ['test/browser.ini']
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
"use strict";
|
||||
|
||||
const {Cc, Ci, Cu, Cr} = require("chrome");
|
||||
const { PerformanceFront, getPerformanceActorsConnection } = require("devtools/performance/front");
|
||||
|
||||
Cu.import("resource://gre/modules/Task.jsm");
|
||||
|
||||
|
@ -27,16 +28,17 @@ PerformancePanel.prototype = {
|
|||
* Open is effectively an asynchronous constructor.
|
||||
*
|
||||
* @return object
|
||||
* A promise that is resolved when the Profiler completes opening.
|
||||
* A promise that is resolved when the Performance tool
|
||||
* completes opening.
|
||||
*/
|
||||
open: Task.async(function*() {
|
||||
this.panelWin.gToolbox = this._toolbox;
|
||||
this.panelWin.gTarget = this.target;
|
||||
|
||||
// Mock Front for now
|
||||
let gFront = {};
|
||||
EventEmitter.decorate(gFront);
|
||||
this.panelWin.gFront = gFront;
|
||||
this._connection = getPerformanceActorsConnection(this.target);
|
||||
yield this._connection.open();
|
||||
|
||||
this.panelWin.gFront = new PerformanceFront(this._connection);
|
||||
|
||||
yield this.panelWin.startupPerformance();
|
||||
|
||||
|
@ -55,6 +57,9 @@ PerformancePanel.prototype = {
|
|||
return;
|
||||
}
|
||||
|
||||
// Destroy the connection to ensure packet handlers are removed from client.
|
||||
this._connection.destroy();
|
||||
|
||||
yield this.panelWin.shutdownPerformance();
|
||||
this.emit("destroyed");
|
||||
this._destroyed = true;
|
||||
|
|
|
@ -0,0 +1,30 @@
|
|||
[DEFAULT]
|
||||
skip-if = e10s # Handle in Bug 1077464 for profiler
|
||||
subsuite = devtools
|
||||
support-files =
|
||||
doc_simple-test.html
|
||||
head.js
|
||||
|
||||
# Commented out tests are profiler tests
|
||||
# that need to be moved over to performance tool
|
||||
|
||||
[browser_perf-aaa-run-first-leaktest.js]
|
||||
[browser_perf-front-basic-timeline-01.js]
|
||||
[browser_perf-front-basic-profiler-01.js]
|
||||
# bug 1077464
|
||||
#[browser_perf-front-profiler-01.js]
|
||||
[browser_perf-front-profiler-02.js]
|
||||
[browser_perf-front-profiler-03.js]
|
||||
[browser_perf-front-profiler-04.js]
|
||||
# bug 1077464
|
||||
#[browser_perf-front-profiler-05.js]
|
||||
# bug 1077464
|
||||
#[browser_perf-front-profiler-06.js]
|
||||
# needs shared connection with profiler's shared connection
|
||||
#[browser_perf-shared-connection-01.js]
|
||||
[browser_perf-shared-connection-02.js]
|
||||
[browser_perf-shared-connection-03.js]
|
||||
# bug 1077464
|
||||
#[browser_perf-shared-connection-04.js]
|
||||
[browser_perf-data-samples.js]
|
||||
[browser_perf-data-massaging-01.js]
|
|
@ -0,0 +1,22 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
/**
|
||||
* Tests if the performance tool leaks on initialization and sudden destruction.
|
||||
* You can also use this initialization format as a template for other tests.
|
||||
*/
|
||||
|
||||
function spawnTest () {
|
||||
let { target, panel, toolbox } = yield initPerformance(SIMPLE_URL);
|
||||
|
||||
ok(target, "Should have a target available.");
|
||||
ok(toolbox, "Should have a toolbox available.");
|
||||
ok(panel, "Should have a panel available.");
|
||||
|
||||
ok(panel.panelWin.gToolbox, "Should have a toolbox reference on the panel window.");
|
||||
ok(panel.panelWin.gTarget, "Should have a target reference on the panel window.");
|
||||
ok(panel.panelWin.gFront, "Should have a front reference on the panel window.");
|
||||
|
||||
yield teardown(panel);
|
||||
finish();
|
||||
}
|
|
@ -0,0 +1,63 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
/**
|
||||
* Tests if the retrieved profiler data samples are correctly filtered and
|
||||
* normalized before passed to consumers.
|
||||
*/
|
||||
|
||||
const WAIT_TIME = 1000; // ms
|
||||
|
||||
function spawnTest () {
|
||||
let { panel } = yield initPerformance(SIMPLE_URL);
|
||||
let front = panel.panelWin.gFront;
|
||||
|
||||
// Perform the first recording...
|
||||
|
||||
yield front.startRecording();
|
||||
let profilingStartTime = front._profilingStartTime;
|
||||
info("Started profiling at: " + profilingStartTime);
|
||||
|
||||
busyWait(WAIT_TIME); // allow the profiler module to sample some cpu activity
|
||||
|
||||
let firstRecordingData = yield front.stopRecording();
|
||||
let firstRecordingFinishTime = firstRecordingData.profilerData.currentTime;
|
||||
|
||||
is(profilingStartTime, 0,
|
||||
"The profiling start time should be 0 for the first recording.");
|
||||
ok(firstRecordingData.recordingDuration >= WAIT_TIME,
|
||||
"The first recording duration is correct.");
|
||||
ok(firstRecordingFinishTime >= WAIT_TIME,
|
||||
"The first recording finish time is correct.");
|
||||
|
||||
// Perform the second recording...
|
||||
|
||||
yield front.startRecording();
|
||||
profilingStartTime = front._profilingStartTime;
|
||||
info("Started profiling at: " + profilingStartTime);
|
||||
|
||||
busyWait(WAIT_TIME); // allow the profiler module to sample more cpu activity
|
||||
|
||||
let secondRecordingData = yield front.stopRecording();
|
||||
let secondRecordingFinishTime = secondRecordingData.profilerData.currentTime;
|
||||
let secondRecordingProfile = secondRecordingData.profilerData.profile;
|
||||
let secondRecordingSamples = secondRecordingProfile.threads[0].samples;
|
||||
|
||||
isnot(profilingStartTime, 0,
|
||||
"The profiling start time should not be 0 on the second recording.");
|
||||
ok(secondRecordingData.recordingDuration >= WAIT_TIME,
|
||||
"The second recording duration is correct.");
|
||||
ok(secondRecordingFinishTime - firstRecordingFinishTime >= WAIT_TIME,
|
||||
"The second recording finish time is correct.");
|
||||
|
||||
ok(secondRecordingSamples[0].time < profilingStartTime,
|
||||
"The second recorded sample times were normalized.");
|
||||
ok(secondRecordingSamples[0].time > 0,
|
||||
"The second recorded sample times were normalized correctly.");
|
||||
ok(!secondRecordingSamples.find(e => e.time + profilingStartTime <= firstRecordingFinishTime),
|
||||
"There should be no samples from the first recording in the second one, " +
|
||||
"even though the total number of frames did not overflow.");
|
||||
|
||||
yield teardown(panel);
|
||||
finish();
|
||||
}
|
|
@ -0,0 +1,34 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
/**
|
||||
* Tests if the retrieved profiler data samples always have a (root) node.
|
||||
* If this ever changes, the |ThreadNode.prototype.insert| function in
|
||||
* browser/devtools/profiler/utils/tree-model.js will have to be changed.
|
||||
*/
|
||||
|
||||
const WAIT_TIME = 1000; // ms
|
||||
|
||||
function spawnTest () {
|
||||
let { panel } = yield initPerformance(SIMPLE_URL);
|
||||
let front = panel.panelWin.gFront;
|
||||
|
||||
yield front.startRecording();
|
||||
busyWait(WAIT_TIME); // allow the profiler module to sample some cpu activity
|
||||
|
||||
let recordingData = yield front.stopRecording();
|
||||
let profile = recordingData.profilerData.profile;
|
||||
|
||||
for (let thread of profile.threads) {
|
||||
info("Checking thread: " + thread.name);
|
||||
|
||||
for (let sample of thread.samples) {
|
||||
if (sample.frames[0].location != "(root)") {
|
||||
ok(false, "The sample " + sample.toSource() + " doesn't have a root node.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
yield teardown(panel);
|
||||
finish();
|
||||
}
|
|
@ -0,0 +1,25 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
/**
|
||||
* Test basic functionality of PerformanceFront
|
||||
*/
|
||||
|
||||
let WAIT = 1000;
|
||||
|
||||
function spawnTest () {
|
||||
let { target, front } = yield initBackend(SIMPLE_URL);
|
||||
|
||||
yield front.startRecording();
|
||||
|
||||
yield busyWait(WAIT);
|
||||
|
||||
let { recordingDuration, profilerData } = yield front.stopRecording();
|
||||
|
||||
ok(recordingDuration > 500, "recordingDuration exists");
|
||||
ok(profilerData, "profilerData exists");
|
||||
|
||||
yield removeTab(target.tab);
|
||||
finish();
|
||||
|
||||
}
|
|
@ -0,0 +1,84 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
/**
|
||||
* Test basic functionality of PerformanceFront, retrieving timeline data.
|
||||
*/
|
||||
|
||||
function spawnTest () {
|
||||
Services.prefs.setBoolPref("devtools.performance.ui.show-timeline-memory", true);
|
||||
|
||||
let { target, front } = yield initBackend(SIMPLE_URL);
|
||||
|
||||
let lastMemoryDelta = 0;
|
||||
let lastTickDelta = 0;
|
||||
|
||||
let counters = {
|
||||
markers: [],
|
||||
memory: [],
|
||||
ticks: []
|
||||
};
|
||||
|
||||
let deferreds = {
|
||||
markers: Promise.defer(),
|
||||
memory: Promise.defer(),
|
||||
ticks: Promise.defer()
|
||||
}
|
||||
|
||||
front.on("markers", handler);
|
||||
front.on("memory", handler);
|
||||
front.on("ticks", handler);
|
||||
|
||||
yield front.startRecording();
|
||||
|
||||
yield Promise.all(Object.keys(deferreds).map(type => deferreds[type].promise));
|
||||
|
||||
yield front.stopRecording();
|
||||
|
||||
is(counters.markers.length, 1, "one marker event fired.");
|
||||
is(counters.memory.length, 3, "three memory events fired.");
|
||||
is(counters.ticks.length, 3, "three ticks events fired.");
|
||||
|
||||
yield removeTab(target.tab);
|
||||
finish();
|
||||
|
||||
function handler (name, ...args) {
|
||||
if (name === "memory") {
|
||||
let [delta, measurement] = args;
|
||||
is(typeof delta, "number", "received `delta` in memory event");
|
||||
ok(delta > lastMemoryDelta, "received `delta` in memory event");
|
||||
ok(measurement.total, "received `total` in memory event");
|
||||
ok(measurement.domSize, "received `domSize` in memory event");
|
||||
ok(measurement.jsObjectsSize, "received `jsObjectsSize` in memory event");
|
||||
|
||||
counters.memory.push({ delta: delta, measurement: measurement });
|
||||
lastMemoryDelta = delta;
|
||||
} else if (name === "ticks") {
|
||||
let [delta, timestamps] = args;
|
||||
ok(delta > lastTickDelta, "received `delta` in ticks event");
|
||||
|
||||
// First tick doesn't contain any timestamps
|
||||
if (counters.ticks.length) {
|
||||
ok(timestamps.length, "received `timestamps` in ticks event");
|
||||
}
|
||||
|
||||
counters.ticks.push({ delta: delta, timestamps: timestamps});
|
||||
lastTickDelta = delta;
|
||||
} else if (name === "markers") {
|
||||
let [markers] = args;
|
||||
ok(markers[0].start, "received atleast one marker with `start`");
|
||||
ok(markers[0].end, "received atleast one marker with `end`");
|
||||
ok(markers[0].name, "received atleast one marker with `name`");
|
||||
counters.markers.push(markers);
|
||||
front.off(name, handler);
|
||||
deferreds[name].resolve();
|
||||
} else {
|
||||
throw new Error("unknown event");
|
||||
}
|
||||
|
||||
if (name !== "markers" && counters[name].length === 3) {
|
||||
front.off(name, handler);
|
||||
deferreds[name].resolve();
|
||||
}
|
||||
};
|
||||
}
|
|
@ -0,0 +1,37 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
/**
|
||||
* Tests if the profiler connection front does not activate the built-in
|
||||
* profiler module if not necessary, and doesn't deactivate it when
|
||||
* a recording is stopped.
|
||||
*/
|
||||
|
||||
let test = Task.async(function*() {
|
||||
let { target, panel, toolbox } = yield initPerformance(SIMPLE_URL);
|
||||
let front = panel.panelWin.gFront;
|
||||
|
||||
ok(!nsIProfilerModule.IsActive(),
|
||||
"The built-in profiler module should not have been automatically started.");
|
||||
|
||||
let activated = front.once("profiler-activated");
|
||||
yield front.startRecording();
|
||||
yield activated;
|
||||
yield front.stopRecording();
|
||||
ok(nsIProfilerModule.IsActive(),
|
||||
"The built-in profiler module should still be active (1).");
|
||||
|
||||
let alreadyActive = front.once("profiler-already-active");
|
||||
yield front.startRecording();
|
||||
yield alreadyActive;
|
||||
yield front.stopRecording();
|
||||
ok(nsIProfilerModule.IsActive(),
|
||||
"The built-in profiler module should still be active (2).");
|
||||
|
||||
yield teardown(panel);
|
||||
|
||||
ok(!nsIProfilerModule.IsActive(),
|
||||
"The built-in profiler module should have been automatically stoped.");
|
||||
|
||||
finish();
|
||||
});
|
|
@ -0,0 +1,33 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
/**
|
||||
* Tests if the built-in profiler module doesn't deactivate when the toolbox
|
||||
* is destroyed if there are other consumers using it.
|
||||
*/
|
||||
|
||||
let test = Task.async(function*() {
|
||||
let { panel: firstPanel } = yield initPerformance(SIMPLE_URL);
|
||||
let firstFront = firstPanel.panelWin.gFront;
|
||||
|
||||
let activated = firstFront.once("profiler-activated");
|
||||
yield firstFront.startRecording();
|
||||
yield activated;
|
||||
|
||||
let { panel: secondPanel } = yield initPerformance(SIMPLE_URL);
|
||||
let secondFront = secondPanel.panelWin.gFront;
|
||||
|
||||
let alreadyActive = secondFront.once("profiler-already-active");
|
||||
yield secondFront.startRecording();
|
||||
yield alreadyActive;
|
||||
|
||||
yield teardown(firstPanel);
|
||||
ok(nsIProfilerModule.IsActive(),
|
||||
"The built-in profiler module should still be active.");
|
||||
|
||||
yield teardown(secondPanel);
|
||||
ok(!nsIProfilerModule.IsActive(),
|
||||
"The built-in profiler module should have been automatically stoped.");
|
||||
|
||||
finish();
|
||||
});
|
|
@ -0,0 +1,43 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
/**
|
||||
* Tests if the built-in profiler module is not reactivated if no other
|
||||
* consumer was using it over the remote debugger protocol, and ensures
|
||||
* that the actor will work properly even in such cases (e.g. the Gecko Profiler
|
||||
* addon was installed and automatically activated the profiler module).
|
||||
*/
|
||||
|
||||
let test = Task.async(function*() {
|
||||
// Ensure the profiler is already running when the test starts.
|
||||
let ENTRIES = 1000000;
|
||||
let INTERVAL = 1;
|
||||
let FEATURES = ["js"];
|
||||
nsIProfilerModule.StartProfiler(ENTRIES, INTERVAL, FEATURES, FEATURES.length);
|
||||
|
||||
let { panel: firstPanel } = yield initPerformance(SIMPLE_URL);
|
||||
let firstFront = firstPanel.panelWin.gFront;
|
||||
|
||||
let alredyActive = firstFront.once("profiler-already-active");
|
||||
yield firstFront.startRecording();
|
||||
yield alredyActive;
|
||||
ok(firstFront._profilingStartTime > 0, "The profiler was not restarted.");
|
||||
|
||||
let { panel: secondPanel } = yield initPerformance(SIMPLE_URL);
|
||||
let secondFront = secondPanel.panelWin.gFront;
|
||||
|
||||
let alreadyActive = secondFront.once("profiler-already-active");
|
||||
yield secondFront.startRecording();
|
||||
yield alreadyActive;
|
||||
ok(secondFront._profilingStartTime > 0, "The profiler was not restarted.");
|
||||
|
||||
yield teardown(firstPanel);
|
||||
ok(nsIProfilerModule.IsActive(),
|
||||
"The built-in profiler module should still be active.");
|
||||
|
||||
yield teardown(secondPanel);
|
||||
ok(!nsIProfilerModule.IsActive(),
|
||||
"The built-in profiler module should have been automatically stoped.");
|
||||
|
||||
finish();
|
||||
});
|
|
@ -0,0 +1,39 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
/**
|
||||
* Tests if the shared PerformanceActorsConnection is only opened once.
|
||||
*/
|
||||
|
||||
let gProfilerConnectionsOpened = 0;
|
||||
Services.obs.addObserver(profilerConnectionObserver, "performance-actors-connection-opened", false);
|
||||
|
||||
function spawnTest () {
|
||||
let { target, panel } = yield initPerformance(SIMPLE_URL);
|
||||
|
||||
is(gProfilerConnectionsOpened, 1,
|
||||
"Only one profiler connection was opened.");
|
||||
|
||||
let sharedConnection = getPerformanceActorsConnection(target);
|
||||
|
||||
ok(sharedConnection,
|
||||
"A shared profiler connection for the current toolbox was retrieved.");
|
||||
is(sharedConnection._request, panel.panelWin.gFront._request,
|
||||
"The same shared profiler connection is used by the panel's front.");
|
||||
|
||||
yield sharedConnection.open();
|
||||
is(gProfilerConnectionsOpened, 1,
|
||||
"No additional profiler connections were opened.");
|
||||
|
||||
yield teardown(panel);
|
||||
finish();
|
||||
}
|
||||
|
||||
function profilerConnectionObserver(subject, topic, data) {
|
||||
is(topic, "performance-actors-connection-opened", "The correct topic was observed.");
|
||||
gProfilerConnectionsOpened++;
|
||||
}
|
||||
|
||||
registerCleanupFunction(() => {
|
||||
Services.obs.removeObserver(profilerConnectionObserver, "performance-actors-connection-opened");
|
||||
});
|
|
@ -0,0 +1,29 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
/**
|
||||
* Tests if the shared PerformanceActorsConnection can properly send requests.
|
||||
*/
|
||||
|
||||
function spawnTest () {
|
||||
let { panel } = yield initPerformance(SIMPLE_URL);
|
||||
let front = panel.panelWin.gFront;
|
||||
|
||||
ok(!nsIProfilerModule.IsActive(),
|
||||
"The built-in profiler module should not have been automatically started.");
|
||||
|
||||
let result = yield front._request("profiler", "startProfiler");
|
||||
is(result.started, true,
|
||||
"The request finished successfully and the profiler should've been started.");
|
||||
ok(nsIProfilerModule.IsActive(),
|
||||
"The built-in profiler module should now be active.");
|
||||
|
||||
result = yield front._request("profiler", "stopProfiler");
|
||||
is(result.started, false,
|
||||
"The request finished successfully and the profiler should've been stopped.");
|
||||
ok(!nsIProfilerModule.IsActive(),
|
||||
"The built-in profiler module should now be inactive.");
|
||||
|
||||
yield teardown(panel);
|
||||
finish();
|
||||
}
|
|
@ -0,0 +1,22 @@
|
|||
<!-- Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ -->
|
||||
<!doctype html>
|
||||
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8"/>
|
||||
<title>Profiler test page</title>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<script type="text/javascript">
|
||||
function test() {
|
||||
var a = "Hello world!";
|
||||
}
|
||||
|
||||
// Prevent this script from being garbage collected.
|
||||
window.setInterval(test, 1);
|
||||
</script>
|
||||
</body>
|
||||
|
||||
</html>
|
|
@ -0,0 +1,209 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
"use strict";
|
||||
|
||||
const { classes: Cc, interfaces: Ci, utils: Cu, results: Cr } = Components;
|
||||
|
||||
let { Services } = Cu.import("resource://gre/modules/Services.jsm", {});
|
||||
|
||||
// Enable logging for all the tests. Both the debugger server and frontend will
|
||||
// be affected by this pref.
|
||||
let gEnableLogging = Services.prefs.getBoolPref("devtools.debugger.log");
|
||||
Services.prefs.setBoolPref("devtools.debugger.log", false);
|
||||
|
||||
let { Task } = Cu.import("resource://gre/modules/Task.jsm", {});
|
||||
let { Promise } = Cu.import("resource://gre/modules/Promise.jsm", {});
|
||||
let { gDevTools } = Cu.import("resource:///modules/devtools/gDevTools.jsm", {});
|
||||
let { DevToolsUtils } = Cu.import("resource://gre/modules/devtools/DevToolsUtils.jsm", {});
|
||||
let { devtools } = Cu.import("resource://gre/modules/devtools/Loader.jsm", {});
|
||||
let { DebuggerServer } = Cu.import("resource://gre/modules/devtools/dbg-server.jsm", {});
|
||||
let { getPerformanceActorsConnection, PerformanceFront } = devtools.require("devtools/performance/front");
|
||||
let nsIProfilerModule = Cc["@mozilla.org/tools/profiler;1"].getService(Ci.nsIProfiler);
|
||||
let TargetFactory = devtools.TargetFactory;
|
||||
let mm = null;
|
||||
|
||||
const FRAME_SCRIPT_UTILS_URL = "chrome://browser/content/devtools/frame-script-utils.js"
|
||||
const EXAMPLE_URL = "http://example.com/browser/browser/devtools/performance/test/";
|
||||
const SIMPLE_URL = EXAMPLE_URL + "doc_simple-test.html";
|
||||
|
||||
// All tests are asynchronous.
|
||||
waitForExplicitFinish();
|
||||
|
||||
let gToolEnabled = Services.prefs.getBoolPref("devtools.performance_dev.enabled");
|
||||
let gShowTimelineMemory = Services.prefs.getBoolPref("devtools.performance.ui.show-timeline-memory");
|
||||
|
||||
gDevTools.testing = true;
|
||||
|
||||
/**
|
||||
* Call manually in tests that use frame script utils after initializing
|
||||
* the tool. Must be called after initializing so we can detect
|
||||
* whether or not `content` is a CPOW or not. Call after init but before navigating
|
||||
* to different pages.
|
||||
*/
|
||||
function loadFrameScripts () {
|
||||
mm = gBrowser.selectedBrowser.messageManager;
|
||||
mm.loadFrameScript(FRAME_SCRIPT_UTILS_URL, false);
|
||||
}
|
||||
|
||||
registerCleanupFunction(() => {
|
||||
gDevTools.testing = false;
|
||||
info("finish() was called, cleaning up...");
|
||||
|
||||
Services.prefs.setBoolPref("devtools.performance.ui.show-timeline-memory", gShowTimelineMemory);
|
||||
Services.prefs.setBoolPref("devtools.debugger.log", gEnableLogging);
|
||||
Services.prefs.setBoolPref("devtools.performance_dev.enabled", gToolEnabled);
|
||||
// Make sure the profiler module is stopped when the test finishes.
|
||||
nsIProfilerModule.StopProfiler();
|
||||
|
||||
Cu.forceGC();
|
||||
});
|
||||
|
||||
function addTab(aUrl, aWindow) {
|
||||
info("Adding tab: " + aUrl);
|
||||
|
||||
let deferred = Promise.defer();
|
||||
let targetWindow = aWindow || window;
|
||||
let targetBrowser = targetWindow.gBrowser;
|
||||
|
||||
targetWindow.focus();
|
||||
let tab = targetBrowser.selectedTab = targetBrowser.addTab(aUrl);
|
||||
let linkedBrowser = tab.linkedBrowser;
|
||||
|
||||
linkedBrowser.addEventListener("load", function onLoad() {
|
||||
linkedBrowser.removeEventListener("load", onLoad, true);
|
||||
info("Tab added and finished loading: " + aUrl);
|
||||
deferred.resolve(tab);
|
||||
}, true);
|
||||
|
||||
return deferred.promise;
|
||||
}
|
||||
|
||||
function removeTab(aTab, aWindow) {
|
||||
info("Removing tab.");
|
||||
|
||||
let deferred = Promise.defer();
|
||||
let targetWindow = aWindow || window;
|
||||
let targetBrowser = targetWindow.gBrowser;
|
||||
let tabContainer = targetBrowser.tabContainer;
|
||||
|
||||
tabContainer.addEventListener("TabClose", function onClose(aEvent) {
|
||||
tabContainer.removeEventListener("TabClose", onClose, false);
|
||||
info("Tab removed and finished closing.");
|
||||
deferred.resolve();
|
||||
}, false);
|
||||
|
||||
targetBrowser.removeTab(aTab);
|
||||
return deferred.promise;
|
||||
}
|
||||
|
||||
function handleError(aError) {
|
||||
ok(false, "Got an error: " + aError.message + "\n" + aError.stack);
|
||||
finish();
|
||||
}
|
||||
|
||||
function once(aTarget, aEventName, aUseCapture = false) {
|
||||
info("Waiting for event: '" + aEventName + "' on " + aTarget + ".");
|
||||
|
||||
let deferred = Promise.defer();
|
||||
|
||||
for (let [add, remove] of [
|
||||
["on", "off"], // Use event emitter before DOM events for consistency
|
||||
["addEventListener", "removeEventListener"],
|
||||
["addListener", "removeListener"]
|
||||
]) {
|
||||
if ((add in aTarget) && (remove in aTarget)) {
|
||||
aTarget[add](aEventName, function onEvent(...aArgs) {
|
||||
aTarget[remove](aEventName, onEvent, aUseCapture);
|
||||
deferred.resolve(...aArgs);
|
||||
}, aUseCapture);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return deferred.promise;
|
||||
}
|
||||
|
||||
function test () {
|
||||
Task.spawn(spawnTest).then(finish, handleError);
|
||||
}
|
||||
|
||||
function initBackend(aUrl) {
|
||||
info("Initializing a performance front.");
|
||||
|
||||
if (!DebuggerServer.initialized) {
|
||||
DebuggerServer.init(() => true);
|
||||
DebuggerServer.addBrowserActors();
|
||||
}
|
||||
|
||||
return Task.spawn(function*() {
|
||||
let tab = yield addTab(aUrl);
|
||||
let target = TargetFactory.forTab(tab);
|
||||
|
||||
yield target.makeRemote();
|
||||
|
||||
yield gDevTools.showToolbox(target, "performance");
|
||||
|
||||
let connection = getPerformanceActorsConnection(target);
|
||||
yield connection.open();
|
||||
let front = new PerformanceFront(connection);
|
||||
return { target, front };
|
||||
});
|
||||
}
|
||||
|
||||
function initPerformance(aUrl) {
|
||||
info("Initializing a performance pane.");
|
||||
|
||||
return Task.spawn(function*() {
|
||||
let tab = yield addTab(aUrl);
|
||||
let target = TargetFactory.forTab(tab);
|
||||
|
||||
yield target.makeRemote();
|
||||
|
||||
Services.prefs.setBoolPref("devtools.performance_dev.enabled", true);
|
||||
let toolbox = yield gDevTools.showToolbox(target, "performance");
|
||||
let panel = toolbox.getCurrentPanel();
|
||||
return { target, panel, toolbox };
|
||||
});
|
||||
}
|
||||
|
||||
function* teardown(panel) {
|
||||
info("Destroying the performance tool.");
|
||||
|
||||
let tab = panel.target.tab;
|
||||
yield panel._toolbox.destroy();
|
||||
yield removeTab(tab);
|
||||
}
|
||||
|
||||
function idleWait(time) {
|
||||
return DevToolsUtils.waitForTime(time);
|
||||
}
|
||||
|
||||
function consoleMethod (...args) {
|
||||
if (!mm) {
|
||||
throw new Error("`loadFrameScripts()` must be called before using frame scripts.");
|
||||
}
|
||||
mm.sendAsyncMessage("devtools:test:console", args);
|
||||
}
|
||||
|
||||
function* consoleProfile(connection, label) {
|
||||
let notified = connection.once("profile");
|
||||
consoleMethod("profile", label);
|
||||
yield notified;
|
||||
}
|
||||
|
||||
function* consoleProfileEnd(connection) {
|
||||
let notified = connection.once("profileEnd");
|
||||
consoleMethod("profileEnd");
|
||||
yield notified;
|
||||
}
|
||||
|
||||
function busyWait(time) {
|
||||
let start = Date.now();
|
||||
let stack;
|
||||
while (Date.now() - start < time) { stack = Components.stack; }
|
||||
}
|
||||
|
||||
function idleWait(time) {
|
||||
return DevToolsUtils.waitForTime(time);
|
||||
}
|
||||
|
|
@ -17,6 +17,11 @@ addMessageListener("devtools:test:reload", function ({ data }) {
|
|||
content.location.reload(data.forceget);
|
||||
});
|
||||
|
||||
addMessageListener("devtools:test:console", function ({ data }) {
|
||||
let method = data.shift();
|
||||
content.console[method].apply(content.console, data);
|
||||
});
|
||||
|
||||
addEventListener("load", function() {
|
||||
sendAsyncMessage("devtools:test:load");
|
||||
}, true);
|
||||
|
|
|
@ -73,7 +73,7 @@
|
|||
}
|
||||
|
||||
#nav-bar {
|
||||
background-image: linear-gradient(@toolbarHighlight@, rgba(255,255,255,0));
|
||||
background-image: linear-gradient(@toolbarHighlight@, transparent);
|
||||
box-shadow: 0 1px 0 @toolbarHighlight@ inset;
|
||||
padding-top: 2px;
|
||||
padding-bottom: 2px;
|
||||
|
@ -1540,12 +1540,12 @@ richlistitem[type~="action"][actiontype="switchtab"] > .ac-url-box > .ac-action-
|
|||
}
|
||||
|
||||
#urlbar-reload-button:not([disabled]):hover {
|
||||
background-image: radial-gradient(circle closest-side, hsla(200,100%,70%,.2), hsla(200,100%,70%,0));
|
||||
background-image: radial-gradient(circle closest-side, hsla(200,100%,70%,.2), transparent);
|
||||
-moz-image-region: rect(14px, 14px, 28px, 0);
|
||||
}
|
||||
|
||||
#urlbar-reload-button:not([disabled]):hover:active {
|
||||
background-image: radial-gradient(circle closest-side, hsla(200,100%,60%,.1), hsla(200,100%,60%,0));
|
||||
background-image: radial-gradient(circle closest-side, hsla(200,100%,60%,.1), transparent);
|
||||
-moz-image-region: rect(28px, 14px, 42px, 0);
|
||||
}
|
||||
|
||||
|
@ -1558,12 +1558,12 @@ richlistitem[type~="action"][actiontype="switchtab"] > .ac-url-box > .ac-action-
|
|||
}
|
||||
|
||||
#urlbar-go-button:hover {
|
||||
background-image: radial-gradient(circle closest-side, hsla(110,70%,50%,.2), hsla(110,70%,50%,0));
|
||||
background-image: radial-gradient(circle closest-side, hsla(110,70%,50%,.2), transparent);
|
||||
-moz-image-region: rect(14px, 42px, 28px, 28px);
|
||||
}
|
||||
|
||||
#urlbar-go-button:hover:active {
|
||||
background-image: radial-gradient(circle closest-side, hsla(110,70%,50%,.1), hsla(110,70%,50%,0));
|
||||
background-image: radial-gradient(circle closest-side, hsla(110,70%,50%,.1), transparent);
|
||||
-moz-image-region: rect(28px, 42px, 42px, 28px);
|
||||
}
|
||||
|
||||
|
@ -1576,12 +1576,12 @@ richlistitem[type~="action"][actiontype="switchtab"] > .ac-url-box > .ac-action-
|
|||
}
|
||||
|
||||
#urlbar-stop-button:not([disabled]):hover {
|
||||
background-image: radial-gradient(circle closest-side, hsla(5,100%,75%,.3), hsla(5,100%,75%,0));
|
||||
background-image: radial-gradient(circle closest-side, hsla(5,100%,75%,.3), transparent);
|
||||
-moz-image-region: rect(14px, 28px, 28px, 14px);
|
||||
}
|
||||
|
||||
#urlbar-stop-button:hover:active {
|
||||
background-image: radial-gradient(circle closest-side, hsla(5,100%,75%,.1), hsla(5,100%,75%,0));
|
||||
background-image: radial-gradient(circle closest-side, hsla(5,100%,75%,.1), transparent);
|
||||
-moz-image-region: rect(28px, 28px, 42px, 14px);
|
||||
}
|
||||
|
||||
|
@ -1590,11 +1590,6 @@ richlistitem[type~="action"][actiontype="switchtab"] > .ac-url-box > .ac-action-
|
|||
list-style-image: url("chrome://browser/skin/Info.png");
|
||||
}
|
||||
|
||||
/* Loop */
|
||||
#loop-call-button {
|
||||
list-style-image: url("chrome://global/skin/loop/loop-call.png");
|
||||
}
|
||||
|
||||
/* social share panel */
|
||||
|
||||
.social-share-frame {
|
||||
|
@ -2123,7 +2118,7 @@ toolbarbutton.chevron > .toolbarbutton-icon {
|
|||
|
||||
.chat-titlebar {
|
||||
background-color: #d9d9d9;
|
||||
background-image: linear-gradient(@toolbarHighlight@, rgba(255,255,255,0));
|
||||
background-image: linear-gradient(@toolbarHighlight@, transparent);
|
||||
}
|
||||
|
||||
.chat-titlebar[selected] {
|
||||
|
@ -2133,7 +2128,7 @@ toolbarbutton.chevron > .toolbarbutton-icon {
|
|||
.chatbar-button {
|
||||
-moz-appearance: none;
|
||||
background-color: #d9d9d9;
|
||||
background-image: linear-gradient(@toolbarHighlight@, rgba(255,255,255,0));
|
||||
background-image: linear-gradient(@toolbarHighlight@, transparent);
|
||||
}
|
||||
|
||||
.chatbar-button > .toolbarbutton-icon {
|
||||
|
@ -2146,7 +2141,7 @@ toolbarbutton.chevron > .toolbarbutton-icon {
|
|||
}
|
||||
|
||||
.chatbar-button[activity] {
|
||||
background-image: radial-gradient(circle farthest-corner at center 3px, rgb(233,242,252) 3%, rgba(172,206,255,0.75) 40%, rgba(87,151,201,0.5) 80%, rgba(87,151,201,0));
|
||||
background-image: radial-gradient(circle farthest-corner at center 3px, rgb(233,242,252) 3%, rgba(172,206,255,0.75) 40%, rgba(87,151,201,0.5) 80%, transparent);
|
||||
}
|
||||
|
||||
chatbox {
|
||||
|
|
|
@ -169,7 +169,7 @@ richlistitem[type="download"]:last-child {
|
|||
border-top: 1px solid hsla(0,0%,100%,.3);
|
||||
border-bottom: 1px solid hsla(0,0%,0%,.2);
|
||||
background-color: Highlight;
|
||||
background-image: linear-gradient(hsla(0,0%,100%,.1), hsla(0,0%,100%,0));
|
||||
background-image: linear-gradient(hsla(0,0%,100%,.1), transparent);
|
||||
color: HighlightText;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
|
|
@ -25,7 +25,7 @@
|
|||
--toolbarbutton-hover-boxshadow: 0 1px 0 hsla(0,0%,100%,.5),
|
||||
0 1px 0 hsla(0,0%,100%,.5) inset;
|
||||
|
||||
--toolbarbutton-active-background: hsla(0,0%,0%,.02) linear-gradient(hsla(0,0%,0%,.12), hsla(0,0%,0%,0)) border-box;
|
||||
--toolbarbutton-active-background: hsla(0,0%,0%,.02) linear-gradient(hsla(0,0%,0%,.12), transparent) border-box;
|
||||
--toolbarbutton-active-boxshadow: 0 1px 0 hsla(0,0%,100%,.5),
|
||||
0 1px 0 hsla(0,0%,0%,.05) inset,
|
||||
0 1px 1px hsla(0,0%,0%,.2) inset;
|
||||
|
@ -2128,7 +2128,7 @@ toolbarbutton[sdk-button="true"][cui-areatype="toolbar"] > .toolbarbutton-icon {
|
|||
.urlbar-history-dropmarker[open="true"],
|
||||
.urlbar-history-dropmarker:hover:active {
|
||||
-moz-image-region: var(--urlbar-dropmarker-active-region);
|
||||
background-image: radial-gradient(circle closest-side, hsla(205,100%,70%,.3), hsla(205,100%,70%,0));
|
||||
background-image: radial-gradient(circle closest-side, hsla(205,100%,70%,.3), transparent);
|
||||
}
|
||||
|
||||
@media (min-resolution: 2dppx) {
|
||||
|
@ -2157,7 +2157,7 @@ toolbarbutton[sdk-button="true"][cui-areatype="toolbar"] > .toolbarbutton-icon {
|
|||
|
||||
.urlbar-icon[open="true"],
|
||||
.urlbar-icon:hover:active {
|
||||
background-image: radial-gradient(circle closest-side, hsla(205,100%,70%,.3), hsla(205,100%,70%,0));
|
||||
background-image: radial-gradient(circle closest-side, hsla(205,100%,70%,.3), transparent);
|
||||
}
|
||||
|
||||
#urlbar-search-splitter {
|
||||
|
@ -2373,7 +2373,7 @@ richlistitem[type~="action"][actiontype="switchtab"][selected="true"] > .ac-url-
|
|||
}
|
||||
|
||||
#urlbar > toolbarbutton:not([disabled]):hover:active {
|
||||
background-image: radial-gradient(circle closest-side, hsla(205,100%,70%,.3), hsla(205,100%,70%,0));
|
||||
background-image: radial-gradient(circle closest-side, hsla(205,100%,70%,.3), transparent);
|
||||
}
|
||||
|
||||
#urlbar-go-button {
|
||||
|
@ -4523,7 +4523,7 @@ menulist.translate-infobar-element > .menulist-dropmarker {
|
|||
|
||||
.chat-titlebar {
|
||||
background-color: #d9d9d9;
|
||||
background-image: linear-gradient(rgba(255,255,255,.43), rgba(255,255,255,0));
|
||||
background-image: linear-gradient(rgba(255,255,255,.43), transparent);
|
||||
}
|
||||
|
||||
.chat-titlebar[selected] {
|
||||
|
@ -4532,7 +4532,7 @@ menulist.translate-infobar-element > .menulist-dropmarker {
|
|||
|
||||
.chatbar-button {
|
||||
background-color: #d9d9d9;
|
||||
background-image: linear-gradient(rgba(255,255,255,.43), rgba(255,255,255,0));
|
||||
background-image: linear-gradient(rgba(255,255,255,.43), transparent);
|
||||
border-top-left-radius: @toolbarbuttonCornerRadius@;
|
||||
border-top-right-radius: @toolbarbuttonCornerRadius@;
|
||||
}
|
||||
|
|
|
@ -12,14 +12,14 @@
|
|||
#PanelUI-help[panel-multiview-anchor="true"]::after,
|
||||
toolbarbutton[panel-multiview-anchor="true"] {
|
||||
background-image: url(chrome://browser/skin/customizableui/subView-arrow-back-inverted@2x.png),
|
||||
linear-gradient(rgba(255,255,255,0.3), rgba(255,255,255,0));
|
||||
linear-gradient(rgba(255,255,255,0.3), transparent);
|
||||
background-size: 16px, auto;
|
||||
}
|
||||
|
||||
#PanelUI-help[panel-multiview-anchor="true"]:-moz-locale-dir(rtl)::after,
|
||||
toolbarbutton[panel-multiview-anchor="true"]:-moz-locale-dir(rtl) {
|
||||
background-image: url(chrome://browser/skin/customizableui/subView-arrow-back-inverted-rtl@2x.png),
|
||||
linear-gradient(rgba(255,255,255,0.3), rgba(255,255,255,0));
|
||||
linear-gradient(rgba(255,255,255,0.3), transparent);
|
||||
}
|
||||
|
||||
#PanelUI-fxa-status {
|
||||
|
|
|
@ -352,7 +352,7 @@ toolbarpaletteitem[place="toolbar"] {
|
|||
}
|
||||
|
||||
#customization-lwtheme-menu-footer {
|
||||
background: linear-gradient(hsla(210,4%,10%,.05) 60%, hsla(210,4%,10%,0)) border-box;
|
||||
background: linear-gradient(hsla(210,4%,10%,.05) 60%, transparent) border-box;
|
||||
border-top: 1px solid hsla(210,4%,10%,.05);
|
||||
margin-bottom: -10px;
|
||||
}
|
||||
|
@ -368,7 +368,7 @@ toolbarpaletteitem[place="toolbar"] {
|
|||
}
|
||||
|
||||
.customization-lwtheme-menu-footeritem:hover {
|
||||
background: linear-gradient(hsla(210,4%,10%,.08) 40%, hsla(210,4%,10%,0)) padding-box;
|
||||
background: linear-gradient(hsla(210,4%,10%,.08) 40%, transparent) padding-box;
|
||||
}
|
||||
|
||||
.customization-lwtheme-menu-footeritem:first-child {
|
||||
|
|
|
@ -87,9 +87,9 @@
|
|||
}
|
||||
|
||||
#PanelUI-button {
|
||||
background-image: linear-gradient(to bottom, hsla(0,0%,100%,0), hsla(0,0%,100%,.3) 30%, hsla(0,0%,100%,.3) 70%, hsla(0,0%,100%,0)),
|
||||
linear-gradient(to bottom, hsla(210,54%,20%,0), hsla(210,54%,20%,.3) 30%, hsla(210,54%,20%,.3) 70%, hsla(210,54%,20%,0)),
|
||||
linear-gradient(to bottom, hsla(0,0%,100%,0), hsla(0,0%,100%,.3) 30%, hsla(0,0%,100%,.3) 70%, hsla(0,0%,100%,0));
|
||||
background-image: linear-gradient(to bottom, transparent, hsla(0,0%,100%,.3) 30%, hsla(0,0%,100%,.3) 70%, transparent),
|
||||
linear-gradient(to bottom, transparent, hsla(210,54%,20%,.3) 30%, hsla(210,54%,20%,.3) 70%, transparent),
|
||||
linear-gradient(to bottom, transparent, hsla(0,0%,100%,.3) 30%, hsla(0,0%,100%,.3) 70%, transparent);
|
||||
background-size: 1px calc(100% - 1px), 1px calc(100% - 1px), 1px calc(100% - 1px) !important;
|
||||
background-position: 0px 0px, 1px 0px, 2px 0px;
|
||||
background-repeat: no-repeat;
|
||||
|
@ -874,7 +874,7 @@ toolbarbutton[panel-multiview-anchor="true"] > .toolbarbutton-menubutton-button
|
|||
}
|
||||
|
||||
#PanelUI-help[panel-multiview-anchor="true"] {
|
||||
background-image: linear-gradient(rgba(255,255,255,0.3), rgba(255,255,255,0));
|
||||
background-image: linear-gradient(rgba(255,255,255,0.3), transparent);
|
||||
background-position: 0;
|
||||
}
|
||||
|
||||
|
@ -885,7 +885,7 @@ toolbarbutton[panel-multiview-anchor="true"] > .toolbarbutton-menubutton-button
|
|||
height: 100%;
|
||||
width: @exitSubviewGutterWidth@;
|
||||
background-image: url(chrome://browser/skin/customizableui/subView-arrow-back-inverted.png),
|
||||
linear-gradient(rgba(255,255,255,0.3), rgba(255,255,255,0));
|
||||
linear-gradient(rgba(255,255,255,0.3), transparent);
|
||||
background-repeat: no-repeat;
|
||||
background-color: Highlight;
|
||||
background-position: left 10px center, 0;
|
||||
|
@ -893,20 +893,20 @@ toolbarbutton[panel-multiview-anchor="true"] > .toolbarbutton-menubutton-button
|
|||
|
||||
#PanelUI-help[panel-multiview-anchor="true"]:-moz-locale-dir(rtl)::after {
|
||||
background-image: url(chrome://browser/skin/customizableui/subView-arrow-back-inverted-rtl.png),
|
||||
linear-gradient(rgba(255,255,255,0.3), rgba(255,255,255,0));
|
||||
linear-gradient(rgba(255,255,255,0.3), transparent);
|
||||
background-position: right 10px center, 0;
|
||||
}
|
||||
|
||||
toolbarbutton[panel-multiview-anchor="true"] {
|
||||
background-image: url(chrome://browser/skin/customizableui/subView-arrow-back-inverted.png),
|
||||
linear-gradient(rgba(255,255,255,0.3), rgba(255,255,255,0));
|
||||
linear-gradient(rgba(255,255,255,0.3), transparent);
|
||||
background-position: right calc(@menuPanelButtonWidth@ / 2 - @exitSubviewGutterWidth@ + 2px) center;
|
||||
background-repeat: no-repeat, repeat;
|
||||
}
|
||||
|
||||
toolbarbutton[panel-multiview-anchor="true"]:-moz-locale-dir(rtl) {
|
||||
background-image: url(chrome://browser/skin/customizableui/subView-arrow-back-inverted-rtl.png),
|
||||
linear-gradient(rgba(255,255,255,0.3), rgba(255,255,255,0));
|
||||
linear-gradient(rgba(255,255,255,0.3), transparent);
|
||||
background-position: left calc(@menuPanelButtonWidth@ / 2 - @exitSubviewGutterWidth@ + 2px) center;
|
||||
}
|
||||
|
||||
|
@ -1005,9 +1005,9 @@ toolbarpaletteitem[haswideitem][place="panel"] + toolbarpaletteitem[haswideitem]
|
|||
-moz-appearance: none;
|
||||
width: 3px;
|
||||
-moz-box-align: stretch;
|
||||
background-image: linear-gradient(to bottom, hsla(0,0%,100%,0), hsla(0,0%,100%,.3) 40%, hsla(0,0%,100%,.3) 60%, hsla(0,0%,100%,0)),
|
||||
linear-gradient(to bottom, hsla(210,54%,20%,0), hsla(210,54%,20%,.15) 40%, hsla(210,54%,20%,.15) 60%, hsla(210,54%,20%,0)),
|
||||
linear-gradient(to bottom, hsla(0,0%,100%,0), hsla(0,0%,100%,.3) 40%, hsla(0,0%,100%,.3) 60%, hsla(0,0%,100%,0));
|
||||
background-image: linear-gradient(to bottom, transparent, hsla(0,0%,100%,.3) 40%, hsla(0,0%,100%,.3) 60%, transparent),
|
||||
linear-gradient(to bottom, transparent, hsla(210,54%,20%,.15) 40%, hsla(210,54%,20%,.15) 60%, transparent),
|
||||
linear-gradient(to bottom, transparent, hsla(0,0%,100%,.3) 40%, hsla(0,0%,100%,.3) 60%, transparent);
|
||||
background-size: 1px, 1px, 1px;
|
||||
background-position: 0 0, 1px 0, 2px 0;
|
||||
background-repeat: no-repeat;
|
||||
|
|
|
@ -303,7 +303,7 @@ button {
|
|||
|
||||
header {
|
||||
padding-top: 140px;
|
||||
background-image: linear-gradient(to bottom, rgba(0,0,0,0), rgba(0,0,0,0.7));
|
||||
background-image: linear-gradient(to bottom, transparent, rgba(0,0,0,0.7));
|
||||
color: #FFF;
|
||||
text-shadow: 0 1px 2px rgba(0,0,0,0.8);
|
||||
padding: 10px;
|
||||
|
|
|
@ -524,9 +524,9 @@
|
|||
.devtools-separator {
|
||||
margin: 0 2px;
|
||||
width: 2px;
|
||||
background-image: linear-gradient(hsla(204,45%,98%,0), hsla(204,45%,98%,.1), hsla(204,45%,98%,0)),
|
||||
linear-gradient(hsla(206,37%,4%,0), hsla(206,37%,4%,.6), hsla(206,37%,4%,0)),
|
||||
linear-gradient(hsla(204,45%,98%,0), hsla(204,45%,98%,.1), hsla(204,45%,98%,0));
|
||||
background-image: linear-gradient(transparent, hsla(204,45%,98%,.1), transparent),
|
||||
linear-gradient(transparent, hsla(206,37%,4%,.6), transparent),
|
||||
linear-gradient(transparent, hsla(204,45%,98%,.1), transparent);
|
||||
background-size: 1px 100%;
|
||||
background-repeat: no-repeat;
|
||||
background-position: 0, 1px, 2px;
|
||||
|
|
|
@ -126,7 +126,7 @@ chatbar > chatbox > .chat-titlebar > .chat-swap-button {
|
|||
}
|
||||
|
||||
.chat-titlebar[activity] {
|
||||
background-image: radial-gradient(ellipse closest-side at center, rgb(255,255,255), rgba(255,255,255,0));
|
||||
background-image: radial-gradient(ellipse closest-side at center, rgb(255,255,255), transparent);
|
||||
background-repeat: no-repeat;
|
||||
background-size: 100% 20px;
|
||||
background-position: 0 -10px;
|
||||
|
|
|
@ -294,7 +294,7 @@
|
|||
}
|
||||
|
||||
.tabbrowser-tab[pinned][titlechanged]:not([selected="true"]) > .tab-stack > .tab-content {
|
||||
background-image: radial-gradient(farthest-corner at center bottom, rgb(255,255,255) 3%, rgba(186,221,251,0.75) 20%, rgba(127,179,255,0.25) 40%, rgba(127,179,255,0) 70%);
|
||||
background-image: radial-gradient(farthest-corner at center bottom, rgb(255,255,255) 3%, rgba(186,221,251,0.75) 20%, rgba(127,179,255,0.25) 40%, transparent 70%);
|
||||
background-position: center bottom @tabToolbarNavbarOverlap@;
|
||||
background-repeat: no-repeat;
|
||||
background-size: 85% 100%;
|
||||
|
|
|
@ -287,7 +287,7 @@
|
|||
#nav-bar {
|
||||
border-top: 1px solid @toolbarShadowColor@ !important;
|
||||
background-clip: padding-box;
|
||||
background-image: linear-gradient(@toolbarHighlight@, rgba(255,255,255,0));
|
||||
background-image: linear-gradient(@toolbarHighlight@, transparent);
|
||||
box-shadow: 0 1px 0 @toolbarHighlight@ inset;
|
||||
}
|
||||
|
||||
|
@ -877,7 +877,7 @@ toolbarbutton[sdk-button="true"][cui-areatype="toolbar"] > .toolbarbutton-icon {
|
|||
#TabsToolbar .toolbarbutton-1 > .toolbarbutton-menubutton-button:not([disabled=true]):hover,
|
||||
.tabbrowser-arrowscrollbox > .scrollbutton-up:not([disabled=true]):hover,
|
||||
.tabbrowser-arrowscrollbox > .scrollbutton-down:not([disabled=true]):hover {
|
||||
background-image: linear-gradient(rgba(255,255,255,0), rgba(255,255,255,.5)),
|
||||
background-image: linear-gradient(transparent, rgba(255,255,255,.5)),
|
||||
linear-gradient(transparent, rgba(0,0,0,.25) 30%),
|
||||
linear-gradient(transparent, rgba(0,0,0,.25) 30%);
|
||||
background-position: 1px -1px, 0 -1px, 100% -1px;
|
||||
|
@ -1223,12 +1223,12 @@ html|*.urlbar-input:-moz-lwtheme::-moz-placeholder,
|
|||
}
|
||||
|
||||
.urlbar-icon:hover {
|
||||
background-image: radial-gradient(circle closest-side, hsla(200,100%,70%,.3), hsla(200,100%,70%,0));
|
||||
background-image: radial-gradient(circle closest-side, hsla(200,100%,70%,.3), transparent);
|
||||
}
|
||||
|
||||
.urlbar-icon[open="true"],
|
||||
.urlbar-icon:hover:active {
|
||||
background-image: radial-gradient(circle closest-side, hsla(200,100%,70%,.1), hsla(200,100%,70%,0));
|
||||
background-image: radial-gradient(circle closest-side, hsla(200,100%,70%,.1), transparent);
|
||||
}
|
||||
|
||||
#urlbar-search-splitter {
|
||||
|
@ -1343,13 +1343,13 @@ html|*.urlbar-input:-moz-lwtheme::-moz-placeholder,
|
|||
}
|
||||
|
||||
.urlbar-history-dropmarker:hover {
|
||||
background-image: radial-gradient(circle closest-side, hsla(205,100%,70%,.3), hsla(205,100%,70%,0));
|
||||
background-image: radial-gradient(circle closest-side, hsla(205,100%,70%,.3), transparent);
|
||||
-moz-image-region: rect(0px, 22px, 14px, 11px);
|
||||
}
|
||||
|
||||
.urlbar-history-dropmarker:hover:active,
|
||||
.urlbar-history-dropmarker[open="true"] {
|
||||
background-image: radial-gradient(circle closest-side, hsla(205,100%,70%,.1), hsla(205,100%,70%,0));
|
||||
background-image: radial-gradient(circle closest-side, hsla(205,100%,70%,.1), transparent);
|
||||
-moz-image-region: rect(0px, 33px, 14px, 22px);
|
||||
}
|
||||
|
||||
|
@ -1495,12 +1495,12 @@ richlistitem[type~="action"][actiontype="switchtab"] > .ac-url-box > .ac-action-
|
|||
}
|
||||
|
||||
#urlbar-reload-button:not([disabled]):hover {
|
||||
background-image: radial-gradient(circle closest-side, hsla(200,100%,70%,.2), hsla(200,100%,70%,0));
|
||||
background-image: radial-gradient(circle closest-side, hsla(200,100%,70%,.2), transparent);
|
||||
-moz-image-region: rect(14px, 14px, 28px, 0);
|
||||
}
|
||||
|
||||
#urlbar-reload-button:not([disabled]):hover:active {
|
||||
background-image: radial-gradient(circle closest-side, hsla(200,100%,60%,.1), hsla(200,100%,60%,0));
|
||||
background-image: radial-gradient(circle closest-side, hsla(200,100%,60%,.1), transparent);
|
||||
-moz-image-region: rect(28px, 14px, 42px, 0);
|
||||
}
|
||||
|
||||
|
@ -1513,12 +1513,12 @@ richlistitem[type~="action"][actiontype="switchtab"] > .ac-url-box > .ac-action-
|
|||
}
|
||||
|
||||
#urlbar-go-button:hover {
|
||||
background-image: radial-gradient(circle closest-side, hsla(110,70%,50%,.2), hsla(110,70%,50%,0));
|
||||
background-image: radial-gradient(circle closest-side, hsla(110,70%,50%,.2), transparent);
|
||||
-moz-image-region: rect(14px, 42px, 28px, 28px);
|
||||
}
|
||||
|
||||
#urlbar-go-button:hover:active {
|
||||
background-image: radial-gradient(circle closest-side, hsla(110,70%,50%,.1), hsla(110,70%,50%,0));
|
||||
background-image: radial-gradient(circle closest-side, hsla(110,70%,50%,.1), transparent);
|
||||
-moz-image-region: rect(28px, 42px, 42px, 28px);
|
||||
}
|
||||
|
||||
|
@ -1531,12 +1531,12 @@ richlistitem[type~="action"][actiontype="switchtab"] > .ac-url-box > .ac-action-
|
|||
}
|
||||
|
||||
#urlbar-stop-button:not([disabled]):hover {
|
||||
background-image: radial-gradient(circle closest-side, hsla(5,100%,75%,.3), hsla(5,100%,75%,0));
|
||||
background-image: radial-gradient(circle closest-side, hsla(5,100%,75%,.3), transparent);
|
||||
-moz-image-region: rect(14px, 28px, 28px, 14px);
|
||||
}
|
||||
|
||||
#urlbar-stop-button:hover:active {
|
||||
background-image: radial-gradient(circle closest-side, hsla(5,100%,75%,.1), hsla(5,100%,75%,0));
|
||||
background-image: radial-gradient(circle closest-side, hsla(5,100%,75%,.1), transparent);
|
||||
-moz-image-region: rect(28px, 28px, 42px, 14px);
|
||||
}
|
||||
|
||||
|
@ -2772,7 +2772,7 @@ toolbarpaletteitem[place="palette"] > #switch-to-metro-button {
|
|||
|
||||
.chat-titlebar {
|
||||
background-color: #c4cfde;
|
||||
background-image: linear-gradient(rgba(255,255,255,.5), rgba(255,255,255,0));
|
||||
background-image: linear-gradient(rgba(255,255,255,.5), transparent);
|
||||
}
|
||||
|
||||
.chat-titlebar[selected] {
|
||||
|
@ -2782,7 +2782,7 @@ toolbarpaletteitem[place="palette"] > #switch-to-metro-button {
|
|||
.chatbar-button {
|
||||
-moz-appearance: none;
|
||||
background-color: #c4cfde;
|
||||
background-image: linear-gradient(rgba(255,255,255,.5), rgba(255,255,255,0));
|
||||
background-image: linear-gradient(rgba(255,255,255,.5), transparent);
|
||||
}
|
||||
|
||||
.chatbar-button > .toolbarbutton-icon {
|
||||
|
|
|
@ -21,10 +21,10 @@
|
|||
background-color: transparent;
|
||||
/* four gradients for the bevel highlights on each edge, one for blue background */
|
||||
background-image:
|
||||
linear-gradient(to bottom, rgba(255,255,255,0.9) 3px, rgba(255,255,255,0) 3px),
|
||||
linear-gradient(to right, rgba(255,255,255,0.5) 3px, rgba(255,255,255,0) 3px),
|
||||
linear-gradient(to left, rgba(255,255,255,0.5) 3px, rgba(255,255,255,0) 3px),
|
||||
linear-gradient(to top, rgba(255,255,255,0.4) 3px, rgba(255,255,255,0) 3px),
|
||||
linear-gradient(to bottom, rgba(255,255,255,0.9) 3px, transparent 3px),
|
||||
linear-gradient(to right, rgba(255,255,255,0.5) 3px, transparent 3px),
|
||||
linear-gradient(to left, rgba(255,255,255,0.5) 3px, transparent 3px),
|
||||
linear-gradient(to top, rgba(255,255,255,0.4) 3px, transparent 3px),
|
||||
linear-gradient(to bottom, rgba(163,196,247,0.3), rgba(122,180,246,0.3));
|
||||
background-clip: content-box;
|
||||
border-radius: 6px;
|
||||
|
|
|
@ -84,7 +84,7 @@ browser.jar:
|
|||
skin/classic/browser/Toolbar.png (Toolbar-XP.png)
|
||||
skin/classic/browser/Toolbar-inverted.png
|
||||
skin/classic/browser/Toolbar-lunaSilver.png
|
||||
skin/classic/browser/toolbarbutton-dropdown-arrow.png
|
||||
skin/classic/browser/toolbarbutton-dropdown-arrow.png (toolbarbutton-dropdown-arrow-XPVista7.png)
|
||||
skin/classic/browser/toolbarbutton-dropdown-arrow-inverted.png
|
||||
skin/classic/browser/undoCloseTab.png (../shared/undoCloseTab.png)
|
||||
skin/classic/browser/undoCloseTab@2x.png (../shared/undoCloseTab@2x.png)
|
||||
|
@ -192,13 +192,13 @@ browser.jar:
|
|||
skin/classic/browser/social/chat-icons.svg (../shared/social/chat-icons.svg)
|
||||
skin/classic/browser/social/gear_default.png (../shared/social/gear_default.png)
|
||||
skin/classic/browser/social/gear_clicked.png (../shared/social/gear_clicked.png)
|
||||
skin/classic/browser/tabbrowser/newtab.png (tabbrowser/newtab.png)
|
||||
skin/classic/browser/tabbrowser/newtab.png (tabbrowser/newtab-XPVista7.png)
|
||||
skin/classic/browser/tabbrowser/newtab-inverted.png (tabbrowser/newtab-inverted.png)
|
||||
skin/classic/browser/tabbrowser/connecting.png (tabbrowser/connecting.png)
|
||||
skin/classic/browser/tabbrowser/loading.png (tabbrowser/loading.png)
|
||||
skin/classic/browser/tabbrowser/tab-active-middle.png (tabbrowser/tab-active-middle.png)
|
||||
skin/classic/browser/tabbrowser/tab-active-middle@2x.png (tabbrowser/tab-active-middle@2x.png)
|
||||
skin/classic/browser/tabbrowser/tab-arrow-left.png (tabbrowser/tab-arrow-left.png)
|
||||
skin/classic/browser/tabbrowser/tab-arrow-left.png (tabbrowser/tab-arrow-left-XPVista7.png)
|
||||
skin/classic/browser/tabbrowser/tab-arrow-left-inverted.png (tabbrowser/tab-arrow-left-inverted.png)
|
||||
skin/classic/browser/tabbrowser/tab-background-start.png (tabbrowser/tab-background-start.png)
|
||||
skin/classic/browser/tabbrowser/tab-background-start@2x.png (tabbrowser/tab-background-start@2x.png)
|
||||
|
@ -516,6 +516,7 @@ browser.jar:
|
|||
skin/classic/aero/browser/Toolbar-inverted.png
|
||||
skin/classic/aero/browser/Toolbar-aero.png
|
||||
skin/classic/aero/browser/toolbarbutton-dropdown-arrow.png
|
||||
skin/classic/aero/browser/toolbarbutton-dropdown-arrow-XPVista7.png
|
||||
skin/classic/aero/browser/toolbarbutton-dropdown-arrow-inverted.png
|
||||
skin/classic/aero/browser/undoCloseTab.png (../shared/undoCloseTab.png)
|
||||
skin/classic/aero/browser/undoCloseTab@2x.png (../shared/undoCloseTab@2x.png)
|
||||
|
@ -626,12 +627,14 @@ browser.jar:
|
|||
skin/classic/aero/browser/social/gear_default.png (../shared/social/gear_default.png)
|
||||
skin/classic/aero/browser/social/gear_clicked.png (../shared/social/gear_clicked.png)
|
||||
skin/classic/aero/browser/tabbrowser/newtab.png (tabbrowser/newtab.png)
|
||||
skin/classic/aero/browser/tabbrowser/newtab-XPVista7.png (tabbrowser/newtab-XPVista7.png)
|
||||
skin/classic/aero/browser/tabbrowser/newtab-inverted.png (tabbrowser/newtab-inverted.png)
|
||||
skin/classic/aero/browser/tabbrowser/connecting.png (tabbrowser/connecting.png)
|
||||
skin/classic/aero/browser/tabbrowser/loading.png (tabbrowser/loading.png)
|
||||
skin/classic/aero/browser/tabbrowser/tab-active-middle.png (tabbrowser/tab-active-middle.png)
|
||||
skin/classic/aero/browser/tabbrowser/tab-active-middle@2x.png (tabbrowser/tab-active-middle@2x.png)
|
||||
skin/classic/aero/browser/tabbrowser/tab-arrow-left.png (tabbrowser/tab-arrow-left.png)
|
||||
skin/classic/aero/browser/tabbrowser/tab-arrow-left-XPVista7.png (tabbrowser/tab-arrow-left-XPVista7.png)
|
||||
skin/classic/aero/browser/tabbrowser/tab-arrow-left-inverted.png (tabbrowser/tab-arrow-left-inverted.png)
|
||||
skin/classic/aero/browser/tabbrowser/tab-background-start.png (tabbrowser/tab-background-start.png)
|
||||
skin/classic/aero/browser/tabbrowser/tab-background-start@2x.png (tabbrowser/tab-background-start@2x.png)
|
||||
|
@ -875,5 +878,14 @@ browser.jar:
|
|||
% override chrome://browser/skin/sync-horizontalbar.png chrome://browser/skin/sync-horizontalbar-XPVista7.png os=WINNT osversion<6.2
|
||||
% override chrome://browser/skin/syncProgress-horizontalbar.png chrome://browser/skin/syncProgress-horizontalbar-XPVista7.png os=WINNT osversion<6.2
|
||||
|
||||
% override chrome://browser/skin/toolbarbutton-dropdown-arrow.png chrome://browser/skin/toolbarbutton-dropdown-arrow-XPVista7.png os=WINNT osversion=6
|
||||
% override chrome://browser/skin/toolbarbutton-dropdown-arrow.png chrome://browser/skin/toolbarbutton-dropdown-arrow-XPVista7.png os=WINNT osversion=6.1
|
||||
|
||||
% override chrome://browser/skin/tabbrowser/newtab.png chrome://browser/skin/tabbrowser/newtab-XPVista7.png os=WINNT osversion=6
|
||||
% override chrome://browser/skin/tabbrowser/newtab.png chrome://browser/skin/tabbrowser/newtab-XPVista7.png os=WINNT osversion=6.1
|
||||
|
||||
% override chrome://browser/skin/tabbrowser/tab-arrow-left.png chrome://browser/skin/tabbrowser/tab-arrow-left-XPVista7.png os=WINNT osversion=6
|
||||
% override chrome://browser/skin/tabbrowser/tab-arrow-left.png chrome://browser/skin/tabbrowser/tab-arrow-left-XPVista7.png os=WINNT osversion=6.1
|
||||
|
||||
% override chrome://browser/skin/loop/toolbar.png chrome://browser/skin/loop/toolbar-XPVista7.png os=WINNT osversion=6
|
||||
% override chrome://browser/skin/loop/toolbar.png chrome://browser/skin/loop/toolbar-XPVista7.png os=WINNT osversion=6.1
|
||||
|
|
|
@ -32,7 +32,7 @@
|
|||
}
|
||||
|
||||
#placesToolbar {
|
||||
background-image: linear-gradient(@toolbarHighlight@, rgba(255,255,255,0));
|
||||
background-image: linear-gradient(@toolbarHighlight@, transparent);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
После Ширина: | Высота: | Размер: 237 B |
Двоичные данные
browser/themes/windows/tabbrowser/newtab.png
До Ширина: | Высота: | Размер: 237 B После Ширина: | Высота: | Размер: 105 B |
После Ширина: | Высота: | Размер: 302 B |
Двоичные данные
browser/themes/windows/tabbrowser/tab-arrow-left.png
До Ширина: | Высота: | Размер: 302 B После Ширина: | Высота: | Размер: 122 B |
После Ширина: | Высота: | Размер: 208 B |
Двоичные данные
browser/themes/windows/toolbarbutton-dropdown-arrow.png
До Ширина: | Высота: | Размер: 208 B После Ширина: | Высота: | Размер: 91 B |
|
@ -2873,7 +2873,7 @@ nsDocShell::PopProfileTimelineMarkers(JSContext* aCx,
|
|||
// If we see an unpaired START, we keep it around for the next call
|
||||
// to PopProfileTimelineMarkers. We store the kept START objects in
|
||||
// this array.
|
||||
decltype(mProfileTimelineMarkers) keptMarkers;
|
||||
nsTArray<InternalProfileTimelineMarker*> keptMarkers;
|
||||
|
||||
for (uint32_t i = 0; i < mProfileTimelineMarkers.Length(); ++i) {
|
||||
ProfilerMarkerTracing* startPayload = static_cast<ProfilerMarkerTracing*>(
|
||||
|
|
|
@ -103,6 +103,7 @@ import android.nfc.NfcEvent;
|
|||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.os.StrictMode;
|
||||
import android.support.v4.app.DialogFragment;
|
||||
import android.support.v4.app.FragmentManager;
|
||||
import android.support.v4.content.LocalBroadcastManager;
|
||||
import android.text.TextUtils;
|
||||
|
@ -152,6 +153,7 @@ public class BrowserApp extends GeckoApp
|
|||
private static final String STATE_ABOUT_HOME_TOP_PADDING = "abouthome_top_padding";
|
||||
|
||||
private static final String BROWSER_SEARCH_TAG = "browser_search";
|
||||
private static final String ONBOARD_STARTPANE_TAG = "startpane_dialog";
|
||||
|
||||
// Request ID for startActivityForResult.
|
||||
private static final int ACTIVITY_REQUEST_PREFERENCES = 1001;
|
||||
|
@ -628,8 +630,8 @@ public class BrowserApp extends GeckoApp
|
|||
|
||||
if (prefs.getBoolean(PREF_STARTPANE_ENABLED, false)) {
|
||||
if (!Intent.ACTION_VIEW.equals(intentAction)) {
|
||||
final Intent startIntent = new Intent(this, StartPane.class);
|
||||
context.startActivity(startIntent);
|
||||
final DialogFragment dialog = new StartPane();
|
||||
dialog.show(getSupportFragmentManager(), ONBOARD_STARTPANE_TAG);
|
||||
}
|
||||
// Don't bother trying again to show the v1 minimal first run.
|
||||
prefs.edit().putBoolean(PREF_STARTPANE_ENABLED, false).apply();
|
||||
|
@ -637,7 +639,7 @@ public class BrowserApp extends GeckoApp
|
|||
} finally {
|
||||
StrictMode.setThreadPolicy(savedPolicy);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private Class<?> getMediaPlayerManager() {
|
||||
if (AppConstants.MOZ_MEDIA_PLAYER) {
|
||||
|
|
|
@ -27,13 +27,8 @@ import android.widget.Toast;
|
|||
public final class ReadingListHelper implements GeckoEventListener, NativeEventListener {
|
||||
private static final String LOGTAG = "ReadingListHelper";
|
||||
|
||||
private static final int READER_ADD_SUCCESS = 0;
|
||||
private static final int READER_ADD_FAILED = 1;
|
||||
private static final int READER_ADD_DUPLICATE = 2;
|
||||
|
||||
protected final Context context;
|
||||
|
||||
|
||||
public ReadingListHelper(Context context) {
|
||||
this.context = context;
|
||||
|
||||
|
@ -86,16 +81,6 @@ public final class ReadingListHelper implements GeckoEventListener, NativeEventL
|
|||
* icon, or by tapping the readinglist-add icon in the ReaderMode banner.
|
||||
*/
|
||||
private void handleAddToList(JSONObject message) {
|
||||
final int result = message.optInt("result", READER_ADD_FAILED);
|
||||
if (result != READER_ADD_SUCCESS) {
|
||||
if (result == READER_ADD_FAILED) {
|
||||
showToast(R.string.reading_list_failed, Toast.LENGTH_SHORT);
|
||||
} else if (result == READER_ADD_DUPLICATE) {
|
||||
showToast(R.string.reading_list_duplicate, Toast.LENGTH_SHORT);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
final ContentValues values = new ContentValues();
|
||||
final String url = message.optString("url");
|
||||
|
||||
|
|
|
@ -1,73 +1,71 @@
|
|||
package org.mozilla.gecko;
|
||||
|
||||
import org.mozilla.gecko.fxa.activities.FxAccountGetStartedActivity;
|
||||
import org.mozilla.gecko.util.HardwareUtils;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
import android.support.v4.app.DialogFragment;
|
||||
import android.view.GestureDetector;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.MotionEvent;
|
||||
import android.view.View;
|
||||
import android.view.View.OnClickListener;
|
||||
import android.view.View.OnTouchListener;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.Button;
|
||||
|
||||
public class StartPane extends Activity {
|
||||
public class StartPane extends DialogFragment {
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle bundle) {
|
||||
super.onCreate(bundle);
|
||||
setContentView(R.layout.onboard_start_pane);
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setStyle(DialogFragment.STYLE_NO_TITLE, 0);
|
||||
}
|
||||
|
||||
final Button accountButton = (Button) findViewById(R.id.button_account);
|
||||
accountButton.setOnClickListener(new OnClickListener() {
|
||||
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
Telemetry.sendUIEvent(TelemetryContract.Event.ACTION, TelemetryContract.Method.BUTTON, "firstrun-sync");
|
||||
showAccountSetup();
|
||||
}
|
||||
});
|
||||
|
||||
final Button browserButton = (Button) findViewById(R.id.button_browser);
|
||||
@Override
|
||||
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle bundle) {
|
||||
final View view = inflater.inflate(R.layout.onboard_start_pane, container, false);
|
||||
final Button browserButton = (Button) view.findViewById(R.id.button_browser);
|
||||
browserButton.setOnClickListener(new OnClickListener() {
|
||||
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
Telemetry.sendUIEvent(TelemetryContract.Event.ACTION, TelemetryContract.Method.BUTTON, "firstrun-browser");
|
||||
showBrowser();
|
||||
Telemetry.sendUIEvent(TelemetryContract.Event.ACTION, TelemetryContract.Method.BUTTON, "firstrun-sync");
|
||||
|
||||
// StartPane is on the stack above the browser, so just dismiss this Fragment.
|
||||
StartPane.this.dismiss();
|
||||
}
|
||||
});
|
||||
|
||||
if (!HardwareUtils.isTablet() && !HardwareUtils.isTelevision()) {
|
||||
addDismissHandler();
|
||||
}
|
||||
}
|
||||
final Button accountButton = (Button) view.findViewById(R.id.button_account);
|
||||
accountButton.setOnClickListener(new OnClickListener() {
|
||||
|
||||
private void showBrowser() {
|
||||
// StartPane is on the stack above the browser, so just kill this activity.
|
||||
finish();
|
||||
}
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
Telemetry.sendUIEvent(TelemetryContract.Event.ACTION, TelemetryContract.Method.BUTTON, "firstrun-browser");
|
||||
|
||||
private void showAccountSetup() {
|
||||
final Intent intent = new Intent(this, FxAccountGetStartedActivity.class);
|
||||
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||
startActivity(intent);
|
||||
finish();
|
||||
final Intent intent = new Intent(getActivity(), FxAccountGetStartedActivity.class);
|
||||
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||
startActivity(intent);
|
||||
StartPane.this.dismiss();
|
||||
}
|
||||
});
|
||||
|
||||
addDismissHandler(view);
|
||||
return view;
|
||||
}
|
||||
|
||||
// Add handler for dismissing the StartPane on a single click.
|
||||
private void addDismissHandler() {
|
||||
final GestureDetector gestureDetector = new GestureDetector(this, new GestureDetector.SimpleOnGestureListener() {
|
||||
private void addDismissHandler(View view) {
|
||||
final GestureDetector gestureDetector = new GestureDetector(getActivity(), new GestureDetector.SimpleOnGestureListener() {
|
||||
@Override
|
||||
public boolean onSingleTapUp(MotionEvent e) {
|
||||
StartPane.this.finish();
|
||||
StartPane.this.dismiss();
|
||||
return true;
|
||||
}
|
||||
});
|
||||
|
||||
findViewById(R.id.onboard_content).setOnTouchListener(new OnTouchListener() {
|
||||
view.findViewById(R.id.onboard_content).setOnTouchListener(new OnTouchListener() {
|
||||
@Override
|
||||
public boolean onTouch(View v, MotionEvent event) {
|
||||
return gestureDetector.onTouchEvent(event);
|
||||
|
|
|
@ -359,8 +359,6 @@ size. -->
|
|||
<!ENTITY site_settings_no_settings "There are no settings to clear.">
|
||||
|
||||
<!ENTITY reading_list_added "Page added to your Reading List">
|
||||
<!ENTITY reading_list_failed "Failed to add page to your Reading List">
|
||||
<!ENTITY reading_list_duplicate "Page already in your Reading List">
|
||||
|
||||
<!-- Localization note (reading_list_time_minutes) : This string is used in the "Reading List"
|
||||
panel on the home page to give the user an estimate of how many minutes it will take to
|
||||
|
|
|
@ -10,10 +10,12 @@
|
|||
android:right="-2dp"
|
||||
android:left="-2dp">
|
||||
<shape>
|
||||
<!-- Padding creates vertical space between the text and the underline -->
|
||||
<!-- Padding creates vertical space between the text and the underline,
|
||||
as well as right padding for search icon/clear button -->
|
||||
<padding
|
||||
android:top="@dimen/search_bar_padding_y"
|
||||
android:bottom="@dimen/search_bar_padding_y"/>
|
||||
android:bottom="@dimen/search_bar_padding_y"
|
||||
android:right="@dimen/search_bar_padding_right"/>
|
||||
<solid android:color="@android:color/transparent"/>
|
||||
<stroke android:width="1dp" android:color="@color/edit_text_default"/>
|
||||
</shape>
|
||||
|
|
|
@ -10,10 +10,12 @@
|
|||
android:right="-3dp"
|
||||
android:left="-3dp">
|
||||
<shape>
|
||||
<!-- Padding creates vertical space between the text and the underline -->
|
||||
<!-- Padding creates vertical space between the text and the underline,
|
||||
as well as right padding for search icon/clear button -->
|
||||
<padding
|
||||
android:top="@dimen/search_bar_padding_y"
|
||||
android:bottom="@dimen/search_bar_padding_y"/>
|
||||
android:bottom="@dimen/search_bar_padding_y"
|
||||
android:right="@dimen/search_bar_padding_right"/>
|
||||
<solid android:color="@android:color/transparent"/>
|
||||
<!-- We apply a color filter to set the color for the selected search engine -->
|
||||
<stroke android:width="2dp" android:color="@android:color/white"/>
|
||||
|
|
|
@ -5,10 +5,10 @@
|
|||
|
||||
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
style="@style/OnboardStartLayout"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_width="wrap_content"
|
||||
android:orientation="vertical"
|
||||
android:background="@color/onboard_start"
|
||||
android:windowIsFloating="true">
|
||||
android:background="@color/onboard_start">
|
||||
|
||||
<ScrollView android:id="@+id/onboard_content"
|
||||
android:layout_width="match_parent"
|
||||
|
@ -25,8 +25,8 @@
|
|||
android:layout_height="0dp"
|
||||
android:layout_weight="1"/>
|
||||
|
||||
<RelativeLayout android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
<RelativeLayout android:layout_width="wrap_content"
|
||||
android:layout_height="match_parent"
|
||||
android:paddingTop="15dp">
|
||||
|
||||
<ImageView android:id="@+id/image_shield"
|
||||
|
@ -59,34 +59,35 @@
|
|||
<ImageView android:id="@+id/image_sync"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_centerHorizontal="true"
|
||||
android:layout_below="@id/image_shield"
|
||||
android:layout_toLeftOf="@id/image_logo"
|
||||
android:layout_marginRight="30dp"
|
||||
android:paddingRight="200dp"
|
||||
android:src="@drawable/onboard_start_sync"
|
||||
android:contentDescription="@string/onboard_empty_contentDescription"/>
|
||||
|
||||
<ImageView android:id="@+id/image_addon"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_below="@id/image_private"
|
||||
android:layout_toRightOf="@id/image_logo"
|
||||
android:layout_marginLeft="30dp"
|
||||
android:layout_centerHorizontal="true"
|
||||
android:layout_below="@id/image_shield"
|
||||
android:paddingLeft="200dp"
|
||||
android:src="@drawable/onboard_start_addon"
|
||||
android:contentDescription="@string/onboard_empty_contentDescription"/>
|
||||
|
||||
<TextView android:id="@+id/text_message"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_below="@id/image_logo"
|
||||
android:layout_centerHorizontal="true"
|
||||
android:layout_marginTop="30dp"
|
||||
android:gravity="center"
|
||||
android:padding="10sp"
|
||||
android:text="@string/onboard_start_message"
|
||||
android:textAppearance="@style/OnboardStartTextAppearance"
|
||||
android:textSize="23sp" />
|
||||
|
||||
<TextView android:layout_width="295dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_gravity="center"
|
||||
android:gravity="center"
|
||||
android:layout_below="@id/text_message"
|
||||
|
@ -124,4 +125,4 @@
|
|||
android:text="@string/onboard_start_button_browser"/>
|
||||
|
||||
</LinearLayout>
|
||||
</LinearLayout>
|
||||
</LinearLayout>
|
|
@ -168,11 +168,6 @@
|
|||
<item name="android:layout_gravity">center</item>
|
||||
</style>
|
||||
|
||||
<style name="OnboardStartLayout">
|
||||
<item name="android:layout_height">wrap_content</item>
|
||||
<item name="android:layout_width">400dp</item>
|
||||
</style>
|
||||
|
||||
<style name="TextAppearance.UrlBar.Title" parent="TextAppearance.Medium">
|
||||
<item name="android:textSize">16sp</item>
|
||||
</style>
|
||||
|
|
|
@ -14,6 +14,9 @@
|
|||
<dimen name="search_row_padding">15dp</dimen>
|
||||
<dimen name="search_bar_padding_y">10dp</dimen>
|
||||
|
||||
<!-- Padding to account for search engine icon/clear button -->
|
||||
<dimen name="search_bar_padding_right">25dp</dimen>
|
||||
|
||||
<dimen name="search_history_drawable_padding">10dp</dimen>
|
||||
|
||||
<!-- Widget Buttons -->
|
||||
|
|
|
@ -835,10 +835,6 @@
|
|||
<item name="android:windowIsTranslucent">true</item>
|
||||
<item name="android:backgroundDimEnabled">true</item>
|
||||
</style>
|
||||
<style name="OnboardStartLayout">
|
||||
<item name="android:layout_width">match_parent</item>
|
||||
<item name="android:layout_height">match_parent</item>
|
||||
</style>
|
||||
|
||||
<style name="OnboardStartTextAppearance">
|
||||
<item name="android:textColor">#5F636B</item>
|
||||
|
|
|
@ -294,8 +294,6 @@
|
|||
<string name="site_settings_no_settings">&site_settings_no_settings;</string>
|
||||
|
||||
<string name="reading_list_added">&reading_list_added;</string>
|
||||
<string name="reading_list_failed">&reading_list_failed;</string>
|
||||
<string name="reading_list_duplicate">&reading_list_duplicate;</string>
|
||||
<string name="reading_list_time_minutes">&reading_list_time_minutes;</string>
|
||||
<string name="reading_list_time_over_an_hour">&reading_list_time_over_an_hour;</string>
|
||||
|
||||
|
|
|
@ -10,10 +10,6 @@ let Reader = {
|
|||
|
||||
DEBUG: 0,
|
||||
|
||||
READER_ADD_SUCCESS: 0,
|
||||
READER_ADD_FAILED: 1,
|
||||
READER_ADD_DUPLICATE: 2,
|
||||
|
||||
// Don't try to parse the page if it has too many elements (for memory and
|
||||
// performance reasons)
|
||||
MAX_ELEMS_TO_PARSE: 3000,
|
||||
|
@ -38,7 +34,7 @@ let Reader = {
|
|||
},
|
||||
|
||||
readerModeActiveCallback: function(tabID) {
|
||||
Reader.addTabToReadingList(tabID);
|
||||
Reader._addTabToReadingList(tabID);
|
||||
UITelemetry.addEvent("save.1", "pageaction", null, "reader");
|
||||
},
|
||||
},
|
||||
|
@ -93,50 +89,49 @@ let Reader = {
|
|||
}
|
||||
},
|
||||
|
||||
addTabToReadingList: function(tabID) {
|
||||
_addTabToReadingList: function(tabID) {
|
||||
let tab = BrowserApp.getTabForId(tabID);
|
||||
let currentURI = tab.browser.currentURI;
|
||||
let url = currentURI.spec;
|
||||
let urlWithoutRef = currentURI.specIgnoringRef;
|
||||
|
||||
let sendResult = function(result, article) {
|
||||
article = article || {};
|
||||
|
||||
Messaging.sendRequest({
|
||||
type: "Reader:AddToList",
|
||||
result: result,
|
||||
title: truncate(article.title, MAX_TITLE_LENGTH),
|
||||
url: truncate(url, MAX_URI_LENGTH),
|
||||
length: article.length,
|
||||
excerpt: article.excerpt
|
||||
});
|
||||
}.bind(this);
|
||||
|
||||
let handleArticle = function(article) {
|
||||
if (!article) {
|
||||
sendResult(this.READER_ADD_FAILED, null);
|
||||
return;
|
||||
}
|
||||
|
||||
this.storeArticleInCache(article, function(success) {
|
||||
let result = (success ? this.READER_ADD_SUCCESS : this.READER_ADD_FAILED);
|
||||
sendResult(result, article);
|
||||
}.bind(this));
|
||||
}.bind(this);
|
||||
|
||||
this.getArticleFromCache(urlWithoutRef, function (article) {
|
||||
// If the article is already in reading list, bail
|
||||
this.getArticleFromCache(urlWithoutRef, (article) => {
|
||||
// If the article is already in the cache, just use that.
|
||||
if (article) {
|
||||
sendResult(this.READER_ADD_DUPLICATE, null);
|
||||
this.addArticleToReadingList(article);
|
||||
return;
|
||||
}
|
||||
|
||||
if (tabID != null) {
|
||||
this.getArticleForTab(tabID, urlWithoutRef, handleArticle);
|
||||
} else {
|
||||
this.parseDocumentFromURL(urlWithoutRef, handleArticle);
|
||||
}
|
||||
}.bind(this));
|
||||
// Otherwise, get the article data from the tab.
|
||||
this.getArticleForTab(tabID, urlWithoutRef, (article) => {
|
||||
if (article) {
|
||||
this.addArticleToReadingList(article);
|
||||
} else {
|
||||
// If there was a problem getting the article, just store the
|
||||
// URL and title from the tab.
|
||||
this.addArticleToReadingList({
|
||||
url: urlWithoutRef,
|
||||
title: tab.browser.contentDocument.title,
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
},
|
||||
|
||||
addArticleToReadingList: function(article) {
|
||||
if (!article || !article.url) {
|
||||
Cu.reportError("addArticleToReadingList requires article with valid URL");
|
||||
return;
|
||||
}
|
||||
|
||||
Messaging.sendRequest({
|
||||
type: "Reader:AddToList",
|
||||
url: truncate(article.url, MAX_URI_LENGTH),
|
||||
title: truncate(article.title || "", MAX_TITLE_LENGTH),
|
||||
length: article.length || 0,
|
||||
excerpt: article.excerpt || "",
|
||||
});
|
||||
|
||||
this.storeArticleInCache(article);
|
||||
},
|
||||
|
||||
getStateForParseOnLoad: function Reader_getStateForParseOnLoad() {
|
||||
|
@ -261,10 +256,9 @@ let Reader = {
|
|||
}.bind(this));
|
||||
},
|
||||
|
||||
storeArticleInCache: function Reader_storeArticleInCache(article, callback) {
|
||||
storeArticleInCache: function Reader_storeArticleInCache(article) {
|
||||
this._getCacheDB(function(cacheDB) {
|
||||
if (!cacheDB) {
|
||||
callback(false);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -275,12 +269,10 @@ let Reader = {
|
|||
|
||||
request.onerror = function(event) {
|
||||
this.log("Error storing article in the cache DB: " + article.url);
|
||||
callback(false);
|
||||
}.bind(this);
|
||||
|
||||
request.onsuccess = function(event) {
|
||||
this.log("Stored article in the cache DB: " + article.url);
|
||||
callback(true);
|
||||
}.bind(this);
|
||||
}.bind(this));
|
||||
},
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
|
||||
const { classes: Cc, interfaces: Ci, utils: Cu } = Components;
|
||||
|
||||
Cu.import("resource://gre/modules/PrivateBrowsingUtils.jsm");
|
||||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
|
||||
|
@ -78,7 +79,11 @@ var WebcompatReporter = {
|
|||
let webcompatURL = new URL("http://webcompat.com/");
|
||||
webcompatURL.searchParams.append("open", "1");
|
||||
webcompatURL.searchParams.append("url", url);
|
||||
BrowserApp.addTab(webcompatURL.href);
|
||||
if (PrivateBrowsingUtils.isBrowserPrivate(BrowserApp.selectedTab.browser)) {
|
||||
BrowserApp.addTab(webcompatURL.href, {parentId: BrowserApp.selectedTab.id, isPrivate: true});
|
||||
} else {
|
||||
BrowserApp.addTab(webcompatURL.href);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -320,25 +320,9 @@ AboutReader.prototype = {
|
|||
return;
|
||||
|
||||
if (this._isReadingListItem == 0) {
|
||||
let uptime = UITelemetry.uptimeMillis();
|
||||
gChromeWin.Reader.storeArticleInCache(this._article, function(success) {
|
||||
let result = gChromeWin.Reader.READER_ADD_FAILED;
|
||||
if (success) {
|
||||
result = gChromeWin.Reader.READER_ADD_SUCCESS;
|
||||
UITelemetry.addEvent("save.1", "button", uptime, "reader");
|
||||
}
|
||||
gChromeWin.Reader.addArticleToReadingList(this._article);
|
||||
|
||||
let json = JSON.stringify({ fromAboutReader: true, url: this._article.url });
|
||||
|
||||
Messaging.sendRequest({
|
||||
type: "Reader:AddToList",
|
||||
result: result,
|
||||
title: this._article.title,
|
||||
url: this._article.url,
|
||||
length: this._article.length,
|
||||
excerpt: this._article.excerpt
|
||||
});
|
||||
}.bind(this));
|
||||
UITelemetry.addEvent("save.1", "button", null, "reader");
|
||||
} else {
|
||||
Messaging.sendRequest({
|
||||
type: "Reader:RemoveFromList",
|
||||
|
|
|
@ -212,7 +212,7 @@ let TimelineActor = exports.TimelineActor = protocol.ActorClass({
|
|||
|
||||
if (withMemory) {
|
||||
this._memoryActor = new MemoryActor(this.conn, this.tabActor);
|
||||
events.emit(this, "memory", Date.now(), this._memoryActor.measure());
|
||||
events.emit(this, "memory", this._startTime, this._memoryActor.measure());
|
||||
}
|
||||
if (withTicks) {
|
||||
this._framerateActor = new FramerateActor(this.conn, this.tabActor);
|
||||
|
|
|
@ -36,7 +36,7 @@ button {
|
|||
border-radius: 2px;
|
||||
color: black !important;
|
||||
background-color: hsl(0,0%,90%);
|
||||
background-image: linear-gradient(hsla(0,0%,100%,.7), hsla(0,0%,100%,0));
|
||||
background-image: linear-gradient(hsla(0,0%,100%,.7), transparent);
|
||||
background-clip: padding-box;
|
||||
border: 1px solid;
|
||||
border-color: hsl(0,0%,65%) hsl(0,0%,60%) hsl(0,0%,50%);
|
||||
|
@ -54,7 +54,7 @@ button:hover {
|
|||
}
|
||||
|
||||
button:hover:active {
|
||||
background-image: linear-gradient(hsla(0,0%,100%,.2), hsla(0,0%,100%,0));
|
||||
background-image: linear-gradient(hsla(0,0%,100%,.2), transparent);
|
||||
background-color: hsl(0,0%,70%);
|
||||
box-shadow: 0 1px 0 hsla(0,0%,100%,.2) inset,
|
||||
0 1px 3px hsla(0,0%,0%,.2);
|
||||
|
|
|
@ -797,7 +797,7 @@
|
|||
|
||||
#detail-screenshot[loading] {
|
||||
background-image: url("chrome://global/skin/icons/loading_16.png"),
|
||||
linear-gradient(rgba(255, 255, 255, 0.5), rgba(255, 255, 255, 0));
|
||||
linear-gradient(rgba(255, 255, 255, 0.5), transparent);
|
||||
background-position: 50% 50%;
|
||||
background-repeat: no-repeat;
|
||||
border-radius: 3px;
|
||||
|
@ -805,7 +805,7 @@
|
|||
|
||||
#detail-screenshot[loading="error"] {
|
||||
background-image: url("chrome://global/skin/media/error.png"),
|
||||
linear-gradient(rgba(255, 255, 255, 0.5), rgba(255, 255, 255, 0));
|
||||
linear-gradient(rgba(255, 255, 255, 0.5), transparent);
|
||||
}
|
||||
|
||||
#detail-desc-container {
|
||||
|
@ -1152,7 +1152,7 @@ button.button-link:not([disabled="true"]):active:hover {
|
|||
border: 1px solid rgba(60,73,97,0.5);
|
||||
border-radius: @toolbarbuttonCornerRadius@;
|
||||
box-shadow: inset 0 1px rgba(255,255,255,0.25), 0 1px rgba(255,255,255,0.25);
|
||||
background: linear-gradient(rgba(255,255,255,0.45), rgba(255,255,255,0));
|
||||
background: linear-gradient(rgba(255,255,255,0.45), transparent);
|
||||
background-clip: padding-box;
|
||||
}
|
||||
|
||||
|
@ -1168,7 +1168,7 @@ button.button-link:not([disabled="true"]):active:hover {
|
|||
.header-button[open="true"] {
|
||||
border-color: rgba(45,54,71,0.7);
|
||||
box-shadow: inset 0 0 4px rgb(45,54,71), 0 1px rgba(255,255,255,0.25);
|
||||
background-image: linear-gradient(rgba(45,54,71,0.6), rgba(45,54,71,0));
|
||||
background-image: linear-gradient(rgba(45,54,71,0.6), transparent);
|
||||
}
|
||||
|
||||
/*** telemetry experiments ***/
|
||||
|
|
|
@ -116,10 +116,10 @@ treechildren.autocomplete-treebody::-moz-tree-cell-text(selected) {
|
|||
background-color: transparent;
|
||||
/* four gradients for the bevel highlights on each edge, one for blue background */
|
||||
background-image:
|
||||
linear-gradient(to bottom, rgba(255,255,255,0.9) 3px, rgba(255,255,255,0) 3px),
|
||||
linear-gradient(to right, rgba(255,255,255,0.5) 3px, rgba(255,255,255,0) 3px),
|
||||
linear-gradient(to left, rgba(255,255,255,0.5) 3px, rgba(255,255,255,0) 3px),
|
||||
linear-gradient(to top, rgba(255,255,255,0.4) 3px, rgba(255,255,255,0) 3px),
|
||||
linear-gradient(to bottom, rgba(255,255,255,0.9) 3px, transparent 3px),
|
||||
linear-gradient(to right, rgba(255,255,255,0.5) 3px, transparent 3px),
|
||||
linear-gradient(to left, rgba(255,255,255,0.5) 3px, transparent 3px),
|
||||
linear-gradient(to top, rgba(255,255,255,0.4) 3px, transparent 3px),
|
||||
linear-gradient(to bottom, rgba(163,196,247,0.3), rgba(122,180,246,0.3));
|
||||
background-clip: content-box;
|
||||
border-radius: 6px;
|
||||
|
|
|
@ -38,22 +38,22 @@ html|html {
|
|||
/* Blame shorlander for this monstrosity. */
|
||||
background-image: /* Side gradients */
|
||||
linear-gradient(to right,
|
||||
rgba(255,255,255,0.2), rgba(255,255,255,0) 40%,
|
||||
rgba(255,255,255,0) 60%, rgba(255,255,255,0.2)),
|
||||
rgba(255,255,255,0.2), transparent 40%,
|
||||
transparent 60%, rgba(255,255,255,0.2)),
|
||||
/* Aero-style light beams */
|
||||
-moz-linear-gradient(left 32deg,
|
||||
/* First light beam */
|
||||
rgba(255,255,255,0) 19.5%, rgba(255,255,255,0.1) 20%,
|
||||
transparent 19.5%, rgba(255,255,255,0.1) 20%,
|
||||
rgba(255,255,255,0.1) 21.5%, rgba(255,255,255,0.2) 22%,
|
||||
rgba(255,255,255,0.2) 25.5%, rgba(255,255,255,0.1) 26%,
|
||||
rgba(255,255,255,0.1) 27.5%, rgba(255,255,255,0) 28%,
|
||||
rgba(255,255,255,0.1) 27.5%, transparent 28%,
|
||||
/* Second light beam */
|
||||
rgba(255,255,255,0) 49.5%, rgba(255,255,255,0.1) 50%,
|
||||
transparent 49.5%, rgba(255,255,255,0.1) 50%,
|
||||
rgba(255,255,255,0.1) 52.5%, rgba(255,255,255,0.2) 53%,
|
||||
rgba(255,255,255,0.2) 54.5%, rgba(255,255,255,0.1) 55%,
|
||||
rgba(255,255,255,0.1) 57.5%, rgba(255,255,255,0) 58%,
|
||||
rgba(255,255,255,0.1) 57.5%, transparent 58%,
|
||||
/* Third light beam */
|
||||
rgba(255,255,255,0) 87%, rgba(255,255,255,0.2) 90%),
|
||||
transparent 87%, rgba(255,255,255,0.2) 90%),
|
||||
/* Texture */
|
||||
url("chrome://global/skin/inContentUI/background-texture.png");
|
||||
}
|
||||
|
@ -88,7 +88,7 @@ html|html {
|
|||
-moz-appearance: none;
|
||||
color: black;
|
||||
padding: 0 5px;
|
||||
background: linear-gradient(rgba(251, 252, 253, 0.95), rgba(246, 247, 248, 0) 49%,
|
||||
background: linear-gradient(rgba(251, 252, 253, 0.95), transparent 49%,
|
||||
rgba(211, 212, 213, 0.45) 51%, rgba(225, 226, 229, 0.3));
|
||||
background-clip: padding-box;
|
||||
border-radius: 3px;
|
||||
|
|
|
@ -790,7 +790,7 @@
|
|||
|
||||
#detail-screenshot[loading] {
|
||||
background-image: url("chrome://global/skin/icons/loading_16.png"),
|
||||
linear-gradient(rgba(255, 255, 255, 0.5), rgba(255, 255, 255, 0));
|
||||
linear-gradient(rgba(255, 255, 255, 0.5), transparent);
|
||||
background-position: 50% 50%;
|
||||
background-repeat: no-repeat;
|
||||
border-radius: 3px;
|
||||
|
@ -798,7 +798,7 @@
|
|||
|
||||
#detail-screenshot[loading="error"] {
|
||||
background-image: url("chrome://global/skin/media/error.png"),
|
||||
linear-gradient(rgba(255, 255, 255, 0.5), rgba(255, 255, 255, 0));
|
||||
linear-gradient(rgba(255, 255, 255, 0.5), transparent);
|
||||
}
|
||||
|
||||
#detail-desc-container {
|
||||
|
@ -1161,7 +1161,7 @@ button.button-link:not([disabled="true"]):active:hover {
|
|||
padding: 1px 3px;
|
||||
color: #444;
|
||||
text-shadow: 0 0 3px white;
|
||||
background: linear-gradient(rgba(251, 252, 253, 0.95), rgba(246, 247, 248, 0) 49%,
|
||||
background: linear-gradient(rgba(251, 252, 253, 0.95), transparent 49%,
|
||||
rgba(211, 212, 213, 0.45) 51%, rgba(225, 226, 229, 0.3));
|
||||
background-clip: padding-box;
|
||||
border: 1px solid rgba(31, 64, 100, 0.4);
|
||||
|
|