mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Merge m-c to b2g-inbound on a CLOSED TREE. a=merge
This commit is contained in:
commit
12d25024ad
@ -3,7 +3,7 @@
|
|||||||
- You can obtain one at http://mozilla.org/MPL/2.0/. */
|
- You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
const Cc = Components.classes;
|
const Cc = Components.classes;
|
||||||
const Ci = Components.interfaces;
|
const Ci = Components.interfaces;
|
||||||
const Cu = Components.utils;
|
const Cu = Components.utils;
|
||||||
@ -42,7 +42,9 @@ function init_all() {
|
|||||||
this.removeAttribute("keyboard-navigation");
|
this.removeAttribute("keyboard-navigation");
|
||||||
});
|
});
|
||||||
|
|
||||||
gotoPref("paneGeneral");
|
if (document.getElementById("category-general").selected) {
|
||||||
|
gotoPref("paneGeneral");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function selectCategory(name) {
|
function selectCategory(name) {
|
||||||
|
@ -6,6 +6,7 @@ support-files =
|
|||||||
[browser_advanced_update.js]
|
[browser_advanced_update.js]
|
||||||
[browser_bug410900.js]
|
[browser_bug410900.js]
|
||||||
[browser_bug731866.js]
|
[browser_bug731866.js]
|
||||||
|
[browser_bug1020245_openPreferences_to_paneContent.js]
|
||||||
[browser_bug795764_cachedisabled.js]
|
[browser_bug795764_cachedisabled.js]
|
||||||
[browser_connection.js]
|
[browser_connection.js]
|
||||||
[browser_connection_bug388287.js]
|
[browser_connection_bug388287.js]
|
||||||
|
@ -0,0 +1,25 @@
|
|||||||
|
/* Any copyright is dedicated to the Public Domain.
|
||||||
|
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||||
|
|
||||||
|
add_task(function test() {
|
||||||
|
waitForExplicitFinish();
|
||||||
|
let deferred = Promise.defer();
|
||||||
|
gBrowser.selectedTab = gBrowser.addTab("about:blank");
|
||||||
|
openPreferences("paneContent");
|
||||||
|
let newTabBrowser = gBrowser.getBrowserForTab(gBrowser.selectedTab);
|
||||||
|
|
||||||
|
newTabBrowser.addEventListener("Initialized", function PrefInit() {
|
||||||
|
newTabBrowser.removeEventListener("Initialized", PrefInit, true);
|
||||||
|
newTabBrowser.contentWindow.addEventListener("load", function prefLoad() {
|
||||||
|
newTabBrowser.contentWindow.removeEventListener("load", prefLoad);
|
||||||
|
let sel = gBrowser.contentWindow.history.state;
|
||||||
|
is(sel, "paneContent", "Content pane was selected");
|
||||||
|
deferred.resolve();
|
||||||
|
gBrowser.removeCurrentTab();
|
||||||
|
});
|
||||||
|
}, true);
|
||||||
|
|
||||||
|
yield deferred.promise;
|
||||||
|
|
||||||
|
finish();
|
||||||
|
});
|
@ -223,6 +223,14 @@ let NetMonitorController = {
|
|||||||
this.webConsoleClient = null;
|
this.webConsoleClient = null;
|
||||||
},
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks whether the netmonitor connection is active.
|
||||||
|
* @return boolean
|
||||||
|
*/
|
||||||
|
isConnected: function() {
|
||||||
|
return !!this.client;
|
||||||
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets up a monitoring session.
|
* Sets up a monitoring session.
|
||||||
*
|
*
|
||||||
|
@ -1980,6 +1980,8 @@ NetworkDetailsView.prototype = {
|
|||||||
*/
|
*/
|
||||||
destroy: function() {
|
destroy: function() {
|
||||||
dumpn("Destroying the NetworkDetailsView");
|
dumpn("Destroying the NetworkDetailsView");
|
||||||
|
|
||||||
|
$("tabpanels", this.widget).removeEventListener("select", this._onTabSelect);
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -2068,7 +2070,10 @@ NetworkDetailsView.prototype = {
|
|||||||
}
|
}
|
||||||
populated[tab] = true;
|
populated[tab] = true;
|
||||||
window.emit(EVENTS.TAB_UPDATED);
|
window.emit(EVENTS.TAB_UPDATED);
|
||||||
NetMonitorView.RequestsMenu.ensureSelectedItemIsVisible();
|
|
||||||
|
if (NetMonitorController.isConnected()) {
|
||||||
|
NetMonitorView.RequestsMenu.ensureSelectedItemIsVisible();
|
||||||
|
}
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -39,8 +39,9 @@ function test() {
|
|||||||
'-H "Connection: keep-alive"'
|
'-H "Connection: keep-alive"'
|
||||||
].join(" ");
|
].join(" ");
|
||||||
|
|
||||||
const EXPECTED_RESULT = Services.appinfo.OS == "WINNT" ?
|
const EXPECTED_RESULT = Services.appinfo.OS == "WINNT"
|
||||||
EXPECTED_WIN_RESULT : EXPECTED_POSIX_RESULT;
|
? EXPECTED_WIN_RESULT
|
||||||
|
: EXPECTED_POSIX_RESULT;
|
||||||
|
|
||||||
let { NetMonitorView } = aMonitor.panelWin;
|
let { NetMonitorView } = aMonitor.panelWin;
|
||||||
let { RequestsMenu } = NetMonitorView;
|
let { RequestsMenu } = NetMonitorView;
|
||||||
|
@ -31,7 +31,7 @@ function test() {
|
|||||||
waitFor(aMonitor.panelWin, RESPONSE_BODY_DISPLAYED).then(() =>
|
waitFor(aMonitor.panelWin, RESPONSE_BODY_DISPLAYED).then(() =>
|
||||||
NetMonitorView.editor("#response-content-textarea")
|
NetMonitorView.editor("#response-content-textarea")
|
||||||
).then((aEditor) => {
|
).then((aEditor) => {
|
||||||
is(aEditor.getText().indexOf("\u044F"), 302, // я
|
is(aEditor.getText().indexOf("\u044F"), 486, // я
|
||||||
"The text shown in the source editor is incorrect.");
|
"The text shown in the source editor is incorrect.");
|
||||||
is(aEditor.getMode(), Editor.modes.html,
|
is(aEditor.getMode(), Editor.modes.html,
|
||||||
"The mode active in the source editor is incorrect.");
|
"The mode active in the source editor is incorrect.");
|
||||||
|
@ -6,6 +6,11 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
function test() {
|
function test() {
|
||||||
|
// These test suite functions are removed from the global scope inside a
|
||||||
|
// cleanup function. However, we still need them.
|
||||||
|
let gInfo = info;
|
||||||
|
let gOk = ok;
|
||||||
|
|
||||||
initNetMonitor(SIMPLE_URL).then(([aTab, aDebuggee, aMonitor]) => {
|
initNetMonitor(SIMPLE_URL).then(([aTab, aDebuggee, aMonitor]) => {
|
||||||
info("Starting test... ");
|
info("Starting test... ");
|
||||||
|
|
||||||
@ -36,20 +41,20 @@ function test() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function checkIfDestroyed(aTag) {
|
function checkIfDestroyed(aTag) {
|
||||||
info("Checking if destruction is ok.");
|
gInfo("Checking if destruction is ok.");
|
||||||
|
|
||||||
ok(aMonitor._view,
|
gOk(aMonitor._view,
|
||||||
"The network monitor view object still exists (" + aTag + ").");
|
"The network monitor view object still exists (" + aTag + ").");
|
||||||
ok(aMonitor._controller,
|
gOk(aMonitor._controller,
|
||||||
"The network monitor controller object still exists (" + aTag + ").");
|
"The network monitor controller object still exists (" + aTag + ").");
|
||||||
ok(aMonitor._controller._shutdown,
|
gOk(aMonitor._controller._shutdown,
|
||||||
"The network monitor controller object still exists and is destroyed (" + aTag + ").");
|
"The network monitor controller object still exists and is destroyed (" + aTag + ").");
|
||||||
|
|
||||||
ok(!aMonitor._controller.client,
|
gOk(!aMonitor._controller.client,
|
||||||
"There shouldn't be a client available after destruction (" + aTag + ").");
|
"There shouldn't be a client available after destruction (" + aTag + ").");
|
||||||
ok(!aMonitor._controller.tabClient,
|
gOk(!aMonitor._controller.tabClient,
|
||||||
"There shouldn't be a tabClient available after destruction (" + aTag + ").");
|
"There shouldn't be a tabClient available after destruction (" + aTag + ").");
|
||||||
ok(!aMonitor._controller.webConsoleClient,
|
gOk(!aMonitor._controller.webConsoleClient,
|
||||||
"There shouldn't be a webConsoleClient available after destruction (" + aTag + ").");
|
"There shouldn't be a webConsoleClient available after destruction (" + aTag + ").");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -75,12 +80,12 @@ function test() {
|
|||||||
|
|
||||||
aMonitor._controller.shutdownNetMonitor()
|
aMonitor._controller.shutdownNetMonitor()
|
||||||
.then(() => {
|
.then(() => {
|
||||||
info("Shutting down again shouldn't do anything special.");
|
gInfo("Shutting down again shouldn't do anything special.");
|
||||||
checkIfDestroyed(2);
|
checkIfDestroyed(2);
|
||||||
return aMonitor._controller.disconnect();
|
return aMonitor._controller.disconnect();
|
||||||
})
|
})
|
||||||
.then(() => {
|
.then(() => {
|
||||||
info("Disconnecting again shouldn't do anything special.");
|
gInfo("Disconnecting again shouldn't do anything special.");
|
||||||
checkIfDestroyed(3);
|
checkIfDestroyed(3);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -86,10 +86,8 @@ function test() {
|
|||||||
|
|
||||||
ok(requestItem.attachment.requestHeaders,
|
ok(requestItem.attachment.requestHeaders,
|
||||||
"There should be a requestHeaders attachment available.");
|
"There should be a requestHeaders attachment available.");
|
||||||
ok(requestItem.attachment.requestHeaders.headers.length >= 6,
|
is(requestItem.attachment.requestHeaders.headers.length, 8,
|
||||||
"The requestHeaders attachment has an incorrect |headers| property.");
|
"The requestHeaders attachment has an incorrect |headers| property.");
|
||||||
// Can't test for an exact total number of headers, because it seems to
|
|
||||||
// vary across pgo/non-pgo builds.
|
|
||||||
isnot(requestItem.attachment.requestHeaders.headersSize, 0,
|
isnot(requestItem.attachment.requestHeaders.headersSize, 0,
|
||||||
"The requestHeaders attachment has an incorrect |headersSize| property.");
|
"The requestHeaders attachment has an incorrect |headersSize| property.");
|
||||||
// Can't test for the exact request headers size because the value may
|
// Can't test for the exact request headers size because the value may
|
||||||
@ -118,9 +116,9 @@ function test() {
|
|||||||
|
|
||||||
ok(requestItem.attachment.responseHeaders,
|
ok(requestItem.attachment.responseHeaders,
|
||||||
"There should be a responseHeaders attachment available.");
|
"There should be a responseHeaders attachment available.");
|
||||||
is(requestItem.attachment.responseHeaders.headers.length, 6,
|
is(requestItem.attachment.responseHeaders.headers.length, 9,
|
||||||
"The responseHeaders attachment has an incorrect |headers| property.");
|
"The responseHeaders attachment has an incorrect |headers| property.");
|
||||||
is(requestItem.attachment.responseHeaders.headersSize, 173,
|
is(requestItem.attachment.responseHeaders.headersSize, 255,
|
||||||
"The responseHeaders attachment has an incorrect |headersSize| property.");
|
"The responseHeaders attachment has an incorrect |headersSize| property.");
|
||||||
|
|
||||||
verifyRequestItemTarget(requestItem, "GET", SIMPLE_SJS);
|
verifyRequestItemTarget(requestItem, "GET", SIMPLE_SJS);
|
||||||
@ -146,7 +144,7 @@ function test() {
|
|||||||
"The status attachment has an incorrect value.");
|
"The status attachment has an incorrect value.");
|
||||||
is(requestItem.attachment.statusText, "Och Aye",
|
is(requestItem.attachment.statusText, "Och Aye",
|
||||||
"The statusText attachment has an incorrect value.");
|
"The statusText attachment has an incorrect value.");
|
||||||
is(requestItem.attachment.headersSize, 173,
|
is(requestItem.attachment.headersSize, 255,
|
||||||
"The headersSize attachment has an incorrect value.");
|
"The headersSize attachment has an incorrect value.");
|
||||||
|
|
||||||
verifyRequestItemTarget(requestItem, "GET", SIMPLE_SJS, {
|
verifyRequestItemTarget(requestItem, "GET", SIMPLE_SJS, {
|
||||||
|
@ -63,10 +63,8 @@ function test() {
|
|||||||
|
|
||||||
is(tabpanel.querySelectorAll(".variables-view-scope").length, 2,
|
is(tabpanel.querySelectorAll(".variables-view-scope").length, 2,
|
||||||
"There should be 2 header scopes displayed in this tabpanel.");
|
"There should be 2 header scopes displayed in this tabpanel.");
|
||||||
ok(tabpanel.querySelectorAll(".variable-or-property").length >= 12,
|
is(tabpanel.querySelectorAll(".variable-or-property").length, 17,
|
||||||
"There should be at least 12 header values displayed in this tabpanel.");
|
"There should be 17 header values displayed in this tabpanel.");
|
||||||
// Can't test for an exact total number of headers, because it seems to
|
|
||||||
// vary across pgo/non-pgo builds.
|
|
||||||
|
|
||||||
is(tabpanel.querySelectorAll(".variables-view-empty-notice").length, 0,
|
is(tabpanel.querySelectorAll(".variables-view-empty-notice").length, 0,
|
||||||
"The empty notice should not be displayed in this tabpanel.");
|
"The empty notice should not be displayed in this tabpanel.");
|
||||||
@ -76,7 +74,7 @@ function test() {
|
|||||||
|
|
||||||
is(responseScope.querySelector(".name").getAttribute("value"),
|
is(responseScope.querySelector(".name").getAttribute("value"),
|
||||||
L10N.getStr("responseHeaders") + " (" +
|
L10N.getStr("responseHeaders") + " (" +
|
||||||
L10N.getFormatStr("networkMenu.sizeKB", L10N.numberWithDecimals(173/1024, 3)) + ")",
|
L10N.getFormatStr("networkMenu.sizeKB", L10N.numberWithDecimals(255/1024, 3)) + ")",
|
||||||
"The response headers scope doesn't have the correct title.");
|
"The response headers scope doesn't have the correct title.");
|
||||||
|
|
||||||
ok(requestScope.querySelector(".name").getAttribute("value").contains(
|
ok(requestScope.querySelector(".name").getAttribute("value").contains(
|
||||||
@ -87,20 +85,24 @@ function test() {
|
|||||||
// sure it's smaller than 1 MB though, so it starts with a 0.
|
// sure it's smaller than 1 MB though, so it starts with a 0.
|
||||||
|
|
||||||
is(responseScope.querySelectorAll(".variables-view-variable .name")[0].getAttribute("value"),
|
is(responseScope.querySelectorAll(".variables-view-variable .name")[0].getAttribute("value"),
|
||||||
"Connection", "The first response header name was incorrect.");
|
"Cache-Control", "The first response header name was incorrect.");
|
||||||
is(responseScope.querySelectorAll(".variables-view-variable .value")[0].getAttribute("value"),
|
is(responseScope.querySelectorAll(".variables-view-variable .value")[0].getAttribute("value"),
|
||||||
"\"close\"", "The first response header value was incorrect.");
|
"\"no-cache, no-store, must-revalidate\"", "The first response header value was incorrect.");
|
||||||
is(responseScope.querySelectorAll(".variables-view-variable .name")[1].getAttribute("value"),
|
is(responseScope.querySelectorAll(".variables-view-variable .name")[1].getAttribute("value"),
|
||||||
"Content-Length", "The second response header name was incorrect.");
|
"Connection", "The second response header name was incorrect.");
|
||||||
is(responseScope.querySelectorAll(".variables-view-variable .value")[1].getAttribute("value"),
|
is(responseScope.querySelectorAll(".variables-view-variable .value")[1].getAttribute("value"),
|
||||||
"\"12\"", "The second response header value was incorrect.");
|
"\"close\"", "The second response header value was incorrect.");
|
||||||
is(responseScope.querySelectorAll(".variables-view-variable .name")[2].getAttribute("value"),
|
is(responseScope.querySelectorAll(".variables-view-variable .name")[2].getAttribute("value"),
|
||||||
"Content-Type", "The third response header name was incorrect.");
|
"Content-Length", "The third response header name was incorrect.");
|
||||||
is(responseScope.querySelectorAll(".variables-view-variable .value")[2].getAttribute("value"),
|
is(responseScope.querySelectorAll(".variables-view-variable .value")[2].getAttribute("value"),
|
||||||
"\"text/plain; charset=utf-8\"", "The third response header value was incorrect.");
|
"\"12\"", "The third response header value was incorrect.");
|
||||||
is(responseScope.querySelectorAll(".variables-view-variable .name")[5].getAttribute("value"),
|
is(responseScope.querySelectorAll(".variables-view-variable .name")[3].getAttribute("value"),
|
||||||
|
"Content-Type", "The fourth response header name was incorrect.");
|
||||||
|
is(responseScope.querySelectorAll(".variables-view-variable .value")[3].getAttribute("value"),
|
||||||
|
"\"text/plain; charset=utf-8\"", "The fourth response header value was incorrect.");
|
||||||
|
is(responseScope.querySelectorAll(".variables-view-variable .name")[8].getAttribute("value"),
|
||||||
"foo-bar", "The last response header name was incorrect.");
|
"foo-bar", "The last response header name was incorrect.");
|
||||||
is(responseScope.querySelectorAll(".variables-view-variable .value")[5].getAttribute("value"),
|
is(responseScope.querySelectorAll(".variables-view-variable .value")[8].getAttribute("value"),
|
||||||
"\"baz\"", "The last response header value was incorrect.");
|
"\"baz\"", "The last response header value was incorrect.");
|
||||||
|
|
||||||
is(requestScope.querySelectorAll(".variables-view-variable .name")[0].getAttribute("value"),
|
is(requestScope.querySelectorAll(".variables-view-variable .name")[0].getAttribute("value"),
|
||||||
@ -108,21 +110,17 @@ function test() {
|
|||||||
is(requestScope.querySelectorAll(".variables-view-variable .value")[0].getAttribute("value"),
|
is(requestScope.querySelectorAll(".variables-view-variable .value")[0].getAttribute("value"),
|
||||||
"\"example.com\"", "The first request header value was incorrect.");
|
"\"example.com\"", "The first request header value was incorrect.");
|
||||||
is(requestScope.querySelectorAll(".variables-view-variable .name")[5].getAttribute("value"),
|
is(requestScope.querySelectorAll(".variables-view-variable .name")[5].getAttribute("value"),
|
||||||
"Connection", "The penultimate request header name was incorrect.");
|
"Connection", "The ante-penultimate request header name was incorrect.");
|
||||||
is(requestScope.querySelectorAll(".variables-view-variable .value")[5].getAttribute("value"),
|
is(requestScope.querySelectorAll(".variables-view-variable .value")[5].getAttribute("value"),
|
||||||
"\"keep-alive\"", "The penultimate request header value was incorrect.");
|
"\"keep-alive\"", "The ante-penultimate request header value was incorrect.");
|
||||||
|
is(requestScope.querySelectorAll(".variables-view-variable .name")[6].getAttribute("value"),
|
||||||
let lastReqHeaderName = requestScope.querySelectorAll(".variables-view-variable .name")[6];
|
"Pragma", "The penultimate request header name was incorrect.");
|
||||||
let lastReqHeaderValue = requestScope.querySelectorAll(".variables-view-variable .value")[6];
|
is(requestScope.querySelectorAll(".variables-view-variable .value")[6].getAttribute("value"),
|
||||||
if (lastReqHeaderName && lastReqHeaderValue) {
|
"\"no-cache\"", "The penultimate request header value was incorrect.");
|
||||||
is(lastReqHeaderName.getAttribute("value"),
|
is(requestScope.querySelectorAll(".variables-view-variable .name")[7].getAttribute("value"),
|
||||||
"Cache-Control", "The last request header name was incorrect.");
|
"Cache-Control", "The last request header name was incorrect.");
|
||||||
is(lastReqHeaderValue.getAttribute("value"),
|
is(requestScope.querySelectorAll(".variables-view-variable .value")[7].getAttribute("value"),
|
||||||
"\"max-age=0\"", "The last request header value was incorrect.");
|
"\"no-cache\"", "The last request header value was incorrect.");
|
||||||
} else {
|
|
||||||
info("The number of request headers was 6 instead of 7. Technically, " +
|
|
||||||
"not a failure in this particular test, but needs investigation.");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function testCookiesTab() {
|
function testCookiesTab() {
|
||||||
|
@ -15,11 +15,38 @@ function test() {
|
|||||||
RequestsMenu.lazyUpdate = false;
|
RequestsMenu.lazyUpdate = false;
|
||||||
|
|
||||||
waitForNetworkEvents(aMonitor, 2).then(() => {
|
waitForNetworkEvents(aMonitor, 2).then(() => {
|
||||||
let divisions = $all(".requests-menu-timings-division[division-scale=second]");
|
let millisecondDivs = $all(".requests-menu-timings-division[division-scale=millisecond]");
|
||||||
|
let secondDivs = $all(".requests-menu-timings-division[division-scale=second]");
|
||||||
|
let minuteDivs = $all(".requests-menu-timings-division[division-scale=minute]");
|
||||||
|
|
||||||
ok(divisions.length,
|
info("Number of millisecond divisions: " + millisecondDivs.length);
|
||||||
|
info("Number of second divisions: " + secondDivs.length);
|
||||||
|
info("Number of minute divisions: " + minuteDivs.length);
|
||||||
|
|
||||||
|
for (let div of millisecondDivs) {
|
||||||
|
info("Millisecond division: " + div.getAttribute("value"));
|
||||||
|
}
|
||||||
|
for (let div of secondDivs) {
|
||||||
|
info("Second division: " + div.getAttribute("value"));
|
||||||
|
}
|
||||||
|
for (let div of minuteDivs) {
|
||||||
|
info("Minute division: " + div.getAttribute("value"));
|
||||||
|
}
|
||||||
|
|
||||||
|
is(RequestsMenu.itemCount, 2,
|
||||||
|
"There should be only two requests made.");
|
||||||
|
|
||||||
|
let firstRequest = RequestsMenu.getItemAtIndex(0);
|
||||||
|
let lastRequest = RequestsMenu.getItemAtIndex(1);
|
||||||
|
|
||||||
|
info("First request happened at: " +
|
||||||
|
firstRequest.attachment.responseHeaders.headers.find(e => e.name == "Date").value);
|
||||||
|
info("Last request happened at: " +
|
||||||
|
lastRequest.attachment.responseHeaders.headers.find(e => e.name == "Date").value);
|
||||||
|
|
||||||
|
ok(secondDivs.length,
|
||||||
"There should be at least one division on the seconds time scale.");
|
"There should be at least one division on the seconds time scale.");
|
||||||
ok(divisions[0].getAttribute("value").match(/\d+\.\d{2}\s\w+/),
|
ok(secondDivs[0].getAttribute("value").match(/\d+\.\d{2}\s\w+/),
|
||||||
"The division on the seconds time scale looks legit.");
|
"The division on the seconds time scale looks legit.");
|
||||||
|
|
||||||
teardown(aMonitor).then(finish);
|
teardown(aMonitor).then(finish);
|
||||||
|
@ -97,24 +97,49 @@ function removeTab(aTab, aWindow) {
|
|||||||
targetBrowser.removeTab(aTab);
|
targetBrowser.removeTab(aTab);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function waitForNavigation(aTarget) {
|
||||||
|
let deferred = promise.defer();
|
||||||
|
aTarget.once("will-navigate", () => {
|
||||||
|
aTarget.once("navigate", () => {
|
||||||
|
deferred.resolve();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
return deferred.promise;
|
||||||
|
}
|
||||||
|
|
||||||
|
function reconfigureTab(aTarget, aOptions) {
|
||||||
|
let deferred = promise.defer();
|
||||||
|
aTarget.activeTab.reconfigure(aOptions, deferred.resolve);
|
||||||
|
return deferred.promise;
|
||||||
|
};
|
||||||
|
|
||||||
|
function toggleCache(aTarget, aEnabled) {
|
||||||
|
let options = { cacheEnabled: aEnabled, performReload: true };
|
||||||
|
let navigationFinished = waitForNavigation(aTarget);
|
||||||
|
return reconfigureTab(aTarget, options).then(() => navigationFinished);
|
||||||
|
}
|
||||||
|
|
||||||
function initNetMonitor(aUrl, aWindow) {
|
function initNetMonitor(aUrl, aWindow) {
|
||||||
info("Initializing a network monitor pane.");
|
info("Initializing a network monitor pane.");
|
||||||
|
|
||||||
return addTab(aUrl).then((aTab) => {
|
return Task.spawn(function*() {
|
||||||
|
let tab = yield addTab(aUrl);
|
||||||
info("Net tab added successfully: " + aUrl);
|
info("Net tab added successfully: " + aUrl);
|
||||||
|
|
||||||
let deferred = promise.defer();
|
let debuggee = tab.linkedBrowser.contentWindow.wrappedJSObject;
|
||||||
let debuggee = aTab.linkedBrowser.contentWindow.wrappedJSObject;
|
let target = TargetFactory.forTab(tab);
|
||||||
let target = TargetFactory.forTab(aTab);
|
|
||||||
|
|
||||||
gDevTools.showToolbox(target, "netmonitor").then((aToolbox) => {
|
yield target.makeRemote();
|
||||||
info("Netork monitor pane shown successfully.");
|
info("Target remoted.");
|
||||||
|
|
||||||
let monitor = aToolbox.getCurrentPanel();
|
yield toggleCache(target, false);
|
||||||
deferred.resolve([aTab, debuggee, monitor]);
|
info("Network cache disabled");
|
||||||
});
|
|
||||||
|
|
||||||
return deferred.promise;
|
let toolbox = yield gDevTools.showToolbox(target, "netmonitor");
|
||||||
|
info("Netork monitor pane shown successfully.");
|
||||||
|
|
||||||
|
let monitor = toolbox.getCurrentPanel();
|
||||||
|
return [tab, debuggee, monitor];
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5,6 +5,9 @@
|
|||||||
<html>
|
<html>
|
||||||
<head>
|
<head>
|
||||||
<meta charset="utf-8"/>
|
<meta charset="utf-8"/>
|
||||||
|
<meta http-equiv="Cache-Control" content="no-cache, no-store, must-revalidate" />
|
||||||
|
<meta http-equiv="Pragma" content="no-cache" />
|
||||||
|
<meta http-equiv="Expires" content="0" />
|
||||||
<title>Network Monitor test page</title>
|
<title>Network Monitor test page</title>
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
|
@ -5,6 +5,9 @@
|
|||||||
<html>
|
<html>
|
||||||
<head>
|
<head>
|
||||||
<meta charset="utf-8"/>
|
<meta charset="utf-8"/>
|
||||||
|
<meta http-equiv="Cache-Control" content="no-cache, no-store, must-revalidate" />
|
||||||
|
<meta http-equiv="Pragma" content="no-cache" />
|
||||||
|
<meta http-equiv="Expires" content="0" />
|
||||||
<title>Network Monitor test page</title>
|
<title>Network Monitor test page</title>
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
|
@ -5,6 +5,9 @@
|
|||||||
<html>
|
<html>
|
||||||
<head>
|
<head>
|
||||||
<meta charset="utf-8"/>
|
<meta charset="utf-8"/>
|
||||||
|
<meta http-equiv="Cache-Control" content="no-cache, no-store, must-revalidate" />
|
||||||
|
<meta http-equiv="Pragma" content="no-cache" />
|
||||||
|
<meta http-equiv="Expires" content="0" />
|
||||||
<title>Network Monitor test page</title>
|
<title>Network Monitor test page</title>
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
|
@ -5,6 +5,9 @@
|
|||||||
<html>
|
<html>
|
||||||
<head>
|
<head>
|
||||||
<meta charset="utf-8"/>
|
<meta charset="utf-8"/>
|
||||||
|
<meta http-equiv="Cache-Control" content="no-cache, no-store, must-revalidate" />
|
||||||
|
<meta http-equiv="Pragma" content="no-cache" />
|
||||||
|
<meta http-equiv="Expires" content="0" />
|
||||||
<title>Network Monitor test page</title>
|
<title>Network Monitor test page</title>
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
|
@ -5,6 +5,9 @@
|
|||||||
<html>
|
<html>
|
||||||
<head>
|
<head>
|
||||||
<meta charset="utf-8"/>
|
<meta charset="utf-8"/>
|
||||||
|
<meta http-equiv="Cache-Control" content="no-cache, no-store, must-revalidate" />
|
||||||
|
<meta http-equiv="Pragma" content="no-cache" />
|
||||||
|
<meta http-equiv="Expires" content="0" />
|
||||||
<title>Network Monitor test page</title>
|
<title>Network Monitor test page</title>
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
|
@ -5,6 +5,9 @@
|
|||||||
<html>
|
<html>
|
||||||
<head>
|
<head>
|
||||||
<meta charset="utf-8"/>
|
<meta charset="utf-8"/>
|
||||||
|
<meta http-equiv="Cache-Control" content="no-cache, no-store, must-revalidate" />
|
||||||
|
<meta http-equiv="Pragma" content="no-cache" />
|
||||||
|
<meta http-equiv="Expires" content="0" />
|
||||||
<title>Network Monitor test page</title>
|
<title>Network Monitor test page</title>
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
|
@ -5,6 +5,9 @@
|
|||||||
<html>
|
<html>
|
||||||
<head>
|
<head>
|
||||||
<meta charset="utf-8"/>
|
<meta charset="utf-8"/>
|
||||||
|
<meta http-equiv="Cache-Control" content="no-cache, no-store, must-revalidate" />
|
||||||
|
<meta http-equiv="Pragma" content="no-cache" />
|
||||||
|
<meta http-equiv="Expires" content="0" />
|
||||||
<title>Network Monitor test page</title>
|
<title>Network Monitor test page</title>
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
|
@ -5,6 +5,9 @@
|
|||||||
<html>
|
<html>
|
||||||
<head>
|
<head>
|
||||||
<meta charset="utf-8"/>
|
<meta charset="utf-8"/>
|
||||||
|
<meta http-equiv="Cache-Control" content="no-cache, no-store, must-revalidate" />
|
||||||
|
<meta http-equiv="Pragma" content="no-cache" />
|
||||||
|
<meta http-equiv="Expires" content="0" />
|
||||||
<title>Network Monitor test page</title>
|
<title>Network Monitor test page</title>
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
|
@ -5,6 +5,9 @@
|
|||||||
<html>
|
<html>
|
||||||
<head>
|
<head>
|
||||||
<meta charset="utf-8"/>
|
<meta charset="utf-8"/>
|
||||||
|
<meta http-equiv="Cache-Control" content="no-cache, no-store, must-revalidate" />
|
||||||
|
<meta http-equiv="Pragma" content="no-cache" />
|
||||||
|
<meta http-equiv="Expires" content="0" />
|
||||||
<title>Network Monitor test page</title>
|
<title>Network Monitor test page</title>
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
|
@ -5,6 +5,9 @@
|
|||||||
<html>
|
<html>
|
||||||
<head>
|
<head>
|
||||||
<meta charset="utf-8"/>
|
<meta charset="utf-8"/>
|
||||||
|
<meta http-equiv="Cache-Control" content="no-cache, no-store, must-revalidate" />
|
||||||
|
<meta http-equiv="Pragma" content="no-cache" />
|
||||||
|
<meta http-equiv="Expires" content="0" />
|
||||||
<title>Network Monitor test page</title>
|
<title>Network Monitor test page</title>
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
|
@ -5,6 +5,9 @@
|
|||||||
<html>
|
<html>
|
||||||
<head>
|
<head>
|
||||||
<meta charset="utf-8"/>
|
<meta charset="utf-8"/>
|
||||||
|
<meta http-equiv="Cache-Control" content="no-cache, no-store, must-revalidate" />
|
||||||
|
<meta http-equiv="Pragma" content="no-cache" />
|
||||||
|
<meta http-equiv="Expires" content="0" />
|
||||||
<title>Network Monitor test page</title>
|
<title>Network Monitor test page</title>
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
|
@ -5,6 +5,9 @@
|
|||||||
<html>
|
<html>
|
||||||
<head>
|
<head>
|
||||||
<meta charset="utf-8"/>
|
<meta charset="utf-8"/>
|
||||||
|
<meta http-equiv="Cache-Control" content="no-cache, no-store, must-revalidate" />
|
||||||
|
<meta http-equiv="Pragma" content="no-cache" />
|
||||||
|
<meta http-equiv="Expires" content="0" />
|
||||||
<title>Network Monitor test page</title>
|
<title>Network Monitor test page</title>
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
|
@ -5,6 +5,9 @@
|
|||||||
<html>
|
<html>
|
||||||
<head>
|
<head>
|
||||||
<meta charset="utf-8"/>
|
<meta charset="utf-8"/>
|
||||||
|
<meta http-equiv="Cache-Control" content="no-cache, no-store, must-revalidate" />
|
||||||
|
<meta http-equiv="Pragma" content="no-cache" />
|
||||||
|
<meta http-equiv="Expires" content="0" />
|
||||||
<title>Network Monitor test page</title>
|
<title>Network Monitor test page</title>
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
|
@ -5,6 +5,9 @@
|
|||||||
<html>
|
<html>
|
||||||
<head>
|
<head>
|
||||||
<meta charset="utf-8"/>
|
<meta charset="utf-8"/>
|
||||||
|
<meta http-equiv="Cache-Control" content="no-cache, no-store, must-revalidate" />
|
||||||
|
<meta http-equiv="Pragma" content="no-cache" />
|
||||||
|
<meta http-equiv="Expires" content="0" />
|
||||||
<title>Network Monitor test page</title>
|
<title>Network Monitor test page</title>
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
|
@ -5,6 +5,9 @@
|
|||||||
<html>
|
<html>
|
||||||
<head>
|
<head>
|
||||||
<meta charset="utf-8"/>
|
<meta charset="utf-8"/>
|
||||||
|
<meta http-equiv="Cache-Control" content="no-cache, no-store, must-revalidate" />
|
||||||
|
<meta http-equiv="Pragma" content="no-cache" />
|
||||||
|
<meta http-equiv="Expires" content="0" />
|
||||||
<title>Network Monitor test page</title>
|
<title>Network Monitor test page</title>
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
|
@ -5,6 +5,9 @@
|
|||||||
<html>
|
<html>
|
||||||
<head>
|
<head>
|
||||||
<meta charset="utf-8"/>
|
<meta charset="utf-8"/>
|
||||||
|
<meta http-equiv="Cache-Control" content="no-cache, no-store, must-revalidate" />
|
||||||
|
<meta http-equiv="Pragma" content="no-cache" />
|
||||||
|
<meta http-equiv="Expires" content="0" />
|
||||||
<title>Network Monitor test page</title>
|
<title>Network Monitor test page</title>
|
||||||
<style>
|
<style>
|
||||||
input {
|
input {
|
||||||
|
@ -5,6 +5,9 @@
|
|||||||
<html>
|
<html>
|
||||||
<head>
|
<head>
|
||||||
<meta charset="utf-8"/>
|
<meta charset="utf-8"/>
|
||||||
|
<meta http-equiv="Cache-Control" content="no-cache, no-store, must-revalidate" />
|
||||||
|
<meta http-equiv="Pragma" content="no-cache" />
|
||||||
|
<meta http-equiv="Expires" content="0" />
|
||||||
<title>Network Monitor test page</title>
|
<title>Network Monitor test page</title>
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
|
@ -5,6 +5,9 @@
|
|||||||
<html>
|
<html>
|
||||||
<head>
|
<head>
|
||||||
<meta charset="utf-8"/>
|
<meta charset="utf-8"/>
|
||||||
|
<meta http-equiv="Cache-Control" content="no-cache, no-store, must-revalidate" />
|
||||||
|
<meta http-equiv="Pragma" content="no-cache" />
|
||||||
|
<meta http-equiv="Expires" content="0" />
|
||||||
<title>Network Monitor test page</title>
|
<title>Network Monitor test page</title>
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
|
@ -5,6 +5,9 @@
|
|||||||
<html>
|
<html>
|
||||||
<head>
|
<head>
|
||||||
<meta charset="utf-8"/>
|
<meta charset="utf-8"/>
|
||||||
|
<meta http-equiv="Cache-Control" content="no-cache, no-store, must-revalidate" />
|
||||||
|
<meta http-equiv="Pragma" content="no-cache" />
|
||||||
|
<meta http-equiv="Expires" content="0" />
|
||||||
<title>Network Monitor test page</title>
|
<title>Network Monitor test page</title>
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
|
@ -5,6 +5,9 @@
|
|||||||
<html>
|
<html>
|
||||||
<head>
|
<head>
|
||||||
<meta charset="utf-8"/>
|
<meta charset="utf-8"/>
|
||||||
|
<meta http-equiv="Cache-Control" content="no-cache, no-store, must-revalidate" />
|
||||||
|
<meta http-equiv="Pragma" content="no-cache" />
|
||||||
|
<meta http-equiv="Expires" content="0" />
|
||||||
<title>Network Monitor test page</title>
|
<title>Network Monitor test page</title>
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
@ -25,8 +28,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
(function performRequests() {
|
(function performRequests() {
|
||||||
get("request_0", function() {
|
get("request_0", function() {});
|
||||||
});
|
|
||||||
})();
|
})();
|
||||||
</script>
|
</script>
|
||||||
</body>
|
</body>
|
||||||
|
@ -5,6 +5,9 @@
|
|||||||
<html>
|
<html>
|
||||||
<head>
|
<head>
|
||||||
<meta charset="utf-8"/>
|
<meta charset="utf-8"/>
|
||||||
|
<meta http-equiv="Cache-Control" content="no-cache, no-store, must-revalidate" />
|
||||||
|
<meta http-equiv="Pragma" content="no-cache" />
|
||||||
|
<meta http-equiv="Expires" content="0" />
|
||||||
<title>Network Monitor test page</title>
|
<title>Network Monitor test page</title>
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
|
@ -5,6 +5,9 @@
|
|||||||
<html>
|
<html>
|
||||||
<head>
|
<head>
|
||||||
<meta charset="utf-8"/>
|
<meta charset="utf-8"/>
|
||||||
|
<meta http-equiv="Cache-Control" content="no-cache, no-store, must-revalidate" />
|
||||||
|
<meta http-equiv="Pragma" content="no-cache" />
|
||||||
|
<meta http-equiv="Expires" content="0" />
|
||||||
<title>Network Monitor test page</title>
|
<title>Network Monitor test page</title>
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
@ -30,7 +33,7 @@
|
|||||||
get("sjs_content-type-test-server.sjs?sts=304&fmt=audio");
|
get("sjs_content-type-test-server.sjs?sts=304&fmt=audio");
|
||||||
get("sjs_content-type-test-server.sjs?sts=304&fmt=video");
|
get("sjs_content-type-test-server.sjs?sts=304&fmt=video");
|
||||||
get("sjs_content-type-test-server.sjs?sts=304&fmt=flash");
|
get("sjs_content-type-test-server.sjs?sts=304&fmt=flash");
|
||||||
get("test-image.png");
|
get("test-image.png?v=" + Math.random());
|
||||||
</script>
|
</script>
|
||||||
</body>
|
</body>
|
||||||
|
|
||||||
|
@ -5,6 +5,9 @@
|
|||||||
<html>
|
<html>
|
||||||
<head>
|
<head>
|
||||||
<meta charset="utf-8"/>
|
<meta charset="utf-8"/>
|
||||||
|
<meta http-equiv="Cache-Control" content="no-cache, no-store, must-revalidate" />
|
||||||
|
<meta http-equiv="Pragma" content="no-cache" />
|
||||||
|
<meta http-equiv="Expires" content="0" />
|
||||||
<title>Network Monitor test page</title>
|
<title>Network Monitor test page</title>
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
|
@ -13,8 +13,11 @@ function handleRequest(request, response) {
|
|||||||
let cachedCount = 0;
|
let cachedCount = 0;
|
||||||
let cacheExpire = 60; // seconds
|
let cacheExpire = 60; // seconds
|
||||||
|
|
||||||
function maybeMakeCached() {
|
function setCacheHeaders() {
|
||||||
if (status != 304) {
|
if (status != 304) {
|
||||||
|
response.setHeader("Cache-Control", "no-cache, no-store, must-revalidate");
|
||||||
|
response.setHeader("Pragma", "no-cache");
|
||||||
|
response.setHeader("Expires", "0");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// Spice things up a little!
|
// Spice things up a little!
|
||||||
@ -31,7 +34,7 @@ function handleRequest(request, response) {
|
|||||||
case "txt": {
|
case "txt": {
|
||||||
response.setStatusLine(request.httpVersion, status, "DA DA DA");
|
response.setStatusLine(request.httpVersion, status, "DA DA DA");
|
||||||
response.setHeader("Content-Type", "text/plain", false);
|
response.setHeader("Content-Type", "text/plain", false);
|
||||||
maybeMakeCached();
|
setCacheHeaders();
|
||||||
response.write("Братан, ты вообще качаешься?");
|
response.write("Братан, ты вообще качаешься?");
|
||||||
response.finish();
|
response.finish();
|
||||||
break;
|
break;
|
||||||
@ -39,7 +42,7 @@ function handleRequest(request, response) {
|
|||||||
case "xml": {
|
case "xml": {
|
||||||
response.setStatusLine(request.httpVersion, status, "OK");
|
response.setStatusLine(request.httpVersion, status, "OK");
|
||||||
response.setHeader("Content-Type", "text/xml; charset=utf-8", false);
|
response.setHeader("Content-Type", "text/xml; charset=utf-8", false);
|
||||||
maybeMakeCached();
|
setCacheHeaders();
|
||||||
response.write("<label value='greeting'>Hello XML!</label>");
|
response.write("<label value='greeting'>Hello XML!</label>");
|
||||||
response.finish();
|
response.finish();
|
||||||
break;
|
break;
|
||||||
@ -48,7 +51,7 @@ function handleRequest(request, response) {
|
|||||||
let content = params.filter((s) => s.contains("res="))[0].split("=")[1];
|
let content = params.filter((s) => s.contains("res="))[0].split("=")[1];
|
||||||
response.setStatusLine(request.httpVersion, status, "OK");
|
response.setStatusLine(request.httpVersion, status, "OK");
|
||||||
response.setHeader("Content-Type", "text/html; charset=utf-8", false);
|
response.setHeader("Content-Type", "text/html; charset=utf-8", false);
|
||||||
maybeMakeCached();
|
setCacheHeaders();
|
||||||
response.write(content || "<p>Hello HTML!</p>");
|
response.write(content || "<p>Hello HTML!</p>");
|
||||||
response.finish();
|
response.finish();
|
||||||
break;
|
break;
|
||||||
@ -57,7 +60,7 @@ function handleRequest(request, response) {
|
|||||||
let str = new Array(102400 /* 100 KB in bytes */).join(".");
|
let str = new Array(102400 /* 100 KB in bytes */).join(".");
|
||||||
response.setStatusLine(request.httpVersion, status, "OK");
|
response.setStatusLine(request.httpVersion, status, "OK");
|
||||||
response.setHeader("Content-Type", "text/html; charset=utf-8", false);
|
response.setHeader("Content-Type", "text/html; charset=utf-8", false);
|
||||||
maybeMakeCached();
|
setCacheHeaders();
|
||||||
response.write("<p>" + str + "</p>");
|
response.write("<p>" + str + "</p>");
|
||||||
response.finish();
|
response.finish();
|
||||||
break;
|
break;
|
||||||
@ -65,7 +68,7 @@ function handleRequest(request, response) {
|
|||||||
case "css": {
|
case "css": {
|
||||||
response.setStatusLine(request.httpVersion, status, "OK");
|
response.setStatusLine(request.httpVersion, status, "OK");
|
||||||
response.setHeader("Content-Type", "text/css; charset=utf-8", false);
|
response.setHeader("Content-Type", "text/css; charset=utf-8", false);
|
||||||
maybeMakeCached();
|
setCacheHeaders();
|
||||||
response.write("body:pre { content: 'Hello CSS!' }");
|
response.write("body:pre { content: 'Hello CSS!' }");
|
||||||
response.finish();
|
response.finish();
|
||||||
break;
|
break;
|
||||||
@ -73,7 +76,7 @@ function handleRequest(request, response) {
|
|||||||
case "js": {
|
case "js": {
|
||||||
response.setStatusLine(request.httpVersion, status, "OK");
|
response.setStatusLine(request.httpVersion, status, "OK");
|
||||||
response.setHeader("Content-Type", "application/javascript; charset=utf-8", false);
|
response.setHeader("Content-Type", "application/javascript; charset=utf-8", false);
|
||||||
maybeMakeCached();
|
setCacheHeaders();
|
||||||
response.write("function() { return 'Hello JS!'; }");
|
response.write("function() { return 'Hello JS!'; }");
|
||||||
response.finish();
|
response.finish();
|
||||||
break;
|
break;
|
||||||
@ -81,7 +84,7 @@ function handleRequest(request, response) {
|
|||||||
case "json": {
|
case "json": {
|
||||||
response.setStatusLine(request.httpVersion, status, "OK");
|
response.setStatusLine(request.httpVersion, status, "OK");
|
||||||
response.setHeader("Content-Type", "application/json; charset=utf-8", false);
|
response.setHeader("Content-Type", "application/json; charset=utf-8", false);
|
||||||
maybeMakeCached();
|
setCacheHeaders();
|
||||||
response.write("{ \"greeting\": \"Hello JSON!\" }");
|
response.write("{ \"greeting\": \"Hello JSON!\" }");
|
||||||
response.finish();
|
response.finish();
|
||||||
break;
|
break;
|
||||||
@ -90,7 +93,7 @@ function handleRequest(request, response) {
|
|||||||
let fun = params.filter((s) => s.contains("jsonp="))[0].split("=")[1];
|
let fun = params.filter((s) => s.contains("jsonp="))[0].split("=")[1];
|
||||||
response.setStatusLine(request.httpVersion, status, "OK");
|
response.setStatusLine(request.httpVersion, status, "OK");
|
||||||
response.setHeader("Content-Type", "text/json; charset=utf-8", false);
|
response.setHeader("Content-Type", "text/json; charset=utf-8", false);
|
||||||
maybeMakeCached();
|
setCacheHeaders();
|
||||||
response.write(fun + "({ \"greeting\": \"Hello JSONP!\" })");
|
response.write(fun + "({ \"greeting\": \"Hello JSONP!\" })");
|
||||||
response.finish();
|
response.finish();
|
||||||
break;
|
break;
|
||||||
@ -99,7 +102,7 @@ function handleRequest(request, response) {
|
|||||||
let fun = params.filter((s) => s.contains("jsonp="))[0].split("=")[1];
|
let fun = params.filter((s) => s.contains("jsonp="))[0].split("=")[1];
|
||||||
response.setStatusLine(request.httpVersion, status, "OK");
|
response.setStatusLine(request.httpVersion, status, "OK");
|
||||||
response.setHeader("Content-Type", "text/json; charset=utf-8", false);
|
response.setHeader("Content-Type", "text/json; charset=utf-8", false);
|
||||||
maybeMakeCached();
|
setCacheHeaders();
|
||||||
response.write(" " + fun + " ( { \"greeting\": \"Hello weird JSONP!\" } ) ; ");
|
response.write(" " + fun + " ( { \"greeting\": \"Hello weird JSONP!\" } ) ; ");
|
||||||
response.finish();
|
response.finish();
|
||||||
break;
|
break;
|
||||||
@ -108,7 +111,7 @@ function handleRequest(request, response) {
|
|||||||
let str = "{ \"greeting\": \"Hello long string JSON!\" },";
|
let str = "{ \"greeting\": \"Hello long string JSON!\" },";
|
||||||
response.setStatusLine(request.httpVersion, status, "OK");
|
response.setStatusLine(request.httpVersion, status, "OK");
|
||||||
response.setHeader("Content-Type", "text/json; charset=utf-8", false);
|
response.setHeader("Content-Type", "text/json; charset=utf-8", false);
|
||||||
maybeMakeCached();
|
setCacheHeaders();
|
||||||
response.write("[" + new Array(2048).join(str).slice(0, -1) + "]");
|
response.write("[" + new Array(2048).join(str).slice(0, -1) + "]");
|
||||||
response.finish();
|
response.finish();
|
||||||
break;
|
break;
|
||||||
@ -116,7 +119,7 @@ function handleRequest(request, response) {
|
|||||||
case "json-malformed": {
|
case "json-malformed": {
|
||||||
response.setStatusLine(request.httpVersion, status, "OK");
|
response.setStatusLine(request.httpVersion, status, "OK");
|
||||||
response.setHeader("Content-Type", "text/json; charset=utf-8", false);
|
response.setHeader("Content-Type", "text/json; charset=utf-8", false);
|
||||||
maybeMakeCached();
|
setCacheHeaders();
|
||||||
response.write("{ \"greeting\": \"Hello malformed JSON!\" },");
|
response.write("{ \"greeting\": \"Hello malformed JSON!\" },");
|
||||||
response.finish();
|
response.finish();
|
||||||
break;
|
break;
|
||||||
@ -124,7 +127,7 @@ function handleRequest(request, response) {
|
|||||||
case "json-text-mime": {
|
case "json-text-mime": {
|
||||||
response.setStatusLine(request.httpVersion, status, "OK");
|
response.setStatusLine(request.httpVersion, status, "OK");
|
||||||
response.setHeader("Content-Type", "text/plain; charset=utf-8", false);
|
response.setHeader("Content-Type", "text/plain; charset=utf-8", false);
|
||||||
maybeMakeCached();
|
setCacheHeaders();
|
||||||
response.write("{ \"greeting\": \"Hello third-party JSON!\" }");
|
response.write("{ \"greeting\": \"Hello third-party JSON!\" }");
|
||||||
response.finish();
|
response.finish();
|
||||||
break;
|
break;
|
||||||
@ -132,7 +135,7 @@ function handleRequest(request, response) {
|
|||||||
case "json-custom-mime": {
|
case "json-custom-mime": {
|
||||||
response.setStatusLine(request.httpVersion, status, "OK");
|
response.setStatusLine(request.httpVersion, status, "OK");
|
||||||
response.setHeader("Content-Type", "text/x-bigcorp-json; charset=utf-8", false);
|
response.setHeader("Content-Type", "text/x-bigcorp-json; charset=utf-8", false);
|
||||||
maybeMakeCached();
|
setCacheHeaders();
|
||||||
response.write("{ \"greeting\": \"Hello oddly-named JSON!\" }");
|
response.write("{ \"greeting\": \"Hello oddly-named JSON!\" }");
|
||||||
response.finish();
|
response.finish();
|
||||||
break;
|
break;
|
||||||
@ -140,41 +143,42 @@ function handleRequest(request, response) {
|
|||||||
case "font": {
|
case "font": {
|
||||||
response.setStatusLine(request.httpVersion, status, "OK");
|
response.setStatusLine(request.httpVersion, status, "OK");
|
||||||
response.setHeader("Content-Type", "font/woff", false);
|
response.setHeader("Content-Type", "font/woff", false);
|
||||||
maybeMakeCached();
|
setCacheHeaders();
|
||||||
response.finish();
|
response.finish();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case "image": {
|
case "image": {
|
||||||
response.setStatusLine(request.httpVersion, status, "OK");
|
response.setStatusLine(request.httpVersion, status, "OK");
|
||||||
response.setHeader("Content-Type", "image/png", false);
|
response.setHeader("Content-Type", "image/png", false);
|
||||||
maybeMakeCached();
|
setCacheHeaders();
|
||||||
response.finish();
|
response.finish();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case "audio": {
|
case "audio": {
|
||||||
response.setStatusLine(request.httpVersion, status, "OK");
|
response.setStatusLine(request.httpVersion, status, "OK");
|
||||||
response.setHeader("Content-Type", "audio/ogg", false);
|
response.setHeader("Content-Type", "audio/ogg", false);
|
||||||
maybeMakeCached();
|
setCacheHeaders();
|
||||||
response.finish();
|
response.finish();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case "video": {
|
case "video": {
|
||||||
response.setStatusLine(request.httpVersion, status, "OK");
|
response.setStatusLine(request.httpVersion, status, "OK");
|
||||||
response.setHeader("Content-Type", "video/webm", false);
|
response.setHeader("Content-Type", "video/webm", false);
|
||||||
maybeMakeCached();
|
setCacheHeaders();
|
||||||
response.finish();
|
response.finish();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case "flash": {
|
case "flash": {
|
||||||
response.setStatusLine(request.httpVersion, status, "OK");
|
response.setStatusLine(request.httpVersion, status, "OK");
|
||||||
response.setHeader("Content-Type", "application/x-shockwave-flash", false);
|
response.setHeader("Content-Type", "application/x-shockwave-flash", false);
|
||||||
maybeMakeCached();
|
setCacheHeaders();
|
||||||
response.finish();
|
response.finish();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default: {
|
default: {
|
||||||
response.setStatusLine(request.httpVersion, 404, "Not Found");
|
response.setStatusLine(request.httpVersion, 404, "Not Found");
|
||||||
response.setHeader("Content-Type", "text/html; charset=utf-8", false);
|
response.setHeader("Content-Type", "text/html; charset=utf-8", false);
|
||||||
|
setCacheHeaders();
|
||||||
response.write("<blink>Not Found</blink>");
|
response.write("<blink>Not Found</blink>");
|
||||||
response.finish();
|
response.finish();
|
||||||
break;
|
break;
|
||||||
|
@ -3,6 +3,11 @@
|
|||||||
|
|
||||||
function handleRequest(request, response) {
|
function handleRequest(request, response) {
|
||||||
response.setStatusLine(request.httpVersion, 200, "Och Aye");
|
response.setStatusLine(request.httpVersion, 200, "Och Aye");
|
||||||
|
|
||||||
|
response.setHeader("Cache-Control", "no-cache, no-store, must-revalidate");
|
||||||
|
response.setHeader("Pragma", "no-cache");
|
||||||
|
response.setHeader("Expires", "0");
|
||||||
|
|
||||||
response.setHeader("Content-Type", "text/plain; charset=utf-8", false);
|
response.setHeader("Content-Type", "text/plain; charset=utf-8", false);
|
||||||
response.setHeader("Foo-Bar", "baz", false);
|
response.setHeader("Foo-Bar", "baz", false);
|
||||||
response.write("Hello world!");
|
response.write("Hello world!");
|
||||||
|
@ -11,6 +11,11 @@ function handleRequest(request, response) {
|
|||||||
|
|
||||||
Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer).initWithCallback(() => {
|
Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer).initWithCallback(() => {
|
||||||
response.setStatusLine(request.httpVersion, index == 1 ? 101 : index * 100, "Meh");
|
response.setStatusLine(request.httpVersion, index == 1 ? 101 : index * 100, "Meh");
|
||||||
|
|
||||||
|
response.setHeader("Cache-Control", "no-cache, no-store, must-revalidate");
|
||||||
|
response.setHeader("Pragma", "no-cache");
|
||||||
|
response.setHeader("Expires", "0");
|
||||||
|
|
||||||
response.setHeader("Content-Type", "text/" + index, false);
|
response.setHeader("Content-Type", "text/" + index, false);
|
||||||
response.write(new Array(index * 10).join(index)); // + 0.01 KB
|
response.write(new Array(index * 10).join(index)); // + 0.01 KB
|
||||||
response.finish();
|
response.finish();
|
||||||
|
@ -27,6 +27,11 @@ function handleRequest(request, response) {
|
|||||||
response.setStatusLine(request.httpVersion, 501, "Not Implemented");
|
response.setStatusLine(request.httpVersion, 501, "Not Implemented");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
response.setHeader("Cache-Control", "no-cache, no-store, must-revalidate");
|
||||||
|
response.setHeader("Pragma", "no-cache");
|
||||||
|
response.setHeader("Expires", "0");
|
||||||
|
|
||||||
response.setHeader("Content-Type", "text/plain; charset=utf-8", false);
|
response.setHeader("Content-Type", "text/plain; charset=utf-8", false);
|
||||||
response.write("Hello status code " + status + "!");
|
response.write("Hello status code " + status + "!");
|
||||||
response.finish();
|
response.finish();
|
||||||
|
@ -37,7 +37,7 @@ function testParseCssProperty() {
|
|||||||
target.appendChild(frag);
|
target.appendChild(frag);
|
||||||
|
|
||||||
is(target.innerHTML,
|
is(target.innerHTML,
|
||||||
'1px solid <span style="background-color:red" class="test-colorswatch"></span><span>#F00</span>',
|
'1px solid <span data-color="#F00"><span style="background-color:red" class="test-colorswatch"></span><span>#F00</span></span>',
|
||||||
"CSS property correctly parsed");
|
"CSS property correctly parsed");
|
||||||
|
|
||||||
target.innerHTML = "";
|
target.innerHTML = "";
|
||||||
@ -48,8 +48,8 @@ function testParseCssProperty() {
|
|||||||
});
|
});
|
||||||
target.appendChild(frag);
|
target.appendChild(frag);
|
||||||
is(target.innerHTML,
|
is(target.innerHTML,
|
||||||
'linear-gradient(to right, <span style="background-color:#F60" class="test-colorswatch"></span><span class="test-color">#F60</span> 10%, ' +
|
'linear-gradient(to right, <span data-color="#F60"><span style="background-color:#F60" class="test-colorswatch"></span><span class="test-color">#F60</span></span> 10%, ' +
|
||||||
'<span style="background-color:rgba(0,0,0,1)" class="test-colorswatch"></span><span class="test-color">#000</span>)',
|
'<span data-color="#000"><span style="background-color:rgba(0,0,0,1)" class="test-colorswatch"></span><span class="test-color">#000</span></span>)',
|
||||||
"Gradient CSS property correctly parsed");
|
"Gradient CSS property correctly parsed");
|
||||||
|
|
||||||
target.innerHTML = "";
|
target.innerHTML = "";
|
||||||
@ -69,7 +69,7 @@ function testParseHTMLAttribute() {
|
|||||||
ok(target, "captain, we have the div");
|
ok(target, "captain, we have the div");
|
||||||
target.appendChild(frag);
|
target.appendChild(frag);
|
||||||
|
|
||||||
let expected = 'color:<span class="theme-color">#F00</span>; font-size: 12px; ' +
|
let expected = 'color:<span data-color="#F00"><span class="theme-color">#F00</span></span>; font-size: 12px; ' +
|
||||||
'background-image: url(\'<a href="chrome://branding/content/about-logo.png" ' +
|
'background-image: url(\'<a href="chrome://branding/content/about-logo.png" ' +
|
||||||
'class="theme-link" ' +
|
'class="theme-link" ' +
|
||||||
'target="_blank">chrome://branding/content/about-logo.png</a>\')';
|
'target="_blank">chrome://branding/content/about-logo.png</a>\')';
|
||||||
|
@ -1011,6 +1011,7 @@ SwatchColorPickerTooltip.prototype = Heritage.extend(SwatchBasedEditorTooltip.pr
|
|||||||
_selectColor: function(color) {
|
_selectColor: function(color) {
|
||||||
if (this.activeSwatch) {
|
if (this.activeSwatch) {
|
||||||
this.activeSwatch.style.backgroundColor = color;
|
this.activeSwatch.style.backgroundColor = color;
|
||||||
|
this.activeSwatch.parentNode.dataset.color = color;
|
||||||
this.currentSwatchColor.textContent = color;
|
this.currentSwatchColor.textContent = color;
|
||||||
this.preview(color);
|
this.preview(color);
|
||||||
}
|
}
|
||||||
|
@ -149,6 +149,7 @@ function CssHtmlTree(aStyleInspector, aPageStyle)
|
|||||||
this._onSelectAll = this._onSelectAll.bind(this);
|
this._onSelectAll = this._onSelectAll.bind(this);
|
||||||
this._onClick = this._onClick.bind(this);
|
this._onClick = this._onClick.bind(this);
|
||||||
this._onCopy = this._onCopy.bind(this);
|
this._onCopy = this._onCopy.bind(this);
|
||||||
|
this._onCopyColor = this._onCopyColor.bind(this);
|
||||||
|
|
||||||
this.styleDocument.addEventListener("copy", this._onCopy);
|
this.styleDocument.addEventListener("copy", this._onCopy);
|
||||||
this.styleDocument.addEventListener("mousedown", this.focusWindow);
|
this.styleDocument.addEventListener("mousedown", this.focusWindow);
|
||||||
@ -584,6 +585,13 @@ CssHtmlTree.prototype = {
|
|||||||
command: this._onCopy
|
command: this._onCopy
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Copy color
|
||||||
|
this.menuitemCopyColor = createMenuItem(this._contextmenu, {
|
||||||
|
label: "ruleView.contextmenu.copyColor",
|
||||||
|
accesskey: "ruleView.contextmenu.copyColor.accessKey",
|
||||||
|
command: this._onCopyColor
|
||||||
|
});
|
||||||
|
|
||||||
// Show Original Sources
|
// Show Original Sources
|
||||||
this.menuitemSources= createMenuItem(this._contextmenu, {
|
this.menuitemSources= createMenuItem(this._contextmenu, {
|
||||||
label: "ruleView.contextmenu.showOrigSources",
|
label: "ruleView.contextmenu.showOrigSources",
|
||||||
@ -619,6 +627,39 @@ CssHtmlTree.prototype = {
|
|||||||
let accessKey = label + ".accessKey";
|
let accessKey = label + ".accessKey";
|
||||||
this.menuitemSources.setAttribute("accesskey",
|
this.menuitemSources.setAttribute("accesskey",
|
||||||
CssHtmlTree.l10n(accessKey));
|
CssHtmlTree.l10n(accessKey));
|
||||||
|
|
||||||
|
this.menuitemCopyColor.hidden = !this._isColorPopup();
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A helper that determines if the popup was opened with a click to a color
|
||||||
|
* value and saves the color to this._colorToCopy.
|
||||||
|
*
|
||||||
|
* @return {Boolean}
|
||||||
|
* true if click on color opened the popup, false otherwise.
|
||||||
|
*/
|
||||||
|
_isColorPopup: function () {
|
||||||
|
this._colorToCopy = "";
|
||||||
|
|
||||||
|
let trigger = this.popupNode;
|
||||||
|
if (!trigger) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
let container = (trigger.nodeType == trigger.TEXT_NODE) ?
|
||||||
|
trigger.parentElement : trigger;
|
||||||
|
|
||||||
|
let isColorNode = el => el.dataset && "color" in el.dataset;
|
||||||
|
|
||||||
|
while (!isColorNode(container)) {
|
||||||
|
container = container.parentNode;
|
||||||
|
if (!container) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
this._colorToCopy = container.dataset["color"];
|
||||||
|
return true;
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -626,6 +667,7 @@ CssHtmlTree.prototype = {
|
|||||||
*/
|
*/
|
||||||
_onContextMenu: function(event) {
|
_onContextMenu: function(event) {
|
||||||
try {
|
try {
|
||||||
|
this.popupNode = event.explicitOriginalTarget;
|
||||||
this.styleDocument.defaultView.focus();
|
this.styleDocument.defaultView.focus();
|
||||||
this._contextmenu.openPopupAtScreen(event.screenX, event.screenY, true);
|
this._contextmenu.openPopupAtScreen(event.screenX, event.screenY, true);
|
||||||
} catch(e) {
|
} catch(e) {
|
||||||
@ -660,6 +702,10 @@ CssHtmlTree.prototype = {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
_onCopyColor: function() {
|
||||||
|
clipboardHelper.copyString(this._colorToCopy, this.styleDocument);
|
||||||
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Copy selected text.
|
* Copy selected text.
|
||||||
*
|
*
|
||||||
@ -751,12 +797,18 @@ CssHtmlTree.prototype = {
|
|||||||
this.menuitemSelectAll.removeEventListener("command", this._onSelectAll);
|
this.menuitemSelectAll.removeEventListener("command", this._onSelectAll);
|
||||||
this.menuitemSelectAll = null;
|
this.menuitemSelectAll = null;
|
||||||
|
|
||||||
|
// Destroy Copy Color menuitem.
|
||||||
|
this.menuitemCopyColor.removeEventListener("command", this._onCopyColor);
|
||||||
|
this.menuitemCopyColor = null;
|
||||||
|
|
||||||
// Destroy the context menu.
|
// Destroy the context menu.
|
||||||
this._contextmenu.removeEventListener("popupshowing", this._contextMenuUpdate);
|
this._contextmenu.removeEventListener("popupshowing", this._contextMenuUpdate);
|
||||||
this._contextmenu.parentNode.removeChild(this._contextmenu);
|
this._contextmenu.parentNode.removeChild(this._contextmenu);
|
||||||
this._contextmenu = null;
|
this._contextmenu = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.popupNode = null;
|
||||||
|
|
||||||
this.tooltip.stopTogglingOnHover(this.propertyContainer);
|
this.tooltip.stopTogglingOnHover(this.propertyContainer);
|
||||||
this.tooltip.destroy();
|
this.tooltip.destroy();
|
||||||
|
|
||||||
|
@ -1079,6 +1079,7 @@ function CssRuleView(aInspector, aDoc, aStore, aPageStyle) {
|
|||||||
this._contextMenuUpdate = this._contextMenuUpdate.bind(this);
|
this._contextMenuUpdate = this._contextMenuUpdate.bind(this);
|
||||||
this._onSelectAll = this._onSelectAll.bind(this);
|
this._onSelectAll = this._onSelectAll.bind(this);
|
||||||
this._onCopy = this._onCopy.bind(this);
|
this._onCopy = this._onCopy.bind(this);
|
||||||
|
this._onCopyColor = this._onCopyColor.bind(this);
|
||||||
this._onToggleOrigSources = this._onToggleOrigSources.bind(this);
|
this._onToggleOrigSources = this._onToggleOrigSources.bind(this);
|
||||||
|
|
||||||
this.element.addEventListener("copy", this._onCopy);
|
this.element.addEventListener("copy", this._onCopy);
|
||||||
@ -1138,6 +1139,11 @@ CssRuleView.prototype = {
|
|||||||
accesskey: "ruleView.contextmenu.copy.accessKey",
|
accesskey: "ruleView.contextmenu.copy.accessKey",
|
||||||
command: this._onCopy
|
command: this._onCopy
|
||||||
});
|
});
|
||||||
|
this.menuitemCopyColor = createMenuItem(this._contextmenu, {
|
||||||
|
label: "ruleView.contextmenu.copyColor",
|
||||||
|
accesskey: "ruleView.contextmenu.copyColor.accessKey",
|
||||||
|
command: this._onCopyColor
|
||||||
|
});
|
||||||
this.menuitemSources= createMenuItem(this._contextmenu, {
|
this.menuitemSources= createMenuItem(this._contextmenu, {
|
||||||
label: "ruleView.contextmenu.showOrigSources",
|
label: "ruleView.contextmenu.showOrigSources",
|
||||||
accesskey: "ruleView.contextmenu.showOrigSources.accessKey",
|
accesskey: "ruleView.contextmenu.showOrigSources.accessKey",
|
||||||
@ -1261,6 +1267,7 @@ CssRuleView.prototype = {
|
|||||||
copy = false;
|
copy = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.menuitemCopyColor.hidden = !this._isColorPopup();
|
||||||
this.menuitemCopy.disabled = !copy;
|
this.menuitemCopy.disabled = !copy;
|
||||||
|
|
||||||
let label = "ruleView.contextmenu.showOrigSources";
|
let label = "ruleView.contextmenu.showOrigSources";
|
||||||
@ -1275,6 +1282,37 @@ CssRuleView.prototype = {
|
|||||||
_strings.GetStringFromName(accessKey));
|
_strings.GetStringFromName(accessKey));
|
||||||
},
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A helper that determines if the popup was opened with a click to a color
|
||||||
|
* value and saves the color to this._colorToCopy.
|
||||||
|
*
|
||||||
|
* @return {Boolean}
|
||||||
|
* true if click on color opened the popup, false otherwise.
|
||||||
|
*/
|
||||||
|
_isColorPopup: function () {
|
||||||
|
this._colorToCopy = "";
|
||||||
|
|
||||||
|
let trigger = this.doc.popupNode;
|
||||||
|
if (!trigger) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
let container = (trigger.nodeType == trigger.TEXT_NODE) ?
|
||||||
|
trigger.parentElement : trigger;
|
||||||
|
|
||||||
|
let isColorNode = el => el.dataset && "color" in el.dataset;
|
||||||
|
|
||||||
|
while (!isColorNode(container)) {
|
||||||
|
container = container.parentNode;
|
||||||
|
if (!container) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
this._colorToCopy = container.dataset["color"];
|
||||||
|
return true;
|
||||||
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Select all text.
|
* Select all text.
|
||||||
*/
|
*/
|
||||||
@ -1327,6 +1365,13 @@ CssRuleView.prototype = {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Copy the most recently selected color value to clipboard.
|
||||||
|
*/
|
||||||
|
_onCopyColor: function() {
|
||||||
|
clipboardHelper.copyString(this._colorToCopy, this.styleDocument);
|
||||||
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Toggle the original sources pref.
|
* Toggle the original sources pref.
|
||||||
*/
|
*/
|
||||||
@ -1400,6 +1445,10 @@ CssRuleView.prototype = {
|
|||||||
this.menuitemCopy.removeEventListener("command", this._onCopy);
|
this.menuitemCopy.removeEventListener("command", this._onCopy);
|
||||||
this.menuitemCopy = null;
|
this.menuitemCopy = null;
|
||||||
|
|
||||||
|
// Destroy Copy Color menuitem.
|
||||||
|
this.menuitemCopyColor.removeEventListener("command", this._onCopyColor);
|
||||||
|
this.menuitemCopyColor = null;
|
||||||
|
|
||||||
this.menuitemSources.removeEventListener("command", this._onToggleOrigSources);
|
this.menuitemSources.removeEventListener("command", this._onToggleOrigSources);
|
||||||
this.menuitemSources = null;
|
this.menuitemSources = null;
|
||||||
|
|
||||||
|
@ -87,6 +87,8 @@ skip-if = os == "win" && debug # bug 963492
|
|||||||
[browser_ruleview_user-agent-styles.js]
|
[browser_ruleview_user-agent-styles.js]
|
||||||
[browser_ruleview_user-agent-styles-uneditable.js]
|
[browser_ruleview_user-agent-styles-uneditable.js]
|
||||||
[browser_ruleview_user-property-reset.js]
|
[browser_ruleview_user-property-reset.js]
|
||||||
|
[browser_styleinspector_context-menu-copy-color_01.js]
|
||||||
|
[browser_styleinspector_context-menu-copy-color_02.js]
|
||||||
[browser_styleinspector_csslogic-content-stylesheets.js]
|
[browser_styleinspector_csslogic-content-stylesheets.js]
|
||||||
[browser_styleinspector_csslogic-inherited-properties.js]
|
[browser_styleinspector_csslogic-inherited-properties.js]
|
||||||
[browser_styleinspector_csslogic-specificity.js]
|
[browser_styleinspector_csslogic-specificity.js]
|
||||||
|
@ -0,0 +1,139 @@
|
|||||||
|
/* vim: set ft=javascript ts=2 et sw=2 tw=80: */
|
||||||
|
/* Any copyright is dedicated to the Public Domain.
|
||||||
|
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
// Test "Copy color" item of the context menu #1: Test _isColorPopup.
|
||||||
|
|
||||||
|
const TEST_COLOR = "#123ABC";
|
||||||
|
const COLOR_SELECTOR = "span[data-color]";
|
||||||
|
|
||||||
|
let test = asyncTest(function* () {
|
||||||
|
const TEST_DOC = '<html> \
|
||||||
|
<body> \
|
||||||
|
<div style="color: ' + TEST_COLOR + '; \
|
||||||
|
margin: 0px; \
|
||||||
|
background: ' + TEST_COLOR + ';"> \
|
||||||
|
Test "Copy color" context menu option \
|
||||||
|
</div> \
|
||||||
|
</body> \
|
||||||
|
</html>';
|
||||||
|
|
||||||
|
const TEST_CASES = [
|
||||||
|
{
|
||||||
|
viewName: "RuleView",
|
||||||
|
initializer: openRuleView
|
||||||
|
},
|
||||||
|
{
|
||||||
|
viewName: "ComputedView",
|
||||||
|
initializer: openComputedView
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
yield addTab("data:text/html;charset=utf8," + encodeURIComponent(TEST_DOC));
|
||||||
|
|
||||||
|
for (let test of TEST_CASES) {
|
||||||
|
yield testView(test);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
function* testView({viewName, initializer}) {
|
||||||
|
info("Testing " + viewName);
|
||||||
|
|
||||||
|
let {inspector, view} = yield initializer();
|
||||||
|
yield selectNode("div", inspector);
|
||||||
|
|
||||||
|
testIsColorValueNode(view);
|
||||||
|
testIsColorPopupOnAllNodes(view);
|
||||||
|
yield clearCurrentNodeSelection(inspector);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A function testing that isColorValueNode correctly detects nodes part of
|
||||||
|
* color values.
|
||||||
|
*/
|
||||||
|
function testIsColorValueNode(view) {
|
||||||
|
info("Testing that child nodes of color nodes are detected.");
|
||||||
|
let root = rootElement(view);
|
||||||
|
let colorNode = root.querySelector(COLOR_SELECTOR);
|
||||||
|
|
||||||
|
ok(colorNode, "Color node found");
|
||||||
|
for (let node of iterateNodes(colorNode)) {
|
||||||
|
ok(isColorValueNode(node), "Node is part of color value.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A function testing that _isColorPopup returns a correct value for all nodes
|
||||||
|
* in the view.
|
||||||
|
*/
|
||||||
|
function testIsColorPopupOnAllNodes(view) {
|
||||||
|
let root = rootElement(view);
|
||||||
|
for (let node of iterateNodes(root)) {
|
||||||
|
testIsColorPopupOnNode(view, node);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test result of _isColorPopup with given node.
|
||||||
|
* @param object view
|
||||||
|
* A CSSRuleView or CssHtmlTree instance.
|
||||||
|
* @param Node node
|
||||||
|
* A node to check.
|
||||||
|
*/
|
||||||
|
function testIsColorPopupOnNode(view, node) {
|
||||||
|
info("Testing node " + node);
|
||||||
|
if (view.doc) {
|
||||||
|
view.doc.popupNode = node;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
view.popupNode = node;
|
||||||
|
}
|
||||||
|
view._colorToCopy = "";
|
||||||
|
|
||||||
|
let result = view._isColorPopup();
|
||||||
|
let correct = isColorValueNode(node);
|
||||||
|
|
||||||
|
is(result, correct, "_isColorPopup returned the expected value " + correct);
|
||||||
|
is(view._colorToCopy, (correct) ? TEST_COLOR : "",
|
||||||
|
"_colorToCopy was set to the expected value");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if a node is part of color value i.e. it has parent with a 'data-color'
|
||||||
|
* attribute.
|
||||||
|
*/
|
||||||
|
function isColorValueNode(node) {
|
||||||
|
let container = (node.nodeType == node.TEXT_NODE) ?
|
||||||
|
node.parentElement : node;
|
||||||
|
|
||||||
|
let isColorNode = el => el.dataset && "color" in el.dataset;
|
||||||
|
|
||||||
|
while (!isColorNode(container)) {
|
||||||
|
container = container.parentNode;
|
||||||
|
if (!container) {
|
||||||
|
info("No color. Node is not part of color value.");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
info("Found a color. Node is part of color value.");
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A generator that iterates recursively trough all child nodes of baseNode.
|
||||||
|
*/
|
||||||
|
function* iterateNodes(baseNode) {
|
||||||
|
yield baseNode;
|
||||||
|
|
||||||
|
for (let child of baseNode.childNodes) {
|
||||||
|
yield* iterateNodes(child);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the root element for the given view, rule or computed.
|
||||||
|
*/
|
||||||
|
let rootElement = view => (view.element) ? view.element : view.styleDocument;
|
@ -0,0 +1,99 @@
|
|||||||
|
/* vim: set ft=javascript ts=2 et sw=2 tw=80: */
|
||||||
|
/* Any copyright is dedicated to the Public Domain.
|
||||||
|
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
// Test "Copy color" item of the context menu #2: Test that correct color is
|
||||||
|
// copied if the color changes.
|
||||||
|
|
||||||
|
const TEST_COLOR = "#123ABC";
|
||||||
|
|
||||||
|
let test = asyncTest(function* () {
|
||||||
|
const PAGE_CONTENT = [
|
||||||
|
'<style type="text/css">',
|
||||||
|
' div {',
|
||||||
|
' color: ' + TEST_COLOR + ';',
|
||||||
|
' }',
|
||||||
|
'</style>',
|
||||||
|
'<div>Testing the color picker tooltip!</div>'
|
||||||
|
].join("\n");
|
||||||
|
|
||||||
|
yield addTab("data:text/html;charset=utf8,Test context menu Copy color");
|
||||||
|
content.document.body.innerHTML = PAGE_CONTENT;
|
||||||
|
|
||||||
|
let {inspector, view} = yield openRuleView();
|
||||||
|
yield testCopyToClipboard(inspector, view);
|
||||||
|
yield testManualEdit(inspector, view);
|
||||||
|
yield testColorPickerEdit(inspector, view);
|
||||||
|
});
|
||||||
|
|
||||||
|
function* testCopyToClipboard(inspector, view) {
|
||||||
|
info("Testing that color is copied to clipboard");
|
||||||
|
|
||||||
|
yield selectNode("div", inspector);
|
||||||
|
|
||||||
|
let win = view.doc.defaultView;
|
||||||
|
let element = getRuleViewProperty(view, "div", "color").valueSpan
|
||||||
|
.querySelector(".ruleview-colorswatch");
|
||||||
|
|
||||||
|
let popup = once(view._contextmenu, "popupshown");
|
||||||
|
EventUtils.synthesizeMouseAtCenter(element, {button: 2, type: "contextmenu"}, win);
|
||||||
|
yield popup;
|
||||||
|
|
||||||
|
ok(!view.menuitemCopyColor.hidden, "Copy color is visible");
|
||||||
|
|
||||||
|
yield waitForClipboard(() => view.menuitemCopyColor.click(), TEST_COLOR);
|
||||||
|
view._contextmenu.hidePopup();
|
||||||
|
}
|
||||||
|
|
||||||
|
function* testManualEdit(inspector, view) {
|
||||||
|
info("Testing manually edited colors");
|
||||||
|
yield selectNode("div", inspector);
|
||||||
|
|
||||||
|
let {valueSpan} = getRuleViewProperty(view, "div", "color");
|
||||||
|
|
||||||
|
let newColor = "#C9184E"
|
||||||
|
let editor = yield focusEditableField(valueSpan);
|
||||||
|
|
||||||
|
info("Typing new value");
|
||||||
|
let input = editor.input;
|
||||||
|
let onBlur = once(input, "blur");
|
||||||
|
for (let ch of newColor + ";"){
|
||||||
|
EventUtils.sendChar(ch, view.doc.defaultView);
|
||||||
|
}
|
||||||
|
|
||||||
|
yield onBlur;
|
||||||
|
yield wait(1);
|
||||||
|
|
||||||
|
let colorValue = getRuleViewProperty(view, "div", "color").valueSpan.firstChild;
|
||||||
|
is(colorValue.dataset.color, newColor, "data-color was updated");
|
||||||
|
|
||||||
|
view.doc.popupNode = colorValue;
|
||||||
|
view._isColorPopup();
|
||||||
|
|
||||||
|
is(view._colorToCopy, newColor, "_colorToCopy has the new value");
|
||||||
|
}
|
||||||
|
|
||||||
|
function* testColorPickerEdit(inspector, view) {
|
||||||
|
info("Testing colors edited via color picker");
|
||||||
|
yield selectNode("div", inspector);
|
||||||
|
|
||||||
|
let swatch = getRuleViewProperty(view, "div", "color").valueSpan
|
||||||
|
.querySelector(".ruleview-colorswatch");
|
||||||
|
|
||||||
|
info("Opening the color picker");
|
||||||
|
let picker = view.colorPicker;
|
||||||
|
let onShown = picker.tooltip.once("shown");
|
||||||
|
swatch.click();
|
||||||
|
yield onShown;
|
||||||
|
|
||||||
|
let rgbaColor = [83, 183, 89, 1];
|
||||||
|
let rgbaColorText = "rgba(83, 183, 89, 1)";
|
||||||
|
yield simulateColorPickerChange(picker, rgbaColor);
|
||||||
|
|
||||||
|
is(swatch.parentNode.dataset.color, rgbaColorText, "data-color was updated");
|
||||||
|
view.doc.popupNode = swatch;
|
||||||
|
view._isColorPopup();
|
||||||
|
|
||||||
|
is(view._colorToCopy, rgbaColorText, "_colorToCopy has the new value");
|
||||||
|
}
|
@ -73,7 +73,7 @@ function test() {
|
|||||||
name: "background-color",
|
name: "background-color",
|
||||||
value: "transparent",
|
value: "transparent",
|
||||||
test: fragment => {
|
test: fragment => {
|
||||||
is(countAll(fragment), 1);
|
is(countAll(fragment), 2);
|
||||||
is(countColors(fragment), 1);
|
is(countColors(fragment), 1);
|
||||||
is(fragment.textContent, "transparent");
|
is(fragment.textContent, "transparent");
|
||||||
}
|
}
|
||||||
@ -98,7 +98,7 @@ function test() {
|
|||||||
name: "border",
|
name: "border",
|
||||||
value: "80em dotted pink",
|
value: "80em dotted pink",
|
||||||
test: fragment => {
|
test: fragment => {
|
||||||
is(countAll(fragment), 1);
|
is(countAll(fragment), 2);
|
||||||
is(countColors(fragment), 1);
|
is(countColors(fragment), 1);
|
||||||
is(getColor(fragment), "pink");
|
is(getColor(fragment), "pink");
|
||||||
}
|
}
|
||||||
@ -119,7 +119,7 @@ function test() {
|
|||||||
is(countUrls(fragment), 1);
|
is(countUrls(fragment), 1);
|
||||||
is(getColor(fragment), "red");
|
is(getColor(fragment), "red");
|
||||||
is(getUrl(fragment), "test.png");
|
is(getUrl(fragment), "test.png");
|
||||||
is(countAll(fragment), 2);
|
is(countAll(fragment), 3);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -130,7 +130,7 @@ function test() {
|
|||||||
is(countUrls(fragment), 1);
|
is(countUrls(fragment), 1);
|
||||||
is(getColor(fragment), "blue");
|
is(getColor(fragment), "blue");
|
||||||
is(getUrl(fragment), "test.png");
|
is(getUrl(fragment), "test.png");
|
||||||
is(countAll(fragment), 2);
|
is(countAll(fragment), 3);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -163,7 +163,7 @@ function test() {
|
|||||||
name: "background",
|
name: "background",
|
||||||
value: "linear-gradient(to right, rgba(183,222,237,1) 0%, rgba(33,180,226,1) 30%, rgba(31,170,217,.5) 44%, #F06 75%, red 100%)",
|
value: "linear-gradient(to right, rgba(183,222,237,1) 0%, rgba(33,180,226,1) 30%, rgba(31,170,217,.5) 44%, #F06 75%, red 100%)",
|
||||||
test: fragment => {
|
test: fragment => {
|
||||||
is(countAll(fragment), 5);
|
is(countAll(fragment), 10);
|
||||||
let allSwatches = fragment.querySelectorAll("." + COLOR_CLASS);
|
let allSwatches = fragment.querySelectorAll("." + COLOR_CLASS);
|
||||||
is(allSwatches.length, 5);
|
is(allSwatches.length, 5);
|
||||||
is(allSwatches[0].textContent, "rgba(183,222,237,1)");
|
is(allSwatches[0].textContent, "rgba(183,222,237,1)");
|
||||||
@ -177,7 +177,7 @@ function test() {
|
|||||||
name: "background",
|
name: "background",
|
||||||
value: "-moz-radial-gradient(center 45deg, circle closest-side, orange 0%, red 100%)",
|
value: "-moz-radial-gradient(center 45deg, circle closest-side, orange 0%, red 100%)",
|
||||||
test: fragment => {
|
test: fragment => {
|
||||||
is(countAll(fragment), 2);
|
is(countAll(fragment), 4);
|
||||||
let allSwatches = fragment.querySelectorAll("." + COLOR_CLASS);
|
let allSwatches = fragment.querySelectorAll("." + COLOR_CLASS);
|
||||||
is(allSwatches.length, 2);
|
is(allSwatches.length, 2);
|
||||||
is(allSwatches[0].textContent, "orange");
|
is(allSwatches[0].textContent, "orange");
|
||||||
@ -188,7 +188,7 @@ function test() {
|
|||||||
name: "background",
|
name: "background",
|
||||||
value: "white url(http://test.com/wow_such_image.png) no-repeat top left",
|
value: "white url(http://test.com/wow_such_image.png) no-repeat top left",
|
||||||
test: fragment => {
|
test: fragment => {
|
||||||
is(countAll(fragment), 2);
|
is(countAll(fragment), 3);
|
||||||
is(countUrls(fragment), 1);
|
is(countUrls(fragment), 1);
|
||||||
is(countColors(fragment), 1);
|
is(countColors(fragment), 1);
|
||||||
}
|
}
|
||||||
@ -213,7 +213,7 @@ function test() {
|
|||||||
name: "background",
|
name: "background",
|
||||||
value: "red url( \"http://wow.com/cool/../../../you're(doingit)wrong\" ) repeat center",
|
value: "red url( \"http://wow.com/cool/../../../you're(doingit)wrong\" ) repeat center",
|
||||||
test: fragment => {
|
test: fragment => {
|
||||||
is(countAll(fragment), 2);
|
is(countAll(fragment), 3);
|
||||||
is(countColors(fragment), 1);
|
is(countColors(fragment), 1);
|
||||||
is(getUrl(fragment), "http://wow.com/cool/../../../you're(doingit)wrong");
|
is(getUrl(fragment), "http://wow.com/cool/../../../you're(doingit)wrong");
|
||||||
}
|
}
|
||||||
|
@ -56,11 +56,13 @@
|
|||||||
tabindex="0"/>
|
tabindex="0"/>
|
||||||
</toolbar>
|
</toolbar>
|
||||||
<splitter class="devtools-horizontal-splitter"/>
|
<splitter class="devtools-horizontal-splitter"/>
|
||||||
<box id="web-audio-content-pane" flex="1">
|
<box id="web-audio-content-pane"
|
||||||
|
class="devtools-responsive-container"
|
||||||
|
flex="1">
|
||||||
<hbox flex="1">
|
<hbox flex="1">
|
||||||
<box id="web-audio-graph" class="devtools-responsive-container" flex="1">
|
<box id="web-audio-graph" flex="1">
|
||||||
<vbox flex="1">
|
<vbox flex="1">
|
||||||
<svg id="graph-svg" flex="1" viewBox="0 0 1000 500"
|
<svg id="graph-svg"
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
xmlns:xlink="http://www.w3.org/1999/xlink">
|
xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||||
<g id="graph-target" transform="translate(20,20)"/>
|
<g id="graph-target" transform="translate(20,20)"/>
|
||||||
|
@ -1396,7 +1396,7 @@ mediaResetDesc=Stop emulating a CSS media type
|
|||||||
# injectFailed) These strings describe the 'inject' commands and all available
|
# injectFailed) These strings describe the 'inject' commands and all available
|
||||||
# parameters.
|
# parameters.
|
||||||
injectDesc=Inject common libraries into the page
|
injectDesc=Inject common libraries into the page
|
||||||
injectManual=Inject common libraries into the content of the page which can also be accessed from the Firefox console.
|
injectManual2=Inject common libraries into the content of the page which can also be accessed from the console.
|
||||||
injectLibraryDesc=Select the library to inject or enter a valid script URI to inject
|
injectLibraryDesc=Select the library to inject or enter a valid script URI to inject
|
||||||
injectLoaded=%1$S loaded
|
injectLoaded=%1$S loaded
|
||||||
injectFailed=Failed to load %1$S - Invalid URI
|
injectFailed=Failed to load %1$S - Invalid URI
|
||||||
|
@ -86,3 +86,11 @@ description {
|
|||||||
font-size: 1.25rem;
|
font-size: 1.25rem;
|
||||||
line-height: 22px;
|
line-height: 22px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#popupPolicyRow {
|
||||||
|
/* Override styles from
|
||||||
|
browser/themes/osx/preferences/preferences.css */
|
||||||
|
margin-bottom: 0 !important;
|
||||||
|
padding-bottom: 0 !important;
|
||||||
|
border-bottom: none;
|
||||||
|
}
|
||||||
|
@ -134,9 +134,7 @@ caption {
|
|||||||
-moz-box-align: center;
|
-moz-box-align: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
#popupPolicyRow,
|
#popupPolicyRow {
|
||||||
#enableSoftwareInstallRow,
|
|
||||||
#enableImagesRow {
|
|
||||||
margin-bottom: 4px !important;
|
margin-bottom: 4px !important;
|
||||||
padding-bottom: 4px !important;
|
padding-bottom: 4px !important;
|
||||||
border-bottom: 1px solid #ccc;
|
border-bottom: 1px solid #ccc;
|
||||||
|
@ -139,7 +139,9 @@ panelmultiview[nosubviews=true] > .panel-viewcontainer > .panel-viewstack > .pan
|
|||||||
|
|
||||||
.panel-subview-header,
|
.panel-subview-header,
|
||||||
.subviewbutton.panel-subview-footer {
|
.subviewbutton.panel-subview-footer {
|
||||||
padding: 12px;
|
box-sizing: border-box;
|
||||||
|
min-height: 41px;
|
||||||
|
padding: 11px 12px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.panel-subview-header {
|
.panel-subview-header {
|
||||||
@ -490,8 +492,9 @@ toolbarpaletteitem[place="palette"] > toolbaritem > toolbarbutton {
|
|||||||
#PanelUI-customize,
|
#PanelUI-customize,
|
||||||
#PanelUI-quit {
|
#PanelUI-quit {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
padding: 10px 0;
|
padding: 11px 0;
|
||||||
min-height: 2em;
|
box-sizing: border-box;
|
||||||
|
min-height: 40px;
|
||||||
-moz-appearance: none;
|
-moz-appearance: none;
|
||||||
box-shadow: none;
|
box-shadow: none;
|
||||||
border: none;
|
border: none;
|
||||||
|
@ -40,8 +40,8 @@
|
|||||||
|
|
||||||
/* Context Graph */
|
/* Context Graph */
|
||||||
svg {
|
svg {
|
||||||
position: fixed;
|
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
|
-moz-box-flex: 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Edges in graph */
|
/* Edges in graph */
|
||||||
@ -111,12 +111,6 @@ text {
|
|||||||
transition: opacity .5s ease-out 0s;
|
transition: opacity .5s ease-out 0s;
|
||||||
}
|
}
|
||||||
|
|
||||||
@media (min-resolution: 2dppx) {
|
|
||||||
.web-audio-inspector .error {
|
|
||||||
background-image: url(alerticon-warning@2x.png);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#inspector-pane-toggle {
|
#inspector-pane-toggle {
|
||||||
background: none;
|
background: none;
|
||||||
box-shadow: none;
|
box-shadow: none;
|
||||||
@ -151,4 +145,28 @@ text {
|
|||||||
#inspector-pane-toggle:active {
|
#inspector-pane-toggle:active {
|
||||||
-moz-image-region: rect(0px,64px,32px,32px);
|
-moz-image-region: rect(0px,64px,32px,32px);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
.web-audio-inspector .error {
|
||||||
|
background-image: url(alerticon-warning@2x.png);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Responsive Styles
|
||||||
|
* `.devtools-responsive-container` takes care of most of
|
||||||
|
* the changing of host types.
|
||||||
|
*/
|
||||||
|
@media (max-width: 700px) {
|
||||||
|
/**
|
||||||
|
* Override the inspector toggle so it's always open
|
||||||
|
* in the portrait view, with the toggle button hidden.
|
||||||
|
*/
|
||||||
|
#inspector-pane-toggle {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
#web-audio-inspector {
|
||||||
|
margin-left: 0px !important;
|
||||||
|
margin-right: 0px !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -324,19 +324,61 @@ case "$target" in
|
|||||||
|
|
||||||
ANDROID_SDK="${android_sdk}"
|
ANDROID_SDK="${android_sdk}"
|
||||||
ANDROID_SDK_ROOT="${android_sdk_root}"
|
ANDROID_SDK_ROOT="${android_sdk_root}"
|
||||||
if test -e "${ANDROID_SDK_ROOT}/extras/android/compatibility/v4/android-support-v4.jar" ; then
|
|
||||||
ANDROID_COMPAT_LIB="${ANDROID_SDK_ROOT}/extras/android/compatibility/v4/android-support-v4.jar"
|
AC_MSG_CHECKING([for compat library dirs])
|
||||||
|
if test -e "${android_sdk_root}/extras/android/compatibility/v4/android-support-v4.jar" ; then
|
||||||
|
ANDROID_COMPAT_DIR_BASE="${android_sdk_root}/extras/android/compatibility";
|
||||||
else
|
else
|
||||||
ANDROID_COMPAT_LIB="${ANDROID_SDK_ROOT}/extras/android/support/v4/android-support-v4.jar";
|
ANDROID_COMPAT_DIR_BASE="${android_sdk_root}/extras/android/support";
|
||||||
fi
|
fi
|
||||||
|
AC_MSG_RESULT([$ANDROID_COMPAT_DIR_BASE])
|
||||||
|
|
||||||
ANDROID_TOOLS="${android_tools}"
|
ANDROID_TOOLS="${android_tools}"
|
||||||
ANDROID_PLATFORM_TOOLS="${android_platform_tools}"
|
ANDROID_PLATFORM_TOOLS="${android_platform_tools}"
|
||||||
ANDROID_BUILD_TOOLS="${android_build_tools}"
|
ANDROID_BUILD_TOOLS="${android_build_tools}"
|
||||||
AC_SUBST(ANDROID_SDK_ROOT)
|
AC_SUBST(ANDROID_SDK_ROOT)
|
||||||
AC_SUBST(ANDROID_SDK)
|
AC_SUBST(ANDROID_SDK)
|
||||||
|
|
||||||
|
ANDROID_COMPAT_LIB=$ANDROID_COMPAT_DIR_BASE/v4/android-support-v4.jar
|
||||||
|
AC_MSG_CHECKING([for v4 compat library])
|
||||||
AC_SUBST(ANDROID_COMPAT_LIB)
|
AC_SUBST(ANDROID_COMPAT_LIB)
|
||||||
if ! test -e $ANDROID_COMPAT_LIB ; then
|
if ! test -e $ANDROID_COMPAT_LIB ; then
|
||||||
AC_MSG_ERROR([You must download the Android support library when targeting Android. Run the Android SDK tool and install Android Support Library under Extras. See https://developer.android.com/tools/extras/support-library.html for more info. (looked for $ANDROID_COMPAT_LIB)])
|
AC_MSG_ERROR([You must download the Android v4 support library when targeting Android. Run the Android SDK tool and install Android Support Library under Extras. See https://developer.android.com/tools/extras/support-library.html for more info. (looked for $ANDROID_COMPAT_LIB)])
|
||||||
|
fi
|
||||||
|
AC_MSG_RESULT([$ANDROID_COMPAT_LIB])
|
||||||
|
|
||||||
|
if test -n "$MOZ_NATIVE_DEVICES" ; then
|
||||||
|
AC_SUBST(MOZ_NATIVE_DEVICES)
|
||||||
|
|
||||||
|
AC_MSG_CHECKING([for google play services])
|
||||||
|
GOOGLE_PLAY_SERVICES_LIB="${ANDROID_SDK_ROOT}/extras/google/google_play_services/libproject/google-play-services_lib/libs/google-play-services.jar"
|
||||||
|
GOOGLE_PLAY_SERVICES_RES="${ANDROID_SDK_ROOT}/extras/google/google_play_services/libproject/google-play-services_lib/res"
|
||||||
|
AC_SUBST(GOOGLE_PLAY_SERVICES_LIB)
|
||||||
|
AC_SUBST(GOOGLE_PLAY_SERVICES_RES)
|
||||||
|
if ! test -e $GOOGLE_PLAY_SERVICES_LIB ; then
|
||||||
|
AC_MSG_ERROR([You must download Google Play Services to build with native video casting support enabled. Run the Android SDK tool and install Google Play Services under Extras. See http://developer.android.com/google/play-services/setup.html for more info. (looked for $GOOGLE_PLAY_SERVICES_LIB) ])
|
||||||
|
fi
|
||||||
|
AC_MSG_RESULT([$GOOGLE_PLAY_SERVICES_LIB])
|
||||||
|
|
||||||
|
ANDROID_APPCOMPAT_LIB="$ANDROID_COMPAT_DIR_BASE/v7/appcompat/libs/android-support-v7-appcompat.jar"
|
||||||
|
ANDROID_APPCOMPAT_RES="$ANDROID_COMPAT_DIR_BASE/v7/appcompat/res"
|
||||||
|
AC_MSG_CHECKING([for v7 appcompat library])
|
||||||
|
if ! test -e $ANDROID_APPCOMPAT_LIB ; then
|
||||||
|
AC_MSG_ERROR([You must download the v7 app compat Android support library when targeting Android with native video casting support enabled. Run the Android SDK tool and install Android Support Library under Extras. See https://developer.android.com/tools/extras/support-library.html for more info. (looked for $ANDROID_APPCOMPAT_LIB)])
|
||||||
|
fi
|
||||||
|
AC_MSG_RESULT([$ANDROID_APPCOMPAT_LIB])
|
||||||
|
AC_SUBST(ANDROID_APPCOMPAT_LIB)
|
||||||
|
AC_SUBST(ANDROID_APPCOMPAT_RES)
|
||||||
|
|
||||||
|
ANDROID_MEDIAROUTER_LIB="$ANDROID_COMPAT_DIR_BASE/v7/mediarouter/libs/android-support-v7-mediarouter.jar"
|
||||||
|
ANDROID_MEDIAROUTER_RES="$ANDROID_COMPAT_DIR_BASE/v7/mediarouter/res"
|
||||||
|
AC_MSG_CHECKING([for v7 mediarouter library])
|
||||||
|
if ! test -e $ANDROID_MEDIAROUTER_LIB ; then
|
||||||
|
AC_MSG_ERROR([You must download the v7 media router Android support library when targeting Android with native video casting support enabled. Run the Android SDK tool and install Android Support Library under Extras. See https://developer.android.com/tools/extras/support-library.html for more info. (looked for $ANDROID_MEDIAROUTER_LIB)])
|
||||||
|
fi
|
||||||
|
AC_MSG_RESULT([$ANDROID_MEDIAROUTER_LIB])
|
||||||
|
AC_SUBST(ANDROID_MEDIAROUTER_LIB)
|
||||||
|
AC_SUBST(ANDROID_MEDIAROUTER_RES)
|
||||||
fi
|
fi
|
||||||
|
|
||||||
MOZ_PATH_PROG(ZIPALIGN, zipalign, :, [$ANDROID_TOOLS])
|
MOZ_PATH_PROG(ZIPALIGN, zipalign, :, [$ANDROID_TOOLS])
|
||||||
|
@ -95,7 +95,7 @@ GENERATED_DIRS += $(dir-tests)
|
|||||||
# being linked against them. This is a best effort to avoid getting
|
# being linked against them. This is a best effort to avoid getting
|
||||||
# out of sync with base's build config.
|
# out of sync with base's build config.
|
||||||
JARS_DIR := $(DEPTH)/mobile/android/base
|
JARS_DIR := $(DEPTH)/mobile/android/base
|
||||||
JAVA_BOOTCLASSPATH := $(JAVA_BOOTCLASSPATH):$(subst $(NULL) ,:,$(wildcard $(JARS_DIR)/*.jar))
|
JAVA_BOOTCLASSPATH := $(JAVA_BOOTCLASSPATH):$(subst $(NULL) ,:,$(wildcard $(JARS_DIR)/*.jar)):$(ANDROID_COMPAT_LIB)
|
||||||
# We also want to re-compile classes.dex when the associated base
|
# We also want to re-compile classes.dex when the associated base
|
||||||
# content changes.
|
# content changes.
|
||||||
classes.dex: $(wildcard $(JARS_DIR)/*.jar)
|
classes.dex: $(wildcard $(JARS_DIR)/*.jar)
|
||||||
|
@ -2,16 +2,12 @@
|
|||||||
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
# 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/.
|
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||||
|
|
||||||
# Ensure JAVA_CLASSPATH and ANDROID_SDK are defined before including this file.
|
# Ensure ANDROID_SDK is defined before including this file.
|
||||||
# We use common android defaults for boot class path and java version.
|
# We use common android defaults for boot class path and java version.
|
||||||
ifndef ANDROID_SDK
|
ifndef ANDROID_SDK
|
||||||
$(error ANDROID_SDK must be defined before including android-common.mk)
|
$(error ANDROID_SDK must be defined before including android-common.mk)
|
||||||
endif
|
endif
|
||||||
|
|
||||||
ifndef JAVA_CLASSPATH
|
|
||||||
$(error JAVA_CLASSPATH must be defined before including android-common.mk)
|
|
||||||
endif
|
|
||||||
|
|
||||||
# DEBUG_JARSIGNER always debug signs.
|
# DEBUG_JARSIGNER always debug signs.
|
||||||
DEBUG_JARSIGNER=$(PYTHON) $(abspath $(topsrcdir)/mobile/android/debug_sign_tool.py) \
|
DEBUG_JARSIGNER=$(PYTHON) $(abspath $(topsrcdir)/mobile/android/debug_sign_tool.py) \
|
||||||
--keytool=$(KEYTOOL) \
|
--keytool=$(KEYTOOL) \
|
||||||
@ -20,7 +16,7 @@ DEBUG_JARSIGNER=$(PYTHON) $(abspath $(topsrcdir)/mobile/android/debug_sign_tool.
|
|||||||
|
|
||||||
# For Android, this defaults to $(ANDROID_SDK)/android.jar
|
# For Android, this defaults to $(ANDROID_SDK)/android.jar
|
||||||
ifndef JAVA_BOOTCLASSPATH
|
ifndef JAVA_BOOTCLASSPATH
|
||||||
JAVA_BOOTCLASSPATH = $(ANDROID_SDK)/android.jar:$(ANDROID_COMPAT_LIB)
|
JAVA_BOOTCLASSPATH = $(ANDROID_SDK)/android.jar
|
||||||
endif
|
endif
|
||||||
|
|
||||||
# For Android, we default to 1.5
|
# For Android, we default to 1.5
|
||||||
@ -31,7 +27,7 @@ endif
|
|||||||
JAVAC_FLAGS = \
|
JAVAC_FLAGS = \
|
||||||
-target $(JAVA_VERSION) \
|
-target $(JAVA_VERSION) \
|
||||||
-source $(JAVA_VERSION) \
|
-source $(JAVA_VERSION) \
|
||||||
-classpath $(JAVA_CLASSPATH) \
|
$(if $(JAVA_CLASSPATH),-classpath $(JAVA_CLASSPATH),) \
|
||||||
-bootclasspath $(JAVA_BOOTCLASSPATH) \
|
-bootclasspath $(JAVA_BOOTCLASSPATH) \
|
||||||
-encoding UTF8 \
|
-encoding UTF8 \
|
||||||
-g:source,lines \
|
-g:source,lines \
|
||||||
|
@ -14,3 +14,4 @@ skip = false
|
|||||||
[test_touchcaret.py]
|
[test_touchcaret.py]
|
||||||
b2g = false ; Bug 1020261
|
b2g = false ; Bug 1020261
|
||||||
[test_selectioncarets.py]
|
[test_selectioncarets.py]
|
||||||
|
skip-if = os == "win" #perma-fail on Windows
|
||||||
|
@ -194,6 +194,10 @@ pref("extensions.minCompatibleAppVersion", "11.0");
|
|||||||
pref("extensions.update.url", "https://versioncheck.addons.mozilla.org/update/VersionCheck.php?reqVersion=%REQ_VERSION%&id=%ITEM_ID%&version=%ITEM_VERSION%&maxAppVersion=%ITEM_MAXAPPVERSION%&status=%ITEM_STATUS%&appID=%APP_ID%&appVersion=%APP_VERSION%&appOS=%APP_OS%&appABI=%APP_ABI%&locale=%APP_LOCALE%¤tAppVersion=%CURRENT_APP_VERSION%&updateType=%UPDATE_TYPE%&compatMode=%COMPATIBILITY_MODE%");
|
pref("extensions.update.url", "https://versioncheck.addons.mozilla.org/update/VersionCheck.php?reqVersion=%REQ_VERSION%&id=%ITEM_ID%&version=%ITEM_VERSION%&maxAppVersion=%ITEM_MAXAPPVERSION%&status=%ITEM_STATUS%&appID=%APP_ID%&appVersion=%APP_VERSION%&appOS=%APP_OS%&appABI=%APP_ABI%&locale=%APP_LOCALE%¤tAppVersion=%CURRENT_APP_VERSION%&updateType=%UPDATE_TYPE%&compatMode=%COMPATIBILITY_MODE%");
|
||||||
pref("extensions.update.background.url", "https://versioncheck-bg.addons.mozilla.org/update/VersionCheck.php?reqVersion=%REQ_VERSION%&id=%ITEM_ID%&version=%ITEM_VERSION%&maxAppVersion=%ITEM_MAXAPPVERSION%&status=%ITEM_STATUS%&appID=%APP_ID%&appVersion=%APP_VERSION%&appOS=%APP_OS%&appABI=%APP_ABI%&locale=%APP_LOCALE%¤tAppVersion=%CURRENT_APP_VERSION%&updateType=%UPDATE_TYPE%&compatMode=%COMPATIBILITY_MODE%");
|
pref("extensions.update.background.url", "https://versioncheck-bg.addons.mozilla.org/update/VersionCheck.php?reqVersion=%REQ_VERSION%&id=%ITEM_ID%&version=%ITEM_VERSION%&maxAppVersion=%ITEM_MAXAPPVERSION%&status=%ITEM_STATUS%&appID=%APP_ID%&appVersion=%APP_VERSION%&appOS=%APP_OS%&appABI=%APP_ABI%&locale=%APP_LOCALE%¤tAppVersion=%CURRENT_APP_VERSION%&updateType=%UPDATE_TYPE%&compatMode=%COMPATIBILITY_MODE%");
|
||||||
|
|
||||||
|
pref("extensions.hotfix.id", "firefox-android-hotfix@mozilla.org");
|
||||||
|
pref("extensions.hotfix.cert.checkAttributes", true);
|
||||||
|
pref("extensions.hotfix.certs.1.sha1Fingerprint", "91:53:98:0C:C1:86:DF:47:8F:35:22:9E:11:C9:A7:31:04:49:A1:AA");
|
||||||
|
|
||||||
/* preferences for the Get Add-ons pane */
|
/* preferences for the Get Add-ons pane */
|
||||||
pref("extensions.getAddons.cache.enabled", true);
|
pref("extensions.getAddons.cache.enabled", true);
|
||||||
pref("extensions.getAddons.maxResults", 15);
|
pref("extensions.getAddons.maxResults", 15);
|
||||||
|
@ -83,6 +83,11 @@
|
|||||||
|
|
||||||
<meta-data android:name="com.sec.android.support.multiwindow" android:value="true"/>
|
<meta-data android:name="com.sec.android.support.multiwindow" android:value="true"/>
|
||||||
|
|
||||||
|
#ifdef GOOGLE_PLAY_SERVICES
|
||||||
|
<!-- This resources comes from Google Play Services. Required for casting support. -->
|
||||||
|
<meta-data android:name="com.google.android.gms.version" android:value="@integer/google_play_services_version" />
|
||||||
|
#endif
|
||||||
|
|
||||||
<!-- If the windowSoftInputMode adjust* flag changes below, the
|
<!-- If the windowSoftInputMode adjust* flag changes below, the
|
||||||
setSoftInputMode call in BrowserSearch#onStop must also be updated. -->
|
setSoftInputMode call in BrowserSearch#onStop must also be updated. -->
|
||||||
<activity android:name=".App"
|
<activity android:name=".App"
|
||||||
|
@ -487,7 +487,7 @@ abstract public class BrowserApp extends GeckoApp
|
|||||||
Telemetry.sendUIEvent(TelemetryContract.Event.LOAD_URL, TelemetryContract.Method.INTENT);
|
Telemetry.sendUIEvent(TelemetryContract.Event.LOAD_URL, TelemetryContract.Method.INTENT);
|
||||||
}
|
}
|
||||||
|
|
||||||
((GeckoApp.MainLayout) mMainLayout).setTouchEventInterceptor(new HideTabsTouchListener());
|
((GeckoApp.MainLayout) mMainLayout).setTouchEventInterceptor(new HideOnTouchListener());
|
||||||
((GeckoApp.MainLayout) mMainLayout).setMotionEventInterceptor(new MotionEventInterceptor() {
|
((GeckoApp.MainLayout) mMainLayout).setMotionEventInterceptor(new MotionEventInterceptor() {
|
||||||
@Override
|
@Override
|
||||||
public boolean onInterceptMotionEvent(View view, MotionEvent event) {
|
public boolean onInterceptMotionEvent(View view, MotionEvent event) {
|
||||||
@ -1990,11 +1990,17 @@ abstract public class BrowserApp extends GeckoApp
|
|||||||
mBrowserSearch.setUserVisibleHint(false);
|
mBrowserSearch.setUserVisibleHint(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
private class HideTabsTouchListener implements TouchEventInterceptor {
|
/**
|
||||||
|
* Hides certain UI elements (e.g. button toast, tabs tray) when the
|
||||||
|
* user touches the main layout.
|
||||||
|
*/
|
||||||
|
private class HideOnTouchListener implements TouchEventInterceptor {
|
||||||
private boolean mIsHidingTabs = false;
|
private boolean mIsHidingTabs = false;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean onInterceptTouchEvent(View view, MotionEvent event) {
|
public boolean onInterceptTouchEvent(View view, MotionEvent event) {
|
||||||
|
getButtonToast().hide(false, ButtonToast.ReasonHidden.TOUCH_OUTSIDE);
|
||||||
|
|
||||||
// We need to account for scroll state for the touched view otherwise
|
// We need to account for scroll state for the touched view otherwise
|
||||||
// tapping on an "empty" part of the view will still be considered a
|
// tapping on an "empty" part of the view will still be considered a
|
||||||
// valid touch event.
|
// valid touch event.
|
||||||
|
@ -59,7 +59,23 @@ GARBAGE += \
|
|||||||
|
|
||||||
GARBAGE_DIRS += classes db jars res sync services generated
|
GARBAGE_DIRS += classes db jars res sync services generated
|
||||||
|
|
||||||
JAVA_CLASSPATH = $(ANDROID_SDK)/android.jar
|
JAVA_BOOTCLASSPATH = \
|
||||||
|
$(ANDROID_SDK)/android.jar \
|
||||||
|
$(ANDROID_COMPAT_LIB) \
|
||||||
|
$(NULL)
|
||||||
|
|
||||||
|
JAVA_BOOTCLASSPATH := $(subst $(NULL) ,:,$(strip $(JAVA_BOOTCLASSPATH)))
|
||||||
|
|
||||||
|
# If native devices are enabled, add Google Play Services and some of the v7 compat libraries
|
||||||
|
ifdef MOZ_NATIVE_DEVICES
|
||||||
|
JAVA_CLASSPATH += \
|
||||||
|
$(GOOGLE_PLAY_SERVICES_LIB) \
|
||||||
|
$(ANDROID_MEDIAROUTER_LIB) \
|
||||||
|
$(ANDROID_APPCOMPAT_LIB) \
|
||||||
|
$(NULL)
|
||||||
|
endif
|
||||||
|
|
||||||
|
JAVA_CLASSPATH := $(subst $(NULL) ,:,$(strip $(JAVA_CLASSPATH)))
|
||||||
|
|
||||||
ALL_JARS = \
|
ALL_JARS = \
|
||||||
gecko-R.jar \
|
gecko-R.jar \
|
||||||
@ -83,9 +99,16 @@ include $(topsrcdir)/config/config.mk
|
|||||||
# because Android resource classes must be compiled together in order to avoid overlapping resource
|
# because Android resource classes must be compiled together in order to avoid overlapping resource
|
||||||
# indices.
|
# indices.
|
||||||
|
|
||||||
|
library_jars = \
|
||||||
|
$(JAVA_CLASSPATH) \
|
||||||
|
$(JAVA_BOOTCLASSPATH) \
|
||||||
|
$(NULL)
|
||||||
|
|
||||||
|
library_jars := $(subst $(NULL) ,:,$(strip $(library_jars)))
|
||||||
|
|
||||||
classes.dex: .proguard.deps
|
classes.dex: .proguard.deps
|
||||||
$(REPORT_BUILD)
|
$(REPORT_BUILD)
|
||||||
$(DX) --dex --output=classes.dex jars-proguarded $(ANDROID_COMPAT_LIB)
|
$(DX) --dex --output=classes.dex jars-proguarded $(subst :, ,$(ANDROID_COMPAT_LIB):$(JAVA_CLASSPATH))
|
||||||
|
|
||||||
ifdef MOZ_DISABLE_PROGUARD
|
ifdef MOZ_DISABLE_PROGUARD
|
||||||
PROGUARD_PASSES=0
|
PROGUARD_PASSES=0
|
||||||
@ -113,7 +136,7 @@ endif
|
|||||||
-optimizationpasses $(PROGUARD_PASSES) \
|
-optimizationpasses $(PROGUARD_PASSES) \
|
||||||
-injars $(subst ::,:,$(subst $(NULL) ,:,$(strip $(ALL_JARS)))) \
|
-injars $(subst ::,:,$(subst $(NULL) ,:,$(strip $(ALL_JARS)))) \
|
||||||
-outjars jars-proguarded \
|
-outjars jars-proguarded \
|
||||||
-libraryjars $(ANDROID_SDK)/android.jar:$(ANDROID_COMPAT_LIB)
|
-libraryjars $(library_jars)
|
||||||
|
|
||||||
CLASSES_WITH_JNI= \
|
CLASSES_WITH_JNI= \
|
||||||
org.mozilla.gecko.ANRReporter \
|
org.mozilla.gecko.ANRReporter \
|
||||||
@ -141,16 +164,15 @@ ANNOTATION_PROCESSOR_JAR_FILES := $(DEPTH)/build/annotationProcessors/annotation
|
|||||||
|
|
||||||
GeneratedJNIWrappers.cpp: $(ANNOTATION_PROCESSOR_JAR_FILES)
|
GeneratedJNIWrappers.cpp: $(ANNOTATION_PROCESSOR_JAR_FILES)
|
||||||
GeneratedJNIWrappers.cpp: $(ALL_JARS)
|
GeneratedJNIWrappers.cpp: $(ALL_JARS)
|
||||||
$(JAVA) -classpath gecko-mozglue.jar:$(JAVA_BOOTCLASSPATH):$(ANNOTATION_PROCESSOR_JAR_FILES) org.mozilla.gecko.annotationProcessors.AnnotationProcessor $(ALL_JARS)
|
$(JAVA) -classpath gecko-mozglue.jar:$(JAVA_BOOTCLASSPATH):$(JAVA_CLASSPATH):$(ANNOTATION_PROCESSOR_JAR_FILES) org.mozilla.gecko.annotationProcessors.AnnotationProcessor $(ALL_JARS)
|
||||||
|
|
||||||
gecko_package_dir = generated/org/mozilla/gecko
|
|
||||||
# Like generated/org/mozilla/fennec_$USERID.
|
# Like generated/org/mozilla/fennec_$USERID.
|
||||||
android_package_dir = $(addprefix generated/,$(subst .,/,$(ANDROID_PACKAGE_NAME)))
|
android_package_dir = $(addprefix generated/,$(subst .,/,$(ANDROID_PACKAGE_NAME)))
|
||||||
|
|
||||||
# These _PP_JAVAFILES are specified in moz.build and defined in
|
# These _PP_JAVAFILES are specified in moz.build and defined in
|
||||||
# backend.mk, which is included by config.mk. Therefore this needs to
|
# backend.mk, which is included by config.mk. Therefore this needs to
|
||||||
# be defined after config.mk is included.
|
# be defined after config.mk is included.
|
||||||
PP_JAVAFILES := $(filter-out $(gecko_package_dir)/R.java,$(gecko-mozglue_PP_JAVAFILES) $(gecko-browser_PP_JAVAFILES))
|
PP_JAVAFILES := $(filter-out generated/org/mozilla/gecko/R.java,$(gecko-mozglue_PP_JAVAFILES) $(gecko-browser_PP_JAVAFILES))
|
||||||
|
|
||||||
manifest := \
|
manifest := \
|
||||||
AndroidManifest.xml.in \
|
AndroidManifest.xml.in \
|
||||||
@ -163,9 +185,9 @@ PP_TARGETS += manifest
|
|||||||
# generates these files into generated/org/mozilla/gecko for
|
# generates these files into generated/org/mozilla/gecko for
|
||||||
# consumption by the build system and IDEs.
|
# consumption by the build system and IDEs.
|
||||||
|
|
||||||
preprocessed := $(addsuffix .in,$(subst $(gecko_package_dir)/,,$(filter $(gecko_package_dir)/%,$(PP_JAVAFILES))))
|
preprocessed := $(addsuffix .in,$(subst generated/org/mozilla/gecko/,,$(filter generated/org/mozilla/gecko/%,$(PP_JAVAFILES))))
|
||||||
|
|
||||||
preprocessed_PATH := $(gecko_package_dir)
|
preprocessed_PATH := generated/org/mozilla/gecko
|
||||||
preprocessed_KEEP_PATH := 1
|
preprocessed_KEEP_PATH := 1
|
||||||
|
|
||||||
PP_TARGETS += preprocessed
|
PP_TARGETS += preprocessed
|
||||||
@ -222,6 +244,7 @@ $(ANDROID_GENERATED_RESFILES): $(call mkdir_deps,$(sort $(dir $(ANDROID_GENERATE
|
|||||||
$(TOUCH) $@
|
$(TOUCH) $@
|
||||||
$(MAKE) -C locales
|
$(MAKE) -C locales
|
||||||
|
|
||||||
|
|
||||||
# This .deps pattern saves an invocation of the sub-Make: the single
|
# This .deps pattern saves an invocation of the sub-Make: the single
|
||||||
# invocation generates both strings.xml and suggestedsites.json. The
|
# invocation generates both strings.xml and suggestedsites.json. The
|
||||||
# trailing semi-colon defines an empty recipe: defining no recipe at
|
# trailing semi-colon defines an empty recipe: defining no recipe at
|
||||||
@ -268,7 +291,24 @@ geckoview_resources.zip: $(all_resources) $(GLOBAL_DEPS)
|
|||||||
# Make to treat the target differently, in a way that defeats our
|
# Make to treat the target differently, in a way that defeats our
|
||||||
# dependencies.
|
# dependencies.
|
||||||
|
|
||||||
$(gecko_package_dir)/R.java: .aapt.deps ;
|
generated/org/mozilla/gecko/R.java: .aapt.deps ;
|
||||||
|
|
||||||
|
# If native devices are enabled, add Google Play Services, build their resources
|
||||||
|
generated/android/support/v7/appcompat/R.java: .aapt.deps ;
|
||||||
|
generated/android/support/v7/mediarouter/R.java: .aapt.deps ;
|
||||||
|
generated/com/google/android/gms/R.java: .aapt.deps ;
|
||||||
|
|
||||||
|
ifdef MOZ_NATIVE_DEVICES
|
||||||
|
extra_packages += android.support.v7.appcompat
|
||||||
|
extra_res_dirs += $(ANDROID_APPCOMPAT_RES)
|
||||||
|
|
||||||
|
extra_packages += android.support.v7.mediarouter
|
||||||
|
extra_res_dirs += $(ANDROID_MEDIAROUTER_RES)
|
||||||
|
|
||||||
|
extra_packages += com.google.android.gms
|
||||||
|
extra_res_dirs += $(GOOGLE_PLAY_SERVICES_RES)
|
||||||
|
endif
|
||||||
|
|
||||||
gecko.ap_: .aapt.deps ;
|
gecko.ap_: .aapt.deps ;
|
||||||
R.txt: .aapt.deps ;
|
R.txt: .aapt.deps ;
|
||||||
|
|
||||||
@ -289,6 +329,8 @@ gecko-nodeps/R.txt: .aapt.nodeps ;
|
|||||||
|
|
||||||
ANDROID_AAPT_IGNORE := !.svn:!.git:.*:<dir>_*:!CVS:!thumbs.db:!picasa.ini:!*.scc:*~:\#*:*.rej:*.orig
|
ANDROID_AAPT_IGNORE := !.svn:!.git:.*:<dir>_*:!CVS:!thumbs.db:!picasa.ini:!*.scc:*~:\#*:*.rej:*.orig
|
||||||
|
|
||||||
|
extra_packages := $(subst $(NULL) ,:,$(strip $(extra_packages)))
|
||||||
|
|
||||||
# 1: target file.
|
# 1: target file.
|
||||||
# 2: dependencies.
|
# 2: dependencies.
|
||||||
# 3: name of ap_ file to write.
|
# 3: name of ap_ file to write.
|
||||||
@ -301,10 +343,15 @@ ANDROID_AAPT_IGNORE := !.svn:!.git:.*:<dir>_*:!CVS:!thumbs.db:!picasa.ini:!*.scc
|
|||||||
define aapt_command
|
define aapt_command
|
||||||
$(1): $$(call mkdir_deps,$(filter-out ./,$(dir $(3) $(4) $(5)))) $(2)
|
$(1): $$(call mkdir_deps,$(filter-out ./,$(dir $(3) $(4) $(5)))) $(2)
|
||||||
@$$(TOUCH) $$@
|
@$$(TOUCH) $$@
|
||||||
$$(AAPT) package -f -M AndroidManifest.xml -I $$(ANDROID_SDK)/android.jar \
|
$$(AAPT) package -f -m \
|
||||||
|
-M AndroidManifest.xml \
|
||||||
|
-I $(ANDROID_SDK)/android.jar \
|
||||||
--auto-add-overlay \
|
--auto-add-overlay \
|
||||||
$$(addprefix -S ,$$(ANDROID_RES_DIRS)) \
|
$$(addprefix -S ,$$(ANDROID_RES_DIRS)) \
|
||||||
--custom-package org.mozilla.gecko --non-constant-id \
|
$(if $(extra_res_dirs),$$(addprefix -S ,$$(extra_res_dirs)),) \
|
||||||
|
$(if $(extra_packages),--extra-packages $$(extra_packages),) \
|
||||||
|
--custom-package org.mozilla.gecko \
|
||||||
|
--non-constant-id \
|
||||||
-F $(3) \
|
-F $(3) \
|
||||||
-J $(4) \
|
-J $(4) \
|
||||||
--output-text-symbols $(5) \
|
--output-text-symbols $(5) \
|
||||||
@ -319,12 +366,12 @@ endef
|
|||||||
# toolkit/mozapps/installer/packager.mk.
|
# toolkit/mozapps/installer/packager.mk.
|
||||||
|
|
||||||
# .aapt.deps: $(all_resources)
|
# .aapt.deps: $(all_resources)
|
||||||
$(eval $(call aapt_command,.aapt.deps,$(all_resources),gecko.ap_,$(gecko_package_dir)/,./))
|
$(eval $(call aapt_command,.aapt.deps,$(all_resources),gecko.ap_,generated/,./))
|
||||||
|
|
||||||
# .aapt.nodeps: $(CURDIR)/AndroidManifest.xml FORCE
|
# .aapt.nodeps: $(CURDIR)/AndroidManifest.xml FORCE
|
||||||
$(eval $(call aapt_command,.aapt.nodeps,$(CURDIR)/AndroidManifest.xml FORCE,gecko-nodeps.ap_,gecko-nodeps/,gecko-nodeps/))
|
$(eval $(call aapt_command,.aapt.nodeps,$(CURDIR)/AndroidManifest.xml FORCE,gecko-nodeps.ap_,gecko-nodeps/,gecko-nodeps/))
|
||||||
|
|
||||||
fennec_ids.txt: $(gecko_package_dir)/R.java fennec-ids-generator.py
|
fennec_ids.txt: generated/org/mozilla/gecko/R.java fennec-ids-generator.py
|
||||||
$(PYTHON) $(topsrcdir)/mobile/android/base/fennec-ids-generator.py -i $< -o $@
|
$(PYTHON) $(topsrcdir)/mobile/android/base/fennec-ids-generator.py -i $< -o $@
|
||||||
|
|
||||||
# Override the Java settings with some specific android settings
|
# Override the Java settings with some specific android settings
|
||||||
|
@ -153,6 +153,10 @@ public class BrowserDB {
|
|||||||
sSuggestedSites = suggestedSites;
|
sSuggestedSites = suggestedSites;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static boolean hideSuggestedSite(String url) {
|
||||||
|
return sSuggestedSites.hideSite(url);
|
||||||
|
}
|
||||||
|
|
||||||
public static void invalidateCachedState() {
|
public static void invalidateCachedState() {
|
||||||
sDb.invalidateCachedState();
|
sDb.invalidateCachedState();
|
||||||
}
|
}
|
||||||
|
@ -10,18 +10,21 @@ import android.content.SharedPreferences;
|
|||||||
import android.database.Cursor;
|
import android.database.Cursor;
|
||||||
import android.database.MatrixCursor;
|
import android.database.MatrixCursor;
|
||||||
import android.database.MatrixCursor.RowBuilder;
|
import android.database.MatrixCursor.RowBuilder;
|
||||||
|
import android.net.Uri;
|
||||||
import android.text.TextUtils;
|
import android.text.TextUtils;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
|
import java.util.HashSet;
|
||||||
import java.util.LinkedHashMap;
|
import java.util.LinkedHashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
import org.json.JSONArray;
|
import org.json.JSONArray;
|
||||||
import org.json.JSONException;
|
|
||||||
import org.json.JSONObject;
|
import org.json.JSONObject;
|
||||||
|
|
||||||
import org.mozilla.gecko.GeckoSharedPrefs;
|
import org.mozilla.gecko.GeckoSharedPrefs;
|
||||||
@ -30,6 +33,7 @@ import org.mozilla.gecko.db.BrowserContract;
|
|||||||
import org.mozilla.gecko.mozglue.RobocopTarget;
|
import org.mozilla.gecko.mozglue.RobocopTarget;
|
||||||
import org.mozilla.gecko.preferences.GeckoPreferences;
|
import org.mozilla.gecko.preferences.GeckoPreferences;
|
||||||
import org.mozilla.gecko.util.RawResource;
|
import org.mozilla.gecko.util.RawResource;
|
||||||
|
import org.mozilla.gecko.util.ThreadUtils;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* {@code SuggestedSites} provides API to get a list of locale-specific
|
* {@code SuggestedSites} provides API to get a list of locale-specific
|
||||||
@ -47,11 +51,16 @@ import org.mozilla.gecko.util.RawResource;
|
|||||||
* The default list of suggested sites is stored in a raw Android
|
* The default list of suggested sites is stored in a raw Android
|
||||||
* resource ({@code R.raw.suggestedsites}) which is dynamically
|
* resource ({@code R.raw.suggestedsites}) which is dynamically
|
||||||
* generated at build time for each target locale.
|
* generated at build time for each target locale.
|
||||||
|
*
|
||||||
|
* Changes to the list of suggested sites are saved in SharedPreferences.
|
||||||
*/
|
*/
|
||||||
@RobocopTarget
|
@RobocopTarget
|
||||||
public class SuggestedSites {
|
public class SuggestedSites {
|
||||||
private static final String LOGTAG = "GeckoSuggestedSites";
|
private static final String LOGTAG = "GeckoSuggestedSites";
|
||||||
|
|
||||||
|
// SharedPreference key for suggested sites that should be hidden.
|
||||||
|
public static final String PREF_SUGGESTED_SITES_HIDDEN = "suggestedSites.hidden";
|
||||||
|
|
||||||
private static final String[] COLUMNS = new String[] {
|
private static final String[] COLUMNS = new String[] {
|
||||||
BrowserContract.SuggestedSites._ID,
|
BrowserContract.SuggestedSites._ID,
|
||||||
BrowserContract.SuggestedSites.URL,
|
BrowserContract.SuggestedSites.URL,
|
||||||
@ -88,6 +97,7 @@ public class SuggestedSites {
|
|||||||
private final Context context;
|
private final Context context;
|
||||||
private Map<String, Site> cachedSites;
|
private Map<String, Site> cachedSites;
|
||||||
private Locale cachedLocale;
|
private Locale cachedLocale;
|
||||||
|
private Set<String> cachedBlacklist;
|
||||||
|
|
||||||
public SuggestedSites(Context appContext) {
|
public SuggestedSites(Context appContext) {
|
||||||
context = appContext;
|
context = appContext;
|
||||||
@ -155,7 +165,7 @@ public class SuggestedSites {
|
|||||||
return prefs.getBoolean(GeckoPreferences.PREFS_SUGGESTED_SITES, true);
|
return prefs.getBoolean(GeckoPreferences.PREFS_SUGGESTED_SITES, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
private Site getSiteForUrl(String url) {
|
private synchronized Site getSiteForUrl(String url) {
|
||||||
if (cachedSites == null) {
|
if (cachedSites == null) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@ -199,7 +209,7 @@ public class SuggestedSites {
|
|||||||
* @param locale the target locale.
|
* @param locale the target locale.
|
||||||
* @param excludeUrls list of URLs to be excluded from the list.
|
* @param excludeUrls list of URLs to be excluded from the list.
|
||||||
*/
|
*/
|
||||||
public Cursor get(int limit, Locale locale, List<String> excludeUrls) {
|
public synchronized Cursor get(int limit, Locale locale, List<String> excludeUrls) {
|
||||||
final MatrixCursor cursor = new MatrixCursor(COLUMNS);
|
final MatrixCursor cursor = new MatrixCursor(COLUMNS);
|
||||||
|
|
||||||
// Return an empty cursor if suggested sites have been
|
// Return an empty cursor if suggested sites have been
|
||||||
@ -219,6 +229,8 @@ public class SuggestedSites {
|
|||||||
return cursor;
|
return cursor;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
excludeUrls = includeBlacklist(excludeUrls);
|
||||||
|
|
||||||
final int sitesCount = cachedSites.size();
|
final int sitesCount = cachedSites.size();
|
||||||
Log.d(LOGTAG, "Number of suggested sites: " + sitesCount);
|
Log.d(LOGTAG, "Number of suggested sites: " + sitesCount);
|
||||||
|
|
||||||
@ -257,4 +269,83 @@ public class SuggestedSites {
|
|||||||
final Site site = getSiteForUrl(url);
|
final Site site = getSiteForUrl(url);
|
||||||
return (site != null ? site.bgColor : null);
|
return (site != null ? site.bgColor : null);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
private Set<String> loadBlacklist() {
|
||||||
|
Log.d(LOGTAG, "Loading blacklisted suggested sites from SharedPreferences.");
|
||||||
|
final Set<String> blacklist = new HashSet<String>();
|
||||||
|
|
||||||
|
final SharedPreferences preferences = GeckoSharedPrefs.forProfile(context);
|
||||||
|
final String sitesString = preferences.getString(PREF_SUGGESTED_SITES_HIDDEN, null);
|
||||||
|
|
||||||
|
if (sitesString != null) {
|
||||||
|
for (String site : sitesString.trim().split(" ")) {
|
||||||
|
blacklist.add(Uri.decode(site));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return blacklist;
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<String> includeBlacklist(List<String> originalList) {
|
||||||
|
if (cachedBlacklist == null) {
|
||||||
|
cachedBlacklist = loadBlacklist();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cachedBlacklist.isEmpty()) {
|
||||||
|
return originalList;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (originalList == null) {
|
||||||
|
originalList = new ArrayList<String>();
|
||||||
|
}
|
||||||
|
|
||||||
|
originalList.addAll(cachedBlacklist);
|
||||||
|
return originalList;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Blacklist a suggested site so it will no longer be returned as a suggested site.
|
||||||
|
* This method should only be called from a background thread because it may write
|
||||||
|
* to SharedPreferences.
|
||||||
|
*
|
||||||
|
* Urls that are not Suggested Sites are ignored.
|
||||||
|
*
|
||||||
|
* @param url String url of site to blacklist
|
||||||
|
* @return true is blacklisted, false otherwise
|
||||||
|
*/
|
||||||
|
public synchronized boolean hideSite(String url) {
|
||||||
|
ThreadUtils.assertNotOnUiThread();
|
||||||
|
|
||||||
|
if (cachedSites == null) {
|
||||||
|
refresh();
|
||||||
|
if (cachedSites == null) {
|
||||||
|
Log.w(LOGTAG, "Could not load suggested sites!");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cachedSites.containsKey(url)) {
|
||||||
|
if (cachedBlacklist == null) {
|
||||||
|
cachedBlacklist = loadBlacklist();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if site has already been blacklisted, just in case.
|
||||||
|
if (!cachedBlacklist.contains(url)) {
|
||||||
|
|
||||||
|
saveToBlacklist(url);
|
||||||
|
cachedBlacklist.add(url);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void saveToBlacklist(String url) {
|
||||||
|
final SharedPreferences prefs = GeckoSharedPrefs.forProfile(context);
|
||||||
|
final String prefString = prefs.getString(PREF_SUGGESTED_SITES_HIDDEN, "");
|
||||||
|
final String siteString = prefString.concat(" " + Uri.encode(url));
|
||||||
|
prefs.edit().putString(PREF_SUGGESTED_SITES_HIDDEN, siteString).commit();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -19,6 +19,7 @@ import org.mozilla.gecko.Tabs;
|
|||||||
import org.mozilla.gecko.Telemetry;
|
import org.mozilla.gecko.Telemetry;
|
||||||
import org.mozilla.gecko.TelemetryContract;
|
import org.mozilla.gecko.TelemetryContract;
|
||||||
import org.mozilla.gecko.db.BrowserContract.Combined;
|
import org.mozilla.gecko.db.BrowserContract.Combined;
|
||||||
|
import org.mozilla.gecko.db.BrowserContract.SuggestedSites;
|
||||||
import org.mozilla.gecko.db.BrowserDB;
|
import org.mozilla.gecko.db.BrowserDB;
|
||||||
import org.mozilla.gecko.favicons.Favicons;
|
import org.mozilla.gecko.favicons.Favicons;
|
||||||
import org.mozilla.gecko.home.TopSitesGridView.TopSitesGridContextMenuInfo;
|
import org.mozilla.gecko.home.TopSitesGridView.TopSitesGridContextMenuInfo;
|
||||||
@ -333,6 +334,9 @@ abstract class HomeFragment extends Fragment {
|
|||||||
|
|
||||||
if (mPosition > -1) {
|
if (mPosition > -1) {
|
||||||
BrowserDB.unpinSite(cr, mPosition);
|
BrowserDB.unpinSite(cr, mPosition);
|
||||||
|
if (BrowserDB.hideSuggestedSite(mUrl)) {
|
||||||
|
cr.notifyChange(SuggestedSites.CONTENT_URI, null);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
BrowserDB.removeBookmarksWithURL(cr, mUrl);
|
BrowserDB.removeBookmarksWithURL(cr, mUrl);
|
||||||
|
@ -16,6 +16,13 @@ resjar.sources = []
|
|||||||
resjar.generated_sources += [
|
resjar.generated_sources += [
|
||||||
'org/mozilla/gecko/R.java',
|
'org/mozilla/gecko/R.java',
|
||||||
]
|
]
|
||||||
|
|
||||||
|
if CONFIG['MOZ_NATIVE_DEVICES']:
|
||||||
|
resjar.generated_sources += ['com/google/android/gms/R.java']
|
||||||
|
DEFINES["GOOGLE_PLAY_SERVICES"] = 1
|
||||||
|
resjar.generated_sources += ['android/support/v7/appcompat/R.java']
|
||||||
|
resjar.generated_sources += ['android/support/v7/mediarouter/R.java']
|
||||||
|
|
||||||
resjar.javac_flags += ['-Xlint:all']
|
resjar.javac_flags += ['-Xlint:all']
|
||||||
|
|
||||||
mgjar = add_java_jar('gecko-mozglue')
|
mgjar = add_java_jar('gecko-mozglue')
|
||||||
@ -470,6 +477,12 @@ gbjar.extra_jars = [
|
|||||||
'sync-thirdparty.jar',
|
'sync-thirdparty.jar',
|
||||||
'websockets.jar',
|
'websockets.jar',
|
||||||
]
|
]
|
||||||
|
|
||||||
|
if CONFIG['MOZ_NATIVE_DEVICES']:
|
||||||
|
gbjar.extra_jars += [CONFIG['ANDROID_APPCOMPAT_LIB']]
|
||||||
|
gbjar.extra_jars += [CONFIG['ANDROID_MEDIAROUTER_LIB']]
|
||||||
|
gbjar.extra_jars += [CONFIG['GOOGLE_PLAY_SERVICES_LIB']]
|
||||||
|
|
||||||
gbjar.javac_flags += ['-Xlint:all,-deprecation,-fallthrough']
|
gbjar.javac_flags += ['-Xlint:all,-deprecation,-fallthrough']
|
||||||
|
|
||||||
spjar = add_java_jar('squareup-picasso')
|
spjar = add_java_jar('squareup-picasso')
|
||||||
|
@ -5,6 +5,6 @@
|
|||||||
|
|
||||||
<shape xmlns:android="http://schemas.android.com/apk/res/android"
|
<shape xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
android:shape="rectangle">
|
android:shape="rectangle">
|
||||||
<solid android:color="@color/toast_button_background" />
|
<solid android:color="@color/toast_background" />
|
||||||
<corners android:radius="@dimen/toast_button_corner_radius" />
|
<corners android:radius="@dimen/toast_button_corner_radius" />
|
||||||
</shape>
|
</shape>
|
||||||
|
@ -1,10 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<!-- 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/. -->
|
|
||||||
|
|
||||||
<resources>
|
|
||||||
<!-- Button toast colors. -->
|
|
||||||
<color name="toast_button_background">#FF656565</color>
|
|
||||||
<color name="toast_button_pressed">#FFB1B1B1</color>
|
|
||||||
</resources>
|
|
@ -14,8 +14,8 @@
|
|||||||
<item name="android:background">@null</item>
|
<item name="android:background">@null</item>
|
||||||
<item name="android:paddingLeft">24dp</item>
|
<item name="android:paddingLeft">24dp</item>
|
||||||
<item name="android:paddingRight">24dp</item>
|
<item name="android:paddingRight">24dp</item>
|
||||||
<item name="android:paddingTop">18dp</item>
|
<item name="android:paddingTop">11dp</item>
|
||||||
<item name="android:paddingBottom">18dp</item>
|
<item name="android:paddingBottom">11dp</item>
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
<style name="ToastDivider" parent="ToastDividerBase">
|
<style name="ToastDivider" parent="ToastDividerBase">
|
||||||
|
@ -108,8 +108,9 @@
|
|||||||
<color name="remote_tabs_setup_button_background_hit">#D95300</color>
|
<color name="remote_tabs_setup_button_background_hit">#D95300</color>
|
||||||
|
|
||||||
<!-- Button toast colors. -->
|
<!-- Button toast colors. -->
|
||||||
<color name="toast_button_background">#FF2A2A2A</color>
|
<color name="toast_background">#DD363B40</color>
|
||||||
<color name="toast_button_pressed">#FF3E6784</color>
|
<color name="toast_button_background">#00000000</color>
|
||||||
|
<color name="toast_button_pressed">#DD2C3136</color>
|
||||||
<color name="toast_button_divider">#FFD1D5DA</color>
|
<color name="toast_button_divider">#FFD1D5DA</color>
|
||||||
<color name="toast_button_text">#FFFFFFFF</color>
|
<color name="toast_button_text">#FFFFFFFF</color>
|
||||||
</resources>
|
</resources>
|
||||||
|
@ -611,8 +611,8 @@
|
|||||||
<item name="android:background">@null</item>
|
<item name="android:background">@null</item>
|
||||||
<item name="android:paddingLeft">12dp</item>
|
<item name="android:paddingLeft">12dp</item>
|
||||||
<item name="android:paddingRight">12dp</item>
|
<item name="android:paddingRight">12dp</item>
|
||||||
<item name="android:paddingTop">20dp</item>
|
<item name="android:paddingTop">11dp</item>
|
||||||
<item name="android:paddingBottom">20dp</item>
|
<item name="android:paddingBottom">11dp</item>
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
<style name="ToastDividerBase">
|
<style name="ToastDividerBase">
|
||||||
|
@ -42,6 +42,7 @@ public class ButtonToast {
|
|||||||
|
|
||||||
public enum ReasonHidden {
|
public enum ReasonHidden {
|
||||||
CLICKED,
|
CLICKED,
|
||||||
|
TOUCH_OUTSIDE,
|
||||||
TIMEOUT,
|
TIMEOUT,
|
||||||
REPLACED,
|
REPLACED,
|
||||||
STARTUP
|
STARTUP
|
||||||
|
@ -121,10 +121,13 @@ XPCOMUtils.defineLazyModuleGetter(this, "CharsetMenu",
|
|||||||
Services.scriptloader.loadSubScript(script, sandbox);
|
Services.scriptloader.loadSubScript(script, sandbox);
|
||||||
return sandbox[name];
|
return sandbox[name];
|
||||||
});
|
});
|
||||||
notifications.forEach(function (aNotification) {
|
let observer = (s, t, d) => {
|
||||||
Services.obs.addObserver(function(s, t, d) {
|
Services.obs.removeObserver(observer, t);
|
||||||
window[name].observe(s, t, d)
|
Services.obs.addObserver(window[name], t, false);
|
||||||
}, aNotification, false);
|
window[name].observe(s, t, d); // Explicitly notify new observer
|
||||||
|
};
|
||||||
|
notifications.forEach((notification) => {
|
||||||
|
Services.obs.addObserver(observer, notification, false);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -135,10 +138,13 @@ XPCOMUtils.defineLazyModuleGetter(this, "CharsetMenu",
|
|||||||
].forEach(module => {
|
].forEach(module => {
|
||||||
let [name, notifications, resource] = module;
|
let [name, notifications, resource] = module;
|
||||||
XPCOMUtils.defineLazyModuleGetter(this, name, resource);
|
XPCOMUtils.defineLazyModuleGetter(this, name, resource);
|
||||||
|
let observer = (s, t, d) => {
|
||||||
|
Services.obs.removeObserver(observer, t);
|
||||||
|
Services.obs.addObserver(this[name], t, false);
|
||||||
|
this[name].observe(s, t, d); // Explicitly notify new observer
|
||||||
|
};
|
||||||
notifications.forEach(notification => {
|
notifications.forEach(notification => {
|
||||||
Services.obs.addObserver((s,t,d) => {
|
Services.obs.addObserver(observer, notification, false);
|
||||||
this[name].observe(s,t,d)
|
|
||||||
}, notification, false);
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -194,6 +194,8 @@
|
|||||||
*;
|
*;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
-keep class **.R$*
|
||||||
|
|
||||||
# Disable obfuscation because it makes exception stack traces more difficult to read.
|
# Disable obfuscation because it makes exception stack traces more difficult to read.
|
||||||
-dontobfuscate
|
-dontobfuscate
|
||||||
|
|
||||||
|
@ -69,3 +69,6 @@ MOZ_LOCALE_SWITCHER=1
|
|||||||
|
|
||||||
# Enable second screen and casting support for external devices.
|
# Enable second screen and casting support for external devices.
|
||||||
MOZ_DEVICES=1
|
MOZ_DEVICES=1
|
||||||
|
|
||||||
|
# Enable second screen using native Android libraries
|
||||||
|
MOZ_NATIVE_DEVICES=
|
||||||
|
@ -7,6 +7,7 @@ import android.content.Context;
|
|||||||
import android.content.res.Resources;
|
import android.content.res.Resources;
|
||||||
import android.content.SharedPreferences;
|
import android.content.SharedPreferences;
|
||||||
import android.database.Cursor;
|
import android.database.Cursor;
|
||||||
|
import android.net.Uri;
|
||||||
import android.test.mock.MockResources;
|
import android.test.mock.MockResources;
|
||||||
import android.test.RenamingDelegatingContext;
|
import android.test.RenamingDelegatingContext;
|
||||||
|
|
||||||
@ -20,7 +21,6 @@ import java.util.Locale;
|
|||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
import org.json.JSONArray;
|
import org.json.JSONArray;
|
||||||
import org.json.JSONException;
|
|
||||||
import org.json.JSONObject;
|
import org.json.JSONObject;
|
||||||
|
|
||||||
import org.mozilla.gecko.R;
|
import org.mozilla.gecko.R;
|
||||||
@ -28,7 +28,6 @@ import org.mozilla.gecko.db.BrowserContract;
|
|||||||
import org.mozilla.gecko.db.SuggestedSites;
|
import org.mozilla.gecko.db.SuggestedSites;
|
||||||
import org.mozilla.gecko.GeckoSharedPrefs;
|
import org.mozilla.gecko.GeckoSharedPrefs;
|
||||||
import org.mozilla.gecko.preferences.GeckoPreferences;
|
import org.mozilla.gecko.preferences.GeckoPreferences;
|
||||||
import org.mozilla.gecko.util.RawResource;
|
|
||||||
|
|
||||||
public class TestSuggestedSites extends BrowserTestCase {
|
public class TestSuggestedSites extends BrowserTestCase {
|
||||||
private static class TestContext extends RenamingDelegatingContext {
|
private static class TestContext extends RenamingDelegatingContext {
|
||||||
@ -192,6 +191,44 @@ public class TestSuggestedSites extends BrowserTestCase {
|
|||||||
c.close();
|
c.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void testHiddenSites() {
|
||||||
|
resources.setSuggestedSitesResource(generateSites(6));
|
||||||
|
|
||||||
|
List<String> visibleUrls = new ArrayList<String>(3);
|
||||||
|
visibleUrls.add("url3");
|
||||||
|
visibleUrls.add("url4");
|
||||||
|
visibleUrls.add("url5");
|
||||||
|
|
||||||
|
List<String> hiddenUrls = new ArrayList<String>(3);
|
||||||
|
hiddenUrls.add("url0");
|
||||||
|
hiddenUrls.add("url1");
|
||||||
|
hiddenUrls.add("url2");
|
||||||
|
|
||||||
|
// Add mocked hidden sites to SharedPreferences.
|
||||||
|
StringBuilder hiddenUrlBuilder = new StringBuilder();
|
||||||
|
for (String s : hiddenUrls) {
|
||||||
|
hiddenUrlBuilder.append(" ");
|
||||||
|
hiddenUrlBuilder.append(Uri.encode(s));
|
||||||
|
}
|
||||||
|
|
||||||
|
final String hiddenPref = hiddenUrlBuilder.toString();
|
||||||
|
GeckoSharedPrefs.forProfile(context).edit()
|
||||||
|
.putString(SuggestedSites.PREF_SUGGESTED_SITES_HIDDEN, hiddenPref)
|
||||||
|
.commit();
|
||||||
|
|
||||||
|
Cursor c = new SuggestedSites(context).get(DEFAULT_LIMIT);
|
||||||
|
assertEquals(Math.min(3, DEFAULT_LIMIT), c.getCount());
|
||||||
|
|
||||||
|
c.moveToPosition(-1);
|
||||||
|
while (c.moveToNext()) {
|
||||||
|
String url = c.getString(c.getColumnIndexOrThrow(BrowserContract.SuggestedSites.URL));
|
||||||
|
assertFalse(hiddenUrls.contains(url));
|
||||||
|
assertTrue(visibleUrls.contains(url));
|
||||||
|
}
|
||||||
|
|
||||||
|
c.close();
|
||||||
|
}
|
||||||
|
|
||||||
public void testDisabledState() {
|
public void testDisabledState() {
|
||||||
resources.setSuggestedSitesResource(generateSites(3));
|
resources.setSuggestedSitesResource(generateSites(3));
|
||||||
|
|
||||||
|
@ -41,7 +41,7 @@ want to do then dive in!
|
|||||||
.. toctree::
|
.. toctree::
|
||||||
:maxdepth: 2
|
:maxdepth: 2
|
||||||
|
|
||||||
manifestdestiny
|
manifestparser
|
||||||
gettinginfo
|
gettinginfo
|
||||||
setuprunning
|
setuprunning
|
||||||
mozhttpd
|
mozhttpd
|
||||||
|
@ -33,6 +33,7 @@ class LocalAppNotFoundError(VersionError):
|
|||||||
|
|
||||||
INI_DATA_MAPPING = (('application', 'App'), ('platform', 'Build'))
|
INI_DATA_MAPPING = (('application', 'App'), ('platform', 'Build'))
|
||||||
|
|
||||||
|
|
||||||
class Version(mozlog.LoggingMixin):
|
class Version(mozlog.LoggingMixin):
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
@ -62,6 +63,7 @@ class Version(mozlog.LoggingMixin):
|
|||||||
self._info['application_display_name'] = \
|
self._info['application_display_name'] = \
|
||||||
self._info.get('application_name')
|
self._info.get('application_name')
|
||||||
|
|
||||||
|
|
||||||
class LocalFennecVersion(Version):
|
class LocalFennecVersion(Version):
|
||||||
|
|
||||||
def __init__(self, path, **kwargs):
|
def __init__(self, path, **kwargs):
|
||||||
@ -78,6 +80,7 @@ class LocalFennecVersion(Version):
|
|||||||
else:
|
else:
|
||||||
self.warn('Unable to find %s' % filename)
|
self.warn('Unable to find %s' % filename)
|
||||||
|
|
||||||
|
|
||||||
class LocalVersion(Version):
|
class LocalVersion(Version):
|
||||||
|
|
||||||
def __init__(self, binary, **kwargs):
|
def __init__(self, binary, **kwargs):
|
||||||
@ -168,11 +171,12 @@ class LocalB2GVersion(B2GVersion):
|
|||||||
|
|
||||||
class RemoteB2GVersion(B2GVersion):
|
class RemoteB2GVersion(B2GVersion):
|
||||||
|
|
||||||
def __init__(self, sources=None, dm_type='adb', host=None, **kwargs):
|
def __init__(self, sources=None, dm_type='adb', host=None,
|
||||||
|
device_serial=None, **kwargs):
|
||||||
B2GVersion.__init__(self, sources, **kwargs)
|
B2GVersion.__init__(self, sources, **kwargs)
|
||||||
|
|
||||||
if dm_type == 'adb':
|
if dm_type == 'adb':
|
||||||
dm = mozdevice.DeviceManagerADB()
|
dm = mozdevice.DeviceManagerADB(deviceSerial=device_serial)
|
||||||
elif dm_type == 'sut':
|
elif dm_type == 'sut':
|
||||||
if not host:
|
if not host:
|
||||||
raise Exception('A host for SUT must be supplied.')
|
raise Exception('A host for SUT must be supplied.')
|
||||||
@ -218,7 +222,8 @@ class RemoteB2GVersion(B2GVersion):
|
|||||||
self._info[desired_props[key]] = value
|
self._info[desired_props[key]] = value
|
||||||
|
|
||||||
|
|
||||||
def get_version(binary=None, sources=None, dm_type=None, host=None):
|
def get_version(binary=None, sources=None, dm_type=None, host=None,
|
||||||
|
device_serial=None):
|
||||||
"""
|
"""
|
||||||
Returns the application version information as a dict. You can specify
|
Returns the application version information as a dict. You can specify
|
||||||
a path to the binary of the application or an Android APK file (to get
|
a path to the binary of the application or an Android APK file (to get
|
||||||
@ -231,6 +236,7 @@ def get_version(binary=None, sources=None, dm_type=None, host=None):
|
|||||||
:param sources: Path to the sources.xml file (Firefox OS)
|
:param sources: Path to the sources.xml file (Firefox OS)
|
||||||
:param dm_type: Device manager type. Must be 'adb' or 'sut' (Firefox OS)
|
:param dm_type: Device manager type. Must be 'adb' or 'sut' (Firefox OS)
|
||||||
:param host: Host address of remote Firefox OS instance (SUT)
|
:param host: Host address of remote Firefox OS instance (SUT)
|
||||||
|
:param device_serial: Serial identifier of Firefox OS device (ADB)
|
||||||
"""
|
"""
|
||||||
try:
|
try:
|
||||||
if binary and zipfile.is_zipfile(binary) and 'AndroidManifest.xml' in \
|
if binary and zipfile.is_zipfile(binary) and 'AndroidManifest.xml' in \
|
||||||
@ -241,7 +247,8 @@ def get_version(binary=None, sources=None, dm_type=None, host=None):
|
|||||||
if version._info.get('application_name') == 'B2G':
|
if version._info.get('application_name') == 'B2G':
|
||||||
version = LocalB2GVersion(binary, sources=sources)
|
version = LocalB2GVersion(binary, sources=sources)
|
||||||
except LocalAppNotFoundError:
|
except LocalAppNotFoundError:
|
||||||
version = RemoteB2GVersion(sources=sources, dm_type=dm_type, host=host)
|
version = RemoteB2GVersion(sources=sources, dm_type=dm_type, host=host,
|
||||||
|
device_serial=device_serial)
|
||||||
return version._info
|
return version._info
|
||||||
|
|
||||||
|
|
||||||
@ -253,13 +260,17 @@ def cli(args=sys.argv[1:]):
|
|||||||
parser.add_option('--sources',
|
parser.add_option('--sources',
|
||||||
dest='sources',
|
dest='sources',
|
||||||
help='path to sources.xml (Firefox OS only)')
|
help='path to sources.xml (Firefox OS only)')
|
||||||
|
parser.add_option('--device',
|
||||||
|
help='serial identifier of device to target (Firefox OS '
|
||||||
|
'only)')
|
||||||
(options, args) = parser.parse_args(args)
|
(options, args) = parser.parse_args(args)
|
||||||
|
|
||||||
dm_type = os.environ.get('DM_TRANS', 'adb')
|
dm_type = os.environ.get('DM_TRANS', 'adb')
|
||||||
host = os.environ.get('TEST_DEVICE')
|
host = os.environ.get('TEST_DEVICE')
|
||||||
|
|
||||||
version = get_version(binary=options.binary, sources=options.sources,
|
version = get_version(binary=options.binary, sources=options.sources,
|
||||||
dm_type=dm_type, host=host)
|
dm_type=dm_type, host=host,
|
||||||
|
device_serial=options.device)
|
||||||
for (key, value) in sorted(version.items()):
|
for (key, value) in sorted(version.items()):
|
||||||
if value:
|
if value:
|
||||||
print '%s: %s' % (key, value)
|
print '%s: %s' % (key, value)
|
||||||
|
@ -558,6 +558,8 @@
|
|||||||
try {
|
try {
|
||||||
// See bug 341047 and comments in overflow handler as to why
|
// See bug 341047 and comments in overflow handler as to why
|
||||||
// try..catch is needed here
|
// try..catch is needed here
|
||||||
|
this._updateScrollButtonsDisabledState();
|
||||||
|
|
||||||
let childNodes = this._getScrollableElements();
|
let childNodes = this._getScrollableElements();
|
||||||
if (childNodes && childNodes.length)
|
if (childNodes && childNodes.length)
|
||||||
this.ensureElementIsVisible(childNodes[0], false);
|
this.ensureElementIsVisible(childNodes[0], false);
|
||||||
|
@ -12,7 +12,7 @@ exports.items = [
|
|||||||
{
|
{
|
||||||
name: "inject",
|
name: "inject",
|
||||||
description: gcli.lookup("injectDesc"),
|
description: gcli.lookup("injectDesc"),
|
||||||
manual: gcli.lookup("injectManual"),
|
manual: gcli.lookup("injectManual2"),
|
||||||
params: [{
|
params: [{
|
||||||
name: 'library',
|
name: 'library',
|
||||||
type: {
|
type: {
|
||||||
|
@ -328,18 +328,29 @@ OutputParser.prototype = {
|
|||||||
let colorObj = new colorUtils.CssColor(color);
|
let colorObj = new colorUtils.CssColor(color);
|
||||||
|
|
||||||
if (this._isValidColor(colorObj)) {
|
if (this._isValidColor(colorObj)) {
|
||||||
|
let container = this._createNode("span", {
|
||||||
|
"data-color": color
|
||||||
|
});
|
||||||
|
|
||||||
if (options.colorSwatchClass) {
|
if (options.colorSwatchClass) {
|
||||||
this._appendNode("span", {
|
let swatch = this._createNode("span", {
|
||||||
class: options.colorSwatchClass,
|
class: options.colorSwatchClass,
|
||||||
style: "background-color:" + color
|
style: "background-color:" + color
|
||||||
});
|
});
|
||||||
|
container.appendChild(swatch);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (options.defaultColorType) {
|
if (options.defaultColorType) {
|
||||||
color = colorObj.toString();
|
color = colorObj.toString();
|
||||||
|
container.dataset["color"] = color;
|
||||||
}
|
}
|
||||||
this._appendNode("span", {
|
|
||||||
|
let value = this._createNode("span", {
|
||||||
class: options.colorClass
|
class: options.colorClass
|
||||||
}, color);
|
}, color);
|
||||||
|
|
||||||
|
container.appendChild(value);
|
||||||
|
this.parsed.push(container);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
@ -380,7 +391,7 @@ OutputParser.prototype = {
|
|||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Append a node to the output.
|
* Create a node.
|
||||||
*
|
*
|
||||||
* @param {String} tagName
|
* @param {String} tagName
|
||||||
* Tag type e.g. "div"
|
* Tag type e.g. "div"
|
||||||
@ -389,8 +400,9 @@ OutputParser.prototype = {
|
|||||||
* @param {String} [value]
|
* @param {String} [value]
|
||||||
* If a value is included it will be appended as a text node inside
|
* If a value is included it will be appended as a text node inside
|
||||||
* the tag. This is useful e.g. for span tags.
|
* the tag. This is useful e.g. for span tags.
|
||||||
|
* @return {Node} Newly created Node.
|
||||||
*/
|
*/
|
||||||
_appendNode: function(tagName, attributes, value="") {
|
_createNode: function(tagName, attributes, value="") {
|
||||||
let win = Services.appShell.hiddenDOMWindow;
|
let win = Services.appShell.hiddenDOMWindow;
|
||||||
let doc = win.document;
|
let doc = win.document;
|
||||||
let node = doc.createElementNS(HTML_NS, tagName);
|
let node = doc.createElementNS(HTML_NS, tagName);
|
||||||
@ -407,6 +419,22 @@ OutputParser.prototype = {
|
|||||||
node.appendChild(textNode);
|
node.appendChild(textNode);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return node;
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Append a node to the output.
|
||||||
|
*
|
||||||
|
* @param {String} tagName
|
||||||
|
* Tag type e.g. "div"
|
||||||
|
* @param {Object} attributes
|
||||||
|
* e.g. {class: "someClass", style: "cursor:pointer"};
|
||||||
|
* @param {String} [value]
|
||||||
|
* If a value is included it will be appended as a text node inside
|
||||||
|
* the tag. This is useful e.g. for span tags.
|
||||||
|
*/
|
||||||
|
_appendNode: function(tagName, attributes, value="") {
|
||||||
|
let node = this._createNode(tagName, attributes, value);
|
||||||
this.parsed.push(node);
|
this.parsed.push(node);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -28,12 +28,12 @@ let FramerateActor = exports.FramerateActor = protocol.ActorClass({
|
|||||||
initialize: function(conn, tabActor) {
|
initialize: function(conn, tabActor) {
|
||||||
protocol.Actor.prototype.initialize.call(this, conn);
|
protocol.Actor.prototype.initialize.call(this, conn);
|
||||||
this.tabActor = tabActor;
|
this.tabActor = tabActor;
|
||||||
this._contentWin = tabActor.window;
|
this._chromeWin = getChromeWin(tabActor.window);
|
||||||
this._onRefreshDriverTick = this._onRefreshDriverTick.bind(this);
|
this._onRefreshDriverTick = this._onRefreshDriverTick.bind(this);
|
||||||
},
|
},
|
||||||
destroy: function(conn) {
|
destroy: function(conn) {
|
||||||
protocol.Actor.prototype.destroy.call(this, conn);
|
protocol.Actor.prototype.destroy.call(this, conn);
|
||||||
this.finalize();
|
this.stopRecording();
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -46,8 +46,8 @@ let FramerateActor = exports.FramerateActor = protocol.ActorClass({
|
|||||||
this._recording = true;
|
this._recording = true;
|
||||||
this._ticks = [];
|
this._ticks = [];
|
||||||
|
|
||||||
this._startTime = this._contentWin.performance.now();
|
this._startTime = this._chromeWin.performance.now();
|
||||||
this._contentWin.requestAnimationFrame(this._onRefreshDriverTick);
|
this._chromeWin.requestAnimationFrame(this._onRefreshDriverTick);
|
||||||
}, {
|
}, {
|
||||||
}),
|
}),
|
||||||
|
|
||||||
@ -61,7 +61,7 @@ let FramerateActor = exports.FramerateActor = protocol.ActorClass({
|
|||||||
this._recording = false;
|
this._recording = false;
|
||||||
|
|
||||||
// We don't need to store the ticks array for future use, release it.
|
// We don't need to store the ticks array for future use, release it.
|
||||||
let ticks = this._ticks.filter(e => e >= beginAt && e <= endAt);
|
let ticks = this.getPendingTicks(beginAt, endAt);
|
||||||
this._ticks = null;
|
this._ticks = null;
|
||||||
return ticks;
|
return ticks;
|
||||||
}, {
|
}, {
|
||||||
@ -72,6 +72,22 @@ let FramerateActor = exports.FramerateActor = protocol.ActorClass({
|
|||||||
response: { ticks: RetVal("array:number") }
|
response: { ticks: RetVal("array:number") }
|
||||||
}),
|
}),
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the refresh driver ticks recorded so far.
|
||||||
|
*/
|
||||||
|
getPendingTicks: method(function(beginAt = 0, endAt = Number.MAX_SAFE_INTEGER) {
|
||||||
|
if (!this._ticks) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
return this._ticks.filter(e => e >= beginAt && e <= endAt);
|
||||||
|
}, {
|
||||||
|
request: {
|
||||||
|
beginAt: Arg(0, "nullable:number"),
|
||||||
|
endAt: Arg(1, "nullable:number")
|
||||||
|
},
|
||||||
|
response: { ticks: RetVal("array:number") }
|
||||||
|
}),
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Function invoked along with the refresh driver.
|
* Function invoked along with the refresh driver.
|
||||||
*/
|
*/
|
||||||
@ -79,10 +95,10 @@ let FramerateActor = exports.FramerateActor = protocol.ActorClass({
|
|||||||
if (!this._recording) {
|
if (!this._recording) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
this._contentWin.requestAnimationFrame(this._onRefreshDriverTick);
|
this._chromeWin.requestAnimationFrame(this._onRefreshDriverTick);
|
||||||
|
|
||||||
// Store the amount of time passed since the recording started.
|
// Store the amount of time passed since the recording started.
|
||||||
let currentTime = this._contentWin.performance.now();
|
let currentTime = this._chromeWin.performance.now();
|
||||||
let elapsedTime = currentTime - this._startTime;
|
let elapsedTime = currentTime - this._startTime;
|
||||||
this._ticks.push(elapsedTime);
|
this._ticks.push(elapsedTime);
|
||||||
}
|
}
|
||||||
@ -144,3 +160,19 @@ let FramerateFront = exports.FramerateFront = protocol.FrontClass(FramerateActor
|
|||||||
return timeline;
|
return timeline;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the top level browser window from a content window.
|
||||||
|
*
|
||||||
|
* @param nsIDOMWindow innerWin
|
||||||
|
* The content window to query.
|
||||||
|
* @return nsIDOMWindow
|
||||||
|
* The top level browser window.
|
||||||
|
*/
|
||||||
|
function getChromeWin(innerWin) {
|
||||||
|
return innerWin
|
||||||
|
.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIWebNavigation)
|
||||||
|
.QueryInterface(Ci.nsIDocShellTreeItem).rootTreeItem
|
||||||
|
.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIDOMWindow);
|
||||||
|
}
|
||||||
|
@ -22,6 +22,7 @@ support-files =
|
|||||||
[test_framerate_01.html]
|
[test_framerate_01.html]
|
||||||
[test_framerate_02.html]
|
[test_framerate_02.html]
|
||||||
[test_framerate_03.html]
|
[test_framerate_03.html]
|
||||||
|
[test_framerate_04.html]
|
||||||
[test_inspector-changeattrs.html]
|
[test_inspector-changeattrs.html]
|
||||||
[test_inspector-changevalue.html]
|
[test_inspector-changevalue.html]
|
||||||
[test_inspector-hide.html]
|
[test_inspector-hide.html]
|
||||||
|
@ -0,0 +1,72 @@
|
|||||||
|
<!DOCTYPE HTML>
|
||||||
|
<html>
|
||||||
|
<!--
|
||||||
|
Bug 1023018 - Tests if the framerate actor keeps recording after navigations.
|
||||||
|
-->
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<title>Framerate actor test</title>
|
||||||
|
<script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
|
||||||
|
<script type="application/javascript;version=1.8" src="inspector-helpers.js"></script>
|
||||||
|
<link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css">
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<pre id="test">
|
||||||
|
<script>
|
||||||
|
|
||||||
|
window.onload = function() {
|
||||||
|
SimpleTest.waitForExplicitFinish();
|
||||||
|
var {FramerateFront} = devtools.require("devtools/server/actors/framerate");
|
||||||
|
var TargetFactory = devtools.TargetFactory;
|
||||||
|
|
||||||
|
var url = document.getElementById("testContent").href;
|
||||||
|
attachURL(url, onTab);
|
||||||
|
|
||||||
|
function onTab(_, client, form, contentDoc) {
|
||||||
|
var contentWin = contentDoc.defaultView;
|
||||||
|
var chromeWin = Services.wm.getMostRecentWindow("navigator:browser");
|
||||||
|
var selectedTab = chromeWin.gBrowser.selectedTab;
|
||||||
|
|
||||||
|
var target = TargetFactory.forTab(selectedTab);
|
||||||
|
var front = FramerateFront(client, form);
|
||||||
|
|
||||||
|
front.startRecording().then(() => {
|
||||||
|
window.setTimeout(() => {
|
||||||
|
front.getPendingTicks().then(firstBatch => {
|
||||||
|
target.once("will-navigate", () => {
|
||||||
|
window.setTimeout(() => {
|
||||||
|
front.stopRecording().then(secondBatch => {
|
||||||
|
onRecordingStopped(client, firstBatch, secondBatch);
|
||||||
|
});
|
||||||
|
}, 1000);
|
||||||
|
});
|
||||||
|
contentWin.location.reload();
|
||||||
|
});
|
||||||
|
}, 1000);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function onRecordingStopped(client, firstBatch, secondBatch) {
|
||||||
|
ok(firstBatch, "There should be a first batch recording available.");
|
||||||
|
ok(secondBatch, "There should be a second batch recording available.");
|
||||||
|
|
||||||
|
var diff = secondBatch.length - firstBatch.length;
|
||||||
|
info("Difference in ticks: " + diff);
|
||||||
|
ok(diff > 0, "More ticks should be recorded in the second batch.");
|
||||||
|
|
||||||
|
ok(firstBatch.every((e) => secondBatch.indexOf(e) != -1),
|
||||||
|
"All the ticks in the first batch should be in the second batch as well.");
|
||||||
|
ok(secondBatch.every((e, i, array) => i < array.length - 1 ? e < array[i + 1] : true),
|
||||||
|
"All the ticks in the final batch should be ascending in value.");
|
||||||
|
|
||||||
|
client.close(() => {
|
||||||
|
DebuggerServer.destroy();
|
||||||
|
SimpleTest.finish()
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
</pre>
|
||||||
|
<a id="testContent" target="_blank" href="inspector_getImageData.html">Test Document</a>
|
||||||
|
</body>
|
||||||
|
</html>
|
@ -80,6 +80,14 @@ ruleView.contextmenu.copy=Copy
|
|||||||
# the rule view context menu "Select all" entry.
|
# the rule view context menu "Select all" entry.
|
||||||
ruleView.contextmenu.copy.accessKey=C
|
ruleView.contextmenu.copy.accessKey=C
|
||||||
|
|
||||||
|
# LOCALIZATION NOTE (ruleView.contextmenu.copyColor): Text displayed in the rule
|
||||||
|
# and computed view context menu when a color value was clicked.
|
||||||
|
ruleView.contextmenu.copyColor=Copy Color
|
||||||
|
|
||||||
|
# LOCALIZATION NOTE (ruleView.contextmenu.copyColor.accessKey): Access key for
|
||||||
|
# the rule and computed view context menu "Copy Color" entry.
|
||||||
|
ruleView.contextmenu.copyColor.accessKey=L
|
||||||
|
|
||||||
# LOCALIZATION NOTE (ruleView.contextmenu.showOrigSources): Text displayed in the rule view
|
# LOCALIZATION NOTE (ruleView.contextmenu.showOrigSources): Text displayed in the rule view
|
||||||
# context menu.
|
# context menu.
|
||||||
ruleView.contextmenu.showOrigSources=Show original sources
|
ruleView.contextmenu.showOrigSources=Show original sources
|
||||||
|
@ -133,7 +133,7 @@ public:
|
|||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
JSContext* const cx = container->mThreadContext;
|
JSContext* const cx = container->mThreadContext;
|
||||||
JS::RootedObject object(cx, container->mJSObject);
|
JS::RootedObject object(cx, *container->mJSObject);
|
||||||
MOZ_ASSERT(object);
|
MOZ_ASSERT(object);
|
||||||
|
|
||||||
JSAutoStructuredCloneBuffer buffer;
|
JSAutoStructuredCloneBuffer buffer;
|
||||||
@ -179,9 +179,9 @@ public:
|
|||||||
const jint index = env->GetIntField(object, jObjectIndex);
|
const jint index = env->GetIntField(object, jObjectIndex);
|
||||||
if (index < 0) {
|
if (index < 0) {
|
||||||
// -1 for index field means it's the root object of the container
|
// -1 for index field means it's the root object of the container
|
||||||
return container->mJSObject;
|
return *container->mJSObject;
|
||||||
}
|
}
|
||||||
return container->mRootedObjects[index];
|
return *container->mRootedObjects[index];
|
||||||
}
|
}
|
||||||
|
|
||||||
static jobject CreateObjectInstance(JNIEnv* env, jobject object,
|
static jobject CreateObjectInstance(JNIEnv* env, jobject object,
|
||||||
@ -197,7 +197,8 @@ public:
|
|||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
size_t newIndex = container->mRootedObjects.length();
|
size_t newIndex = container->mRootedObjects.length();
|
||||||
if (!container->mRootedObjects.append(jsObject)) {
|
PersistentObjectPtr rootedJSObject(new PersistentObject(cx, jsObject));
|
||||||
|
if (!container->mRootedObjects.append(Move(rootedJSObject))) {
|
||||||
AndroidBridge::ThrowException(env,
|
AndroidBridge::ThrowException(env,
|
||||||
"java/lang/OutOfMemoryError", "Cannot allocate object");
|
"java/lang/OutOfMemoryError", "Cannot allocate object");
|
||||||
return nullptr;
|
return nullptr;
|
||||||
@ -231,7 +232,7 @@ public:
|
|||||||
MOZ_ASSERT(mBuffer.data());
|
MOZ_ASSERT(mBuffer.data());
|
||||||
MOZ_ALWAYS_TRUE(mBuffer.read(mThreadContext, &value));
|
MOZ_ALWAYS_TRUE(mBuffer.read(mThreadContext, &value));
|
||||||
if (value.isObject()) {
|
if (value.isObject()) {
|
||||||
mJSObject = &value.toObject();
|
mJSObject = new PersistentObject(mThreadContext, &value.toObject());
|
||||||
}
|
}
|
||||||
if (!mJSObject) {
|
if (!mJSObject) {
|
||||||
AndroidBridge::ThrowException(env,
|
AndroidBridge::ThrowException(env,
|
||||||
@ -278,22 +279,25 @@ private:
|
|||||||
return newObject;
|
return newObject;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
typedef JS::PersistentRooted<JSObject*> PersistentObject;
|
||||||
|
typedef ScopedDeletePtr<PersistentObject> PersistentObjectPtr;
|
||||||
|
|
||||||
// Thread that the object is valid on
|
// Thread that the object is valid on
|
||||||
PRThread* mThread;
|
PRThread* mThread;
|
||||||
// Context that the object is valid in
|
// Context that the object is valid in
|
||||||
JSContext* mThreadContext;
|
JSContext* mThreadContext;
|
||||||
// Deserialized object, or nullptr if object is in serialized form
|
// Deserialized object, or nullptr if object is in serialized form
|
||||||
JS::Heap<JSObject*> mJSObject;
|
PersistentObjectPtr mJSObject;
|
||||||
// Serialized object, or empty if object is in deserialized form
|
// Serialized object, or empty if object is in deserialized form
|
||||||
JSAutoStructuredCloneBuffer mBuffer;
|
JSAutoStructuredCloneBuffer mBuffer;
|
||||||
// Objects derived from mJSObject
|
// Objects derived from mJSObject
|
||||||
Vector<JS::Heap<JSObject*>, 4> mRootedObjects;
|
Vector<PersistentObjectPtr, 0> mRootedObjects;
|
||||||
|
|
||||||
// Create a new container containing the given deserialized object
|
// Create a new container containing the given deserialized object
|
||||||
NativeJSContainer(JSContext* cx, JS::HandleObject object)
|
NativeJSContainer(JSContext* cx, JS::HandleObject object)
|
||||||
: mThread(PR_GetCurrentThread())
|
: mThread(PR_GetCurrentThread())
|
||||||
, mThreadContext(cx)
|
, mThreadContext(cx)
|
||||||
, mJSObject(object)
|
, mJSObject(new PersistentObject(cx, object))
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -301,6 +305,7 @@ private:
|
|||||||
NativeJSContainer(JSContext* cx, JSAutoStructuredCloneBuffer&& buffer)
|
NativeJSContainer(JSContext* cx, JSAutoStructuredCloneBuffer&& buffer)
|
||||||
: mThread(PR_GetCurrentThread())
|
: mThread(PR_GetCurrentThread())
|
||||||
, mThreadContext(cx)
|
, mThreadContext(cx)
|
||||||
|
, mJSObject(nullptr)
|
||||||
, mBuffer(Forward<JSAutoStructuredCloneBuffer>(buffer))
|
, mBuffer(Forward<JSAutoStructuredCloneBuffer>(buffer))
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user