merge fx-team to mozilla-central a=merge
@ -5,7 +5,6 @@
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
"use strict";
|
||||
|
||||
const SOURCE_SYNTAX_HIGHLIGHT_MAX_FILE_SIZE = 1048576; // 1 MB in bytes
|
||||
const SOURCE_URL_DEFAULT_MAX_LENGTH = 64; // chars
|
||||
const STACK_FRAMES_SOURCE_URL_MAX_LENGTH = 15; // chars
|
||||
const STACK_FRAMES_SOURCE_URL_TRIM_SECTION = "center";
|
||||
@ -47,6 +46,13 @@ var constants = require('./content/constants');
|
||||
* Object defining the debugger view components.
|
||||
*/
|
||||
var DebuggerView = {
|
||||
|
||||
/**
|
||||
* This is attached so tests can change it without needing to load an
|
||||
* actual large file in automation
|
||||
*/
|
||||
LARGE_FILE_SIZE: 1048576, // 1 MB in bytes
|
||||
|
||||
/**
|
||||
* Initializes the debugger view.
|
||||
*
|
||||
@ -408,12 +414,6 @@ var DebuggerView = {
|
||||
* The source text content.
|
||||
*/
|
||||
_setEditorMode: function(aUrl, aContentType = "", aTextContent = "") {
|
||||
// Avoid setting the editor mode for very large files.
|
||||
// Is this still necessary? See bug 929225.
|
||||
if (aTextContent.length >= SOURCE_SYNTAX_HIGHLIGHT_MAX_FILE_SIZE) {
|
||||
return void this.editor.setMode(Editor.modes.text);
|
||||
}
|
||||
|
||||
// Use JS mode for files with .js and .jsm extensions.
|
||||
if (SourceUtils.isJavaScript(aUrl, aContentType)) {
|
||||
return void this.editor.setMode(Editor.modes.js);
|
||||
|
@ -446,6 +446,7 @@ skip-if = true # non-named eval sources turned off for now, bug 1124106
|
||||
skip-if = e10s && debug
|
||||
[browser_dbg_sources-labels.js]
|
||||
skip-if = e10s && debug
|
||||
[browser_dbg_sources-large.js]
|
||||
[browser_dbg_sources-sorting.js]
|
||||
skip-if = e10s && debug
|
||||
[browser_dbg_sources-bookmarklet.js]
|
||||
|
@ -0,0 +1,75 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
/**
|
||||
* Tests that large files are treated differently in the debugger:
|
||||
* 1) No parsing to determine current symbol is attempted when
|
||||
* starting a search
|
||||
*/
|
||||
|
||||
const TAB_URL = EXAMPLE_URL + "doc_function-search.html";
|
||||
|
||||
function test() {
|
||||
initDebugger(TAB_URL).then(([aTab, aDebuggee, aPanel]) => {
|
||||
const gTab = aTab;
|
||||
const gDebuggee = aDebuggee;
|
||||
const gPanel = aPanel;
|
||||
const gDebugger = gPanel.panelWin;
|
||||
|
||||
const gEditor = gDebugger.DebuggerView.editor;
|
||||
const gSources = gDebugger.DebuggerView.Sources;
|
||||
const Filtering = gDebugger.DebuggerView.Filtering;
|
||||
|
||||
// Setting max size so that code_function-search-01.js will be
|
||||
// considered a large file on first load
|
||||
gDebugger.DebuggerView.LARGE_FILE_SIZE = 1;
|
||||
|
||||
function testLargeFile() {
|
||||
ok(gEditor.getText().length > gDebugger.DebuggerView.LARGE_FILE_SIZE,
|
||||
"First source is considered a large file.");
|
||||
is(gEditor.getMode().name, "javascript",
|
||||
"Editor is syntax highlighting.");
|
||||
ok(gEditor.getText().includes("First source!"),
|
||||
"Editor text contents appears to be correct.");
|
||||
|
||||
// Press ctrl+f with the cursor in a token
|
||||
gEditor.focus();
|
||||
gEditor.setCursor({ line: 3, ch: 10});
|
||||
synthesizeKeyFromKeyTag(gDebugger.document.getElementById("tokenSearchKey"));
|
||||
is(Filtering._searchbox.value, "#",
|
||||
"Search box is NOT prefilled with current token");
|
||||
}
|
||||
|
||||
function testSmallFile() {
|
||||
ok(gEditor.getText().length < gDebugger.DebuggerView.LARGE_FILE_SIZE,
|
||||
"Second source is considered a small file.");
|
||||
is(gEditor.getMode().name, "javascript",
|
||||
"Editor is syntax highlighting.");
|
||||
ok(gEditor.getText().includes("First source!"),
|
||||
"Editor text contents appears to be correct.");
|
||||
|
||||
// Press ctrl+f with the cursor in a token
|
||||
gEditor.focus();
|
||||
gEditor.setCursor({ line: 3, ch: 10});
|
||||
synthesizeKeyFromKeyTag(gDebugger.document.getElementById("tokenSearchKey"));
|
||||
is(Filtering._searchbox.value, "#test",
|
||||
"Search box is prefilled with current token");
|
||||
}
|
||||
|
||||
Task.spawn(function*() {
|
||||
yield waitForSourceShown(gPanel, "-01.js");
|
||||
yield testLargeFile();
|
||||
|
||||
info("Making it appear as a small file and then reselecting 01.js");
|
||||
gDebugger.DebuggerView.LARGE_FILE_SIZE = 1000;
|
||||
gSources.selectedIndex = 1;
|
||||
yield waitForSourceShown(gPanel, "-02.js");
|
||||
gSources.selectedIndex = 0;
|
||||
yield waitForSourceShown(gPanel, "-01.js");
|
||||
|
||||
yield testSmallFile();
|
||||
|
||||
closeDebuggerAndFinish(gPanel);
|
||||
});
|
||||
});
|
||||
}
|
@ -443,9 +443,11 @@ FilterView.prototype = {
|
||||
this._searchbox.value = aOperator + this.DebuggerView.editor.getSelection();
|
||||
return;
|
||||
}
|
||||
if (SEARCH_AUTOFILL.indexOf(aOperator) != -1) {
|
||||
|
||||
let content = this.DebuggerView.editor.getText();
|
||||
if (content.length < this.DebuggerView.LARGE_FILE_SIZE &&
|
||||
SEARCH_AUTOFILL.indexOf(aOperator) != -1) {
|
||||
let cursor = this.DebuggerView.editor.getCursor();
|
||||
let content = this.DebuggerView.editor.getText();
|
||||
let location = this.DebuggerView.Sources.selectedItem.attachment.source.url;
|
||||
let source = this.Parser.get(content, location);
|
||||
let identifier = source.getIdentifierAt({ line: cursor.line+1, column: cursor.ch });
|
||||
|
@ -24,7 +24,7 @@
|
||||
|
||||
<!-- LOCALIZATION NOTE (netmonitorUI.toolbar.status2): This is the label displayed
|
||||
- in the network table toolbar, above the "status" column. -->
|
||||
<!ENTITY netmonitorUI.toolbar.status2 "✓">
|
||||
<!ENTITY netmonitorUI.toolbar.status3 "Status">
|
||||
|
||||
<!-- LOCALIZATION NOTE (netmonitorUI.toolbar.method): This is the label displayed
|
||||
- in the network table toolbar, above the "method" column. -->
|
||||
|
@ -39,8 +39,7 @@
|
||||
#details-pane-toggle,
|
||||
#details-pane[pane-collapsed],
|
||||
.requests-menu-waterfall,
|
||||
.requests-menu-footer-label,
|
||||
.requests-menu-status-code {
|
||||
.requests-menu-footer-label {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
@ -107,7 +107,7 @@
|
||||
<button id="requests-menu-status-button"
|
||||
class="requests-menu-header-button requests-menu-status"
|
||||
data-key="status"
|
||||
label="&netmonitorUI.toolbar.status2;"
|
||||
label="&netmonitorUI.toolbar.status3;"
|
||||
flex="1">
|
||||
</button>
|
||||
</hbox>
|
||||
|
@ -9,7 +9,7 @@ function test() {
|
||||
initNetMonitor(SIMPLE_URL).then(([aTab, aDebuggee, aMonitor]) => {
|
||||
info("Starting test... ");
|
||||
|
||||
let { document, L10N, NetMonitorView } = aMonitor.panelWin;
|
||||
let { document, L10N, NetMonitorView, NetMonitorController } = aMonitor.panelWin;
|
||||
let { RequestsMenu } = NetMonitorView;
|
||||
|
||||
// Disable transferred size column support for this test.
|
||||
@ -31,6 +31,11 @@ function test() {
|
||||
"No 2d context should be created when the frontend is opened.");
|
||||
|
||||
waitForNetworkEvents(aMonitor, 1).then(() => {
|
||||
// Make sure the DOMContentLoaded and load markers don't interfere with
|
||||
// this test by removing them and redrawing the waterfall (bug 1224088).
|
||||
NetMonitorController.NetworkEventsHandler.clearMarkers();
|
||||
RequestsMenu._flushWaterfallViews(true);
|
||||
|
||||
ok(!document.querySelector("#requests-menu-waterfall-label"),
|
||||
"The timeline label should be hidden after the first request.");
|
||||
ok(document.querySelectorAll(".requests-menu-timings-division").length >= 3,
|
||||
|
@ -235,7 +235,8 @@ CallView.prototype = Heritage.extend(AbstractTreeItem.prototype, {
|
||||
cell.className = "plain call-tree-cell";
|
||||
cell.setAttribute("type", type);
|
||||
cell.setAttribute("crop", "end");
|
||||
cell.setAttribute("value", value);
|
||||
// Add a tabulation to the cell text in case it's is selected and copied.
|
||||
cell.textContent = value + "\t";
|
||||
return cell;
|
||||
},
|
||||
|
||||
@ -261,7 +262,7 @@ CallView.prototype = Heritage.extend(AbstractTreeItem.prototype, {
|
||||
nameNode.className = "plain call-tree-name";
|
||||
nameNode.setAttribute("flex", "1");
|
||||
nameNode.setAttribute("crop", "end");
|
||||
nameNode.setAttribute("value", frameName);
|
||||
nameNode.textContent = frameName;
|
||||
cell.appendChild(nameNode);
|
||||
}
|
||||
|
||||
@ -276,6 +277,17 @@ CallView.prototype = Heritage.extend(AbstractTreeItem.prototype, {
|
||||
arrowNode.setAttribute("invisible", "");
|
||||
}
|
||||
|
||||
// Add a line break to the last description of the row in case it's selected
|
||||
// and copied.
|
||||
let lastDescription = cell.querySelector('description:last-of-type');
|
||||
lastDescription.textContent = lastDescription.textContent + "\n";
|
||||
|
||||
// Add spaces as frameLevel indicators in case the row is selected and
|
||||
// copied. These spaces won't be displayed in the cell content.
|
||||
let firstDescription = cell.querySelector('description:first-of-type');
|
||||
let levelIndicator = frameLevel > 0 ? " ".repeat(frameLevel) : "";
|
||||
firstDescription.textContent = levelIndicator + firstDescription.textContent;
|
||||
|
||||
return cell;
|
||||
},
|
||||
|
||||
@ -285,7 +297,7 @@ CallView.prototype = Heritage.extend(AbstractTreeItem.prototype, {
|
||||
urlNode.className = "plain call-tree-url";
|
||||
urlNode.setAttribute("flex", "1");
|
||||
urlNode.setAttribute("crop", "end");
|
||||
urlNode.setAttribute("value", frameInfo.fileName);
|
||||
urlNode.textContent = frameInfo.fileName;
|
||||
urlNode.setAttribute("tooltiptext", URL_LABEL_TOOLTIP + " → " + frameInfo.url);
|
||||
urlNode.addEventListener("mousedown", this._onUrlClick);
|
||||
cell.appendChild(urlNode);
|
||||
@ -294,21 +306,21 @@ CallView.prototype = Heritage.extend(AbstractTreeItem.prototype, {
|
||||
if (frameInfo.line) {
|
||||
let lineNode = doc.createElement("description");
|
||||
lineNode.className = "plain call-tree-line";
|
||||
lineNode.setAttribute("value", ":" + frameInfo.line);
|
||||
lineNode.textContent = ":" + frameInfo.line;
|
||||
cell.appendChild(lineNode);
|
||||
}
|
||||
|
||||
if (frameInfo.column) {
|
||||
let columnNode = doc.createElement("description");
|
||||
columnNode.className = "plain call-tree-column";
|
||||
columnNode.setAttribute("value", ":" + frameInfo.column);
|
||||
columnNode.textContent = ":" + frameInfo.column;
|
||||
cell.appendChild(columnNode);
|
||||
}
|
||||
|
||||
if (frameInfo.host) {
|
||||
let hostNode = doc.createElement("description");
|
||||
hostNode.className = "plain call-tree-host";
|
||||
hostNode.setAttribute("value", frameInfo.host);
|
||||
hostNode.textContent = frameInfo.host;
|
||||
cell.appendChild(hostNode);
|
||||
}
|
||||
|
||||
@ -320,7 +332,7 @@ CallView.prototype = Heritage.extend(AbstractTreeItem.prototype, {
|
||||
let categoryNode = doc.createElement("description");
|
||||
categoryNode.className = "plain call-tree-category";
|
||||
categoryNode.style.color = frameInfo.categoryData.color;
|
||||
categoryNode.setAttribute("value", frameInfo.categoryData.label);
|
||||
categoryNode.textContent = frameInfo.categoryData.label;
|
||||
cell.appendChild(categoryNode);
|
||||
}
|
||||
},
|
||||
|
@ -7,7 +7,7 @@
|
||||
*/
|
||||
function* spawnTest() {
|
||||
let { panel } = yield initPerformance(SIMPLE_URL);
|
||||
let { EVENTS, $, DetailsView, JsCallTreeView } = panel.panelWin;
|
||||
let { EVENTS, $, $$, DetailsView, JsCallTreeView } = panel.panelWin;
|
||||
|
||||
// Enable platform data to show the categories.
|
||||
Services.prefs.setBoolPref(PLATFORM_DATA_PREF, true);
|
||||
@ -22,17 +22,26 @@ function* spawnTest() {
|
||||
|
||||
is($(".call-tree-cells-container").hasAttribute("categories-hidden"), false,
|
||||
"The call tree cells container should show the categories now.");
|
||||
ok($(".call-tree-category[value=Gecko]"),
|
||||
"A category node with the label `Gecko` is displayed in the tree.");
|
||||
ok(geckoCategoryPresent($$),
|
||||
"A category node with the text `Gecko` is displayed in the tree.");
|
||||
|
||||
// Disable platform data to show the categories.
|
||||
Services.prefs.setBoolPref(PLATFORM_DATA_PREF, false);
|
||||
|
||||
is($(".call-tree-cells-container").getAttribute("categories-hidden"), "",
|
||||
"The call tree cells container should hide the categories now.");
|
||||
ok(!$(".call-tree-category[value=Gecko]"),
|
||||
"A category node with the label `Gecko` doesn't exist in the tree anymore.");
|
||||
ok(!geckoCategoryPresent($$),
|
||||
"A category node with the text `Gecko` doesn't exist in the tree anymore.");
|
||||
|
||||
yield teardown(panel);
|
||||
finish();
|
||||
}
|
||||
|
||||
function geckoCategoryPresent($$) {
|
||||
for (let elem of $$('.call-tree-category')) {
|
||||
if (elem.textContent.trim() == 'Gecko') {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
@ -31,27 +31,27 @@ function test() {
|
||||
|
||||
is(container.childNodes[0].childNodes[0].getAttribute("type"), "duration",
|
||||
"The root node in the tree has a duration cell.");
|
||||
is(container.childNodes[0].childNodes[0].getAttribute("value"), "20 ms",
|
||||
is(container.childNodes[0].childNodes[0].textContent.trim(), "20 ms",
|
||||
"The root node in the tree has the correct duration cell value.");
|
||||
|
||||
is(container.childNodes[0].childNodes[1].getAttribute("type"), "percentage",
|
||||
"The root node in the tree has a percentage cell.");
|
||||
is(container.childNodes[0].childNodes[1].getAttribute("value"), "100%",
|
||||
is(container.childNodes[0].childNodes[1].textContent.trim(), "100%",
|
||||
"The root node in the tree has the correct percentage cell value.");
|
||||
|
||||
is(container.childNodes[0].childNodes[2].getAttribute("type"), "self-duration",
|
||||
"The root node in the tree has a self-duration cell.");
|
||||
is(container.childNodes[0].childNodes[2].getAttribute("value"), "0 ms",
|
||||
is(container.childNodes[0].childNodes[2].textContent.trim(), "0 ms",
|
||||
"The root node in the tree has the correct self-duration cell value.");
|
||||
|
||||
is(container.childNodes[0].childNodes[3].getAttribute("type"), "self-percentage",
|
||||
"The root node in the tree has a self-percentage cell.");
|
||||
is(container.childNodes[0].childNodes[3].getAttribute("value"), "0%",
|
||||
is(container.childNodes[0].childNodes[3].textContent.trim(), "0%",
|
||||
"The root node in the tree has the correct self-percentage cell value.");
|
||||
|
||||
is(container.childNodes[0].childNodes[4].getAttribute("type"), "samples",
|
||||
"The root node in the tree has an samples cell.");
|
||||
is(container.childNodes[0].childNodes[4].getAttribute("value"), "0",
|
||||
is(container.childNodes[0].childNodes[4].textContent.trim(), "0",
|
||||
"The root node in the tree has the correct samples cell value.");
|
||||
|
||||
is(container.childNodes[0].childNodes[5].getAttribute("type"), "function",
|
||||
|
@ -33,13 +33,13 @@ function test() {
|
||||
is(container.childNodes[0].className, "call-tree-item",
|
||||
"The root node in the tree has the correct class name.");
|
||||
|
||||
is($$dur(0).getAttribute("value"), "20 ms",
|
||||
is($$dur(0).textContent.trim(), "20 ms",
|
||||
"The root's duration cell displays the correct value.");
|
||||
is($$perc(0).getAttribute("value"), "100%",
|
||||
is($$perc(0).textContent.trim(), "100%",
|
||||
"The root's percentage cell displays the correct value.");
|
||||
is($$sampl(0).getAttribute("value"), "0",
|
||||
is($$sampl(0).textContent.trim(), "0",
|
||||
"The root's samples cell displays the correct value.");
|
||||
is($$fun(".call-tree-name")[0].getAttribute("value"), "(root)",
|
||||
is($$fun(".call-tree-name")[0].textContent.trim(), "(root)",
|
||||
"The root's function cell displays the correct name.");
|
||||
is($$fun(".call-tree-url")[0], null,
|
||||
"The root's function cell displays no url.");
|
||||
@ -59,23 +59,23 @@ function test() {
|
||||
is(container.childNodes[1].className, "call-tree-item",
|
||||
"The .A node in the tree has the correct class name.");
|
||||
|
||||
is($$dur(1).getAttribute("value"), "20 ms",
|
||||
is($$dur(1).textContent.trim(), "20 ms",
|
||||
"The .A node's duration cell displays the correct value.");
|
||||
is($$perc(1).getAttribute("value"), "100%",
|
||||
is($$perc(1).textContent.trim(), "100%",
|
||||
"The .A node's percentage cell displays the correct value.");
|
||||
is($$sampl(1).getAttribute("value"), "0",
|
||||
is($$sampl(1).textContent.trim(), "0",
|
||||
"The .A node's samples cell displays the correct value.");
|
||||
is($fun(".call-tree-name", $$(".call-tree-item")[1]).getAttribute("value"), "A",
|
||||
is($fun(".call-tree-name", $$(".call-tree-item")[1]).textContent.trim(), "A",
|
||||
"The .A node's function cell displays the correct name.");
|
||||
is($fun(".call-tree-url", $$(".call-tree-item")[1]).getAttribute("value"), "baz",
|
||||
is($fun(".call-tree-url", $$(".call-tree-item")[1]).textContent.trim(), "baz",
|
||||
"The .A node's function cell displays the correct url.");
|
||||
ok($fun(".call-tree-url", $$(".call-tree-item")[1]).getAttribute("tooltiptext").includes("http://foo/bar/baz"),
|
||||
"The .A node's function cell displays the correct url tooltiptext.");
|
||||
is($fun(".call-tree-line", $$(".call-tree-item")[1]).getAttribute("value"), ":12",
|
||||
is($fun(".call-tree-line", $$(".call-tree-item")[1]).textContent.trim(), ":12",
|
||||
"The .A node's function cell displays the correct line.");
|
||||
is($fun(".call-tree-host", $$(".call-tree-item")[1]).getAttribute("value"), "foo",
|
||||
is($fun(".call-tree-host", $$(".call-tree-item")[1]).textContent.trim(), "foo",
|
||||
"The .A node's function cell displays the correct host.");
|
||||
is($fun(".call-tree-category", $$(".call-tree-item")[1]).getAttribute("value"), "Gecko",
|
||||
is($fun(".call-tree-category", $$(".call-tree-item")[1]).textContent.trim(), "Gecko",
|
||||
"The .A node's function cell displays the correct category.");
|
||||
|
||||
let A = treeRoot.getChild();
|
||||
@ -88,42 +88,42 @@ function test() {
|
||||
is(container.childNodes[3].className, "call-tree-item",
|
||||
"The .E node in the tree has the correct class name.");
|
||||
|
||||
is($$dur(2).getAttribute("value"), "15 ms",
|
||||
is($$dur(2).textContent.trim(), "15 ms",
|
||||
"The .A.B node's duration cell displays the correct value.");
|
||||
is($$perc(2).getAttribute("value"), "75%",
|
||||
is($$perc(2).textContent.trim(), "75%",
|
||||
"The .A.B node's percentage cell displays the correct value.");
|
||||
is($$sampl(2).getAttribute("value"), "0",
|
||||
is($$sampl(2).textContent.trim(), "0",
|
||||
"The .A.B node's samples cell displays the correct value.");
|
||||
is($fun(".call-tree-name", $$(".call-tree-item")[2]).getAttribute("value"), "B",
|
||||
is($fun(".call-tree-name", $$(".call-tree-item")[2]).textContent.trim(), "B",
|
||||
"The .A.B node's function cell displays the correct name.");
|
||||
is($fun(".call-tree-url", $$(".call-tree-item")[2]).getAttribute("value"), "baz",
|
||||
is($fun(".call-tree-url", $$(".call-tree-item")[2]).textContent.trim(), "baz",
|
||||
"The .A.B node's function cell displays the correct url.");
|
||||
ok($fun(".call-tree-url", $$(".call-tree-item")[2]).getAttribute("tooltiptext").includes("http://foo/bar/baz"),
|
||||
"The .A.B node's function cell displays the correct url tooltiptext.");
|
||||
is($fun(".call-tree-line", $$(".call-tree-item")[2]).getAttribute("value"), ":34",
|
||||
is($fun(".call-tree-line", $$(".call-tree-item")[2]).textContent.trim(), ":34",
|
||||
"The .A.B node's function cell displays the correct line.");
|
||||
is($fun(".call-tree-host", $$(".call-tree-item")[2]).getAttribute("value"), "foo",
|
||||
is($fun(".call-tree-host", $$(".call-tree-item")[2]).textContent.trim(), "foo",
|
||||
"The .A.B node's function cell displays the correct host.");
|
||||
is($fun(".call-tree-category", $$(".call-tree-item")[2]).getAttribute("value"), "Styles",
|
||||
is($fun(".call-tree-category", $$(".call-tree-item")[2]).textContent.trim(), "Styles",
|
||||
"The .A.B node's function cell displays the correct category.");
|
||||
|
||||
is($$dur(3).getAttribute("value"), "5 ms",
|
||||
is($$dur(3).textContent.trim(), "5 ms",
|
||||
"The .A.E node's duration cell displays the correct value.");
|
||||
is($$perc(3).getAttribute("value"), "25%",
|
||||
is($$perc(3).textContent.trim(), "25%",
|
||||
"The .A.E node's percentage cell displays the correct value.");
|
||||
is($$sampl(3).getAttribute("value"), "0",
|
||||
is($$sampl(3).textContent.trim(), "0",
|
||||
"The .A.E node's samples cell displays the correct value.");
|
||||
is($fun(".call-tree-name", $$(".call-tree-item")[3]).getAttribute("value"), "E",
|
||||
is($fun(".call-tree-name", $$(".call-tree-item")[3]).textContent.trim(), "E",
|
||||
"The .A.E node's function cell displays the correct name.");
|
||||
is($fun(".call-tree-url", $$(".call-tree-item")[3]).getAttribute("value"), "baz",
|
||||
is($fun(".call-tree-url", $$(".call-tree-item")[3]).textContent.trim(), "baz",
|
||||
"The .A.E node's function cell displays the correct url.");
|
||||
ok($fun(".call-tree-url", $$(".call-tree-item")[3]).getAttribute("tooltiptext").includes("http://foo/bar/baz"),
|
||||
"The .A.E node's function cell displays the correct url tooltiptext.");
|
||||
is($fun(".call-tree-line", $$(".call-tree-item")[3]).getAttribute("value"), ":90",
|
||||
is($fun(".call-tree-line", $$(".call-tree-item")[3]).textContent.trim(), ":90",
|
||||
"The .A.E node's function cell displays the correct line.");
|
||||
is($fun(".call-tree-host", $$(".call-tree-item")[3]).getAttribute("value"), "foo",
|
||||
is($fun(".call-tree-host", $$(".call-tree-item")[3]).textContent.trim(), "foo",
|
||||
"The .A.E node's function cell displays the correct host.");
|
||||
is($fun(".call-tree-category", $$(".call-tree-item")[3]).getAttribute("value"), "GC",
|
||||
is($fun(".call-tree-category", $$(".call-tree-item")[3]).textContent.trim(), "GC",
|
||||
"The .A.E node's function cell displays the correct category.");
|
||||
|
||||
finish();
|
||||
|
@ -42,34 +42,34 @@ function test() {
|
||||
is($$fun(6).style.MozMarginStart, "48px",
|
||||
"The .A.E.F node's function cell has the correct indentation.");
|
||||
|
||||
is($$name(0).getAttribute("value"), "(root)",
|
||||
is($$name(0).textContent.trim(), "(root)",
|
||||
"The root node's function cell displays the correct name.");
|
||||
is($$name(1).getAttribute("value"), "A",
|
||||
is($$name(1).textContent.trim(), "A",
|
||||
"The .A node's function cell displays the correct name.");
|
||||
is($$name(2).getAttribute("value"), "B",
|
||||
is($$name(2).textContent.trim(), "B",
|
||||
"The .A.B node's function cell displays the correct name.");
|
||||
is($$name(3).getAttribute("value"), "D",
|
||||
is($$name(3).textContent.trim(), "D",
|
||||
"The .A.B.D node's function cell displays the correct name.");
|
||||
is($$name(4).getAttribute("value"), "C",
|
||||
is($$name(4).textContent.trim(), "C",
|
||||
"The .A.B.C node's function cell displays the correct name.");
|
||||
is($$name(5).getAttribute("value"), "E",
|
||||
is($$name(5).textContent.trim(), "E",
|
||||
"The .A.E node's function cell displays the correct name.");
|
||||
is($$name(6).getAttribute("value"), "F",
|
||||
is($$name(6).textContent.trim(), "F",
|
||||
"The .A.E.F node's function cell displays the correct name.");
|
||||
|
||||
is($$duration(0).getAttribute("value"), "20 ms",
|
||||
is($$duration(0).textContent.trim(), "20 ms",
|
||||
"The root node's function cell displays the correct duration.");
|
||||
is($$duration(1).getAttribute("value"), "20 ms",
|
||||
is($$duration(1).textContent.trim(), "20 ms",
|
||||
"The .A node's function cell displays the correct duration.");
|
||||
is($$duration(2).getAttribute("value"), "15 ms",
|
||||
is($$duration(2).textContent.trim(), "15 ms",
|
||||
"The .A.B node's function cell displays the correct duration.");
|
||||
is($$duration(3).getAttribute("value"), "10 ms",
|
||||
is($$duration(3).textContent.trim(), "10 ms",
|
||||
"The .A.B.D node's function cell displays the correct duration.");
|
||||
is($$duration(4).getAttribute("value"), "5 ms",
|
||||
is($$duration(4).textContent.trim(), "5 ms",
|
||||
"The .A.B.C node's function cell displays the correct duration.");
|
||||
is($$duration(5).getAttribute("value"), "5 ms",
|
||||
is($$duration(5).textContent.trim(), "5 ms",
|
||||
"The .A.E node's function cell displays the correct duration.");
|
||||
is($$duration(6).getAttribute("value"), "5 ms",
|
||||
is($$duration(6).textContent.trim(), "5 ms",
|
||||
"The .A.E.F node's function cell displays the correct duration.");
|
||||
|
||||
finish();
|
||||
@ -108,4 +108,3 @@ var gThread = synthesizeProfileForTest([{
|
||||
{ category: 256, location: "F (http://foo/bar/baz:99)" }
|
||||
]
|
||||
}]);
|
||||
|
||||
|
@ -43,21 +43,21 @@ function test() {
|
||||
"Generalized JS node has correct category");
|
||||
is(JS.target.getAttribute("tooltiptext"), "JIT",
|
||||
"Generalized JS node has correct category");
|
||||
is(JS.target.querySelector(".call-tree-name").getAttribute("value"), "JIT",
|
||||
is(JS.target.querySelector(".call-tree-name").textContent.trim(), "JIT",
|
||||
"Generalized JS node has correct display value as just the category name.");
|
||||
|
||||
is(JS2.target.getAttribute("category"), "js",
|
||||
"Generalized second JS node has correct category");
|
||||
is(JS2.target.getAttribute("tooltiptext"), "JIT",
|
||||
"Generalized second JS node has correct category");
|
||||
is(JS2.target.querySelector(".call-tree-name").getAttribute("value"), "JIT",
|
||||
is(JS2.target.querySelector(".call-tree-name").textContent.trim(), "JIT",
|
||||
"Generalized second JS node has correct display value as just the category name.");
|
||||
|
||||
is(GC.target.getAttribute("category"), "gc",
|
||||
"Generalized GC node has correct category");
|
||||
is(GC.target.getAttribute("tooltiptext"), "GC",
|
||||
"Generalized GC node has correct category");
|
||||
is(GC.target.querySelector(".call-tree-name").getAttribute("value"), "GC",
|
||||
is(GC.target.querySelector(".call-tree-name").textContent.trim(), "GC",
|
||||
"Generalized GC node has correct display value as just the category name.");
|
||||
|
||||
finish();
|
||||
|
@ -63,9 +63,9 @@ function test() {
|
||||
let [total, self, name] = def;
|
||||
name = name.trim();
|
||||
|
||||
is($$name(i).getAttribute("value"), name, `${name} has correct name.`);
|
||||
is($$percentage(i).getAttribute("value"), `${total}%`, `${name} has correct total percent.`);
|
||||
is($$selfpercentage(i).getAttribute("value"), `${self}%`, `${name} has correct self percent.`);
|
||||
is($$name(i).textContent.trim(), name, `${name} has correct name.`);
|
||||
is($$percentage(i).textContent.trim(), `${total}%`, `${name} has correct total percent.`);
|
||||
is($$selfpercentage(i).textContent.trim(), `${self}%`, `${name} has correct self percent.`);
|
||||
});
|
||||
|
||||
finish();
|
||||
|
@ -31,7 +31,7 @@ function* spawnTest() {
|
||||
let rows = $$("#js-calltree-view .call-tree-item");
|
||||
is(rows.length, 4, "4 call tree rows exist");
|
||||
for (let row of rows) {
|
||||
let name = $(".call-tree-name", row).value;
|
||||
let name = $(".call-tree-name", row).textContent.trim();
|
||||
switch (name) {
|
||||
case "A":
|
||||
ok($(".opt-icon", row), "found an opt icon on a leaf node with opt data");
|
||||
|
@ -522,7 +522,6 @@ AbstractTreeItem.prototype = {
|
||||
* Handler for the "click" event on the element displaying this tree item.
|
||||
*/
|
||||
_onClick: function(e) {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
this.focus();
|
||||
},
|
||||
|
@ -116,11 +116,7 @@
|
||||
|
||||
/* Network requests table: specific column dimensions */
|
||||
|
||||
.requests-menu-status {
|
||||
max-width: 4em;
|
||||
width: 4vw;
|
||||
}
|
||||
|
||||
.requests-menu-status,
|
||||
.requests-menu-method-box,
|
||||
.requests-menu-method {
|
||||
max-width: 6em;
|
||||
@ -183,10 +179,6 @@
|
||||
width: 8vw;
|
||||
}
|
||||
|
||||
.requests-menu-transferred {
|
||||
width: 8vw;
|
||||
}
|
||||
|
||||
/* Network requests table: status codes */
|
||||
|
||||
.requests-menu-status-code {
|
||||
@ -795,11 +787,12 @@
|
||||
}
|
||||
|
||||
.requests-menu-status {
|
||||
width: 4vw;
|
||||
max-width: none;
|
||||
width: 12vw;
|
||||
}
|
||||
|
||||
#requests-menu-status-button {
|
||||
min-width: 26px;
|
||||
.requests-menu-status-code {
|
||||
width: auto;
|
||||
}
|
||||
|
||||
.requests-menu-method,
|
||||
@ -809,20 +802,20 @@
|
||||
}
|
||||
|
||||
.requests-menu-icon-and-file {
|
||||
width: 30vw;
|
||||
width: 22vw;
|
||||
}
|
||||
|
||||
.requests-menu-security-and-domain {
|
||||
width: 28vw;
|
||||
width: 18vw;
|
||||
}
|
||||
|
||||
.requests-menu-type,
|
||||
.requests-menu-transferred {
|
||||
width: 12vw;
|
||||
.requests-menu-type {
|
||||
width: 10vw;
|
||||
}
|
||||
|
||||
.requests-menu-transferred,
|
||||
.requests-menu-size {
|
||||
width: 16vw;
|
||||
width: 12vw;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -269,6 +269,16 @@
|
||||
background-color: var(--theme-tab-toolbar-background);
|
||||
}
|
||||
|
||||
.call-tree-item .call-tree-cell,
|
||||
.call-tree-item .call-tree-cell[type=function] description {
|
||||
-moz-user-select: text;
|
||||
}
|
||||
|
||||
.call-tree-item .call-tree-cell::-moz-selection,
|
||||
.call-tree-item .call-tree-cell[type=function] description::-moz-selection {
|
||||
background-color: var(--theme-highlight-orange);
|
||||
}
|
||||
|
||||
.call-tree-item:last-child {
|
||||
border-bottom: 1px solid var(--cell-border-color);
|
||||
}
|
||||
|
@ -28,6 +28,7 @@
|
||||
#include "mozilla/StartupTimeline.h"
|
||||
#include "mozilla/Telemetry.h"
|
||||
#include "mozilla/unused.h"
|
||||
#include "Navigator.h"
|
||||
#include "URIUtils.h"
|
||||
|
||||
#include "nsIContent.h"
|
||||
@ -3128,6 +3129,38 @@ nsDocShell::NameEquals(const char16_t* aName, bool* aResult)
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDocShell::GetCustomUserAgent(nsAString& aCustomUserAgent)
|
||||
{
|
||||
aCustomUserAgent = mCustomUserAgent;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDocShell::SetCustomUserAgent(const nsAString& aCustomUserAgent)
|
||||
{
|
||||
mCustomUserAgent = aCustomUserAgent;
|
||||
RefPtr<nsGlobalWindow> win = mScriptGlobal ?
|
||||
mScriptGlobal->GetCurrentInnerWindowInternal() : nullptr;
|
||||
if (win) {
|
||||
ErrorResult ignored;
|
||||
Navigator* navigator = win->GetNavigator(ignored);
|
||||
ignored.SuppressException();
|
||||
if (navigator) {
|
||||
navigator->ClearUserAgentCache();
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t childCount = mChildList.Length();
|
||||
for (uint32_t i = 0; i < childCount; ++i) {
|
||||
nsCOMPtr<nsIDocShell> childShell = do_QueryInterface(ChildAt(i));
|
||||
if (childShell) {
|
||||
childShell->SetCustomUserAgent(aCustomUserAgent);
|
||||
}
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/* virtual */ int32_t
|
||||
nsDocShell::ItemType()
|
||||
{
|
||||
@ -3255,6 +3288,7 @@ nsDocShell::SetDocLoaderParent(nsDocLoader* aParent)
|
||||
// If parent is another docshell, we inherit all their flags for
|
||||
// allowing plugins, scripting etc.
|
||||
bool value;
|
||||
nsString customUserAgent;
|
||||
nsCOMPtr<nsIDocShell> parentAsDocShell(do_QueryInterface(parent));
|
||||
if (parentAsDocShell) {
|
||||
if (mAllowPlugins && NS_SUCCEEDED(parentAsDocShell->GetAllowPlugins(&value))) {
|
||||
@ -3284,6 +3318,10 @@ nsDocShell::SetDocLoaderParent(nsDocLoader* aParent)
|
||||
if (parentAsDocShell->GetIsPrerendered()) {
|
||||
SetIsPrerendered(true);
|
||||
}
|
||||
if (NS_SUCCEEDED(parentAsDocShell->GetCustomUserAgent(customUserAgent)) &&
|
||||
!customUserAgent.IsEmpty()) {
|
||||
SetCustomUserAgent(customUserAgent);
|
||||
}
|
||||
if (NS_FAILED(parentAsDocShell->GetAllowDNSPrefetch(&value))) {
|
||||
value = false;
|
||||
}
|
||||
|
@ -793,6 +793,7 @@ protected:
|
||||
nsIntRect mBounds;
|
||||
nsString mName;
|
||||
nsString mTitle;
|
||||
nsString mCustomUserAgent;
|
||||
|
||||
/**
|
||||
* Content-Type Hint of the most-recently initiated load. Used for
|
||||
|
@ -43,7 +43,7 @@ interface nsITabParent;
|
||||
|
||||
typedef unsigned long nsLoadFlags;
|
||||
|
||||
[scriptable, builtinclass, uuid(63adb599-6dc9-4746-972e-c22e9018020b)]
|
||||
[scriptable, builtinclass, uuid(bc3524bd-023c-4fc8-ace1-472bc999fb12)]
|
||||
interface nsIDocShell : nsIDocShellTreeItem
|
||||
{
|
||||
/**
|
||||
@ -237,6 +237,11 @@ interface nsIDocShell : nsIDocShellTreeItem
|
||||
*/
|
||||
attribute nsIDOMEventTarget chromeEventHandler;
|
||||
|
||||
/**
|
||||
* This allows chrome to set a custom User agent on a specific docshell
|
||||
*/
|
||||
attribute DOMString customUserAgent;
|
||||
|
||||
/**
|
||||
* Whether to allow plugin execution
|
||||
*/
|
||||
@ -250,7 +255,7 @@ interface nsIDocShell : nsIDocShellTreeItem
|
||||
/**
|
||||
* Attribute stating if refresh based redirects can be allowed
|
||||
*/
|
||||
attribute boolean allowMetaRedirects;
|
||||
attribute boolean allowMetaRedirects;
|
||||
|
||||
/**
|
||||
* Attribute stating if it should allow subframes (framesets/iframes) or not
|
||||
|
@ -84,6 +84,7 @@ skip-if = e10s # Bug 1220927 - Test tries to do addSHistoryListener on content.
|
||||
[browser_multiple_pushState.js]
|
||||
[browser_onbeforeunload_navigation.js]
|
||||
[browser_search_notification.js]
|
||||
[browser_ua_emulation.js]
|
||||
[browser_timelineMarkers-01.js]
|
||||
[browser_timelineMarkers-02.js]
|
||||
[browser_timelineMarkers-03.js]
|
||||
|
52
docshell/test/browser/browser_ua_emulation.js
Normal file
@ -0,0 +1,52 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
"use strict";
|
||||
|
||||
// Test that the docShell UA emulation works
|
||||
add_task(function*() {
|
||||
yield openUrl("data:text/html;charset=utf-8,<iframe id='test-iframe'></iframe>");
|
||||
|
||||
let docshell = content.QueryInterface(Ci.nsIInterfaceRequestor)
|
||||
.getInterface(Ci.nsIWebNavigation)
|
||||
.QueryInterface(Ci.nsIDocShell);
|
||||
is(docshell.customUserAgent, "", "There should initially be no customUserAgent");
|
||||
|
||||
docshell.customUserAgent = "foo";
|
||||
is(content.navigator.userAgent, "foo", "The user agent should be changed to foo");
|
||||
|
||||
let frameWin = content.document.querySelector("#test-iframe").contentWindow;
|
||||
is(frameWin.navigator.userAgent, "foo", "The UA should be passed on to frames.");
|
||||
|
||||
let newFrame = content.document.createElement("iframe");
|
||||
content.document.body.appendChild(newFrame);
|
||||
|
||||
let newFrameWin = newFrame.contentWindow;
|
||||
is(newFrameWin.navigator.userAgent, "foo", "Newly created frames should use the new UA");
|
||||
|
||||
newFrameWin.location.reload();
|
||||
yield waitForEvent(newFrameWin, "load");
|
||||
|
||||
is(newFrameWin.navigator.userAgent, "foo", "New UA should persist across reloads");
|
||||
gBrowser.removeCurrentTab();
|
||||
});
|
||||
|
||||
function waitForEvent(target, event) {
|
||||
return new Promise(function(resolve) {
|
||||
target.addEventListener(event, resolve);
|
||||
});
|
||||
}
|
||||
|
||||
function openUrl(url) {
|
||||
return new Promise(function(resolve, reject) {
|
||||
window.focus();
|
||||
|
||||
let tab = window.gBrowser.selectedTab = window.gBrowser.addTab(url);
|
||||
let linkedBrowser = tab.linkedBrowser;
|
||||
|
||||
linkedBrowser.addEventListener("load", function onload() {
|
||||
linkedBrowser.removeEventListener("load", onload, true);
|
||||
resolve(tab);
|
||||
}, true);
|
||||
});
|
||||
}
|
@ -372,11 +372,22 @@ Navigator::GetUserAgent(nsAString& aUserAgent)
|
||||
nsCOMPtr<nsIURI> codebaseURI;
|
||||
nsCOMPtr<nsPIDOMWindow> window;
|
||||
|
||||
if (mWindow && mWindow->GetDocShell()) {
|
||||
if (mWindow) {
|
||||
window = mWindow;
|
||||
nsIDocument* doc = mWindow->GetExtantDoc();
|
||||
if (doc) {
|
||||
doc->NodePrincipal()->GetURI(getter_AddRefs(codebaseURI));
|
||||
nsIDocShell* docshell = window->GetDocShell();
|
||||
nsString customUserAgent;
|
||||
if (docshell) {
|
||||
docshell->GetCustomUserAgent(customUserAgent);
|
||||
|
||||
if (!customUserAgent.IsEmpty()) {
|
||||
aUserAgent = customUserAgent;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsIDocument* doc = mWindow->GetExtantDoc();
|
||||
if (doc) {
|
||||
doc->NodePrincipal()->GetURI(getter_AddRefs(codebaseURI));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -2741,6 +2752,12 @@ Navigator::AppName(nsAString& aAppName, bool aUsePrefOverriddenValue)
|
||||
aAppName.AssignLiteral("Netscape");
|
||||
}
|
||||
|
||||
void
|
||||
Navigator::ClearUserAgentCache()
|
||||
{
|
||||
NavigatorBinding::ClearCachedUserAgentValue(this);
|
||||
}
|
||||
|
||||
nsresult
|
||||
Navigator::GetUserAgent(nsPIDOMWindow* aWindow, nsIURI* aURI,
|
||||
bool aIsCallerChrome,
|
||||
|
@ -182,6 +182,10 @@ public:
|
||||
bool aIsCallerChrome,
|
||||
nsAString& aUserAgent);
|
||||
|
||||
// Clears the user agent cache by calling:
|
||||
// NavigatorBinding::ClearCachedUserAgentValue(this);
|
||||
void ClearUserAgentCache();
|
||||
|
||||
already_AddRefed<Promise> GetDataStores(const nsAString& aName,
|
||||
const nsAString& aOwner,
|
||||
ErrorResult& aRv);
|
||||
|
@ -41,7 +41,7 @@ interface NavigatorID {
|
||||
readonly attribute DOMString appVersion;
|
||||
[Constant, Cached]
|
||||
readonly attribute DOMString platform;
|
||||
[Constant, Cached, Throws=Workers]
|
||||
[Pure, Cached, Throws=Workers]
|
||||
readonly attribute DOMString userAgent;
|
||||
[Constant, Cached]
|
||||
readonly attribute DOMString product; // constant "Gecko"
|
||||
|
@ -3031,7 +3031,6 @@ public class BrowserApp extends GeckoApp
|
||||
bookmark.setVisible(!inGuestMode);
|
||||
bookmark.setCheckable(true);
|
||||
bookmark.setChecked(tab.isBookmark());
|
||||
bookmark.setIcon(resolveBookmarkIconID(tab.isBookmark()));
|
||||
bookmark.setTitle(resolveBookmarkTitleID(tab.isBookmark()));
|
||||
|
||||
reader.setEnabled(isAboutReader || !AboutPages.isAboutPage(tab.getURL()));
|
||||
@ -3039,9 +3038,14 @@ public class BrowserApp extends GeckoApp
|
||||
reader.setCheckable(true);
|
||||
final boolean isPageInReadingList = tab.isInReadingList();
|
||||
reader.setChecked(isPageInReadingList);
|
||||
reader.setIcon(resolveReadingListIconID(isPageInReadingList));
|
||||
reader.setTitle(resolveReadingListTitleID(isPageInReadingList));
|
||||
|
||||
if (Versions.feature11Plus) {
|
||||
// We don't use icons on GB builds so not resolving icons might conserve resources.
|
||||
bookmark.setIcon(resolveBookmarkIconID(tab.isBookmark()));
|
||||
reader.setIcon(resolveReadingListIconID(isPageInReadingList));
|
||||
}
|
||||
|
||||
back.setEnabled(tab.canDoBack());
|
||||
forward.setEnabled(tab.canDoForward());
|
||||
desktopMode.setChecked(tab.getDesktopMode());
|
||||
@ -3233,13 +3237,19 @@ public class BrowserApp extends GeckoApp
|
||||
if (item.isChecked()) {
|
||||
Telemetry.sendUIEvent(TelemetryContract.Event.UNSAVE, TelemetryContract.Method.MENU, "bookmark");
|
||||
tab.removeBookmark();
|
||||
item.setIcon(resolveBookmarkIconID(false));
|
||||
item.setTitle(resolveBookmarkTitleID(false));
|
||||
if (Versions.feature11Plus) {
|
||||
// We don't use icons on GB builds so not resolving icons might conserve resources.
|
||||
item.setIcon(resolveBookmarkIconID(false));
|
||||
}
|
||||
} else {
|
||||
Telemetry.sendUIEvent(TelemetryContract.Event.SAVE, TelemetryContract.Method.MENU, "bookmark");
|
||||
tab.addBookmark();
|
||||
item.setIcon(resolveBookmarkIconID(true));
|
||||
item.setTitle(resolveBookmarkTitleID(true));
|
||||
if (Versions.feature11Plus) {
|
||||
// We don't use icons on GB builds so not resolving icons might conserve resources.
|
||||
item.setIcon(resolveBookmarkIconID(true));
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
@ -3251,13 +3261,19 @@ public class BrowserApp extends GeckoApp
|
||||
if (item.isChecked()) {
|
||||
Telemetry.sendUIEvent(TelemetryContract.Event.UNSAVE, TelemetryContract.Method.MENU, "reading_list");
|
||||
tab.removeFromReadingList();
|
||||
item.setIcon(resolveReadingListIconID(false));
|
||||
item.setTitle(resolveReadingListTitleID(false));
|
||||
if (Versions.feature11Plus) {
|
||||
// We don't use icons on GB builds so not resolving icons might conserve resources.
|
||||
item.setIcon(resolveReadingListIconID(false));
|
||||
}
|
||||
} else {
|
||||
Telemetry.sendUIEvent(TelemetryContract.Event.SAVE, TelemetryContract.Method.MENU, "reading_list");
|
||||
tab.addToReadingList();
|
||||
item.setIcon(resolveReadingListIconID(true));
|
||||
item.setTitle(resolveReadingListTitleID(true));
|
||||
if (Versions.feature11Plus) {
|
||||
// We don't use icons on GB builds so not resolving icons might conserve resources.
|
||||
item.setIcon(resolveReadingListIconID(true));
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
|
@ -349,11 +349,7 @@ public abstract class GeckoApp
|
||||
|
||||
@Override
|
||||
public MenuInflater getMenuInflater() {
|
||||
if (Versions.feature11Plus) {
|
||||
return new GeckoMenuInflater(this);
|
||||
} else {
|
||||
return super.getMenuInflater();
|
||||
}
|
||||
return new GeckoMenuInflater(this);
|
||||
}
|
||||
|
||||
public MenuPanel getMenuPanel() {
|
||||
@ -404,7 +400,7 @@ public abstract class GeckoApp
|
||||
|
||||
@Override
|
||||
public View onCreatePanelView(int featureId) {
|
||||
if (Versions.feature11Plus && featureId == Window.FEATURE_OPTIONS_PANEL) {
|
||||
if (featureId == Window.FEATURE_OPTIONS_PANEL) {
|
||||
if (mMenuPanel == null) {
|
||||
mMenuPanel = new MenuPanel(this, null);
|
||||
} else {
|
||||
@ -420,7 +416,7 @@ public abstract class GeckoApp
|
||||
|
||||
@Override
|
||||
public boolean onCreatePanelMenu(int featureId, Menu menu) {
|
||||
if (Versions.feature11Plus && featureId == Window.FEATURE_OPTIONS_PANEL) {
|
||||
if (featureId == Window.FEATURE_OPTIONS_PANEL) {
|
||||
if (mMenuPanel == null) {
|
||||
mMenuPanel = (MenuPanel) onCreatePanelView(featureId);
|
||||
}
|
||||
@ -439,7 +435,7 @@ public abstract class GeckoApp
|
||||
|
||||
@Override
|
||||
public boolean onPreparePanel(int featureId, View view, Menu menu) {
|
||||
if (Versions.feature11Plus && featureId == Window.FEATURE_OPTIONS_PANEL) {
|
||||
if (featureId == Window.FEATURE_OPTIONS_PANEL) {
|
||||
return onPrepareOptionsMenu(menu);
|
||||
}
|
||||
|
||||
@ -453,7 +449,7 @@ public abstract class GeckoApp
|
||||
GeckoAppShell.sendEventToGecko(GeckoEvent.createBroadcastEvent("FullScreen:Exit", null));
|
||||
}
|
||||
|
||||
if (Versions.feature11Plus && featureId == Window.FEATURE_OPTIONS_PANEL) {
|
||||
if (featureId == Window.FEATURE_OPTIONS_PANEL) {
|
||||
if (mMenu == null) {
|
||||
// getMenuPanel() will force the creation of the menu as well
|
||||
MenuPanel panel = getMenuPanel();
|
||||
@ -518,10 +514,8 @@ public abstract class GeckoApp
|
||||
|
||||
@Override
|
||||
public void onOptionsMenuClosed(Menu menu) {
|
||||
if (Versions.feature11Plus) {
|
||||
mMenuPanel.removeAllViews();
|
||||
mMenuPanel.addView((GeckoMenu) mMenu);
|
||||
}
|
||||
mMenuPanel.removeAllViews();
|
||||
mMenuPanel.addView((GeckoMenu) mMenu);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -2161,6 +2155,7 @@ public abstract class GeckoApp
|
||||
"PrivateBrowsing:Data",
|
||||
"Session:StatePurged",
|
||||
"Share:Text",
|
||||
"Snackbar:Show",
|
||||
"SystemUI:Visibility",
|
||||
"ToggleChrome:Focus",
|
||||
"ToggleChrome:Hide",
|
||||
|
@ -137,7 +137,6 @@ OnSharedPreferenceChangeListener
|
||||
private static final String PREFS_ADVANCED = NON_PREF_PREFIX + "advanced.enabled";
|
||||
private static final String PREFS_ACCESSIBILITY = NON_PREF_PREFIX + "accessibility.enabled";
|
||||
private static final String PREFS_CUSTOMIZE_HOME = NON_PREF_PREFIX + "customize_home";
|
||||
private static final String PREFS_CUSTOMIZE_IMAGE_BLOCKING = "browser.image_blocking";
|
||||
private static final String PREFS_TRACKING_PROTECTION_PRIVATE_BROWSING = "privacy.trackingprotection.pbmode.enabled";
|
||||
private static final String PREFS_TRACKING_PROTECTION_LEARN_MORE = NON_PREF_PREFIX + "trackingprotection.learn_more";
|
||||
private static final String PREFS_CLEAR_PRIVATE_DATA = NON_PREF_PREFIX + "privacy.clear";
|
||||
@ -839,12 +838,6 @@ OnSharedPreferenceChangeListener
|
||||
i--;
|
||||
continue;
|
||||
}
|
||||
} else if (PREFS_CUSTOMIZE_IMAGE_BLOCKING.equals(key)) {
|
||||
if (!AppConstants.NIGHTLY_BUILD) {
|
||||
preferences.removePreference(pref);
|
||||
i--;
|
||||
continue;
|
||||
}
|
||||
} else if (PREFS_CLEAR_PRIVATE_DATA.equals(key) || PREFS_CLEAR_PRIVATE_DATA_EXIT.equals(key)) {
|
||||
if (!Restrictions.isAllowed(this, Restrictable.CLEAR_HISTORY)) {
|
||||
preferences.removePreference(pref);
|
||||
|
@ -367,13 +367,8 @@ public class TabsPanel extends LinearLayout
|
||||
|
||||
mAddTab.setVisibility(View.VISIBLE);
|
||||
|
||||
if (!HardwareUtils.hasMenuButton()) {
|
||||
mMenuButton.setVisibility(View.VISIBLE);
|
||||
mMenuButton.setEnabled(true);
|
||||
mPopupMenu.setAnchor(mMenuButton);
|
||||
} else {
|
||||
mPopupMenu.setAnchor(mAddTab);
|
||||
}
|
||||
mMenuButton.setEnabled(true);
|
||||
mPopupMenu.setAnchor(mMenuButton);
|
||||
}
|
||||
|
||||
public int getVerticalPanelHeight() {
|
||||
|
@ -129,7 +129,6 @@ public abstract class BrowserToolbar extends ThemedRelativeLayout
|
||||
private OnStopEditingListener stopEditingListener;
|
||||
|
||||
protected final BrowserApp activity;
|
||||
protected boolean hasSoftMenuButton;
|
||||
|
||||
protected UIMode uiMode;
|
||||
protected TabHistoryController tabHistoryController;
|
||||
@ -194,7 +193,6 @@ public abstract class BrowserToolbar extends ThemedRelativeLayout
|
||||
|
||||
menuButton = (ThemedFrameLayout) findViewById(R.id.menu);
|
||||
menuIcon = (ThemedImageView) findViewById(R.id.menu_icon);
|
||||
hasSoftMenuButton = !HardwareUtils.hasMenuButton();
|
||||
|
||||
// The focusOrder List should be filled by sub-classes.
|
||||
focusOrder = new ArrayList<View>();
|
||||
@ -321,17 +319,14 @@ public abstract class BrowserToolbar extends ThemedRelativeLayout
|
||||
});
|
||||
tabsButton.setImageLevel(0);
|
||||
|
||||
if (hasSoftMenuButton) {
|
||||
menuButton.setVisibility(View.VISIBLE);
|
||||
menuButton.setOnClickListener(new Button.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View view) {
|
||||
// Drop the soft keyboard.
|
||||
urlEditLayout.clearFocus();
|
||||
activity.openOptionsMenu();
|
||||
}
|
||||
});
|
||||
}
|
||||
menuButton.setOnClickListener(new Button.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View view) {
|
||||
// Drop the soft keyboard.
|
||||
urlEditLayout.clearFocus();
|
||||
activity.openOptionsMenu();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -660,7 +655,7 @@ public abstract class BrowserToolbar extends ThemedRelativeLayout
|
||||
|
||||
public void setToolBarButtonsAlpha(float alpha) {
|
||||
ViewHelper.setAlpha(tabsCounter, alpha);
|
||||
if (hasSoftMenuButton && !HardwareUtils.isTablet()) {
|
||||
if (!HardwareUtils.isTablet()) {
|
||||
ViewHelper.setAlpha(menuIcon, alpha);
|
||||
}
|
||||
}
|
||||
@ -855,10 +850,6 @@ public abstract class BrowserToolbar extends ThemedRelativeLayout
|
||||
}
|
||||
|
||||
public boolean openOptionsMenu() {
|
||||
if (!hasSoftMenuButton) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Initialize the popup.
|
||||
if (menuPopup == null) {
|
||||
View panel = activity.getMenuPanel();
|
||||
@ -882,10 +873,6 @@ public abstract class BrowserToolbar extends ThemedRelativeLayout
|
||||
}
|
||||
|
||||
public boolean closeOptionsMenu() {
|
||||
if (!hasSoftMenuButton) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (menuPopup != null && menuPopup.isShowing()) {
|
||||
menuPopup.dismiss();
|
||||
}
|
||||
|
@ -118,15 +118,11 @@ class BrowserToolbarPhone extends BrowserToolbarPhoneBase {
|
||||
animator.attach(tabsCounter,
|
||||
PropertyAnimator.Property.TRANSLATION_X,
|
||||
curveTranslation);
|
||||
|
||||
if (!HardwareUtils.hasMenuButton()) {
|
||||
animator.attach(menuButton,
|
||||
PropertyAnimator.Property.TRANSLATION_X,
|
||||
curveTranslation);
|
||||
|
||||
animator.attach(menuIcon,
|
||||
PropertyAnimator.Property.TRANSLATION_X,
|
||||
curveTranslation);
|
||||
}
|
||||
animator.attach(menuButton,
|
||||
PropertyAnimator.Property.TRANSLATION_X,
|
||||
curveTranslation);
|
||||
animator.attach(menuIcon,
|
||||
PropertyAnimator.Property.TRANSLATION_X,
|
||||
curveTranslation);
|
||||
}
|
||||
}
|
||||
|
@ -127,24 +127,18 @@ abstract class BrowserToolbarPhoneBase extends BrowserToolbar {
|
||||
public void triggerTabsPanelTransition(final PropertyAnimator animator, final boolean areTabsShown) {
|
||||
if (areTabsShown) {
|
||||
ViewHelper.setAlpha(tabsCounter, 0.0f);
|
||||
if (hasSoftMenuButton) {
|
||||
ViewHelper.setAlpha(menuIcon, 0.0f);
|
||||
}
|
||||
ViewHelper.setAlpha(menuIcon, 0.0f);
|
||||
return;
|
||||
}
|
||||
|
||||
final PropertyAnimator buttonsAnimator =
|
||||
new PropertyAnimator(animator.getDuration(), buttonsInterpolator);
|
||||
|
||||
buttonsAnimator.attach(tabsCounter,
|
||||
PropertyAnimator.Property.ALPHA,
|
||||
1.0f);
|
||||
if (hasSoftMenuButton) {
|
||||
buttonsAnimator.attach(menuIcon,
|
||||
PropertyAnimator.Property.ALPHA,
|
||||
1.0f);
|
||||
}
|
||||
|
||||
buttonsAnimator.attach(menuIcon,
|
||||
PropertyAnimator.Property.ALPHA,
|
||||
1.0f);
|
||||
buttonsAnimator.start();
|
||||
}
|
||||
|
||||
|
@ -54,17 +54,12 @@ class BrowserToolbarPreHC extends BrowserToolbarPhoneBase {
|
||||
|
||||
// Prevent taps through the editing mode cancel button (bug 1001243).
|
||||
tabsButton.setEnabled(!isEditing);
|
||||
menuButton.setEnabled(!isEditing);
|
||||
|
||||
ViewHelper.setTranslationX(urlBarTranslatingEdge, entryTranslation);
|
||||
ViewHelper.setTranslationX(tabsButton, curveTranslation);
|
||||
ViewHelper.setTranslationX(tabsCounter, curveTranslation);
|
||||
|
||||
if (!HardwareUtils.hasMenuButton()) {
|
||||
// Prevent tabs through the editing mode cancel button (bug 1001243).
|
||||
menuButton.setEnabled(!isEditing);
|
||||
|
||||
ViewHelper.setTranslationX(menuButton, curveTranslation);
|
||||
ViewHelper.setTranslationX(menuIcon, curveTranslation);
|
||||
}
|
||||
ViewHelper.setTranslationX(menuButton, curveTranslation);
|
||||
ViewHelper.setTranslationX(menuIcon, curveTranslation);
|
||||
}
|
||||
}
|
||||
|
@ -69,7 +69,7 @@ abstract class BrowserToolbarTabletBase extends BrowserToolbar {
|
||||
ColorUtils.getColor(context, R.color.tabs_tray_icon_grey), PorterDuff.Mode.SRC_IN);
|
||||
|
||||
menuButtonMarginView = findViewById(R.id.menu_margin);
|
||||
if (menuButtonMarginView != null && !HardwareUtils.hasMenuButton()) {
|
||||
if (menuButtonMarginView != null) {
|
||||
menuButtonMarginView.setVisibility(View.VISIBLE);
|
||||
}
|
||||
}
|
||||
|
@ -36,7 +36,6 @@ public final class HardwareUtils {
|
||||
private static volatile boolean sIsLargeTablet;
|
||||
private static volatile boolean sIsSmallTablet;
|
||||
private static volatile boolean sIsTelevision;
|
||||
private static volatile boolean sHasMenuButton;
|
||||
|
||||
private HardwareUtils() {
|
||||
}
|
||||
@ -51,23 +50,16 @@ public final class HardwareUtils {
|
||||
// Pre-populate common flags from the context.
|
||||
final int screenLayoutSize = context.getResources().getConfiguration().screenLayout & Configuration.SCREENLAYOUT_SIZE_MASK;
|
||||
if (Build.VERSION.SDK_INT >= 11) {
|
||||
sHasMenuButton = false;
|
||||
if (screenLayoutSize == Configuration.SCREENLAYOUT_SIZE_XLARGE) {
|
||||
sIsLargeTablet = true;
|
||||
} else if (screenLayoutSize == Configuration.SCREENLAYOUT_SIZE_LARGE) {
|
||||
sIsSmallTablet = true;
|
||||
}
|
||||
if (Build.VERSION.SDK_INT >= 14) {
|
||||
sHasMenuButton = ViewConfiguration.get(context).hasPermanentMenuKey();
|
||||
|
||||
if (Build.VERSION.SDK_INT >= 16) {
|
||||
if (context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_TELEVISION)) {
|
||||
sIsTelevision = true;
|
||||
}
|
||||
if (Build.VERSION.SDK_INT >= 16) {
|
||||
if (context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_TELEVISION)) {
|
||||
sIsTelevision = true;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
sHasMenuButton = true;
|
||||
}
|
||||
|
||||
sInited = true;
|
||||
@ -89,10 +81,6 @@ public final class HardwareUtils {
|
||||
return sIsTelevision;
|
||||
}
|
||||
|
||||
public static boolean hasMenuButton() {
|
||||
return sHasMenuButton;
|
||||
}
|
||||
|
||||
public static int getMemSize() {
|
||||
return SysInfo.getMemSize();
|
||||
}
|
||||
|
@ -270,3 +270,8 @@
|
||||
<!-- Localization note: the format string below will be replaced
|
||||
with the Firefox Account's email address. -->
|
||||
<!ENTITY fxaccount_sync_finish_migrating_notification_text 'Tap to sign in as &formatS;'>
|
||||
|
||||
<!-- Localization note: the following strings are used in a
|
||||
notification and should be kept as short as possible. -->
|
||||
<!ENTITY old_sync_deprecated_notification_title 'Sign in to continue syncing'>
|
||||
<!ENTITY old_sync_deprecated_notification_content 'Your account is no longer supported'>
|
||||
|
Before Width: | Height: | Size: 292 B After Width: | Height: | Size: 292 B |
Before Width: | Height: | Size: 1.1 KiB |
Before Width: | Height: | Size: 1.7 KiB |
Before Width: | Height: | Size: 606 B |
Before Width: | Height: | Size: 1.2 KiB |
Before Width: | Height: | Size: 480 B |
Before Width: | Height: | Size: 1.1 KiB |
Before Width: | Height: | Size: 361 B After Width: | Height: | Size: 361 B |
Before Width: | Height: | Size: 1.7 KiB |
Before Width: | Height: | Size: 2.1 KiB |
Before Width: | Height: | Size: 790 B |
Before Width: | Height: | Size: 1.6 KiB |
Before Width: | Height: | Size: 620 B |
Before Width: | Height: | Size: 1.6 KiB |
@ -0,0 +1,13 @@
|
||||
<?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/. -->
|
||||
|
||||
<!-- This asset is properly available in large-* dirs so this null
|
||||
reference exists for build time on API 9 builds. -->
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:shape="rectangle">
|
||||
|
||||
<solid android:color="@android:color/transparent"/>
|
||||
|
||||
</shape>
|
@ -0,0 +1,13 @@
|
||||
<?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/. -->
|
||||
|
||||
<!-- This asset is properly available in large-* dirs so this null
|
||||
reference exists for build time on API 9 builds. -->
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:shape="rectangle">
|
||||
|
||||
<solid android:color="@android:color/transparent"/>
|
||||
|
||||
</shape>
|
@ -124,8 +124,7 @@
|
||||
android:layout_toLeftOf="@id/menu_margin"
|
||||
android:layout_alignWithParentIfMissing="true"
|
||||
android:contentDescription="@string/menu"
|
||||
android:background="@drawable/browser_toolbar_action_bar_button"
|
||||
android:visibility="gone">
|
||||
android:background="@drawable/browser_toolbar_action_bar_button">
|
||||
|
||||
<org.mozilla.gecko.widget.themed.ThemedImageView
|
||||
android:id="@+id/menu_icon"
|
||||
|
@ -41,8 +41,7 @@
|
||||
style="@style/UrlBar.ImageButton"
|
||||
android:layout_alignParentRight="true"
|
||||
android:contentDescription="@string/menu"
|
||||
android:background="@drawable/shaped_button"
|
||||
android:visibility="gone">
|
||||
android:background="@drawable/shaped_button">
|
||||
|
||||
<org.mozilla.gecko.widget.themed.ThemedImageView
|
||||
android:id="@+id/menu_icon"
|
||||
|
@ -53,8 +53,7 @@
|
||||
style="@style/UrlBar.ImageButton"
|
||||
android:layout_width="@dimen/tabs_panel_button_width"
|
||||
android:background="@drawable/action_bar_button_inverse"
|
||||
android:contentDescription="@string/menu"
|
||||
android:visibility="gone">
|
||||
android:contentDescription="@string/menu">
|
||||
|
||||
<ImageButton
|
||||
style="@style/UrlBar.ImageButton"
|
||||
|
@ -6,28 +6,24 @@
|
||||
<menu xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
|
||||
<item android:id="@+id/reload"
|
||||
android:icon="@drawable/ic_menu_reload"
|
||||
android:title="@string/reload"/>
|
||||
|
||||
<!-- We keep the reference so calls to findView don't fail. Hide
|
||||
to avoid taking up real estate on the users' screen. -->
|
||||
<item android:id="@+id/back"
|
||||
android:icon="@drawable/ic_menu_back"
|
||||
android:title="@string/back"
|
||||
android:visible="false"/>
|
||||
|
||||
<item android:id="@+id/forward"
|
||||
android:icon="@drawable/ic_menu_forward"
|
||||
android:title="@string/forward"/>
|
||||
|
||||
<item android:id="@+id/bookmark"
|
||||
android:icon="@drawable/ic_menu_bookmark_add"
|
||||
android:title="@string/bookmark"/>
|
||||
|
||||
<item android:id="@+id/new_tab"
|
||||
android:icon="@drawable/ic_menu_new_tab"
|
||||
android:title="@string/new_tab"/>
|
||||
|
||||
<item android:id="@+id/new_private_tab"
|
||||
android:icon="@drawable/ic_menu_new_private_tab"
|
||||
android:title="@string/new_private_tab"/>
|
||||
|
||||
<item android:id="@+id/share"
|
||||
@ -36,13 +32,6 @@
|
||||
<item android:id="@+id/reading_list"
|
||||
android:title="@string/overlay_share_reading_list_btn_label" />
|
||||
|
||||
<item android:id="@+id/save_as_pdf"
|
||||
android:title="@string/save_as_pdf" />
|
||||
|
||||
<item android:id="@+id/print"
|
||||
android:visible="false"
|
||||
android:title="@string/print" />
|
||||
|
||||
<item android:id="@+id/find_in_page"
|
||||
android:title="@string/find_in_page" />
|
||||
|
||||
@ -50,14 +39,47 @@
|
||||
android:title="@string/desktop_mode"
|
||||
android:checkable="true" />
|
||||
|
||||
<item android:id="@+id/addons"
|
||||
android:title="@string/addons"/>
|
||||
<item android:id="@+id/page"
|
||||
android:title="@string/page">
|
||||
|
||||
<item android:id="@+id/downloads"
|
||||
android:title="@string/downloads"/>
|
||||
<menu>
|
||||
<item android:id="@+id/subscribe"
|
||||
android:title="@string/contextmenu_subscribe"/>
|
||||
|
||||
<item android:id="@+id/logins"
|
||||
android:title="@string/logins"/>
|
||||
<item android:id="@+id/save_as_pdf"
|
||||
android:title="@string/save_as_pdf"/>
|
||||
|
||||
<item android:id="@+id/print"
|
||||
android:title="@string/print"/>
|
||||
|
||||
<item android:id="@+id/add_search_engine"
|
||||
android:title="@string/contextmenu_add_search_engine"/>
|
||||
|
||||
<item android:id="@+id/add_to_launcher"
|
||||
android:title="@string/contextmenu_add_to_launcher"/>
|
||||
</menu>
|
||||
|
||||
</item>
|
||||
|
||||
<item android:id="@+id/tools"
|
||||
android:title="@string/tools">
|
||||
|
||||
<menu>
|
||||
<item android:id="@+id/downloads"
|
||||
android:title="@string/downloads"/>
|
||||
<item android:id="@+id/addons"
|
||||
android:title="@string/addons"/>
|
||||
<item android:id="@+id/logins"
|
||||
android:title="@string/logins"/>
|
||||
<item android:id="@+id/new_guest_session"
|
||||
android:visible="false"
|
||||
android:title="@string/new_guest_session"/>
|
||||
<item android:id="@+id/exit_guest_session"
|
||||
android:visible="false"
|
||||
android:title="@string/exit_guest_session"/>
|
||||
</menu>
|
||||
|
||||
</item>
|
||||
|
||||
<item android:id="@+id/char_encoding"
|
||||
android:visible="false"
|
||||
@ -69,14 +91,6 @@
|
||||
<item android:id="@+id/help"
|
||||
android:title="@string/help_menu" />
|
||||
|
||||
<item android:id="@+id/new_guest_session"
|
||||
android:visible="false"
|
||||
android:title="@string/new_guest_session"/>
|
||||
|
||||
<item android:id="@+id/exit_guest_session"
|
||||
android:visible="false"
|
||||
android:title="@string/exit_guest_session"/>
|
||||
|
||||
<!-- Android will eliminate v11+ resource files from pre-11 builds.
|
||||
Those files are the only place in which certain IDs are defined.
|
||||
This causes compilation errors.
|
||||
@ -87,13 +101,4 @@
|
||||
android:visible="false"
|
||||
android:enabled="false" />
|
||||
|
||||
<item android:id="@+id/page"
|
||||
android:visible="false"
|
||||
android:enabled="false"
|
||||
android:title="@string/page" />
|
||||
|
||||
<item android:id="@+id/tools"
|
||||
android:visible="false"
|
||||
android:enabled="false"
|
||||
android:title="@string/tools" />
|
||||
</menu>
|
||||
|
@ -1003,7 +1003,12 @@ SessionStore.prototype = {
|
||||
// we stop the load above
|
||||
let activeIndex = (aTabData.index || aTabData.entries.length) - 1;
|
||||
aHistory.getEntryAtIndex(activeIndex, true);
|
||||
aHistory.QueryInterface(Ci.nsISHistory).reloadCurrentEntry();
|
||||
|
||||
try {
|
||||
aHistory.QueryInterface(Ci.nsISHistory).reloadCurrentEntry();
|
||||
} catch (e) {
|
||||
// This will throw if the current entry is an error page.
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
|
@ -68,7 +68,12 @@ public class HealthReportUploadService extends BackgroundService {
|
||||
Logger.warn(LOG_TAG, "Got intent without uploadEnabled. Ignoring.");
|
||||
return;
|
||||
}
|
||||
boolean uploadEnabled = intent.getBooleanExtra("uploadEnabled", false);
|
||||
|
||||
// We disabled Health Report uploads in Bug 1230206, because the service is being decommissioned.
|
||||
// We chose this specific place to turn uploads off because we wish to preserve deletions in the
|
||||
// interim, and this is the tested code path for when a user turns off upload, but still expects
|
||||
// deletions to work.
|
||||
boolean uploadEnabled = false;
|
||||
|
||||
// Don't do anything if the device can't talk to the server.
|
||||
if (!backgroundDataIsEnabled()) {
|
||||
|
@ -103,9 +103,11 @@ public class SubmissionPolicy {
|
||||
// with one request.
|
||||
final String obsoleteId = tracker.getNextObsoleteId();
|
||||
if (obsoleteId == null) {
|
||||
Logger.debug(LOG_TAG, "Upload disabled and nothing to delete.");
|
||||
return false;
|
||||
}
|
||||
|
||||
Logger.info(LOG_TAG, "Upload disabled. Deleting obsolete document.");
|
||||
Editor editor = editor();
|
||||
editor.setLastDeleteRequested(localTime); // Write committed by delegate.
|
||||
client.delete(localTime, obsoleteId, new DeleteDelegate(editor));
|
||||
|
@ -213,10 +213,6 @@ public class FxAccountStatusFragment
|
||||
syncNowPreference = ensureFindPreference("sync_now");
|
||||
syncNowPreference.setEnabled(true);
|
||||
syncNowPreference.setOnPreferenceClickListener(this);
|
||||
|
||||
if (HardwareUtils.hasMenuButton()) {
|
||||
syncCategory.removePreference(morePreference);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -54,4 +54,6 @@ public class SyncConstants {
|
||||
|
||||
// Used for BackoffHandler storage for Sync 1.1's SyncAdapter.
|
||||
public static final String BACKOFF_PREF_SUFFIX_11 = "sync";
|
||||
|
||||
public static final String SYNC_ACCOUNT_DEPRECATED_ACTION = AppConstants.MOZ_ANDROID_SHARED_ACCOUNT_TYPE + ".accounts.SYNC_ACCOUNT_DEPRECATED_ACTION";
|
||||
}
|
||||
|
@ -4,6 +4,9 @@
|
||||
|
||||
package org.mozilla.gecko.sync.receivers;
|
||||
|
||||
import org.mozilla.gecko.fxa.FirefoxAccounts;
|
||||
import org.mozilla.gecko.fxa.FxAccountConstants;
|
||||
import org.mozilla.gecko.fxa.activities.FxAccountWebFlowActivity;
|
||||
import org.mozilla.gecko.sync.ExtendedJSONObject;
|
||||
import org.mozilla.gecko.background.common.GlobalConstants;
|
||||
import org.mozilla.gecko.background.common.log.Logger;
|
||||
@ -16,8 +19,10 @@ import org.mozilla.gecko.sync.config.ClientRecordTerminator;
|
||||
import org.mozilla.gecko.sync.net.BasicAuthHeaderProvider;
|
||||
import org.mozilla.gecko.sync.repositories.android.FennecTabsRepository;
|
||||
import org.mozilla.gecko.sync.setup.Constants;
|
||||
import org.mozilla.gecko.sync.setup.SyncAccounts;
|
||||
import org.mozilla.gecko.sync.setup.SyncAccounts.SyncAccountParameters;
|
||||
|
||||
import android.accounts.Account;
|
||||
import android.accounts.AccountManager;
|
||||
import android.app.IntentService;
|
||||
import android.content.Context;
|
||||
@ -41,6 +46,27 @@ public class SyncAccountDeletedService extends IntentService {
|
||||
|
||||
final Context context = this;
|
||||
|
||||
if (SyncConstants.SYNC_ACCOUNT_DEPRECATED_ACTION.equals(intent.getAction())) {
|
||||
// Delete Old Sync account.
|
||||
final Account[] accounts = SyncAccounts.syncAccounts(this);
|
||||
for (Account account : accounts) {
|
||||
AccountManager.get(this).removeAccount(account, null, null);
|
||||
}
|
||||
|
||||
// Offer signin for Firefox Account if we don't already have one.
|
||||
if (!FirefoxAccounts.firefoxAccountsExist(this)) {
|
||||
final Intent fxAccountWebIntent = new Intent(FxAccountConstants.ACTION_FXA_GET_STARTED);
|
||||
fxAccountWebIntent.putExtra(FxAccountWebFlowActivity.EXTRA_ENDPOINT, FxAccountConstants.ENDPOINT_PREFERENCES);
|
||||
fxAccountWebIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||
fxAccountWebIntent.addFlags(Intent.FLAG_ACTIVITY_NO_ANIMATION);
|
||||
context.startActivity(fxAccountWebIntent);
|
||||
}
|
||||
|
||||
// Return early. The SYNC_ACCOUNT_DELETED_ACTION spawn by the account
|
||||
// deletion above will remove the pickle file.
|
||||
return;
|
||||
}
|
||||
|
||||
long intentVersion = intent.getLongExtra(Constants.JSON_KEY_VERSION, 0);
|
||||
long expectedVersion = SyncConstants.SYNC_ACCOUNT_DELETED_INTENT_VERSION;
|
||||
if (intentVersion != expectedVersion) {
|
||||
|
@ -4,10 +4,12 @@
|
||||
|
||||
package org.mozilla.gecko.sync.receivers;
|
||||
|
||||
import org.mozilla.gecko.R;
|
||||
import org.mozilla.gecko.background.common.GlobalConstants;
|
||||
import org.mozilla.gecko.background.common.log.Logger;
|
||||
import org.mozilla.gecko.sync.CredentialException;
|
||||
import org.mozilla.gecko.sync.SyncConfiguration;
|
||||
import org.mozilla.gecko.sync.SyncConstants;
|
||||
import org.mozilla.gecko.sync.ThreadPool;
|
||||
import org.mozilla.gecko.sync.Utils;
|
||||
import org.mozilla.gecko.sync.config.ConfigurationMigrator;
|
||||
@ -17,9 +19,12 @@ import org.mozilla.gecko.sync.setup.SyncAccounts.SyncAccountParameters;
|
||||
|
||||
import android.accounts.Account;
|
||||
import android.accounts.AccountManager;
|
||||
import android.app.NotificationManager;
|
||||
import android.app.PendingIntent;
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.support.v4.app.NotificationCompat.Builder;
|
||||
|
||||
public class UpgradeReceiver extends BroadcastReceiver {
|
||||
private static final String LOG_TAG = "UpgradeReceiver";
|
||||
@ -34,6 +39,14 @@ public class UpgradeReceiver extends BroadcastReceiver {
|
||||
return;
|
||||
}
|
||||
|
||||
// Show account not supported notification.
|
||||
ThreadPool.run(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
notifyAccountDeprecation(context);
|
||||
}
|
||||
});
|
||||
|
||||
// Should filter for specific MY_PACKAGE_REPLACED intent, but Android does
|
||||
// not expose it.
|
||||
ThreadPool.run(new Runnable() {
|
||||
@ -94,4 +107,24 @@ public class UpgradeReceiver extends BroadcastReceiver {
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Show a persistent notification telling the user that their Old Sync account is deprecated.
|
||||
*/
|
||||
private void notifyAccountDeprecation(final Context context) {
|
||||
final Intent notificationIntent = new Intent(SyncConstants.SYNC_ACCOUNT_DEPRECATED_ACTION);
|
||||
notificationIntent.setClass(context, SyncAccountDeletedService.class);
|
||||
final PendingIntent pendingIntent = PendingIntent.getService(context, 0, notificationIntent, PendingIntent.FLAG_UPDATE_CURRENT);
|
||||
final Builder builder = new Builder(context)
|
||||
.setSmallIcon(R.drawable.ic_status_logo)
|
||||
.setContentTitle(context.getString(R.string.old_sync_deprecated_notification_title))
|
||||
.setContentText(context.getString(R.string.old_sync_deprecated_notification_content))
|
||||
.setAutoCancel(true)
|
||||
.setOngoing(true)
|
||||
.setContentIntent(pendingIntent);
|
||||
|
||||
final NotificationManager notificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
|
||||
final int notificationID = SyncConstants.SYNC_ACCOUNT_DEPRECATED_ACTION.hashCode();
|
||||
notificationManager.notify(notificationID, builder.build());
|
||||
}
|
||||
}
|
||||
|
@ -242,3 +242,7 @@
|
||||
|
||||
<!-- Log Personal information -->
|
||||
<string name="fxaccount_enable_debug_mode">&fxaccount_enable_debug_mode;</string>
|
||||
|
||||
<!-- Old Sync Account deprecated notification. -->
|
||||
<string name="old_sync_deprecated_notification_title">&old_sync_deprecated_notification_title;</string>
|
||||
<string name="old_sync_deprecated_notification_content">&old_sync_deprecated_notification_content;</string>
|
||||
|
@ -11,13 +11,13 @@ import static org.mozilla.gecko.tests.helpers.AssertionHelper.fAssertTrue;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.mozilla.gecko.AppConstants;
|
||||
import org.mozilla.gecko.R;
|
||||
import org.mozilla.gecko.menu.MenuItemActionBar;
|
||||
import org.mozilla.gecko.menu.MenuItemDefault;
|
||||
import org.mozilla.gecko.tests.UITestContext;
|
||||
import org.mozilla.gecko.tests.helpers.DeviceHelper;
|
||||
import org.mozilla.gecko.tests.helpers.WaitHelper;
|
||||
import org.mozilla.gecko.util.HardwareUtils;
|
||||
|
||||
import android.text.TextUtils;
|
||||
import android.view.View;
|
||||
@ -31,7 +31,7 @@ import com.jayway.android.robotium.solo.Solo;
|
||||
* A class representing any interactions that take place on the app menu.
|
||||
*/
|
||||
public class AppMenuComponent extends BaseComponent {
|
||||
private static final long MAX_WAITTIME_FOR_MENU_UPDATE_IN_MS = 1000L;
|
||||
private static final long MAX_WAITTIME_FOR_MENU_UPDATE_IN_MS = 7500L;
|
||||
|
||||
private Boolean hasLegacyMenu = null;
|
||||
|
||||
@ -243,9 +243,9 @@ public class AppMenuComponent extends BaseComponent {
|
||||
private void openAppMenu() {
|
||||
assertMenuIsNotOpen();
|
||||
|
||||
// This is a hack needed for tablets where the OverflowMenuButton is always in the GONE state,
|
||||
// This is a hack needed for tablets & GB where the OverflowMenuButton is always in the GONE state,
|
||||
// so we press the menu key instead.
|
||||
if (HardwareUtils.hasMenuButton() || DeviceHelper.isTablet()) {
|
||||
if (DeviceHelper.isTablet() || AppConstants.Versions.preHC) {
|
||||
mSolo.sendKey(Solo.MENU);
|
||||
} else {
|
||||
pressOverflowMenuButton();
|
||||
@ -283,12 +283,14 @@ public class AppMenuComponent extends BaseComponent {
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines whether the app menu is open by searching for the text "New tab".
|
||||
* Determines whether the app menu is open by searching for items in the menu.
|
||||
*
|
||||
* @return true if app menu is open.
|
||||
*/
|
||||
private boolean isMenuOpen() {
|
||||
return isMenuOpen(MenuItem.NEW_TAB.getString(mSolo));
|
||||
// We choose these options because New Tab is near the top of the menu and Page is near the middle/bottom.
|
||||
// Intermittently, the menu doesn't scroll to top so we can't just use the first item in the list.
|
||||
return isMenuOpen(MenuItem.NEW_TAB.getString(mSolo)) || isMenuOpen(MenuItem.PAGE.getString(mSolo));
|
||||
}
|
||||
|
||||
private boolean isLegacyMoreMenuOpen() {
|
||||
|
@ -221,7 +221,7 @@ public class SwitchBoard {
|
||||
if(serverUrl != null) {
|
||||
String params = "uuid="+uuid+"&device="+device+"&lang="+lang+"&country="+country
|
||||
+"&manufacturer="+manufacturer+"&appId="+packageName+"&version="+versionName;
|
||||
if(DEBUG) Log.d(TAG, "Read from server URL: " + serverUrl + params);
|
||||
if(DEBUG) Log.d(TAG, "Read from server URL: " + serverUrl + "?" + params);
|
||||
String serverConfig = readFromUrlGET(serverUrl, params);
|
||||
|
||||
if(DEBUG) Log.d(TAG, serverConfig);
|
||||
|
@ -37,6 +37,7 @@
|
||||
#include "nsIObserverService.h"
|
||||
#include "nsProxyRelease.h"
|
||||
#include "nsPIDOMWindow.h"
|
||||
#include "nsIDocShell.h"
|
||||
#include "nsPerformance.h"
|
||||
#include "nsINetworkInterceptController.h"
|
||||
#include "mozIThirdPartyUtil.h"
|
||||
@ -253,7 +254,7 @@ NS_IMETHODIMP
|
||||
HttpBaseChannel::SetLoadGroup(nsILoadGroup *aLoadGroup)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread(), "Should only be called on the main thread.");
|
||||
|
||||
|
||||
if (!CanSetLoadGroup(aLoadGroup)) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
@ -295,6 +296,47 @@ HttpBaseChannel::SetLoadFlags(nsLoadFlags aLoadFlags)
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
HttpBaseChannel::SetDocshellUserAgentOverride()
|
||||
{
|
||||
// This sets the docshell specific user agent override, it will be overwritten
|
||||
// by UserAgentOverrides.jsm if site-specific user agent overrides are set.
|
||||
nsresult rv;
|
||||
nsCOMPtr<nsILoadContext> loadContext;
|
||||
NS_QueryNotificationCallbacks(this, loadContext);
|
||||
if (!loadContext) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIDOMWindow> domWindow;
|
||||
loadContext->GetAssociatedWindow(getter_AddRefs(domWindow));
|
||||
if (!domWindow) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsPIDOMWindow> pDomWindow = do_QueryInterface(domWindow);
|
||||
if (!pDomWindow) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsIDocShell* docshell = pDomWindow->GetDocShell();
|
||||
if (!docshell) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsString customUserAgent;
|
||||
docshell->GetCustomUserAgent(customUserAgent);
|
||||
if (customUserAgent.IsEmpty()) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_ConvertUTF16toUTF8 utf8CustomUserAgent(customUserAgent);
|
||||
rv = SetRequestHeader(NS_LITERAL_CSTRING("User-Agent"), utf8CustomUserAgent, false);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// HttpBaseChannel::nsIChannel
|
||||
//-----------------------------------------------------------------------------
|
||||
@ -369,7 +411,7 @@ NS_IMETHODIMP
|
||||
HttpBaseChannel::SetNotificationCallbacks(nsIInterfaceRequestor *aCallbacks)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread(), "Should only be called on the main thread.");
|
||||
|
||||
|
||||
if (!CanSetCallbacks(aCallbacks)) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
@ -1379,7 +1421,7 @@ HttpBaseChannel::SetReferrerWithPolicy(nsIURI *referrer,
|
||||
if (eTLDService) {
|
||||
rv = eTLDService->GetBaseDomain(mURI, extraDomains, currentDomain);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
rv = eTLDService->GetBaseDomain(clone, extraDomains, referrerDomain);
|
||||
rv = eTLDService->GetBaseDomain(clone, extraDomains, referrerDomain);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
}
|
||||
|
||||
@ -2446,7 +2488,7 @@ void
|
||||
HttpBaseChannel::ReleaseListeners()
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread(), "Should only be called on the main thread.");
|
||||
|
||||
|
||||
mListener = nullptr;
|
||||
mListenerContext = nullptr;
|
||||
mCallbacks = nullptr;
|
||||
@ -3113,4 +3155,3 @@ HttpBaseChannel::SetCorsPreflightParameters(const nsTArray<nsCString>& aUnsafeHe
|
||||
|
||||
} // namespace net
|
||||
} // namespace mozilla
|
||||
|
||||
|
@ -100,6 +100,7 @@ public:
|
||||
NS_IMETHOD SetLoadGroup(nsILoadGroup *aLoadGroup) override;
|
||||
NS_IMETHOD GetLoadFlags(nsLoadFlags *aLoadFlags) override;
|
||||
NS_IMETHOD SetLoadFlags(nsLoadFlags aLoadFlags) override;
|
||||
NS_IMETHOD SetDocshellUserAgentOverride();
|
||||
|
||||
// nsIChannel
|
||||
NS_IMETHOD GetOriginalURI(nsIURI **aOriginalURI) override;
|
||||
|
@ -1743,6 +1743,9 @@ HttpChannelChild::AsyncOpen(nsIStreamListener *listener, nsISupports *aContext)
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// Set user agent override
|
||||
HttpBaseChannel::SetDocshellUserAgentOverride();
|
||||
|
||||
if (ShouldIntercept()) {
|
||||
mResponseCouldBeSynthesized = true;
|
||||
|
||||
|
@ -5038,6 +5038,9 @@ nsHttpChannel::AsyncOpen(nsIStreamListener *listener, nsISupports *context)
|
||||
gHttpHandler->OnOpeningRequest(this);
|
||||
}
|
||||
|
||||
// Set user agent override
|
||||
HttpBaseChannel::SetDocshellUserAgentOverride();
|
||||
|
||||
mIsPending = true;
|
||||
mWasOpened = true;
|
||||
|
||||
|
@ -2,6 +2,8 @@
|
||||
# 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/.
|
||||
|
||||
import os
|
||||
|
||||
from mozboot.base import BaseBootstrapper
|
||||
|
||||
|
||||
@ -13,8 +15,7 @@ class FedoraBootstrapper(BaseBootstrapper):
|
||||
self.dist_id = dist_id
|
||||
|
||||
self.group_packages = [
|
||||
'Development Tools',
|
||||
'Development Libraries',
|
||||
'C Development Tools and Libraries',
|
||||
]
|
||||
|
||||
self.packages = [
|
||||
@ -43,6 +44,13 @@ class FedoraBootstrapper(BaseBootstrapper):
|
||||
'yasm',
|
||||
]
|
||||
|
||||
self.mobile_android_packages = [
|
||||
'ant',
|
||||
'ncurses-devel.i686',
|
||||
'libstdc++.i686',
|
||||
'zlib-devel.i686',
|
||||
]
|
||||
|
||||
def install_system_packages(self):
|
||||
self.dnf_groupinstall(*self.group_packages)
|
||||
self.dnf_install(*self.packages)
|
||||
@ -51,5 +59,27 @@ class FedoraBootstrapper(BaseBootstrapper):
|
||||
self.dnf_groupinstall(*self.browser_group_packages)
|
||||
self.dnf_install(*self.browser_packages)
|
||||
|
||||
def install_mobile_android_packages(self):
|
||||
import android
|
||||
|
||||
# Install Android specific packages.
|
||||
self.dnf_install(*self.mobile_android_packages)
|
||||
|
||||
# Fetch Android SDK and NDK.
|
||||
mozbuild_path = os.environ.get('MOZBUILD_STATE_PATH', os.path.expanduser(os.path.join('~', '.mozbuild')))
|
||||
self.sdk_path = os.environ.get('ANDROID_SDK_HOME', os.path.join(mozbuild_path, 'android-sdk-linux'))
|
||||
self.ndk_path = os.environ.get('ANDROID_NDK_HOME', os.path.join(mozbuild_path, 'android-ndk-r10e'))
|
||||
self.sdk_url = 'https://dl.google.com/android/android-sdk_r24.0.1-linux.tgz'
|
||||
self.ndk_url = android.android_ndk_url('linux')
|
||||
|
||||
android.ensure_android_sdk_and_ndk(path=mozbuild_path,
|
||||
sdk_path=self.sdk_path, sdk_url=self.sdk_url,
|
||||
ndk_path=self.ndk_path, ndk_url=self.ndk_url)
|
||||
|
||||
def suggest_mobile_android_mozconfig(self):
|
||||
import android
|
||||
android.suggest_mozconfig(sdk_path=self.sdk_path,
|
||||
ndk_path=self.ndk_path)
|
||||
|
||||
def upgrade_mercurial(self, current):
|
||||
self.dnf_update('mercurial')
|
||||
|
@ -2304,11 +2304,12 @@ var AddonManagerInternal = {
|
||||
},
|
||||
|
||||
/**
|
||||
* Starts installation of a temporary add-on from a local directory.
|
||||
* @param aDirectory
|
||||
* The directory of the add-on to be temporarily installed
|
||||
* @return a Promise that rejects if the add-on is not restartless
|
||||
* or an add-on with the same ID is already temporarily installed
|
||||
* Installs a temporary add-on from a local file or directory.
|
||||
* @param aFile
|
||||
* An nsIFile for the file or directory of the add-on to be
|
||||
* temporarily installed.
|
||||
* @return a Promise that rejects if the add-on is not a valid restartless
|
||||
* add-on or if the same ID is already temporarily installed.
|
||||
*/
|
||||
installTemporaryAddon: function(aFile) {
|
||||
if (!gStarted)
|
||||
|
@ -3825,18 +3825,18 @@ this.XPIProvider = {
|
||||
},
|
||||
|
||||
/**
|
||||
* Temporarily installs add-on from local directory.
|
||||
* Temporarily installs add-on from a local XPI file or directory.
|
||||
* As this is intended for development, the signature is not checked and
|
||||
* the add-on does not persist on application restart.
|
||||
*
|
||||
* @param aDirectory
|
||||
* The directory containing the unpacked add-on directory or XPI file
|
||||
* @param aFile
|
||||
* An nsIFile for the unpacked add-on directory or XPI file.
|
||||
*
|
||||
* @return a Promise that rejects if the add-on is not restartless
|
||||
* or an add-on with the same ID is already temporarily installed
|
||||
* @return a Promise that rejects if the add-on is not a valid restartless
|
||||
* add-on or if the same ID is already temporarily installed
|
||||
*/
|
||||
installTemporaryAddon: Task.async(function*(aDirectory) {
|
||||
let addon = yield loadManifestFromFile(aDirectory, TemporaryInstallLocation);
|
||||
installTemporaryAddon: Task.async(function*(aFile) {
|
||||
let addon = yield loadManifestFromFile(aFile, TemporaryInstallLocation);
|
||||
|
||||
if (!addon.bootstrap) {
|
||||
throw new Error("Only restartless (bootstrap) add-ons"
|
||||
@ -3887,7 +3887,7 @@ this.XPIProvider = {
|
||||
XPIProvider.callBootstrapMethod(addon, file, "install",
|
||||
BOOTSTRAP_REASONS.ADDON_INSTALL);
|
||||
addon.state = AddonManager.STATE_INSTALLED;
|
||||
logger.debug("Install of temporary addon in " + aDirectory.path + " completed.");
|
||||
logger.debug("Install of temporary addon in " + aFile.path + " completed.");
|
||||
addon.visible = true;
|
||||
addon.enabled = true;
|
||||
addon.active = true;
|
||||
@ -7977,8 +7977,7 @@ Object.assign(SystemAddonInstallLocation.prototype, {
|
||||
});
|
||||
|
||||
/**
|
||||
* An object which identifies a directory install location for temporary
|
||||
* add-ons.
|
||||
* An object which identifies an install location for temporary add-ons.
|
||||
*/
|
||||
const TemporaryInstallLocation = {
|
||||
locked: false,
|
||||
|
@ -2363,7 +2363,6 @@ nsWindow::Natives::OnImeReplaceText(int32_t aStart, int32_t aEnd,
|
||||
event.mOffset = uint32_t(aStart);
|
||||
event.mLength = uint32_t(aEnd - aStart);
|
||||
event.mExpandToClusterBoundary = false;
|
||||
event.mReason = nsISelectionListener::IME_REASON;
|
||||
window.DispatchEvent(&event);
|
||||
}
|
||||
|
||||
@ -2492,7 +2491,6 @@ nsWindow::Natives::OnImeUpdateComposition(int32_t aStart, int32_t aEnd)
|
||||
selEvent.mLength = std::max(aStart, aEnd) - selEvent.mOffset;
|
||||
selEvent.mReversed = aStart > aEnd;
|
||||
selEvent.mExpandToClusterBoundary = false;
|
||||
selEvent.mReason = nsISelectionListener::IME_REASON;
|
||||
|
||||
window.DispatchEvent(&selEvent);
|
||||
return;
|
||||
|