This commit is contained in:
Ryan VanderMeulen 2014-01-16 15:07:22 -05:00
Родитель b19c8cefbf 8e6011fca4
Коммит fdd6001939
102 изменённых файлов: 8275 добавлений и 462 удалений

Просмотреть файл

@ -282,7 +282,6 @@ pref("layers.offmainthreadcomposition.async-animations", true);
pref("layers.async-video.enabled", true);
pref("layers.async-pan-zoom.enabled", true);
pref("gfx.content.azure.backends", "cairo");
pref("layers.composer2d.enabled", true);
#endif
// Web Notifications
@ -620,9 +619,11 @@ pref("ui.useOverlayScrollbars", 1);
// Enable the ProcessPriorityManager, and give processes with no visible
// documents a 1s grace period before they're eligible to be marked as
// background.
// background. Background processes that are perceivable due to playing
// media are given a longer grace period to accomodate changing tracks, etc.
pref("dom.ipc.processPriorityManager.enabled", true);
pref("dom.ipc.processPriorityManager.backgroundGracePeriodMS", 1000);
pref("dom.ipc.processPriorityManager.backgroundPerceivableGracePeriodMS", 5000);
pref("dom.ipc.processPriorityManager.temporaryPriorityLockMS", 5000);
// Number of different background levels for background processes. We use

Просмотреть файл

@ -597,9 +597,38 @@ SettingsListener.observe("debug.paint-flashing.enabled", false, function(value)
SettingsListener.observe("layers.draw-borders", false, function(value) {
Services.prefs.setBoolPref("layers.draw-borders", value);
});
SettingsListener.observe("layers.composer2d.enabled", true, function(value) {
Services.prefs.setBoolPref("layers.composer2d.enabled", value);
});
(function Composer2DSettingToPref() {
//layers.composer.enabled can be enabled in three ways
//In order of precedence they are:
//
//1. mozSettings "layers.composer.enabled"
//2. a gecko pref "layers.composer.enabled"
//3. presence of ro.display.colorfill at the Gonk level
var req = navigator.mozSettings.createLock().get('layers.composer2d.enabled');
req.onsuccess = function() {
if (typeof(req.result['layers.composer2d.enabled']) === 'undefined') {
var enabled = false;
if (Services.prefs.getPrefType('layers.composer2d.enabled') == Ci.nsIPrefBranch.PREF_BOOL) {
enabled = Services.prefs.getBoolPref('layers.composer2d.enabled');
} else {
#ifdef MOZ_WIDGET_GONK
enabled = (libcutils.property_get('ro.display.colorfill') === '1');
#endif
}
navigator.mozSettings.createLock().set({'layers.composer2d.enabled': enabled });
}
SettingsListener.observe("layers.composer2d.enabled", true, function(value) {
Services.prefs.setBoolPref("layers.composer2d.enabled", value);
});
};
req.onerror = function() {
dump("Error configuring layers.composer2d.enabled setting");
};
})();
// ================ Accessibility ============
SettingsListener.observe("accessibility.screenreader", false, function(value) {

Просмотреть файл

@ -1,4 +1,4 @@
{
"revision": "35ba072bcabf79e9c32776e9322c41e0020c9264",
"revision": "a4c7ffc5619edd7e87fd763bd8a32291f4d394ac",
"repo_path": "/integration/gaia-central"
}

Просмотреть файл

@ -1155,8 +1155,10 @@ pref("devtools.tilt.outro_transition", true);
// clear any recent files, but rather hide the
// 'Open Recent'-menu.
// - showTrailingSpace: Whether to highlight trailing space or not.
// - enableCodeFolding: Whether to enable code folding or not.
pref("devtools.scratchpad.recentFilesMax", 10);
pref("devtools.scratchpad.showTrailingSpace", false);
pref("devtools.scratchpad.enableCodeFolding", true);
// Enable the Style Editor.
pref("devtools.styleeditor.enabled", true);
@ -1234,8 +1236,10 @@ pref("devtools.hud.loglimit.console", 200);
// The developer tools editor configuration:
// - tabsize: how many spaces to use when a Tab character is displayed.
// - expandtab: expand Tab characters to spaces.
// - keymap: which keymap to use (can be 'default', 'emacs' or 'vim')
pref("devtools.editor.tabsize", 4);
pref("devtools.editor.expandtab", true);
pref("devtools.editor.keymap", "default");
// Enable the Font Inspector
pref("devtools.fontinspector.enabled", true);

Просмотреть файл

@ -277,3 +277,7 @@ let ClickEventHandler = {
}
};
ClickEventHandler.init();
addEventListener("DOMWebNotificationClicked", function(event) {
sendAsyncMessage("DOMWebNotificationClicked", {});
}, false);

Просмотреть файл

@ -2946,7 +2946,7 @@
let browser = aMessage.target;
switch (aMessage.name) {
case "DOMTitleChanged":
case "DOMTitleChanged": {
let tab = this._getTabForBrowser(browser);
if (!tab)
return;
@ -2954,7 +2954,8 @@
if (titleChanged && !tab.selected && !tab.hasAttribute("busy"))
tab.setAttribute("titlechanged", "true");
break;
case "contextmenu":
}
case "contextmenu": {
gContextMenuContentData = { event: aMessage.objects.event,
browser: browser };
let popup = browser.ownerDocument.getElementById("contentAreaContextMenu");
@ -2963,6 +2964,16 @@
gContextMenuContentData.event.clientY,
true, false, null);
break;
}
case "DOMWebNotificationClicked": {
let tab = this._getTabForBrowser(browser);
if (!tab)
return;
this.selectedTab = tab;
let focusManager = Cc["@mozilla.org/focus-manager;1"].getService(Ci.nsIFocusManager);
focusManager.activeWindow = window;
break;
}
}
]]></body>
</method>
@ -3020,6 +3031,7 @@
messageManager.addMessageListener("DOMTitleChanged", this);
messageManager.addMessageListener("contextmenu", this);
}
messageManager.addMessageListener("DOMWebNotificationClicked", this);
]]>
</constructor>

Просмотреть файл

@ -51,6 +51,7 @@ support-files =
file_bug906190_redirected.html
file_bug906190.js
file_bug906190.sjs
file_dom_notifications.html
file_fullscreen-window-open.html
head.js
healthreport_testRemoteCommands.html
@ -268,6 +269,7 @@ skip-if = os == "linux" # Intermittent failures, bug 917535
[browser_middleMouse_inherit.js]
[browser_minimize.js]
[browser_mixedcontent_securityflags.js]
[browser_notification_tab_switching.js]
[browser_offlineQuotaNotification.js]
[browser_overflowScroll.js]
[browser_pageInfo.js]

Просмотреть файл

@ -0,0 +1,58 @@
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/
*/
"use strict";
let tab;
let notification;
let notificationURL = "http://example.org/browser/browser/base/content/test/general/file_dom_notifications.html";
function test () {
waitForExplicitFinish();
let pm = Services.perms;
registerCleanupFunction(function() {
pm.remove(notificationURL, "desktop-notification");
gBrowser.removeTab(tab);
window.restore();
});
pm.add(makeURI(notificationURL), "desktop-notification", pm.ALLOW_ACTION);
tab = gBrowser.addTab(notificationURL);
tab.linkedBrowser.addEventListener("load", onLoad, true);
}
function onLoad() {
isnot(gBrowser.selectedTab, tab, "Notification page loaded as a background tab");
tab.linkedBrowser.removeEventListener("load", onLoad, true);
let win = tab.linkedBrowser.contentWindow.wrappedJSObject;
notification = win.showNotification();
notification.addEventListener("show", onAlertShowing);
}
function onAlertShowing() {
info("Notification alert showing");
notification.removeEventListener("show", onAlertShowing);
let alertWindow = findChromeWindowByURI("chrome://global/content/alerts/alert.xul");
if (!alertWindow) {
todo(false, "Notifications don't use XUL windows on all platforms.");
notification.close();
finish();
return;
}
gBrowser.tabContainer.addEventListener("TabSelect", onTabSelect);
EventUtils.synthesizeMouseAtCenter(alertWindow.document.getElementById("alertTitleLabel"), {}, alertWindow);
info("Clicked on notification");
alertWindow.close();
}
function onTabSelect() {
gBrowser.tabContainer.removeEventListener("TabSelect", onTabSelect);
is(gBrowser.selectedTab.linkedBrowser.contentWindow.location.href, notificationURL,
"Notification tab should be selected.");
finish();
}

Просмотреть файл

@ -0,0 +1,23 @@
<html>
<head>
<script>
"use strict";
function showNotification() {
var options = {
dir: undefined,
lang: undefined,
body: "Test body",
tag: "Test tag",
icon: undefined,
};
return new Notification("Test title", options);
}
</script>
</head>
<body>
<form id="notificationForm" onsubmit="showNotification();">
<input type="submit" value="Show notification" id="submit"/>
</form>
</body>
</html>

Просмотреть файл

@ -2483,7 +2483,7 @@ EventListenersView.prototype = Heritage.extend(WidgetMethods, {
// Check all the event items in this group.
this.items
.filter(e => e.description == description)
.filter(e => e.attachment.group == description)
.forEach(e => this.callMethod("checkItem", e.target, checked));
},

Просмотреть файл

@ -84,7 +84,7 @@ support-files =
[browser_dbg_break-on-dom-02.js]
[browser_dbg_break-on-dom-03.js]
[browser_dbg_break-on-dom-04.js]
# [browser_dbg_break-on-dom-05.js]
[browser_dbg_break-on-dom-05.js]
[browser_dbg_break-on-dom-06.js]
[browser_dbg_break-on-dom-07.js]
[browser_dbg_break-on-dom-08.js]

Просмотреть файл

@ -44,6 +44,13 @@ browser.jar:
content/browser/devtools/codemirror/search.js (sourceeditor/codemirror/search/search.js)
content/browser/devtools/codemirror/dialog.js (sourceeditor/codemirror/dialog/dialog.js)
content/browser/devtools/codemirror/dialog.css (sourceeditor/codemirror/dialog/dialog.css)
content/browser/devtools/codemirror/emacs.js (sourceeditor/codemirror/keymap/emacs.js)
content/browser/devtools/codemirror/vim.js (sourceeditor/codemirror/keymap/vim.js)
content/browser/devtools/codemirror/foldcode.js (sourceeditor/codemirror/fold/foldcode.js)
content/browser/devtools/codemirror/brace-fold.js (sourceeditor/codemirror/fold/brace-fold.js)
content/browser/devtools/codemirror/comment-fold.js (sourceeditor/codemirror/fold/comment-fold.js)
content/browser/devtools/codemirror/xml-fold.js (sourceeditor/codemirror/fold/xml-fold.js)
content/browser/devtools/codemirror/foldgutter.js (sourceeditor/codemirror/fold/foldgutter.js)
content/browser/devtools/codemirror/mozilla.css (sourceeditor/codemirror/mozilla.css)
content/browser/devtools/debugger.xul (debugger/debugger.xul)
content/browser/devtools/debugger.css (debugger/debugger.css)

Просмотреть файл

@ -30,6 +30,7 @@ const SCRATCHPAD_L10N = "chrome://browser/locale/devtools/scratchpad.properties"
const DEVTOOLS_CHROME_ENABLED = "devtools.chrome.enabled";
const PREF_RECENT_FILES_MAX = "devtools.scratchpad.recentFilesMax";
const SHOW_TRAILING_SPACE = "devtools.scratchpad.showTrailingSpace";
const ENABLE_CODE_FOLDING = "devtools.scratchpad.enableCodeFolding";
const VARIABLES_VIEW_URL = "chrome://browser/content/devtools/widgets/VariablesView.xul";
@ -1484,18 +1485,25 @@ var Scratchpad = {
this._instanceId = ScratchpadManager.createUid();
}
this.editor = new Editor({
let config = {
mode: Editor.modes.js,
value: initialText,
lineNumbers: true,
showTrailingSpace: Services.prefs.getBoolPref(SHOW_TRAILING_SPACE),
contextMenu: "scratchpad-text-popup"
});
};
if (Services.prefs.getBoolPref(ENABLE_CODE_FOLDING)) {
config.foldGutter = true;
config.gutters = ["CodeMirror-linenumbers", "CodeMirror-foldgutter"];
}
this.editor = new Editor(config);
this.editor.appendTo(document.querySelector("#scratchpad-editor")).then(() => {
var lines = initialText.split("\n");
this.editor.on("change", this._onChanged);
this.editor.on("save", () => this.saveFile());
this.editor.focus();
this.editor.setCursor({ line: lines.length, ch: lines.pop().length });

Просмотреть файл

@ -9,6 +9,7 @@ support-files =
[browser_se_aaa_run_first_leaktest.js]
[browser_se_bfcache.js]
skip-if = true # Bug 942473, caused by Bug 940541
[browser_se_editors-contents.js]
[browser_se_editors-error-gutter.js]
[browser_se_editors-error-tooltip.js]

Просмотреть файл

@ -10,18 +10,19 @@ function ifWebGLSupported() {
let { gFront, $, EVENTS, ShadersListView, ShadersEditorsView } = panel.panelWin;
let reloaded = reload(target);
yield once(gFront, "program-linked");
let firstProgram = yield once(gFront, "program-linked");
yield reloaded;
let navigated = navigate(target, MULTIPLE_CONTEXTS_URL);
yield getPrograms(gFront, 2);
let [secondProgram, thirdProgram] = yield getPrograms(gFront, 2);
yield navigated;
let vsEditor = yield ShadersEditorsView._getEditor("vs");
let fsEditor = yield ShadersEditorsView._getEditor("fs");
yield navigateInHistory(target, "back", "will-navigate");
yield waitForSources();
yield once(panel.panelWin, EVENTS.PROGRAMS_ADDED);
yield once(panel.panelWin, EVENTS.SOURCES_SHOWN);
is($("#content").hidden, false,
"The tool's content should not be hidden.");
@ -36,7 +37,8 @@ function ifWebGLSupported() {
"The fragment shader editor contains the correct text.");
yield navigateInHistory(target, "forward", "will-navigate");
yield waitForSources();
yield once(panel.panelWin, EVENTS.PROGRAMS_ADDED);
yield once(panel.panelWin, EVENTS.SOURCES_SHOWN);
is($("#content").hidden, false,
"The tool's content should not be hidden.");
@ -52,18 +54,4 @@ function ifWebGLSupported() {
yield teardown(panel);
finish();
function waitForSources() {
let deferred = promise.defer();
let win = panel.panelWin;
// These events must fire in this in order and the second event fires
// synchronously after the first event, so we can't use Promise.all and the
// `once` helper.
win.once(win.EVENTS.PROGRAMS_ADDED, () => {
win.once(win.EVENTS.SOURCES_SHOWN, () => {
deferred.resolve();
});
});
return deferred.promise;
}
}

Просмотреть файл

@ -39,6 +39,13 @@ in the LICENSE file:
* comment.js
* dialog/dialog.css
* dialog/dialog.js
* keymap/emacs.js
* keymap/vim.js
* fold/foldcode.js
* fold/brace-fold.js
* fold/comment-fold.js
* fold/xml-fold.js
* fold/foldgutter.js
* xml.js
* css.js
* javascript.js

Просмотреть файл

@ -0,0 +1,93 @@
CodeMirror.registerHelper("fold", "brace", function(cm, start) {
var line = start.line, lineText = cm.getLine(line);
var startCh, tokenType;
function findOpening(openCh) {
for (var at = start.ch, pass = 0;;) {
var found = at <= 0 ? -1 : lineText.lastIndexOf(openCh, at - 1);
if (found == -1) {
if (pass == 1) break;
pass = 1;
at = lineText.length;
continue;
}
if (pass == 1 && found < start.ch) break;
tokenType = cm.getTokenTypeAt(CodeMirror.Pos(line, found + 1));
if (!/^(comment|string)/.test(tokenType)) return found + 1;
at = found - 1;
}
}
var startToken = "{", endToken = "}", startCh = findOpening("{");
if (startCh == null) {
startToken = "[", endToken = "]";
startCh = findOpening("[");
}
if (startCh == null) return;
var count = 1, lastLine = cm.lastLine(), end, endCh;
outer: for (var i = line; i <= lastLine; ++i) {
var text = cm.getLine(i), pos = i == line ? startCh : 0;
for (;;) {
var nextOpen = text.indexOf(startToken, pos), nextClose = text.indexOf(endToken, pos);
if (nextOpen < 0) nextOpen = text.length;
if (nextClose < 0) nextClose = text.length;
pos = Math.min(nextOpen, nextClose);
if (pos == text.length) break;
if (cm.getTokenTypeAt(CodeMirror.Pos(i, pos + 1)) == tokenType) {
if (pos == nextOpen) ++count;
else if (!--count) { end = i; endCh = pos; break outer; }
}
++pos;
}
}
if (end == null || line == end && endCh == startCh) return;
return {from: CodeMirror.Pos(line, startCh),
to: CodeMirror.Pos(end, endCh)};
});
CodeMirror.braceRangeFinder = CodeMirror.fold.brace; // deprecated
CodeMirror.registerHelper("fold", "import", function(cm, start) {
function hasImport(line) {
if (line < cm.firstLine() || line > cm.lastLine()) return null;
var start = cm.getTokenAt(CodeMirror.Pos(line, 1));
if (!/\S/.test(start.string)) start = cm.getTokenAt(CodeMirror.Pos(line, start.end + 1));
if (start.type != "keyword" || start.string != "import") return null;
// Now find closing semicolon, return its position
for (var i = line, e = Math.min(cm.lastLine(), line + 10); i <= e; ++i) {
var text = cm.getLine(i), semi = text.indexOf(";");
if (semi != -1) return {startCh: start.end, end: CodeMirror.Pos(i, semi)};
}
}
var start = start.line, has = hasImport(start), prev;
if (!has || hasImport(start - 1) || ((prev = hasImport(start - 2)) && prev.end.line == start - 1))
return null;
for (var end = has.end;;) {
var next = hasImport(end.line + 1);
if (next == null) break;
end = next.end;
}
return {from: cm.clipPos(CodeMirror.Pos(start, has.startCh + 1)), to: end};
});
CodeMirror.importRangeFinder = CodeMirror.fold["import"]; // deprecated
CodeMirror.registerHelper("fold", "include", function(cm, start) {
function hasInclude(line) {
if (line < cm.firstLine() || line > cm.lastLine()) return null;
var start = cm.getTokenAt(CodeMirror.Pos(line, 1));
if (!/\S/.test(start.string)) start = cm.getTokenAt(CodeMirror.Pos(line, start.end + 1));
if (start.type == "meta" && start.string.slice(0, 8) == "#include") return start.start + 8;
}
var start = start.line, has = hasInclude(start);
if (has == null || hasInclude(start - 1) != null) return null;
for (var end = start;;) {
var next = hasInclude(end + 1);
if (next == null) break;
++end;
}
return {from: CodeMirror.Pos(start, has + 1),
to: cm.clipPos(CodeMirror.Pos(end))};
});
CodeMirror.includeRangeFinder = CodeMirror.fold.include; // deprecated

Просмотреть файл

@ -0,0 +1,40 @@
CodeMirror.registerHelper("fold", "comment", function(cm, start) {
var mode = cm.getModeAt(start), startToken = mode.blockCommentStart, endToken = mode.blockCommentEnd;
if (!startToken || !endToken) return;
var line = start.line, lineText = cm.getLine(line);
var startCh;
for (var at = start.ch, pass = 0;;) {
var found = at <= 0 ? -1 : lineText.lastIndexOf(startToken, at - 1);
if (found == -1) {
if (pass == 1) return;
pass = 1;
at = lineText.length;
continue;
}
if (pass == 1 && found < start.ch) return;
if (/comment/.test(cm.getTokenTypeAt(CodeMirror.Pos(line, found + 1)))) {
startCh = found + startToken.length;
break;
}
at = found - 1;
}
var depth = 1, lastLine = cm.lastLine(), end, endCh;
outer: for (var i = line; i <= lastLine; ++i) {
var text = cm.getLine(i), pos = i == line ? startCh : 0;
for (;;) {
var nextOpen = text.indexOf(startToken, pos), nextClose = text.indexOf(endToken, pos);
if (nextOpen < 0) nextOpen = text.length;
if (nextClose < 0) nextClose = text.length;
pos = Math.min(nextOpen, nextClose);
if (pos == text.length) break;
if (pos == nextOpen) ++depth;
else if (!--depth) { end = i; endCh = pos; break outer; }
++pos;
}
}
if (end == null || line == end && endCh == startCh) return;
return {from: CodeMirror.Pos(line, startCh),
to: CodeMirror.Pos(end, endCh)};
});

Просмотреть файл

@ -0,0 +1,75 @@
(function() {
"use strict";
function doFold(cm, pos, options, force) {
var finder = options && (options.call ? options : options.rangeFinder);
if (!finder) finder = cm.getHelper(pos, "fold");
if (!finder) return;
if (typeof pos == "number") pos = CodeMirror.Pos(pos, 0);
var minSize = options && options.minFoldSize || 0;
function getRange(allowFolded) {
var range = finder(cm, pos);
if (!range || range.to.line - range.from.line < minSize) return null;
var marks = cm.findMarksAt(range.from);
for (var i = 0; i < marks.length; ++i) {
if (marks[i].__isFold && force !== "fold") {
if (!allowFolded) return null;
range.cleared = true;
marks[i].clear();
}
}
return range;
}
var range = getRange(true);
if (options && options.scanUp) while (!range && pos.line > cm.firstLine()) {
pos = CodeMirror.Pos(pos.line - 1, 0);
range = getRange(false);
}
if (!range || range.cleared || force === "unfold") return;
var myWidget = makeWidget(options);
CodeMirror.on(myWidget, "mousedown", function() { myRange.clear(); });
var myRange = cm.markText(range.from, range.to, {
replacedWith: myWidget,
clearOnEnter: true,
__isFold: true
});
myRange.on("clear", function(from, to) {
CodeMirror.signal(cm, "unfold", cm, from, to);
});
CodeMirror.signal(cm, "fold", cm, range.from, range.to);
}
function makeWidget(options) {
var widget = (options && options.widget) || "\u2194";
if (typeof widget == "string") {
var text = document.createTextNode(widget);
widget = document.createElement("span");
widget.appendChild(text);
widget.className = "CodeMirror-foldmarker";
}
return widget;
}
// Clumsy backwards-compatible interface
CodeMirror.newFoldFunction = function(rangeFinder, widget) {
return function(cm, pos) { doFold(cm, pos, {rangeFinder: rangeFinder, widget: widget}); };
};
// New-style interface
CodeMirror.defineExtension("foldCode", function(pos, options, force) {
doFold(this, pos, options, force);
});
CodeMirror.registerHelper("fold", "combine", function() {
var funcs = Array.prototype.slice.call(arguments, 0);
return function(cm, start) {
for (var i = 0; i < funcs.length; ++i) {
var found = funcs[i](cm, start);
if (found) return found;
}
};
});
})();

Просмотреть файл

@ -0,0 +1,124 @@
(function() {
"use strict";
CodeMirror.defineOption("foldGutter", false, function(cm, val, old) {
if (old && old != CodeMirror.Init) {
cm.clearGutter(cm.state.foldGutter.options.gutter);
cm.state.foldGutter = null;
cm.off("gutterClick", onGutterClick);
cm.off("change", onChange);
cm.off("viewportChange", onViewportChange);
cm.off("fold", onFold);
cm.off("unfold", onFold);
cm.off("swapDoc", updateInViewport);
}
if (val) {
cm.state.foldGutter = new State(parseOptions(val));
updateInViewport(cm);
cm.on("gutterClick", onGutterClick);
cm.on("change", onChange);
cm.on("viewportChange", onViewportChange);
cm.on("fold", onFold);
cm.on("unfold", onFold);
cm.on("swapDoc", updateInViewport);
}
});
var Pos = CodeMirror.Pos;
function State(options) {
this.options = options;
this.from = this.to = 0;
}
function parseOptions(opts) {
if (opts === true) opts = {};
if (opts.gutter == null) opts.gutter = "CodeMirror-foldgutter";
if (opts.indicatorOpen == null) opts.indicatorOpen = "CodeMirror-foldgutter-open";
if (opts.indicatorFolded == null) opts.indicatorFolded = "CodeMirror-foldgutter-folded";
return opts;
}
function isFolded(cm, line) {
var marks = cm.findMarksAt(Pos(line));
for (var i = 0; i < marks.length; ++i)
if (marks[i].__isFold && marks[i].find().from.line == line) return true;
}
function marker(spec) {
if (typeof spec == "string") {
var elt = document.createElement("div");
elt.className = spec;
return elt;
} else {
return spec.cloneNode(true);
}
}
function updateFoldInfo(cm, from, to) {
var opts = cm.state.foldGutter.options, cur = from;
cm.eachLine(from, to, function(line) {
var mark = null;
if (isFolded(cm, cur)) {
mark = marker(opts.indicatorFolded);
} else {
var pos = Pos(cur, 0), func = opts.rangeFinder || cm.getHelper(pos, "fold");
var range = func && func(cm, pos);
if (range && range.from.line + 1 < range.to.line)
mark = marker(opts.indicatorOpen);
}
cm.setGutterMarker(line, opts.gutter, mark);
++cur;
});
}
function updateInViewport(cm) {
var vp = cm.getViewport(), state = cm.state.foldGutter;
if (!state) return;
cm.operation(function() {
updateFoldInfo(cm, vp.from, vp.to);
});
state.from = vp.from; state.to = vp.to;
}
function onGutterClick(cm, line, gutter) {
var opts = cm.state.foldGutter.options;
if (gutter != opts.gutter) return;
cm.foldCode(Pos(line, 0), opts.rangeFinder);
}
function onChange(cm) {
var state = cm.state.foldGutter, opts = cm.state.foldGutter.options;
state.from = state.to = 0;
clearTimeout(state.changeUpdate);
state.changeUpdate = setTimeout(function() { updateInViewport(cm); }, opts.foldOnChangeTimeSpan || 600);
}
function onViewportChange(cm) {
var state = cm.state.foldGutter, opts = cm.state.foldGutter.options;
clearTimeout(state.changeUpdate);
state.changeUpdate = setTimeout(function() {
var vp = cm.getViewport();
if (state.from == state.to || vp.from - state.to > 20 || state.from - vp.to > 20) {
updateInViewport(cm);
} else {
cm.operation(function() {
if (vp.from < state.from) {
updateFoldInfo(cm, vp.from, state.from);
state.from = vp.from;
}
if (vp.to > state.to) {
updateFoldInfo(cm, state.to, vp.to);
state.to = vp.to;
}
});
}
}, opts.updateViewportTimeSpan || 400);
}
function onFold(cm, from) {
var state = cm.state.foldGutter, line = from.line;
if (line >= state.from && line < state.to)
updateFoldInfo(cm, line, line + 1);
}
})();

Просмотреть файл

@ -0,0 +1,167 @@
(function() {
"use strict";
var Pos = CodeMirror.Pos;
function cmp(a, b) { return a.line - b.line || a.ch - b.ch; }
var nameStartChar = "A-Z_a-z\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\u02FF\\u0370-\\u037D\\u037F-\\u1FFF\\u200C-\\u200D\\u2070-\\u218F\\u2C00-\\u2FEF\\u3001-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFFD";
var nameChar = nameStartChar + "\-\:\.0-9\\u00B7\\u0300-\\u036F\\u203F-\\u2040";
var xmlTagStart = new RegExp("<(/?)([" + nameStartChar + "][" + nameChar + "]*)", "g");
function Iter(cm, line, ch, range) {
this.line = line; this.ch = ch;
this.cm = cm; this.text = cm.getLine(line);
this.min = range ? range.from : cm.firstLine();
this.max = range ? range.to - 1 : cm.lastLine();
}
function tagAt(iter, ch) {
var type = iter.cm.getTokenTypeAt(Pos(iter.line, ch));
return type && /\btag\b/.test(type);
}
function nextLine(iter) {
if (iter.line >= iter.max) return;
iter.ch = 0;
iter.text = iter.cm.getLine(++iter.line);
return true;
}
function prevLine(iter) {
if (iter.line <= iter.min) return;
iter.text = iter.cm.getLine(--iter.line);
iter.ch = iter.text.length;
return true;
}
function toTagEnd(iter) {
for (;;) {
var gt = iter.text.indexOf(">", iter.ch);
if (gt == -1) { if (nextLine(iter)) continue; else return; }
if (!tagAt(iter, gt + 1)) { iter.ch = gt + 1; continue; }
var lastSlash = iter.text.lastIndexOf("/", gt);
var selfClose = lastSlash > -1 && !/\S/.test(iter.text.slice(lastSlash + 1, gt));
iter.ch = gt + 1;
return selfClose ? "selfClose" : "regular";
}
}
function toTagStart(iter) {
for (;;) {
var lt = iter.ch ? iter.text.lastIndexOf("<", iter.ch - 1) : -1;
if (lt == -1) { if (prevLine(iter)) continue; else return; }
if (!tagAt(iter, lt + 1)) { iter.ch = lt; continue; }
xmlTagStart.lastIndex = lt;
iter.ch = lt;
var match = xmlTagStart.exec(iter.text);
if (match && match.index == lt) return match;
}
}
function toNextTag(iter) {
for (;;) {
xmlTagStart.lastIndex = iter.ch;
var found = xmlTagStart.exec(iter.text);
if (!found) { if (nextLine(iter)) continue; else return; }
if (!tagAt(iter, found.index + 1)) { iter.ch = found.index + 1; continue; }
iter.ch = found.index + found[0].length;
return found;
}
}
function toPrevTag(iter) {
for (;;) {
var gt = iter.ch ? iter.text.lastIndexOf(">", iter.ch - 1) : -1;
if (gt == -1) { if (prevLine(iter)) continue; else return; }
if (!tagAt(iter, gt + 1)) { iter.ch = gt; continue; }
var lastSlash = iter.text.lastIndexOf("/", gt);
var selfClose = lastSlash > -1 && !/\S/.test(iter.text.slice(lastSlash + 1, gt));
iter.ch = gt + 1;
return selfClose ? "selfClose" : "regular";
}
}
function findMatchingClose(iter, tag) {
var stack = [];
for (;;) {
var next = toNextTag(iter), end, startLine = iter.line, startCh = iter.ch - (next ? next[0].length : 0);
if (!next || !(end = toTagEnd(iter))) return;
if (end == "selfClose") continue;
if (next[1]) { // closing tag
for (var i = stack.length - 1; i >= 0; --i) if (stack[i] == next[2]) {
stack.length = i;
break;
}
if (i < 0 && (!tag || tag == next[2])) return {
tag: next[2],
from: Pos(startLine, startCh),
to: Pos(iter.line, iter.ch)
};
} else { // opening tag
stack.push(next[2]);
}
}
}
function findMatchingOpen(iter, tag) {
var stack = [];
for (;;) {
var prev = toPrevTag(iter);
if (!prev) return;
if (prev == "selfClose") { toTagStart(iter); continue; }
var endLine = iter.line, endCh = iter.ch;
var start = toTagStart(iter);
if (!start) return;
if (start[1]) { // closing tag
stack.push(start[2]);
} else { // opening tag
for (var i = stack.length - 1; i >= 0; --i) if (stack[i] == start[2]) {
stack.length = i;
break;
}
if (i < 0 && (!tag || tag == start[2])) return {
tag: start[2],
from: Pos(iter.line, iter.ch),
to: Pos(endLine, endCh)
};
}
}
}
CodeMirror.registerHelper("fold", "xml", function(cm, start) {
var iter = new Iter(cm, start.line, 0);
for (;;) {
var openTag = toNextTag(iter), end;
if (!openTag || iter.line != start.line || !(end = toTagEnd(iter))) return;
if (!openTag[1] && end != "selfClose") {
var start = Pos(iter.line, iter.ch);
var close = findMatchingClose(iter, openTag[2]);
return close && {from: start, to: close.from};
}
}
});
CodeMirror.tagRangeFinder = CodeMirror.fold.xml; // deprecated
CodeMirror.findMatchingTag = function(cm, pos, range) {
var iter = new Iter(cm, pos.line, pos.ch, range);
if (iter.text.indexOf(">") == -1 && iter.text.indexOf("<") == -1) return;
var end = toTagEnd(iter), to = end && Pos(iter.line, iter.ch);
var start = end && toTagStart(iter);
if (!end || end == "selfClose" || !start || cmp(iter, pos) > 0) return;
var here = {from: Pos(iter.line, iter.ch), to: to, tag: start[2]};
if (start[1]) { // closing tag
return {open: findMatchingOpen(iter, start[2]), close: here, at: "close"};
} else { // opening tag
iter = new Iter(cm, to.line, to.ch, range);
return {open: here, close: findMatchingClose(iter, start[2]), at: "open"};
}
};
CodeMirror.findEnclosingTag = function(cm, pos, range) {
var iter = new Iter(cm, pos.line, pos.ch, range);
for (;;) {
var open = findMatchingOpen(iter);
if (!open) break;
var forward = new Iter(cm, pos.line, pos.ch, range);
var close = findMatchingClose(forward, open.tag);
if (close) return {open: open, close: close};
}
};
})();

387
browser/devtools/sourceeditor/codemirror/keymap/emacs.js поставляемый Normal file
Просмотреть файл

@ -0,0 +1,387 @@
(function() {
"use strict";
var Pos = CodeMirror.Pos;
function posEq(a, b) { return a.line == b.line && a.ch == b.ch; }
// Kill 'ring'
var killRing = [];
function addToRing(str) {
killRing.push(str);
if (killRing.length > 50) killRing.shift();
}
function growRingTop(str) {
if (!killRing.length) return addToRing(str);
killRing[killRing.length - 1] += str;
}
function getFromRing(n) { return killRing[killRing.length - (n ? Math.min(n, 1) : 1)] || ""; }
function popFromRing() { if (killRing.length > 1) killRing.pop(); return getFromRing(); }
var lastKill = null;
function kill(cm, from, to, mayGrow, text) {
if (text == null) text = cm.getRange(from, to);
if (mayGrow && lastKill && lastKill.cm == cm && posEq(from, lastKill.pos) && cm.isClean(lastKill.gen))
growRingTop(text);
else
addToRing(text);
cm.replaceRange("", from, to, "+delete");
if (mayGrow) lastKill = {cm: cm, pos: from, gen: cm.changeGeneration()};
else lastKill = null;
}
// Boundaries of various units
function byChar(cm, pos, dir) {
return cm.findPosH(pos, dir, "char", true);
}
function byWord(cm, pos, dir) {
return cm.findPosH(pos, dir, "word", true);
}
function byLine(cm, pos, dir) {
return cm.findPosV(pos, dir, "line", cm.doc.sel.goalColumn);
}
function byPage(cm, pos, dir) {
return cm.findPosV(pos, dir, "page", cm.doc.sel.goalColumn);
}
function byParagraph(cm, pos, dir) {
var no = pos.line, line = cm.getLine(no);
var sawText = /\S/.test(dir < 0 ? line.slice(0, pos.ch) : line.slice(pos.ch));
var fst = cm.firstLine(), lst = cm.lastLine();
for (;;) {
no += dir;
if (no < fst || no > lst)
return cm.clipPos(Pos(no - dir, dir < 0 ? 0 : null));
line = cm.getLine(no);
var hasText = /\S/.test(line);
if (hasText) sawText = true;
else if (sawText) return Pos(no, 0);
}
}
function bySentence(cm, pos, dir) {
var line = pos.line, ch = pos.ch;
var text = cm.getLine(pos.line), sawWord = false;
for (;;) {
var next = text.charAt(ch + (dir < 0 ? -1 : 0));
if (!next) { // End/beginning of line reached
if (line == (dir < 0 ? cm.firstLine() : cm.lastLine())) return Pos(line, ch);
text = cm.getLine(line + dir);
if (!/\S/.test(text)) return Pos(line, ch);
line += dir;
ch = dir < 0 ? text.length : 0;
continue;
}
if (sawWord && /[!?.]/.test(next)) return Pos(line, ch + (dir > 0 ? 1 : 0));
if (!sawWord) sawWord = /\w/.test(next);
ch += dir;
}
}
function byExpr(cm, pos, dir) {
var wrap;
if (cm.findMatchingBracket && (wrap = cm.findMatchingBracket(pos, true))
&& wrap.match && (wrap.forward ? 1 : -1) == dir)
return dir > 0 ? Pos(wrap.to.line, wrap.to.ch + 1) : wrap.to;
for (var first = true;; first = false) {
var token = cm.getTokenAt(pos);
var after = Pos(pos.line, dir < 0 ? token.start : token.end);
if (first && dir > 0 && token.end == pos.ch || !/\w/.test(token.string)) {
var newPos = cm.findPosH(after, dir, "char");
if (posEq(after, newPos)) return pos;
else pos = newPos;
} else {
return after;
}
}
}
// Prefixes (only crudely supported)
function getPrefix(cm, precise) {
var digits = cm.state.emacsPrefix;
if (!digits) return precise ? null : 1;
clearPrefix(cm);
return digits == "-" ? -1 : Number(digits);
}
function repeated(cmd) {
var f = typeof cmd == "string" ? function(cm) { cm.execCommand(cmd); } : cmd;
return function(cm) {
var prefix = getPrefix(cm);
f(cm);
for (var i = 1; i < prefix; ++i) f(cm);
};
}
function findEnd(cm, by, dir) {
var pos = cm.getCursor(), prefix = getPrefix(cm);
if (prefix < 0) { dir = -dir; prefix = -prefix; }
for (var i = 0; i < prefix; ++i) {
var newPos = by(cm, pos, dir);
if (posEq(newPos, pos)) break;
pos = newPos;
}
return pos;
}
function move(by, dir) {
var f = function(cm) {
cm.extendSelection(findEnd(cm, by, dir));
};
f.motion = true;
return f;
}
function killTo(cm, by, dir) {
kill(cm, cm.getCursor(), findEnd(cm, by, dir), true);
}
function addPrefix(cm, digit) {
if (cm.state.emacsPrefix) {
if (digit != "-") cm.state.emacsPrefix += digit;
return;
}
// Not active yet
cm.state.emacsPrefix = digit;
cm.on("keyHandled", maybeClearPrefix);
cm.on("inputRead", maybeDuplicateInput);
}
var prefixPreservingKeys = {"Alt-G": true, "Ctrl-X": true, "Ctrl-Q": true, "Ctrl-U": true};
function maybeClearPrefix(cm, arg) {
if (!cm.state.emacsPrefixMap && !prefixPreservingKeys.hasOwnProperty(arg))
clearPrefix(cm);
}
function clearPrefix(cm) {
cm.state.emacsPrefix = null;
cm.off("keyHandled", maybeClearPrefix);
cm.off("inputRead", maybeDuplicateInput);
}
function maybeDuplicateInput(cm, event) {
var dup = getPrefix(cm);
if (dup > 1 && event.origin == "+input") {
var one = event.text.join("\n"), txt = "";
for (var i = 1; i < dup; ++i) txt += one;
cm.replaceSelection(txt, "end", "+input");
}
}
function addPrefixMap(cm) {
cm.state.emacsPrefixMap = true;
cm.addKeyMap(prefixMap);
cm.on("keyHandled", maybeRemovePrefixMap);
cm.on("inputRead", maybeRemovePrefixMap);
}
function maybeRemovePrefixMap(cm, arg) {
if (typeof arg == "string" && (/^\d$/.test(arg) || arg == "Ctrl-U")) return;
cm.removeKeyMap(prefixMap);
cm.state.emacsPrefixMap = false;
cm.off("keyHandled", maybeRemovePrefixMap);
cm.off("inputRead", maybeRemovePrefixMap);
}
// Utilities
function setMark(cm) {
cm.setCursor(cm.getCursor());
cm.setExtending(true);
cm.on("change", function() { cm.setExtending(false); });
}
function getInput(cm, msg, f) {
if (cm.openDialog)
cm.openDialog(msg + ": <input type=\"text\" style=\"width: 10em\"/>", f, {bottom: true});
else
f(prompt(msg, ""));
}
function operateOnWord(cm, op) {
var start = cm.getCursor(), end = cm.findPosH(start, 1, "word");
cm.replaceRange(op(cm.getRange(start, end)), start, end);
cm.setCursor(end);
}
function toEnclosingExpr(cm) {
var pos = cm.getCursor(), line = pos.line, ch = pos.ch;
var stack = [];
while (line >= cm.firstLine()) {
var text = cm.getLine(line);
for (var i = ch == null ? text.length : ch; i > 0;) {
var ch = text.charAt(--i);
if (ch == ")")
stack.push("(");
else if (ch == "]")
stack.push("[");
else if (ch == "}")
stack.push("{");
else if (/[\(\{\[]/.test(ch) && (!stack.length || stack.pop() != ch))
return cm.extendSelection(Pos(line, i));
}
--line; ch = null;
}
}
// Actual keymap
var keyMap = CodeMirror.keyMap.emacs = {
"Ctrl-W": function(cm) {kill(cm, cm.getCursor("start"), cm.getCursor("end"));},
"Ctrl-K": repeated(function(cm) {
var start = cm.getCursor(), end = cm.clipPos(Pos(start.line));
var text = cm.getRange(start, end);
if (!/\S/.test(text)) {
text += "\n";
end = Pos(start.line + 1, 0);
}
kill(cm, start, end, true, text);
}),
"Alt-W": function(cm) {
addToRing(cm.getSelection());
},
"Ctrl-Y": function(cm) {
var start = cm.getCursor();
cm.replaceRange(getFromRing(getPrefix(cm)), start, start, "paste");
cm.setSelection(start, cm.getCursor());
},
"Alt-Y": function(cm) {cm.replaceSelection(popFromRing());},
"Ctrl-Space": setMark, "Ctrl-Shift-2": setMark,
"Ctrl-F": move(byChar, 1), "Ctrl-B": move(byChar, -1),
"Right": move(byChar, 1), "Left": move(byChar, -1),
"Ctrl-D": function(cm) { killTo(cm, byChar, 1); },
"Delete": function(cm) { killTo(cm, byChar, 1); },
"Ctrl-H": function(cm) { killTo(cm, byChar, -1); },
"Backspace": function(cm) { killTo(cm, byChar, -1); },
"Alt-F": move(byWord, 1), "Alt-B": move(byWord, -1),
"Alt-D": function(cm) { killTo(cm, byWord, 1); },
"Alt-Backspace": function(cm) { killTo(cm, byWord, -1); },
"Ctrl-N": move(byLine, 1), "Ctrl-P": move(byLine, -1),
"Down": move(byLine, 1), "Up": move(byLine, -1),
"Ctrl-A": "goLineStart", "Ctrl-E": "goLineEnd",
"End": "goLineEnd", "Home": "goLineStart",
"Alt-V": move(byPage, -1), "Ctrl-V": move(byPage, 1),
"PageUp": move(byPage, -1), "PageDown": move(byPage, 1),
"Ctrl-Up": move(byParagraph, -1), "Ctrl-Down": move(byParagraph, 1),
"Alt-A": move(bySentence, -1), "Alt-E": move(bySentence, 1),
"Alt-K": function(cm) { killTo(cm, bySentence, 1); },
"Ctrl-Alt-K": function(cm) { killTo(cm, byExpr, 1); },
"Ctrl-Alt-Backspace": function(cm) { killTo(cm, byExpr, -1); },
"Ctrl-Alt-F": move(byExpr, 1), "Ctrl-Alt-B": move(byExpr, -1),
"Shift-Ctrl-Alt-2": function(cm) {
cm.setSelection(findEnd(cm, byExpr, 1), cm.getCursor());
},
"Ctrl-Alt-T": function(cm) {
var leftStart = byExpr(cm, cm.getCursor(), -1), leftEnd = byExpr(cm, leftStart, 1);
var rightEnd = byExpr(cm, leftEnd, 1), rightStart = byExpr(cm, rightEnd, -1);
cm.replaceRange(cm.getRange(rightStart, rightEnd) + cm.getRange(leftEnd, rightStart) +
cm.getRange(leftStart, leftEnd), leftStart, rightEnd);
},
"Ctrl-Alt-U": repeated(toEnclosingExpr),
"Alt-Space": function(cm) {
var pos = cm.getCursor(), from = pos.ch, to = pos.ch, text = cm.getLine(pos.line);
while (from && /\s/.test(text.charAt(from - 1))) --from;
while (to < text.length && /\s/.test(text.charAt(to))) ++to;
cm.replaceRange(" ", Pos(pos.line, from), Pos(pos.line, to));
},
"Ctrl-O": repeated(function(cm) { cm.replaceSelection("\n", "start"); }),
"Ctrl-T": repeated(function(cm) {
var pos = cm.getCursor();
if (pos.ch < cm.getLine(pos.line).length) pos = Pos(pos.line, pos.ch + 1);
var from = cm.findPosH(pos, -2, "char");
var range = cm.getRange(from, pos);
if (range.length != 2) return;
cm.setSelection(from, pos);
cm.replaceSelection(range.charAt(1) + range.charAt(0), "end");
}),
"Alt-C": repeated(function(cm) {
operateOnWord(cm, function(w) {
var letter = w.search(/\w/);
if (letter == -1) return w;
return w.slice(0, letter) + w.charAt(letter).toUpperCase() + w.slice(letter + 1).toLowerCase();
});
}),
"Alt-U": repeated(function(cm) {
operateOnWord(cm, function(w) { return w.toUpperCase(); });
}),
"Alt-L": repeated(function(cm) {
operateOnWord(cm, function(w) { return w.toLowerCase(); });
}),
"Alt-;": "toggleComment",
"Ctrl-/": repeated("undo"), "Shift-Ctrl--": repeated("undo"),
"Ctrl-Z": repeated("undo"), "Cmd-Z": repeated("undo"),
"Shift-Alt-,": "goDocStart", "Shift-Alt-.": "goDocEnd",
"Ctrl-S": "findNext", "Ctrl-R": "findPrev", "Ctrl-G": "clearSearch", "Shift-Alt-5": "replace",
"Alt-/": "autocomplete",
"Ctrl-J": "newlineAndIndent", "Enter": false, "Tab": "indentAuto",
"Alt-G": function(cm) {cm.setOption("keyMap", "emacs-Alt-G");},
"Ctrl-X": function(cm) {cm.setOption("keyMap", "emacs-Ctrl-X");},
"Ctrl-Q": function(cm) {cm.setOption("keyMap", "emacs-Ctrl-Q");},
"Ctrl-U": addPrefixMap
};
CodeMirror.keyMap["emacs-Ctrl-X"] = {
"Tab": function(cm) {
cm.indentSelection(getPrefix(cm, true) || cm.getOption("indentUnit"));
},
"Ctrl-X": function(cm) {
cm.setSelection(cm.getCursor("head"), cm.getCursor("anchor"));
},
"Ctrl-S": "save", "Ctrl-W": "save", "S": "saveAll", "F": "open", "U": repeated("undo"), "K": "close",
"Delete": function(cm) { kill(cm, cm.getCursor(), bySentence(cm, cm.getCursor(), 1), true); },
auto: "emacs", nofallthrough: true, disableInput: true
};
CodeMirror.keyMap["emacs-Alt-G"] = {
"G": function(cm) {
var prefix = getPrefix(cm, true);
if (prefix != null && prefix > 0) return cm.setCursor(prefix - 1);
getInput(cm, "Goto line", function(str) {
var num;
if (str && !isNaN(num = Number(str)) && num == num|0 && num > 0)
cm.setCursor(num - 1);
});
},
auto: "emacs", nofallthrough: true, disableInput: true
};
CodeMirror.keyMap["emacs-Ctrl-Q"] = {
"Tab": repeated("insertTab"),
auto: "emacs", nofallthrough: true
};
var prefixMap = {"Ctrl-G": clearPrefix};
function regPrefix(d) {
prefixMap[d] = function(cm) { addPrefix(cm, d); };
keyMap["Ctrl-" + d] = function(cm) { addPrefix(cm, d); };
prefixPreservingKeys["Ctrl-" + d] = true;
}
for (var i = 0; i < 10; ++i) regPrefix(String(i));
regPrefix("-");
})();

3703
browser/devtools/sourceeditor/codemirror/keymap/vim.js поставляемый Normal file

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -87,4 +87,34 @@ selector in floating-scrollbar-light.css across all platforms. */
opacity: 0.75;
background-position: left bottom;
background-repeat: repeat-x;
}
/* Fold addon */
.CodeMirror-foldmarker {
color: blue;
text-shadow: #b9f 1px 1px 2px, #b9f -1px -1px 2px, #b9f 1px -1px 2px, #b9f -1px 1px 2px;
font-family: sans-serif;
line-height: .3;
cursor: pointer;
}
.CodeMirror-foldgutter {
width: 16px; /* Same as breakpoints gutter above */
}
.CodeMirror-foldgutter-open,
.CodeMirror-foldgutter-folded {
color: #555;
cursor: pointer;
}
.CodeMirror-foldgutter-open:after {
font-size: 120%;
content: "\25BE";
}
.CodeMirror-foldgutter-folded:after {
font-size: 120%;
content: "\25B8";
}

Просмотреть файл

@ -9,6 +9,7 @@ const { Cu, Cc, Ci, components } = require("chrome");
const TAB_SIZE = "devtools.editor.tabsize";
const EXPAND_TAB = "devtools.editor.expandtab";
const KEYMAP = "devtools.editor.keymap";
const L10N_BUNDLE = "chrome://browser/locale/devtools/sourceeditor.properties";
const XUL_NS = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
@ -30,7 +31,8 @@ const CM_STYLES = [
"chrome://browser/skin/devtools/common.css",
"chrome://browser/content/devtools/codemirror/codemirror.css",
"chrome://browser/content/devtools/codemirror/dialog.css",
"chrome://browser/content/devtools/codemirror/mozilla.css"
"chrome://browser/content/devtools/codemirror/mozilla.css",
"chrome://browser/content/devtools/codemirror/foldgutter.css"
];
const CM_SCRIPTS = [
@ -48,7 +50,14 @@ const CM_SCRIPTS = [
"chrome://browser/content/devtools/codemirror/htmlmixed.js",
"chrome://browser/content/devtools/codemirror/clike.js",
"chrome://browser/content/devtools/codemirror/activeline.js",
"chrome://browser/content/devtools/codemirror/trailingspace.js"
"chrome://browser/content/devtools/codemirror/trailingspace.js",
"chrome://browser/content/devtools/codemirror/emacs.js",
"chrome://browser/content/devtools/codemirror/vim.js",
"chrome://browser/content/devtools/codemirror/foldcode.js",
"chrome://browser/content/devtools/codemirror/brace-fold.js",
"chrome://browser/content/devtools/codemirror/comment-fold.js",
"chrome://browser/content/devtools/codemirror/xml-fold.js",
"chrome://browser/content/devtools/codemirror/foldgutter.js"
];
const CM_IFRAME =
@ -121,6 +130,7 @@ Editor.modes = {
function Editor(config) {
const tabSize = Services.prefs.getIntPref(TAB_SIZE);
const useTabs = !Services.prefs.getBoolPref(EXPAND_TAB);
const keyMap = Services.prefs.getCharPref(KEYMAP);
this.version = null;
this.config = {
@ -147,6 +157,10 @@ function Editor(config) {
this.config.extraKeys[Editor.keyFor("indentLess")] = false;
this.config.extraKeys[Editor.keyFor("indentMore")] = false;
// If alternative keymap is provided, use it.
if (keyMap === "emacs" || keyMap === "vim")
this.config.keyMap = keyMap;
// Overwrite default config with user-provided, if needed.
Object.keys(config).forEach((k) => {
if (k != "extraKeys") {
@ -234,6 +248,8 @@ Editor.prototype = {
scssSpec.valueKeywords = cssValues;
win.CodeMirror.defineMIME("text/x-scss", scssSpec);
win.CodeMirror.commands.save = () => this.emit("save");
// Create a CodeMirror instance add support for context menus,
// overwrite the default controller (otherwise items in the top and
// context menus won't work).

Просмотреть файл

@ -6,7 +6,10 @@ support-files =
cm_mode_test.css
cm_mode_test.js
cm_test.js
cm_emacs_test.js
cm_vim_test.js
codemirror.html
vimemacs.html
head.js
[browser_editor_basic.js]
@ -16,4 +19,5 @@ support-files =
[browser_editor_movelines.js]
[browser_editor_addons.js]
[browser_codemirror.js]
[browser_vimemacs.js]
[browser_sourceeditor_initialization.js]

Просмотреть файл

@ -5,6 +5,7 @@
function test() {
waitForExplicitFinish();
setup((ed, win) => {
let doc = win.document.querySelector("iframe").contentWindow.document;
@ -15,6 +16,19 @@ function test() {
ed.setOption("showTrailingSpace", true);
ok(doc.querySelector(".cm-trailingspace"));
teardown(ed, win);
// foldcode.js and foldgutter.js
ed.setMode(Editor.modes.js);
ed.setText("function main() {\nreturn 'Hello, World!';\n}");
executeSoon(() => testFold(doc, ed, win));
});
}
function testFold(doc, ed, win) {
// Wait until folding arrow is there.
if (!doc.querySelector(".CodeMirror-foldgutter-open")) {
executeSoon(() => testFold(doc, ed, win));
return;
}
teardown(ed, win);
}

Просмотреть файл

@ -0,0 +1,34 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
"use strict";
const HOST = 'mochi.test:8888';
const URI = "http://" + HOST + "/browser/browser/devtools/sourceeditor/test/vimemacs.html";
function test() {
requestLongerTimeout(3);
waitForExplicitFinish();
let tab = gBrowser.addTab();
gBrowser.selectedTab = tab;
let browser = gBrowser.getBrowserForTab(tab);
browser.loadURI(URI);
function check() {
var win = browser.contentWindow.wrappedJSObject;
var doc = win.document;
var out = doc.getElementById("status");
if (!out || !out.classList.contains("done"))
return void setTimeout(check, 100);
ok(!win.failed, "CodeMirror tests all passed");
while (gBrowser.tabs.length > 1) gBrowser.removeCurrentTab();
finish();
}
setTimeout(check, 100);
}

Просмотреть файл

@ -0,0 +1,135 @@
(function() {
"use strict";
var Pos = CodeMirror.Pos;
namespace = "emacs_";
var eventCache = {};
function fakeEvent(keyName) {
var event = eventCache[key];
if (event) return event;
var ctrl, shift, alt;
var key = keyName.replace(/\w+-/g, function(type) {
if (type == "Ctrl-") ctrl = true;
else if (type == "Alt-") alt = true;
else if (type == "Shift-") shift = true;
return "";
});
var code;
for (var c in CodeMirror.keyNames)
if (CodeMirror.keyNames[c] == key) { code = c; break; }
if (c == null) throw new Error("Unknown key: " + key);
return eventCache[keyName] = {
type: "keydown", keyCode: code, ctrlKey: ctrl, shiftKey: shift, altKey: alt,
preventDefault: function(){}, stopPropagation: function(){}
};
}
function sim(name, start /*, actions... */) {
var keys = Array.prototype.slice.call(arguments, 2);
testCM(name, function(cm) {
for (var i = 0; i < keys.length; ++i) {
var cur = keys[i];
if (cur instanceof Pos) cm.setCursor(cur);
else if (cur.call) cur(cm);
else cm.triggerOnKeyDown(fakeEvent(cur));
}
}, {keyMap: "emacs", value: start, mode: "javascript"});
}
function at(line, ch) { return function(cm) { eqPos(cm.getCursor(), Pos(line, ch)); }; }
function txt(str) { return function(cm) { eq(cm.getValue(), str); }; }
sim("motionHSimple", "abc", "Ctrl-F", "Ctrl-F", "Ctrl-B", at(0, 1));
sim("motionHMulti", "abcde",
"Ctrl-4", "Ctrl-F", at(0, 4), "Ctrl--", "Ctrl-2", "Ctrl-F", at(0, 2),
"Ctrl-5", "Ctrl-B", at(0, 0));
sim("motionHWord", "abc. def ghi",
"Alt-F", at(0, 3), "Alt-F", at(0, 8),
"Ctrl-B", "Alt-B", at(0, 5), "Alt-B", at(0, 0));
sim("motionHWordMulti", "abc. def ghi ",
"Ctrl-3", "Alt-F", at(0, 12), "Ctrl-2", "Alt-B", at(0, 5),
"Ctrl--", "Alt-B", at(0, 8));
sim("motionVSimple", "a\nb\nc\n", "Ctrl-N", "Ctrl-N", "Ctrl-P", at(1, 0));
sim("motionVMulti", "a\nb\nc\nd\ne\n",
"Ctrl-2", "Ctrl-N", at(2, 0), "Ctrl-F", "Ctrl--", "Ctrl-N", at(1, 1),
"Ctrl--", "Ctrl-3", "Ctrl-P", at(4, 1));
sim("killYank", "abc\ndef\nghi",
"Ctrl-F", "Ctrl-Space", "Ctrl-N", "Ctrl-N", "Ctrl-W", "Ctrl-E", "Ctrl-Y",
txt("ahibc\ndef\ng"));
sim("killRing", "abcdef",
"Ctrl-Space", "Ctrl-F", "Ctrl-W", "Ctrl-Space", "Ctrl-F", "Ctrl-W",
"Ctrl-Y", "Alt-Y",
txt("acdef"));
sim("copyYank", "abcd",
"Ctrl-Space", "Ctrl-E", "Alt-W", "Ctrl-Y",
txt("abcdabcd"));
sim("killLineSimple", "foo\nbar", "Ctrl-F", "Ctrl-K", txt("f\nbar"));
sim("killLineEmptyLine", "foo\n \nbar", "Ctrl-N", "Ctrl-K", txt("foo\nbar"));
sim("killLineMulti", "foo\nbar\nbaz",
"Ctrl-F", "Ctrl-F", "Ctrl-K", "Ctrl-K", "Ctrl-K", "Ctrl-A", "Ctrl-Y",
txt("o\nbarfo\nbaz"));
sim("moveByParagraph", "abc\ndef\n\n\nhij\nklm\n\n",
"Ctrl-F", "Ctrl-Down", at(2, 0), "Ctrl-Down", at(6, 0),
"Ctrl-N", "Ctrl-Up", at(3, 0), "Ctrl-Up", at(0, 0),
Pos(1, 2), "Ctrl-Down", at(2, 0), Pos(4, 2), "Ctrl-Up", at(3, 0));
sim("moveByParagraphMulti", "abc\n\ndef\n\nhij\n\nklm",
"Ctrl-U", "2", "Ctrl-Down", at(3, 0),
"Shift-Alt-.", "Ctrl-3", "Ctrl-Up", at(1, 0));
sim("moveBySentence", "sentence one! sentence\ntwo\n\nparagraph two",
"Alt-E", at(0, 13), "Alt-E", at(1, 3), "Ctrl-F", "Alt-A", at(0, 13));
sim("moveByExpr", "function foo(a, b) {}",
"Ctrl-Alt-F", at(0, 8), "Ctrl-Alt-F", at(0, 12), "Ctrl-Alt-F", at(0, 18),
"Ctrl-Alt-B", at(0, 12), "Ctrl-Alt-B", at(0, 9));
sim("moveByExprMulti", "foo bar baz bug",
"Ctrl-2", "Ctrl-Alt-F", at(0, 7),
"Ctrl--", "Ctrl-Alt-F", at(0, 4),
"Ctrl--", "Ctrl-2", "Ctrl-Alt-B", at(0, 11));
sim("delExpr", "var x = [\n a,\n b\n c\n];",
Pos(0, 8), "Ctrl-Alt-K", txt("var x = ;"), "Ctrl-/",
Pos(4, 1), "Ctrl-Alt-Backspace", txt("var x = ;"));
sim("delExprMulti", "foo bar baz",
"Ctrl-2", "Ctrl-Alt-K", txt(" baz"),
"Ctrl-/", "Ctrl-E", "Ctrl-2", "Ctrl-Alt-Backspace", txt("foo "));
sim("justOneSpace", "hi bye ",
Pos(0, 4), "Alt-Space", txt("hi bye "),
Pos(0, 4), "Alt-Space", txt("hi b ye "),
"Ctrl-A", "Alt-Space", "Ctrl-E", "Alt-Space", txt(" hi b ye "));
sim("openLine", "foo bar", "Alt-F", "Ctrl-O", txt("foo\n bar"))
sim("transposeChar", "abcd\n\ne",
"Ctrl-F", "Ctrl-T", "Ctrl-T", txt("bcad\n\ne"), at(0, 3),
"Ctrl-F", "Ctrl-T", "Ctrl-T", "Ctrl-T", txt("bcda\n\ne"), at(0, 4),
"Ctrl-F", "Ctrl-T", txt("bcd\na\ne"), at(1, 1));
sim("manipWordCase", "foo BAR bAZ",
"Alt-C", "Alt-L", "Alt-U", txt("Foo bar BAZ"),
"Ctrl-A", "Alt-U", "Alt-L", "Alt-C", txt("FOO bar Baz"));
sim("manipWordCaseMulti", "foo Bar bAz",
"Ctrl-2", "Alt-U", txt("FOO BAR bAz"),
"Ctrl-A", "Ctrl-3", "Alt-C", txt("Foo Bar Baz"));
sim("upExpr", "foo {\n bar[];\n baz(blah);\n}",
Pos(2, 7), "Ctrl-Alt-U", at(2, 5), "Ctrl-Alt-U", at(0, 4));
sim("transposeExpr", "do foo[bar] dah",
Pos(0, 6), "Ctrl-Alt-T", txt("do [bar]foo dah"));
testCM("save", function(cm) {
var saved = false;
CodeMirror.commands.save = function(cm) { saved = cm.getValue(); };
cm.triggerOnKeyDown(fakeEvent("Ctrl-X"));
cm.triggerOnKeyDown(fakeEvent("Ctrl-S"));
is(saved, "hi");
}, {value: "hi", keyMap: "emacs"});
})();

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -2,7 +2,7 @@
<html>
<head>
<meta charset="utf-8">
<title>CodeMirror: Test Suite</title>
<title>CodeMirror: Basic Tests</title>
<link rel="stylesheet" href="chrome://browser/content/devtools/codemirror/codemirror.css">
<link rel="stylesheet" href="cm_mode_test.css">
<!--<link rel="stylesheet" href="../doc/docs.css">-->
@ -13,12 +13,12 @@
<script src="chrome://browser/content/devtools/codemirror/matchbrackets.js"></script>
<script src="chrome://browser/content/devtools/codemirror/comment.js"></script>
<script src="chrome://browser/content/devtools/codemirror/javascript.js"></script>
<script src="chrome://browser/content/devtools/codemirror/vim.js"></script>
<script src="chrome://browser/content/devtools/codemirror/emacs.js"></script>
<!--<script src="../addon/mode/overlay.js"></script>
<script src="../addon/mode/multiplex.js"></script>
<script src="../mode/xml/xml.js"></script>
<script src="../keymap/vim.js"></script>
<script src="../keymap/emacs.js"></script>-->
<script src="../mode/xml/xml.js"></script>-->
<style type="text/css">
.ok {color: #090;}
@ -45,7 +45,7 @@
</style>
</head>
<body>
<h1>CodeMirror: Test Suite</h1>
<h1>CodeMirror: Basic Tests</h1>
<p>A limited set of programmatic sanity tests for CodeMirror.</p>
@ -63,7 +63,13 @@
<script src="cm_mode_test.js"></script>
<script src="cm_mode_javascript_test.js"></script>
<!--<script src="doc_test.js"></script>
<!-- VIM and Emacs mode tests are in vimemacs.html
<script src="cm_vim_test.js"></script>
<script src="cm_emacs_test.js"></script>
-->
<!-- These modes/addons are not used by Editor
<script src="doc_test.js"></script>
<script src="../mode/css/css.js"></script>
<script src="../mode/css/test.js"></script>
<script src="../mode/css/scss_test.js"></script>
@ -80,9 +86,7 @@
<script src="../mode/stex/test.js"></script>
<script src="../mode/xquery/xquery.js"></script>
<script src="../mode/xquery/test.js"></script>
<script src="../addon/mode/multiplex_test.js"></script>
<script src="vim_test.js"></script>
<script src="emacs_test.js"></script>-->
<script src="../addon/mode/multiplex_test.js"></script>-->
<script>
window.onload = runHarness;

Просмотреть файл

@ -24,7 +24,8 @@ function setup(cb) {
let editor = new Editor({
value: "Hello.",
lineNumbers: true,
gutters: [ "breakpoints" ]
foldGutter: true,
gutters: [ "CodeMirror-linenumbers", "breakpoints", "CodeMirror-foldgutter" ]
});
editor.appendTo(box)

Просмотреть файл

@ -0,0 +1,205 @@
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>CodeMirror: VIM/Emacs tests</title>
<link rel="stylesheet" href="chrome://browser/content/devtools/codemirror/codemirror.css">
<link rel="stylesheet" href="cm_mode_test.css">
<!--<link rel="stylesheet" href="../doc/docs.css">-->
<script src="chrome://browser/content/devtools/codemirror/codemirror.js"></script>
<script src="chrome://browser/content/devtools/codemirror/searchcursor.js"></script>
<script src="chrome://browser/content/devtools/codemirror/dialog.js"></script>
<script src="chrome://browser/content/devtools/codemirror/matchbrackets.js"></script>
<script src="chrome://browser/content/devtools/codemirror/comment.js"></script>
<script src="chrome://browser/content/devtools/codemirror/javascript.js"></script>
<script src="chrome://browser/content/devtools/codemirror/vim.js"></script>
<script src="chrome://browser/content/devtools/codemirror/emacs.js"></script>
<!--<script src="../addon/mode/overlay.js"></script>
<script src="../addon/mode/multiplex.js"></script>
<script src="../mode/xml/xml.js"></script>-->
<style type="text/css">
.ok {color: #090;}
.fail {color: #e00;}
.error {color: #c90;}
.done {font-weight: bold;}
#progress {
background: #45d;
color: white;
text-shadow: 0 0 1px #45d, 0 0 2px #45d, 0 0 3px #45d;
font-weight: bold;
white-space: pre;
}
#testground {
visibility: hidden;
}
#testground.offscreen {
visibility: visible;
position: absolute;
left: -10000px;
top: -10000px;
}
.CodeMirror { border: 1px solid black; }
</style>
</head>
<body>
<h1>CodeMirror: VIM/Emacs tests</h1>
<p>A limited set of programmatic sanity tests for CodeMirror.</p>
<div style="border: 1px solid black; padding: 1px; max-width: 700px;">
<div style="width: 0px;" id=progress><div style="padding: 3px;">Ran <span id="progress_ran">0</span><span id="progress_total"> of 0</span> tests</div></div>
</div>
<p id=status>Please enable JavaScript...</p>
<div id=output></div>
<div id=testground></div>
<script src="cm_driver.js"></script>
<script src="cm_vim_test.js"></script>
<script src="cm_emacs_test.js"></script>
<!-- Basic tests are in codemirror.html
<script src="cm_test.js"></script>
<script src="cm_comment_test.js"></script>
<script src="cm_mode_test.js"></script>
<script src="cm_mode_javascript_test.js"></script>
-->
<!-- These modes/addons are not used by Editor
<script src="doc_test.js"></script>
<script src="../mode/css/css.js"></script>
<script src="../mode/css/test.js"></script>
<script src="../mode/css/scss_test.js"></script>
<script src="../mode/xml/xml.js"></script>
<script src="../mode/htmlmixed/htmlmixed.js"></script>
<script src="../mode/ruby/ruby.js"></script>
<script src="../mode/haml/haml.js"></script>
<script src="../mode/haml/test.js"></script>
<script src="../mode/markdown/markdown.js"></script>
<script src="../mode/markdown/test.js"></script>
<script src="../mode/gfm/gfm.js"></script>
<script src="../mode/gfm/test.js"></script>
<script src="../mode/stex/stex.js"></script>
<script src="../mode/stex/test.js"></script>
<script src="../mode/xquery/xquery.js"></script>
<script src="../mode/xquery/test.js"></script>
<script src="../addon/mode/multiplex_test.js"></script>-->
<script>
window.onload = runHarness;
CodeMirror.on(window, 'hashchange', runHarness);
function esc(str) {
return str.replace(/[<&]/, function(ch) { return ch == "<" ? "&lt;" : "&amp;"; });
}
var output = document.getElementById("output"),
progress = document.getElementById("progress"),
progressRan = document.getElementById("progress_ran").childNodes[0],
progressTotal = document.getElementById("progress_total").childNodes[0];
var count = 0,
failed = 0,
bad = "",
running = false, // Flag that states tests are running
quit = false, // Flag to quit tests ASAP
verbose = false, // Adds message for *every* test to output
phantom = false;
function runHarness(){
if (running) {
quit = true;
setStatus("Restarting tests...", '', true);
setTimeout(function(){runHarness();}, 500);
return;
}
if (window.location.hash.substr(1)){
debug = window.location.hash.substr(1).split(",");
} else {
debug = null;
}
quit = false;
running = true;
setStatus("Loading tests...");
count = 0;
failed = 0;
bad = "";
verbose = false;
debugUsed = Array();
totalTests = countTests();
progressTotal.nodeValue = " of " + totalTests;
progressRan.nodeValue = count;
output.innerHTML = '';
document.getElementById("testground").innerHTML = "<form>" +
"<textarea id=\"code\" name=\"code\"></textarea>" +
"<input type=submit value=ok name=submit>" +
"</form>";
runTests(displayTest);
}
function setStatus(message, className, force){
if (quit && !force) return;
if (!message) throw("must provide message");
var status = document.getElementById("status").childNodes[0];
status.nodeValue = message;
status.parentNode.className = className;
}
function addOutput(name, className, code){
var newOutput = document.createElement("dl");
var newTitle = document.createElement("dt");
newTitle.className = className;
newTitle.appendChild(document.createTextNode(name));
newOutput.appendChild(newTitle);
var newMessage = document.createElement("dd");
newMessage.innerHTML = code;
newOutput.appendChild(newTitle);
newOutput.appendChild(newMessage);
output.appendChild(newOutput);
}
function displayTest(type, name, customMessage) {
var message = "???";
if (type != "done") ++count;
progress.style.width = (count * (progress.parentNode.clientWidth - 2) / totalTests) + "px";
progressRan.nodeValue = count;
if (type == "ok") {
message = "Test '" + name + "' succeeded";
if (!verbose) customMessage = false;
} else if (type == "expected") {
message = "Test '" + name + "' failed as expected";
if (!verbose) customMessage = false;
} else if (type == "error" || type == "fail") {
++failed;
message = "Test '" + name + "' failed";
} else if (type == "done") {
if (failed) {
type += " fail";
message = failed + " failure" + (failed > 1 ? "s" : "");
} else if (count < totalTests) {
failed = totalTests - count;
type += " fail";
message = failed + " failure" + (failed > 1 ? "s" : "");
} else {
type += " ok";
message = "All passed";
}
if (debug && debug.length) {
var bogusTests = totalTests - count;
message += " — " + bogusTests + " nonexistent test" +
(bogusTests > 1 ? "s" : "") + " requested by location.hash: " +
"`" + debug.join("`, `") + "`";
} else {
progressTotal.nodeValue = '';
}
customMessage = true; // Hack to avoid adding to output
}
if (verbose && !customMessage) customMessage = message;
setStatus(message, type);
if (customMessage && customMessage.length > 0) {
addOutput(name, type, customMessage);
}
}
</script>
</body>
</html>

Просмотреть файл

@ -197,6 +197,10 @@ StyleSheetEditor.prototype = {
let sourceEditor = new Editor(config);
sourceEditor.appendTo(inputElement).then(() => {
sourceEditor.on("save", () => {
this.saveToFile();
});
sourceEditor.on("change", () => {
this.updateStyleSheet();
});

Просмотреть файл

@ -30,11 +30,11 @@ function consoleOpened(HUD) {
function performTest(node) {
let scrollNode = HUD.outputNode.parentNode;
isnot(scrollNode.scrollTop, 0, "scroll location is not at the top");
let rectNode = node.getBoundingClientRect();
let rectOutput = scrollNode.getBoundingClientRect();
isnot(scrollNode.scrollTop, 0, "scroll location is not at the top");
// Visible scroll viewport.
let height = scrollNode.scrollHeight - scrollNode.scrollTop;

Просмотреть файл

@ -974,6 +974,7 @@ var BrowserUI = {
case "cmd_undoCloseTab":
case "cmd_actions":
case "cmd_panel":
case "cmd_reportingCrashesSubmitURLs":
case "cmd_flyout_back":
case "cmd_sanitize":
case "cmd_volumeLeft":
@ -1081,6 +1082,10 @@ var BrowserUI = {
case "cmd_flyout_back":
FlyoutPanelsUI.onBackButton();
break;
case "cmd_reportingCrashesSubmitURLs":
let urlCheckbox = document.getElementById("prefs-reporting-submitURLs");
Services.prefs.setBoolPref('app.crashreporter.submitURLs', urlCheckbox.checked);
break;
case "cmd_panel":
PanelUI.toggle();
break;

Просмотреть файл

@ -97,6 +97,7 @@
<command id="cmd_history" oncommand="CommandUpdater.doCommand(this.id);"/>
<command id="cmd_sanitize" oncommand="CommandUpdater.doCommand(this.id);"/>
<command id="cmd_contextUI" oncommand="CommandUpdater.doCommand(this.id);"/>
<command id="cmd_reportingCrashesSubmitURLs" oncommand="CommandUpdater.doCommand(this.id);"/>
<!-- scrolling -->
<command id="cmd_scrollPageUp" oncommand="CommandUpdater.doCommand(this.id);"/>
@ -678,10 +679,10 @@ Desktop browser's sync prefs.
<setting pref="app.crashreporter.autosubmit"
type="bool"
title="&optionsHeader.reporting.crashes.label;" />
<setting pref="app.crashreporter.submitURLs"
id="prefs-reporting-submitURLs"
type="bool"
title="&optionsHeader.reporting.crashes.submitURLs;" />
<checkbox id="prefs-reporting-submitURLs"
cropped="end"
label="&optionsHeader.reporting.crashes.submitURLs;"
command="cmd_reportingCrashesSubmitURLs"/>
</settings>
<settings id="prefs-telemetry" label="&optionsHeader.telemetry.title;">
<setting

Просмотреть файл

@ -29,7 +29,8 @@ let PrefsFlyoutPanel = {
});
});
this._prefObserver(null, null, "privacy.donottrackheader.value");
this.observe(null, null, "privacy.donottrackheader.value");
this._updateSubmitURLs();
this._topmostElement = this._elements.PrefsFlyoutPanel;
},
@ -39,23 +40,23 @@ let PrefsFlyoutPanel = {
this._hasShown = true;
Services.prefs.addObserver("privacy.donottrackheader.value",
this._prefObserver,
this,
false);
Services.prefs.addObserver("privacy.donottrackheader.enabled",
this._prefObserver,
this,
false);
Services.prefs.addObserver("app.crashreporter.autosubmit",
this._prefObserver,
this,
false);
Services.prefs.addObserver("app.crashreporter.submitURLs",
this._prefObserver,
this,
false);
}
this._topmostElement.show();
},
_prefObserver: function(subject, topic, data) {
observe: function(subject, topic, data) {
let value = -1;
try {
value = Services.prefs.getIntPref("privacy.donottrackheader.value");
@ -90,26 +91,30 @@ let PrefsFlyoutPanel = {
case "app.crashreporter.autosubmit":
let autosubmit = Services.prefs.getBoolPref("app.crashreporter.autosubmit");
let urlCheckbox = document.getElementById("prefs-reporting-submitURLs");
if (!autosubmit) {
// If the user has selected not to submit crash reports, the UI
// should reflect also that URLs will not be included.
// TODO: Ideally we would grey out the text and the toggle for
// the "include URLs" pref, but the |setting| binding doesn't
// appear to support enabling/disabling. In the meantime, we just
// set the "include URLs" pref to false if the "send crash reports"
// pref has been set to false.
Services.prefs.setBoolPref('app.crashreporter.submitURLs', false);
// disables the submitURLs ui if no crashreports will be submited, but doesn't change the pref
urlCheckbox.setAttribute("disabled", true);
}
else {
urlCheckbox.setAttribute("disabled", false);
}
break;
case "app.crashreporter.submitURLs":
let submitURLs = Services.prefs.getBoolPref("app.crashreporter.submitURLs");
if (submitURLs) {
// If the user has selected to submit URLs, they are implicitly also
// selecting to submit crash reports. Let's update the autosubmit pref
Services.prefs.setBoolPref('app.crashreporter.autosubmit', true);
}
break;
this._updateSubmitURLs();
break;
}
},
_updateSubmitURLs: function() {
let submitURLs = Services.prefs.getBoolPref("app.crashreporter.submitURLs");
let urlCheckbox = document.getElementById("prefs-reporting-submitURLs");
if (submitURLs) {
urlCheckbox.checked = true;
}
else {
urlCheckbox.checked = false;
}
},
};

Просмотреть файл

@ -189,16 +189,17 @@
<body id="errorPage" class="certerror" dir="&locale.dir;">
<!-- Error Title -->
<div id="errorTitle">
<h1 class="errorTitleText">&certerror.longpagetitle;</h1>
</div>
<!-- PAGE CONTAINER (for styling purposes only) -->
<div id="errorPageContainer">
<div id="errorPageContainer" class="section">
<!-- Error Title -->
<div id="errorTitle" class="section-header">
<span id="errorTitleIcon"></span>
<h1 class="errorTitleText">&certerror.longpagetitle;</h1>
</div>
<!-- LONG CONTENT (the section most likely to require scrolling) -->
<div id="errorLongContent">
<div id="errorLongContent" class="section-details">
<div id="introContent">
<p id="introContentP1">&certerror.introPara1;</p>
</div>
@ -228,8 +229,8 @@
</div>
</div>
</div>
</div>
</div>
<!--
- Note: It is important to run the script this way, instead of using
- an onload handler. This is because error pages are loaded as

Просмотреть файл

@ -24,7 +24,7 @@
<script type="application/javascript"><![CDATA[
// Error url MUST be formatted like this:
// about:blocked?e=error_code&u=url
// Note that this file uses document.documentURI to get
// the URL (with the format from above). This is because
// document.location.href gets the current URI off the docshell,
@ -56,7 +56,7 @@
url = url.slice(12);
return url;
}
/**
* Attempt to get the hostname via document.location. Fail back
* to getURL so that we always return something meaningful.
@ -69,7 +69,7 @@
return getURL();
}
}
function initPage()
{
// Handoff to the appropriate initializer, based on error code
@ -81,8 +81,8 @@
initPage_phishing();
break;
}
}
}
/**
* Initialize custom strings and functionality for blocked malware case
*/
@ -103,7 +103,7 @@
document.title = document.getElementById("errorTitleText_malware")
.innerHTML;
}
/**
* Initialize custom strings and functionality for blocked phishing case
*/
@ -143,7 +143,7 @@
left: 20px;
font-size: smaller;
}
#ignoreWarning {
text-align: right;
}
@ -152,16 +152,17 @@
<body id="errorPage" class="blockedsite" dir="&locale.dir;">
<!-- Error Title -->
<div id="errorTitle">
<h1 id="errorTitleText_phishing" class="errorTitleText">&safeb.blocked.phishingPage.title2;</h1>
<h1 id="errorTitleText_malware" class="errorTitleText">&safeb.blocked.malwarePage.title;</h1>
</div>
<div id="errorPageContainer">
<div id="errorPageContainer" class="section">
<!-- Error Title -->
<div id="errorTitle" class="section-header">
<span id="errorTitleIcon"></span>
<h1 id="errorTitleText_phishing" class="errorTitleText">&safeb.blocked.phishingPage.title2;</h1>
<h1 id="errorTitleText_malware" class="errorTitleText">&safeb.blocked.malwarePage.title;</h1>
</div>
<div id="errorLongContent" class="section-details">
<div id="errorLongContent">
<!-- Short Description -->
<div id="errorShortDesc">
<p id="errorShortDescText_phishing">&safeb.blocked.phishingPage.shortDesc2;</p>
@ -173,7 +174,8 @@
<p id="errorLongDescText_phishing">&safeb.blocked.phishingPage.longDesc2;</p>
<p id="errorLongDescText_malware">&safeb.blocked.malwarePage.longDesc;</p>
</div>
</div>
<div class="section-footer">
<!-- Action buttons -->
<div id="buttons">
<!-- Commands handled in browser.js -->

Просмотреть файл

@ -19,7 +19,7 @@
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta name="viewport" content="width=device-width; user-scalable=false;" />
<meta name="viewport" content="width=device-width; user-scalable=false;" />
<title>&loadError.label;</title>
<link rel="stylesheet" href="chrome://global/skin/netError.css" type="text/css" media="all" />
<!-- If the location of the favicon is changed here, the FAVICON_ERRORPAGE_URL symbol in
@ -95,7 +95,7 @@
function initPage()
{
var err = getErrorCode();
// if it's an unknown error or there's no title or description
// defined, get the generic message
var errTitle = document.getElementById("et_" + err);
@ -106,7 +106,7 @@
errDesc = document.getElementById("ed_generic");
}
var title = document.getElementsByClassName("errorTitleText")[0];
var title = document.querySelector(".errorTitleText");
if (title)
{
title.parentNode.replaceChild(errTitle, title);
@ -139,7 +139,7 @@
// Also, if they specified a CSS class, they must supply their own
// favicon. In order to trigger the browser to repaint though, we
// need to remove/add the link element.
// need to remove/add the link element.
var favicon = document.getElementById("favicon");
var faviconParent = favicon.parentNode;
faviconParent.removeChild(favicon);
@ -176,13 +176,13 @@
secOverride.parentNode.removeChild(secOverride);
}
}
function showSecuritySection() {
// Swap link out, content in
document.getElementById('securityOverrideContent').style.display = '';
document.getElementById('securityOverrideLink').style.display = 'none';
}
/* In the case of SSL error pages about domain mismatch, see if
we can hyperlink the user to the correct site. We don't want
to do this generically since it allows MitM attacks to redirect
@ -194,29 +194,29 @@
var sd = document.getElementById("errorShortDescText");
if (sd) {
var desc = getDescription();
// sanitize description text - see bug 441169
// First, find the index of the <a> tag we care about, being careful not to
// use an over-greedy regex
var re = /<a id="cert_domain_link" title="([^"]+)">/;
var result = re.exec(desc);
if(!result)
return;
// Remove sd's existing children
sd.textContent = "";
// Everything up to the link should be text content
sd.appendChild(document.createTextNode(desc.slice(0, result.index)));
// Now create the link itself
var anchorEl = document.createElement("a");
anchorEl.setAttribute("id", "cert_domain_link");
anchorEl.setAttribute("title", result[1]);
anchorEl.appendChild(document.createTextNode(result[1]));
sd.appendChild(anchorEl);
// Finally, append text for anything after the closing </a>
sd.appendChild(document.createTextNode(desc.slice(desc.indexOf("</a>") + "</a>".length)));
}
@ -224,7 +224,7 @@
var link = document.getElementById('cert_domain_link');
if (!link)
return;
var okHost = link.getAttribute("title");
var thisHost = document.location.hostname;
var proto = document.location.protocol;
@ -234,7 +234,7 @@
// get anyone anywhere useful. bug 432491
okHost = okHost.replace(/^\*\./, "www.");
/* case #1:
/* case #1:
* example.com uses an invalid security certificate.
*
* The certificate is only valid for www.example.com
@ -258,7 +258,7 @@
if (endsWith(thisHost, "." + okHost))
link.href = proto + okHost;
}
function endsWith(haystack, needle) {
return haystack.slice(-needle.length) == needle;
}
@ -322,17 +322,18 @@
</div>
</div>
<!-- Error Title -->
<div id="errorTitle">
<h1 class="errorTitleText" />
</div>
<!-- PAGE CONTAINER (for styling purposes only) -->
<div id="errorPageContainer">
<div id="errorPageContainer" class="section">
<!-- Error Title -->
<div id="errorTitle" class="section-header">
<span id="errorTitleIcon"></span>
<h1 class="errorTitleText" />
</div>
<!-- LONG CONTENT (the section most likely to require scrolling) -->
<div id="errorLongContent">
<div id="errorLongContent" class="section-details">
<!-- Short Description -->
<div id="errorShortDesc">
<p id="errorShortDescText" />
@ -349,8 +350,10 @@
</div>
</div>
<!-- Retry Button -->
<button id="errorTryAgain" onclick="retryThis(this);">&retry.label;</button>
<div class="section-footer">
<!-- Retry Button -->
<button id="errorTryAgain" onclick="retryThis(this);">&retry.label;</button>
</div>
</div>

Просмотреть файл

@ -773,7 +773,9 @@ SessionStore.prototype = {
let window = Services.wm.getMostRecentWindow("navigator:browser");
this._selectedWindow = data.selectedWindow;
if (typeof data.selectedWindow == "number") {
this._selectedWindow = data.selectedWindow;
}
let windowIndex = this._selectedWindow - 1;
let tabs = data.windows[windowIndex].tabs;
let selected = data.windows[windowIndex].selected;

Просмотреть файл

@ -269,8 +269,8 @@ public:
/**
* Choose the appropriate launch type based on the user's previously chosen
* host environment, along with system constraints.
* AHE_DESKTOP = 0
* AHE_IMMERSIVE = 1
*
* AHE_DESKTOP = 0, AHE_IMMERSIVE = 1
*/
AHE_TYPE GetLaunchType() {
AHE_TYPE ahe = GetLastAHE();
@ -564,7 +564,8 @@ bool CExecuteCommandVerb::SetTargetPath(IShellItem* aItem)
* Desktop launch - Launch the destop browser to display the current
* target using shellexecute.
*/
void LaunchDesktopBrowserWithParams(CStringW& aBrowserPath, CStringW& aVerb, CStringW& aTarget, CStringW& aParameters,
void LaunchDesktopBrowserWithParams(CStringW& aBrowserPath, CStringW& aVerb,
CStringW& aTarget, CStringW& aParameters,
bool aTargetIsDefaultBrowser, bool aTargetIsBrowser)
{
// If a taskbar shortcut, link or local file is clicked, the target will
@ -589,21 +590,38 @@ void LaunchDesktopBrowserWithParams(CStringW& aBrowserPath, CStringW& aVerb, CSt
Log(L"Desktop Launch: verb:%s exe:%s params:%s", aVerb, aBrowserPath, params);
SHELLEXECUTEINFOW seinfo;
memset(&seinfo, 0, sizeof(seinfo));
seinfo.cbSize = sizeof(SHELLEXECUTEINFOW);
seinfo.fMask = SEE_MASK_FLAG_LOG_USAGE;
seinfo.lpVerb = aVerb;
seinfo.lpFile = aBrowserPath;
seinfo.nShow = SW_SHOWNORMAL;
// Relaunch in Desktop mode uses a special URL to trick Windows into
// switching environments. We shouldn't actually try to open this URL
if (_wcsicmp(aTarget, L"http://-desktop/") != 0) {
seinfo.lpParameters = params;
// switching environments. We shouldn't actually try to open this URL.
if (!_wcsicmp(aTarget, L"http://-desktop/")) {
// Ignore any params and just launch on desktop
params.Empty();
}
ShellExecuteEx(&seinfo);
PROCESS_INFORMATION procInfo;
STARTUPINFO startInfo;
memset(&procInfo, 0, sizeof(PROCESS_INFORMATION));
memset(&startInfo, 0, sizeof(STARTUPINFO));
startInfo.cb = sizeof(STARTUPINFO);
startInfo.dwFlags = STARTF_USESHOWWINDOW;
startInfo.wShowWindow = SW_SHOWNORMAL;
BOOL result =
CreateProcessW(aBrowserPath, static_cast<LPWSTR>(params.GetBuffer()),
NULL, NULL, FALSE, 0, NULL, NULL, &startInfo, &procInfo);
if (!result) {
Log(L"CreateProcess failed! (%d)", GetLastError());
return;
}
// Hand off foreground/focus rights to the browser we create. If we don't
// do this the ceh will keep ownership causing desktop firefox to launch
// deactivated.
if (!AllowSetForegroundWindow(procInfo.dwProcessId)) {
Log(L"AllowSetForegroundWindow failed! (%d)", GetLastError());
}
CloseHandle(procInfo.hThread);
CloseHandle(procInfo.hProcess);
Log(L"Desktop browser process id: %d", procInfo.dwProcessId);
}
void CExecuteCommandVerb::LaunchDesktopBrowser()
@ -613,7 +631,8 @@ void CExecuteCommandVerb::LaunchDesktopBrowser()
return;
}
LaunchDesktopBrowserWithParams(browserPath, mVerb, mTarget, mParameters, mTargetIsDefaultBrowser, mTargetIsBrowser);
LaunchDesktopBrowserWithParams(browserPath, mVerb, mTarget, mParameters,
mTargetIsDefaultBrowser, mTargetIsBrowser);
}
class AutoSetRequestMet

Просмотреть файл

@ -776,6 +776,10 @@ documenttab[selected] .documenttab-selection {
list-style-image: url(chrome://browser/skin/images/navbar-download.png);
}
#download-progress[progress="100"] {
list-style-image: url(chrome://browser/skin/images/navbar-download-finished.png);
}
#pin-button {
list-style-image: url(chrome://browser/skin/images/navbar-pin.png);
}
@ -797,6 +801,10 @@ documenttab[selected] .documenttab-selection {
list-style-image: url(chrome://browser/skin/images/navbar-download@1.4x.png);
}
#download-progress[progress="100"] {
list-style-image: url(chrome://browser/skin/images/navbar-download-finished@1.4x.png);
}
#pin-button {
list-style-image: url(chrome://browser/skin/images/navbar-pin@1.4x.png);
}
@ -819,6 +827,10 @@ documenttab[selected] .documenttab-selection {
list-style-image: url(chrome://browser/skin/images/navbar-download@1.8x.png);
}
#download-progress[progress="100"] {
list-style-image: url(chrome://browser/skin/images/navbar-download-finished@1.8x.png);
}
#pin-button {
list-style-image: url(chrome://browser/skin/images/navbar-pin@1.8x.png);
}

Просмотреть файл

@ -26,6 +26,8 @@
}
.circularprogressindicator-progressRing:not([progress]),
.circularprogressindicator-progressTrack:not([progress]) {
.circularprogressindicator-progressRing[progress="100"],
.circularprogressindicator-progressTrack:not([progress]),
.circularprogressindicator-progressTrack[progress="100"] {
visibility: hidden;
}

Двоичные данные
browser/metro/theme/images/errorpage-warning.png

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 631 B

После

Ширина:  |  Высота:  |  Размер: 1.6 KiB

Двоичные данные
browser/metro/theme/images/errorpage-warning@1.4x.png Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 1.8 KiB

Двоичные данные
browser/metro/theme/images/errorpage-warning@1.8x.png Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 2.1 KiB

Двоичные данные
browser/metro/theme/images/navbar-download-finished.png Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 943 B

Двоичные данные
browser/metro/theme/images/navbar-download-finished@1.4x.png Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 2.1 KiB

Двоичные данные
browser/metro/theme/images/navbar-download-finished@1.8x.png Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 1.7 KiB

Просмотреть файл

@ -21,7 +21,7 @@ chrome.jar:
* skin/platform.css (platform.css)
* skin/tiles.css (tiles.css)
skin/touchcontrols.css (touchcontrols.css)
skin/netError.css (netError.css)
* skin/netError.css (netError.css)
skin/firstrun.css (firstrun.css)
% override chrome://global/skin/about.css chrome://browser/skin/about.css
% override chrome://global/skin/media/videocontrols.css chrome://browser/skin/touchcontrols.css
@ -55,6 +55,9 @@ chrome.jar:
skin/images/navbar-download.png (images/navbar-download.png)
skin/images/navbar-download@1.4x.png (images/navbar-download@1.4x.png)
skin/images/navbar-download@1.8x.png (images/navbar-download@1.8x.png)
skin/images/navbar-download-finished.png (images/navbar-download-finished.png)
skin/images/navbar-download-finished@1.4x.png (images/navbar-download-finished@1.4x.png)
skin/images/navbar-download-finished@1.8x.png (images/navbar-download-finished@1.8x.png)
skin/images/navbar-forward.png (images/navbar-forward.png)
skin/images/navbar-forward@1.4x.png (images/navbar-forward@1.4x.png)
skin/images/navbar-forward@1.8x.png (images/navbar-forward@1.8x.png)
@ -113,7 +116,8 @@ chrome.jar:
skin/images/arrowbox-down-blue-filled.png (images/arrowbox-down-blue-filled.png)
skin/images/favicon-default-32.png (images/favicon-default-32.png)
skin/images/errorpage-warning.png (images/errorpage-warning.png)
skin/images/errorpage-warning.png (images/errorpage-warning.png)
skin/images/errorpage-warning@1.4x.png (images/errorpage-warning@1.4x.png)
skin/images/errorpage-warning@1.8x.png (images/errorpage-warning@1.8x.png)
skin/images/errorpage-larry-white.png (images/errorpage-larry-white.png)
skin/images/errorpage-larry-black.png (images/errorpage-larry-black.png)
skin/images/alert-downloads-30.png (images/alert-downloads-30.png)

Просмотреть файл

@ -10,18 +10,49 @@
* Updated for mobile by: Wes Johnston <wjohnston@mozilla.com>
*/
%filter substitution
%include defines.inc
%include platform.css
/*
* In-browser content styles,
* XXX: should be extracted and consolidated into a shared stylesheet for all in-browser content
*/
body {
margin: 0;
padding: 0 8px 8px;
font-family: "Nokia Sans", Tahoma, sans-serif !important;
background-color: #F4F4F4;
color: rgb(51,51,51);
font-family: "Segoe UI", sans-serif;
font-size: @font_normal@;
line-height: 23px;
}
h1 {
font-size: 22px;
font-size: @metro_font_xlarge@;
font-weight: normal;
line-height: @metro_spacing_large@;
}
h2 {
font-size: @metro_font_large@;
line-height: @metro_spacing_xxxnormal@;
font-weight: normal;
}
h3 {
font-size: @font_normal@;
line-height: @metro_spacing_xxnormal@;
}
h4 {
font-size: @font_normal@;
line-height: @metro_spacing_xxnormal@;
font-style: italic;
display: inline;
}
h2 {
font-size: 16px;
/*
* Net error page styles
*/
a {
text-decoration: none;
}
ul {
@ -34,55 +65,88 @@ li {
padding: 8px 0px;
}
#errorPage {
background-color: #CEE6F4;
}
#errorPage.certerror {
background-color: #EFD400;
}
#errorPage.blockedsite {
background-color: #BF0000;
color: #fff;
}
#errorPage.certerror #errorPageContainer > .section-header,
#errorPage.blockedsite #errorPageContainer > .section-header {
border-bottom: @metro_border_thin@ solid rgb(133,137,140);
}
#errorPageContainer {
max-width: 628px;
margin-left: auto;
margin-right: auto;
margin-top: 60px;
-moz-padding-start: 40px;
-moz-padding-end: 24px;
}
#errorTitle {
background: url("chrome://browser/skin/images/errorpage-warning.png") left center no-repeat;
/* Scaled by .666 of their actual size */
background-size: 40px 40px;
background-origin: content-box;
min-height: 60px;
margin-left: auto;
margin-right: auto;
max-width: 500px;
margin-left: auto;
margin-right: auto;
}
#errorPage.certerror #errorTitle {
#errorTitleIcon {
background-image: url("chrome://browser/skin/images/errorpage-warning.png");
background-position: center center;
background-repeat: no-repeat;
background-size: 40px 40px;
background-origin: content-box;
display: inline-block;
-moz-margin-start: -64px;
-moz-margin-end: 24px;
height: 40px;
vertical-align: middle;
width: 40px;
}
@media (min-resolution: @min_res_140pc@) {
/* Load 140% image when scaled by 140% */
#errorTitleIcon {
background-image: url("chrome://browser/skin/images/errorpage-warning@1.4x.png");
}
}
@media (min-resolution: @min_res_180pc@) {
/* Load 180% image when scaled by 180% */
#errorTitleIcon {
background-image: url("chrome://browser/skin/images/errorpage-warning@1.8x.png");
}
}
#errorPage.certerror #errorTitleIcon {
background-image: url("chrome://browser/skin/images/errorpage-larry-black.png");
}
#errorPage.blockedsite #errorTitle {
#errorPage.blockedsite #errorTitleIcon {
background-image: url("chrome://browser/skin/images/errorpage-larry-white.png");
color: white;
}
.errorTitleText {
padding: 0px 0px 0px 50px;
padding: 0;
display: inline-block;
vertical-align: middle
vertical-align: middle;
}
#errorPageContainer {
background-color: white;
border: 1px solid #999999;
border-radius: 6px;
padding: 6px 20px 20px;
font-size: 14px;
max-width: 500px;
margin-left: auto;
margin-right: auto;
#errorPageContainer > .section-header {
border-bottom: @metro_border_thin@ solid @border_color@;
margin-top: @metro_spacing_xxxnormal@;
padding-bottom: @metro_spacing_snormal@;
}
#errorPageContainer > .section-details {
margin-top: @metro_spacing_xxxnormal@;
padding-bottom: @metro_spacing_xxxnormal@;
}
#errorPageContainer > .section-footer {
padding-bottom: @metro_spacing_xxxnormal@;
}
#errorShortDesc > p:empty {
@ -91,8 +155,8 @@ li {
#errorShortDesc > p {
overflow: auto;
border-bottom: 1px solid #999999;
padding-bottom: 1em;
margin: 0;
}
#errorPage.blockedsite #errorShortDesc > p {
@ -101,6 +165,30 @@ li {
padding-bottom: 0px;
}
#detailsLink {
color: black;
display: table-row;
}
#detailsGrid {
display: table;
}
#detailsContainer {
display: table-row;
}
#detailsLinkLabel {
display: table-cell;
}
.detailsSpacer {
display: table-cell;
padding-right: 8px;
}
#securityOverrideDiv {
padding-top: 10px;
}
@ -110,7 +198,7 @@ div[collapsed] {
background-image: url("chrome://browser/skin/images/arrowright-16.png");
background-size: 11px 11px;
background-repeat: no-repeat;
background-position: left 0.3em;
background-position: left 0.6em;
}
div[collapsed="true"] {
@ -125,7 +213,3 @@ div[collapsed="true"] > p,
div[collapsed="true"] > div {
display: none;
}
button {
padding: 0.3em !important;
}

Просмотреть файл

@ -816,8 +816,8 @@ void
BluetoothA2dpManager::UpdateMetaData(const nsAString& aTitle,
const nsAString& aArtist,
const nsAString& aAlbum,
uint32_t aMediaNumber,
uint32_t aTotalMediaCount,
uint64_t aMediaNumber,
uint64_t aTotalMediaCount,
uint32_t aDuration)
{
MOZ_ASSERT(NS_IsMainThread());
@ -905,7 +905,7 @@ BluetoothA2dpManager::UpdatePlayStatus(uint32_t aDuration,
/*
* This function handles RegisterNotification request from
* AvrcpRegisterNotificationCallback, which updates current
* track/status/position status.
* track/status/position status in the INTERRIM response.
*
* aParam is only valid when position changed
*/
@ -925,16 +925,34 @@ BluetoothA2dpManager::UpdateRegisterNotification(int aEventId, int aParam)
param.play_status = (btrc_play_status_t)mPlayStatus;
break;
case BTRC_EVT_TRACK_CHANGE:
// In AVRCP 1.3 and 1.4, the identifier parameter of EVENT_TRACK_CHANGED
// is different.
// AVRCP 1.4: If no track is selected, we shall return 0xFFFFFFFFFFFFFFFF,
// otherwise return 0x0 in the INTERRIM response. The expanded text in
// version 1.4 is to allow for new UID feature. As for AVRCP 1.3, we shall
// return 0xFFFFFFFF. Since PTS enforces to check this part to comply with
// the most updated spec.
mTrackChangedNotifyType = BTRC_NOTIFICATION_TYPE_INTERIM;
// needs to convert to network big endian format since track stores
// as uint8[8]. 56 = 8 * (BTRC_UID_SIZE -1)
for (int i = 0; i < BTRC_UID_SIZE; ++i) {
param.track[i] = (mMediaNumber >> (56 - 8 * i));
// as uint8[8]. 56 = 8 * (BTRC_UID_SIZE -1).
for (int index = 0; index < BTRC_UID_SIZE; ++index) {
// We cannot easily check if a track is selected, so whenever A2DP is
// streaming, we assume a track is selected.
if (mSinkState == BluetoothA2dpManager::SinkState::SINK_PLAYING) {
param.track[index] = 0x0;
} else {
param.track[index] = 0xFF;
}
}
break;
case BTRC_EVT_PLAY_POS_CHANGED:
// If no track is selected, return 0xFFFFFFFF in the INTERIM response
mPlayPosChangedNotifyType = BTRC_NOTIFICATION_TYPE_INTERIM;
param.song_pos = mPosition;
if (mSinkState == BluetoothA2dpManager::SinkState::SINK_PLAYING) {
param.song_pos = mPosition;
} else {
param.song_pos = 0xFFFFFFFF;
}
mPlaybackInterval = aParam;
break;
default:
@ -971,13 +989,13 @@ BluetoothA2dpManager::GetPosition()
return mPosition;
}
uint32_t
uint64_t
BluetoothA2dpManager::GetMediaNumber()
{
return mMediaNumber;
}
uint32_t
uint64_t
BluetoothA2dpManager::GetTotalMediaNumber()
{
return mTotalMediaCount;

Просмотреть файл

@ -45,8 +45,8 @@ public:
void UpdateMetaData(const nsAString& aTitle,
const nsAString& aArtist,
const nsAString& aAlbum,
uint32_t aMediaNumber,
uint32_t aTotalMediaCount,
uint64_t aMediaNumber,
uint64_t aTotalMediaCount,
uint32_t aDuration);
void UpdatePlayStatus(uint32_t aDuration,
uint32_t aPosition,
@ -56,8 +56,8 @@ public:
uint32_t GetDuration();
ControlPlayStatus GetPlayStatus();
uint32_t GetPosition();
uint32_t GetMediaNumber();
uint32_t GetTotalMediaNumber();
uint64_t GetMediaNumber();
uint64_t GetTotalMediaNumber();
void GetTitle(nsAString& aTitle);
void GetArtist(nsAString& aArtist);
private:
@ -80,8 +80,8 @@ private:
nsString mArtist;
nsString mTitle;
uint32_t mDuration;
uint32_t mMediaNumber;
uint32_t mTotalMediaCount;
uint64_t mMediaNumber;
uint64_t mTotalMediaCount;
uint32_t mPosition;
/*
* mPlaybackInterval specifies the time interval (in seconds) at which

Просмотреть файл

@ -390,8 +390,8 @@ void
BluetoothA2dpManager::UpdateMetaData(const nsAString& aTitle,
const nsAString& aArtist,
const nsAString& aAlbum,
uint32_t aMediaNumber,
uint32_t aTotalMediaCount,
uint64_t aMediaNumber,
uint64_t aTotalMediaCount,
uint32_t aDuration)
{
mTitle.Assign(aTitle);
@ -436,7 +436,7 @@ BluetoothA2dpManager::GetPosition()
return mPosition;
}
uint32_t
uint64_t
BluetoothA2dpManager::GetMediaNumber()
{
return mMediaNumber;

Просмотреть файл

@ -46,8 +46,8 @@ public:
void UpdateMetaData(const nsAString& aTitle,
const nsAString& aArtist,
const nsAString& aAlbum,
uint32_t aMediaNumber,
uint32_t aTotalMediaCount,
uint64_t aMediaNumber,
uint64_t aTotalMediaCount,
uint32_t aDuration);
void UpdatePlayStatus(uint32_t aDuration,
uint32_t aPosition,
@ -56,7 +56,7 @@ public:
uint32_t GetDuration();
ControlPlayStatus GetPlayStatus();
uint32_t GetPosition();
uint32_t GetMediaNumber();
uint64_t GetMediaNumber();
void GetTitle(nsAString& aTitle);
private:
@ -79,8 +79,8 @@ private:
nsString mArtist;
nsString mTitle;
uint32_t mDuration;
uint32_t mMediaNumber;
uint32_t mTotalMediaCount;
uint64_t mMediaNumber;
uint64_t mTotalMediaCount;
uint32_t mPosition;
ControlPlayStatus mPlayStatus;
};

Просмотреть файл

@ -2370,6 +2370,7 @@ BluetoothDBusService::SetProperty(BluetoothObjectType aType,
int type;
int tmp_int;
void* val;
const char* tempStr;
nsCString str;
if (aValue.value().type() == BluetoothValue::Tuint32_t) {
tmp_int = aValue.value().get_uint32_t();
@ -2377,7 +2378,7 @@ BluetoothDBusService::SetProperty(BluetoothObjectType aType,
type = DBUS_TYPE_UINT32;
} else if (aValue.value().type() == BluetoothValue::TnsString) {
str = NS_ConvertUTF16toUTF8(aValue.value().get_nsString());
const char* tempStr = str.get();
tempStr = str.get();
val = &tempStr;
type = DBUS_TYPE_STRING;
} else if (aValue.value().type() == BluetoothValue::Tbool) {

Просмотреть файл

@ -807,7 +807,16 @@ ParticularProcessPriorityManager::ResetPriority()
ProcessPriority processPriority = ComputePriority();
if (mPriority == PROCESS_PRIORITY_UNKNOWN ||
mPriority > processPriority) {
ScheduleResetPriority("backgroundGracePeriodMS");
// Apps set at a perceivable background priority are often playing media.
// Most media will have short gaps while changing tracks between songs,
// switching videos, etc. Give these apps a longer grace period so they
// can get their next track started, if there is one, before getting
// downgraded.
if (mPriority == PROCESS_PRIORITY_BACKGROUND_PERCEIVABLE) {
ScheduleResetPriority("backgroundPerceivableGracePeriodMS");
} else {
ScheduleResetPriority("backgroundGracePeriodMS");
}
return;
}

Просмотреть файл

@ -812,6 +812,10 @@ bool TabParent::SendRealTouchEvent(WidgetTouchEvent& event)
ScrollableLayerGuid guid;
MaybeForwardEventToRenderFrame(event, &guid, &e);
if (mIsDestroyed) {
return false;
}
MapEventCoordinatesForChildProcess(mChildProcessOffsetAtTouchStart, &e);
return (e.message == NS_TOUCH_MOVE) ?

Просмотреть файл

@ -33,16 +33,13 @@ NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(MobileConnectionArray)
NS_INTERFACE_MAP_END
MobileConnectionArray::MobileConnectionArray(nsPIDOMWindow* aWindow)
: mWindow(aWindow)
: mWindow(aWindow), mInitialized(false)
{
int32_t numRil = mozilla::Preferences::GetInt("ril.numRadioInterfaces", 1);
uint32_t numRil = mozilla::Preferences::GetUint("ril.numRadioInterfaces", 1);
MOZ_ASSERT(numRil > 0);
for (int32_t id = 0; id < numRil; id++) {
nsRefPtr<MobileConnection> mobileConnection = new MobileConnection(id);
mobileConnection->Init(aWindow);
mMobileConnections.AppendElement(mobileConnection);
}
bool ret = mMobileConnections.SetLength(numRil);
MOZ_ASSERT(ret);
SetIsDOMBinding();
}
@ -52,12 +49,27 @@ MobileConnectionArray::~MobileConnectionArray()
DropConnections();
}
void
MobileConnectionArray::Init()
{
mInitialized = true;
for (uint32_t id = 0; id < mMobileConnections.Length(); id++) {
nsRefPtr<MobileConnection> mobileConnection = new MobileConnection(id);
mobileConnection->Init(mWindow);
mMobileConnections[id] = mobileConnection;
}
}
void
MobileConnectionArray::DropConnections()
{
for (uint32_t i = 0; i < mMobileConnections.Length(); i++) {
mMobileConnections[i]->Shutdown();
if (mInitialized) {
for (uint32_t i = 0; i < mMobileConnections.Length(); i++) {
mMobileConnections[i]->Shutdown();
}
}
mMobileConnections.Clear();
}
@ -75,7 +87,7 @@ MobileConnectionArray::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aScope)
}
nsIDOMMozMobileConnection*
MobileConnectionArray::Item(uint32_t aIndex) const
MobileConnectionArray::Item(uint32_t aIndex)
{
bool unused;
return IndexedGetter(aIndex, unused);
@ -88,8 +100,12 @@ MobileConnectionArray::Length() const
}
nsIDOMMozMobileConnection*
MobileConnectionArray::IndexedGetter(uint32_t aIndex, bool& aFound) const
MobileConnectionArray::IndexedGetter(uint32_t aIndex, bool& aFound)
{
if (!mInitialized) {
Init();
}
aFound = false;
aFound = aIndex < mMobileConnections.Length();

Просмотреть файл

@ -34,18 +34,24 @@ public:
// WebIDL
nsIDOMMozMobileConnection*
Item(uint32_t aIndex) const;
Item(uint32_t aIndex);
uint32_t
Length() const;
nsIDOMMozMobileConnection*
IndexedGetter(uint32_t aIndex, bool& aFound) const;
IndexedGetter(uint32_t aIndex, bool& aFound);
private:
~MobileConnectionArray();
void DropConnections();
void
Init();
void
DropConnections();
bool mInitialized;
nsCOMPtr<nsPIDOMWindow> mWindow;
nsTArray<nsRefPtr<MobileConnection>> mMobileConnections;

Просмотреть файл

@ -20,3 +20,4 @@ disabled = Bug 808783
[test_call_barring_change_password.js]
[test_mobile_set_radio.js]
[test_mobile_last_known_network.js]
[test_mobile_connections_array_uninitialized.js]

Просмотреть файл

@ -0,0 +1,32 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
MARIONETTE_TIMEOUT = 1000;
SpecialPowers.addPermission("mobileconnection", true, document);
// Permission changes can't change existing Navigator.prototype
// objects, so grab our objects from a new Navigator
let ifr = document.createElement("iframe");
let connections;
ifr.onload = function() {
connections = ifr.contentWindow.navigator.mozMobileConnections;
// mozMobileConnections hasn't been initialized yet.
ok(connections);
is(connections.length, 1);
ifr.parentNode.removeChild(ifr);
ifr = null;
connections = null;
SpecialPowers.gc();
cleanUp();
};
document.body.appendChild(ifr);
function cleanUp() {
SpecialPowers.removePermission("mobileconnection", document);
finish();
}

Просмотреть файл

@ -391,6 +391,13 @@ NotificationObserver::Observe(nsISupports* aSubject, const char* aTopic,
const char16_t* aData)
{
if (!strcmp("alertclickcallback", aTopic)) {
nsCOMPtr<nsPIDOMWindow> window = mNotification->GetOwner();
nsIDocument* doc = window ? window->GetExtantDoc() : nullptr;
if (doc) {
nsContentUtils::DispatchChromeEvent(doc, window,
NS_LITERAL_STRING("DOMWebNotificationClicked"),
true, true);
}
mNotification->DispatchTrustedEvent(NS_LITERAL_STRING("click"));
} else if (!strcmp("alertfinished", aTopic)) {
mNotification->mIsClosed = true;

Просмотреть файл

@ -8,6 +8,8 @@ const {classes: Cc, interfaces: Ci, utils: Cu, results: Cr} = Components;
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
Cu.import("resource://gre/modules/Services.jsm");
Cu.import("resource://gre/modules/NetUtil.jsm");
Cu.import("resource://gre/modules/FileUtils.jsm");
const NETWORKSERVICE_CONTRACTID = "@mozilla.org/network/service;1";
const NETWORKSERVICE_CID = Components.ID("{c14cabaf-bb8e-470d-a2f1-2cb6de6c5e5c}");
@ -52,7 +54,7 @@ function NetworkService() {
this.worker = new ChromeWorker("resource://gre/modules/net_worker.js");
this.worker.onmessage = this.handleWorkerMessage.bind(this);
this.worker.onerror = function onerror(event) {
if(DEBUG) debug("Received error from worker: " + event.filename +
if(DEBUG) debug("Received error from worker: " + event.filename +
":" + event.lineno + ": " + event.message + "\n");
// Prevent the event from bubbling any further.
event.preventDefault();
@ -107,18 +109,37 @@ NetworkService.prototype = {
getNetworkInterfaceStats: function(networkName, callback) {
if(DEBUG) debug("getNetworkInterfaceStats for " + networkName);
let file = new FileUtils.File("/proc/net/dev");
let params = {
cmd: "getNetworkInterfaceStats",
ifname: networkName
};
if (!file) {
callback.networkStatsAvailable(false, -1, -1, new Date());
return;
}
params.report = true;
params.isAsync = true;
NetUtil.asyncFetch(file, function(inputStream, status) {
let result = {
success: true, // netd always return success even interface doesn't exist.
rxBytes: 0,
txBytes: 0
};
result.date = new Date();
this.controlMessage(params, function(result) {
let success = !isError(result.resultCode);
callback.networkStatsAvailable(success, result.rxBytes,
if (Components.isSuccessCode(status)) {
// Find record for corresponding interface.
let statExpr = / +(\S+): +(\d+) +\d+ +\d+ +\d+ +\d+ +\d+ +\d+ +\d+ +(\d+) +\d+ +\d+ +\d+ +\d+ +\d+ +\d+ +\d+/;
let data = NetUtil.readInputStreamToString(inputStream,
inputStream.available()).split("\n");
for (let i = 2; i < data.length; i++) {
let parseResult = statExpr.exec(data[i]);
if (parseResult && parseResult[1] === networkName) {
result.rxBytes = parseInt(parseResult[2], 10);
result.txBytes = parseInt(parseResult[3], 10);
break;
}
}
}
callback.networkStatsAvailable(result.success, result.rxBytes,
result.txBytes, result.date);
});
},

Просмотреть файл

@ -2771,13 +2771,28 @@ RadioInterface.prototype = {
break;
case kNetworkInterfaceStateChangedTopic:
let network = subject.QueryInterface(Ci.nsINetworkInterface);
if (network.state == Ci.nsINetworkInterface.NETWORK_STATE_CONNECTED) {
// Check SNTP when we have data connection, this may not take
// effect immediately before the setting get enabled.
if (this._sntp.isExpired()) {
this._sntp.request();
if (network.state != Ci.nsINetworkInterface.NETWORK_STATE_CONNECTED) {
return;
}
// SNTP can only update when we have mobile or Wifi connections.
if (network.type != Ci.nsINetworkInterface.NETWORK_TYPE_WIFI &&
network.type != Ci.nsINetworkInterface.NETWORK_TYPE_MOBILE) {
return;
}
// If the network comes from RIL, make sure the RIL service is matched.
if (subject instanceof Ci.nsIRilNetworkInterface) {
network = subject.QueryInterface(Ci.nsIRilNetworkInterface);
if (network.serviceId != this.clientId) {
return;
}
}
// SNTP won't update unless the SNTP is already expired.
if (this._sntp.isExpired()) {
this._sntp.request();
}
break;
case kScreenStateChangedTopic:
this.workerMessenger.send("setScreenState", { on: (data === "on") });

Просмотреть файл

@ -142,19 +142,6 @@ function usbTetheringSuccess(params) {
return true;
}
function networkInterfaceStatsFail(params) {
// Notify the main thread.
postMessage(params);
return true;
}
function networkInterfaceStatsSuccess(params) {
// Notify the main thread.
params.txBytes = parseFloat(params.resultReason);
postMessage(params);
return true;
}
function networkInterfaceAlarmFail(params) {
// Notify the main thread.
postMessage(params);
@ -607,18 +594,6 @@ function stopSoftAP(params, callback) {
return doCommand(command, callback);
}
function getRxBytes(params, callback) {
let command = "interface readrxcounter " + params.ifname;
return doCommand(command, callback);
}
function getTxBytes(params, callback) {
params.rxBytes = parseFloat(params.resultReason);
let command = "interface readtxcounter " + params.ifname;
return doCommand(command, callback);
}
function enableAlarm(params, callback) {
let command = "bandwidth enable";
return doCommand(command, callback);
@ -933,24 +908,6 @@ function setUSBTethering(params) {
return true;
}
let gNetworkInterfaceStatsChain = [getRxBytes,
getTxBytes,
networkInterfaceStatsSuccess];
/**
* handling main thread's get network interface stats request
*/
function getNetworkInterfaceStats(params) {
debug("getNetworkInterfaceStats: " + params.ifname);
params.rxBytes = -1;
params.txBytes = -1;
params.date = new Date();
chain(params, gNetworkInterfaceStatsChain, networkInterfaceStatsFail);
return true;
}
let gNetworkInterfaceEnableAlarmChain = [enableAlarm,
setQuota,
setAlarm,

Просмотреть файл

@ -146,6 +146,21 @@ js::ParallelTestsShouldPass(JSContext *cx)
return false;
}
bool
js::intrinsic_SetForkJoinTargetRegion(JSContext *cx, unsigned argc, Value *vp)
{
return true;
}
static bool
intrinsic_SetForkJoinTargetRegionPar(ForkJoinSlice *slice, unsigned argc, Value *vp)
{
return true;
}
const JSJitInfo js::intrinsic_SetForkJoinTargetRegionInfo =
JS_JITINFO_NATIVE_PARALLEL(intrinsic_SetForkJoinTargetRegionPar);
#endif // !JS_THREADSAFE || !JS_ION
///////////////////////////////////////////////////////////////////////////

Просмотреть файл

@ -730,7 +730,7 @@ video > .caption-box {
position: relative;
overflow: hidden;
padding: 1.5%;
box-sizing: border-box;
-moz-box-sizing: border-box;
}
/* emulation of non-standard HTML <marquee> tag */

Просмотреть файл

@ -236,7 +236,7 @@
</activity>
#include ../services/manifests/AnnouncementsAndroidManifest_activities.xml.in
#include ../services/manifests/FxAccountAndroidManifest_services.xml.in
#include ../services/manifests/FxAccountAndroidManifest_activities.xml.in
#include ../services/manifests/SyncAndroidManifest_activities.xml.in
#include ../services/manifests/HealthReportAndroidManifest_activities.xml.in
@ -315,6 +315,7 @@
#include ../services/manifests/AnnouncementsAndroidManifest_services.xml.in
#include ../services/manifests/FxAccountAndroidManifest_services.xml.in
#include ../services/manifests/HealthReportAndroidManifest_services.xml.in
#include ../services/manifests/SyncAndroidManifest_services.xml.in

Просмотреть файл

@ -544,13 +544,9 @@ sync_java_files = [
'fxa/authenticator/FxAccountAuthenticator.java',
'fxa/authenticator/FxAccountAuthenticatorService.java',
'fxa/sync/FxAccount.java',
'fxa/sync/FxAccountBookmarksSyncService.java',
'fxa/sync/FxAccountGlobalSession.java',
'fxa/sync/FxAccountHistorySyncService.java',
'fxa/sync/FxAccountPasswordsSyncService.java',
'fxa/sync/FxAccountSyncAdapter.java',
'fxa/sync/FxAccountSyncService.java',
'fxa/sync/FxAccountTabsSyncService.java',
'sync/AlreadySyncingException.java',
'sync/BadRequiredFieldJSONException.java',
'sync/CollectionKeys.java',

Просмотреть файл

@ -43,9 +43,6 @@ public class FxAccountAuthenticator extends AbstractAccountAuthenticator {
protected static void enableSyncing(Context context, Account account) {
for (String authority : new String[] {
AppConstants.ANDROID_PACKAGE_NAME + ".db.browser",
AppConstants.ANDROID_PACKAGE_NAME + ".db.formhistory",
AppConstants.ANDROID_PACKAGE_NAME + ".db.tabs",
AppConstants.ANDROID_PACKAGE_NAME + ".db.passwords",
}) {
ContentResolver.setSyncAutomatically(account, authority, true);
ContentResolver.setIsSyncable(account, authority, 1);

Просмотреть файл

@ -1,9 +0,0 @@
/* 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/. */
package org.mozilla.gecko.fxa.sync;
public class FxAccountBookmarksSyncService extends FxAccountSyncService {
}

Просмотреть файл

@ -1,9 +0,0 @@
/* 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/. */
package org.mozilla.gecko.fxa.sync;
public class FxAccountHistorySyncService extends FxAccountSyncService {
}

Просмотреть файл

@ -1,9 +0,0 @@
/* 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/. */
package org.mozilla.gecko.fxa.sync;
public class FxAccountPasswordsSyncService extends FxAccountHistorySyncService {
}

Просмотреть файл

@ -8,7 +8,7 @@ import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
public abstract class FxAccountSyncService extends Service {
public class FxAccountSyncService extends Service {
private static final Object syncAdapterLock = new Object();
private static FxAccountSyncAdapter syncAdapter = null;

Просмотреть файл

@ -1,9 +0,0 @@
/* 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/. */
package org.mozilla.gecko.fxa.sync;
public class FxAccountTabsSyncService extends FxAccountSyncService {
}

Просмотреть файл

@ -234,15 +234,19 @@ public final class BitmapUtils {
float[] sumHue = new float[36];
float[] sumSat = new float[36];
float[] sumVal = new float[36];
float[] hsv = new float[3];
for (int row = 0; row < source.getHeight(); row++) {
for (int col = 0; col < source.getWidth(); col++) {
int c = source.getPixel(col, row);
int height = source.getHeight();
int width = source.getWidth();
int[] pixels = new int[width * height];
source.getPixels(pixels, 0, width, 0, 0, width, height);
for (int row = 0; row < height; row++) {
for (int col = 0; col < width; col++) {
int c = pixels[col + row * width];
// Ignore pixels with a certain transparency.
if (Color.alpha(c) < 128)
continue;
float[] hsv = new float[3];
Color.colorToHSV(c, hsv);
// If a threshold is applied, ignore arbitrarily chosen values for "white" and "black".
@ -271,7 +275,6 @@ public final class BitmapUtils {
return Color.argb(255,255,255,255);
// Return a color with the average hue/saturation/value of the bin with the most colors.
float[] hsv = new float[3];
hsv[0] = sumHue[maxBin]/colorBins[maxBin];
hsv[1] = sumSat[maxBin]/colorBins[maxBin];
hsv[2] = sumVal[maxBin]/colorBins[maxBin];

Просмотреть файл

@ -30,10 +30,10 @@ import android.widget.ListView;
import java.util.EnumSet;
/**
* Fragment that displays custom lists.
* Fragment that displays dynamic content specified by a PanelConfig.
*/
public class ListPanel extends HomeFragment {
private static final String LOGTAG = "GeckoListPanel";
public class DynamicPanel extends HomeFragment {
private static final String LOGTAG = "GeckoDynamicPanel";
// Cursor loader ID for the lists
private static final int LOADER_ID_LIST = 0;
@ -41,10 +41,9 @@ public class ListPanel extends HomeFragment {
// The configuration associated with this panel
private PanelConfig mPanelConfig;
// Adapter for the list
// XXX: Right now DynamicPanel is hard-coded to show a single ListView,
// but it should dynamically build views from mPanelConfig (bug 959777).
private HomeListAdapter mAdapter;
// The view shown by the fragment
private ListView mList;
// Callbacks used for the list loader
@ -82,12 +81,13 @@ public class ListPanel extends HomeFragment {
}
if (mPanelConfig == null) {
throw new IllegalStateException("Can't create a ListPanel without a PanelConfig");
throw new IllegalStateException("Can't create a DynamicPanel without a PanelConfig");
}
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
// XXX: Dynamically build views from mPanelConfig (bug 959777).
mList = new HomeListView(getActivity());
return mList;
}
@ -122,6 +122,7 @@ public class ListPanel extends HomeFragment {
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
// XXX: Dynamically set adapters from mPanelConfig (bug 959777).
mAdapter = new HomeListAdapter(getActivity(), null);
mList.setAdapter(mAdapter);

Просмотреть файл

@ -167,8 +167,8 @@ class HomeAdapter extends FragmentStatePagerAdapter {
args.putBoolean(HomePager.CAN_LOAD_ARG, mCanLoadHint);
// Only ListPanel's need the PanelConfig argument
if (mPanelConfig.getType() == PanelType.LIST) {
// Only DynamicPanels need the PanelConfig argument
if (mPanelConfig.getType() == PanelType.DYNAMIC) {
args.putParcelable(HomePager.PANEL_CONFIG_ARG, mPanelConfig);
}

Просмотреть файл

@ -14,12 +14,18 @@ import java.util.EnumSet;
import java.util.List;
final class HomeConfig {
/**
* Used to determine what type of HomeFragment subclass to use when creating
* a given panel. With the exception of DYNAMIC, all of these types correspond
* to a default set of built-in panels. The DYNAMIC panel type is used by
* third-party services to create panels with varying types of content.
*/
public static enum PanelType implements Parcelable {
TOP_SITES("top_sites", TopSitesPanel.class),
BOOKMARKS("bookmarks", BookmarksPanel.class),
HISTORY("history", HistoryPanel.class),
READING_LIST("reading_list", ReadingListPanel.class),
LIST("list", ListPanel.class);
DYNAMIC("dynamic", DynamicPanel.class);
private final String mId;
private final Class<?> mPanelClass;
@ -93,14 +99,6 @@ final class HomeConfig {
mFlags = (EnumSet<Flags>) in.readSerializable();
}
public PanelConfig(PanelType type, String title) {
this(type, title, EnumSet.noneOf(Flags.class));
}
public PanelConfig(PanelType type, String title, EnumSet<Flags> flags) {
this(type, title, type.toString(), flags);
}
public PanelConfig(PanelType type, String title, String id) {
this(type, title, id, EnumSet.noneOf(Flags.class));
}

Просмотреть файл

@ -41,6 +41,12 @@ class HomeConfigPrefsBackend implements HomeConfigBackend {
private static final int IS_DEFAULT = 1;
// UUIDs used to create PanelConfigs for default built-in panels
private static final String TOP_SITES_PANEL_ID = "4becc86b-41eb-429a-a042-88fe8b5a094e";
private static final String BOOKMARKS_PANEL_ID = "7f6d419a-cd6c-4e34-b26f-f68b1b551907";
private static final String READING_LIST_PANEL_ID = "20f4549a-64ad-4c32-93e4-1dcef792733b";
private static final String HISTORY_PANEL_ID = "f134bf20-11f7-4867-ab8b-e8e705d7fbe8";
private final Context mContext;
private PrefsListener mPrefsListener;
private OnChangeListener mChangeListener;
@ -57,21 +63,25 @@ class HomeConfigPrefsBackend implements HomeConfigBackend {
final ArrayList<PanelConfig> panelConfigs = new ArrayList<PanelConfig>();
panelConfigs.add(new PanelConfig(PanelType.TOP_SITES,
mContext.getString(R.string.home_top_sites_title),
EnumSet.of(PanelConfig.Flags.DEFAULT_PANEL)));
mContext.getString(R.string.home_top_sites_title),
TOP_SITES_PANEL_ID,
EnumSet.of(PanelConfig.Flags.DEFAULT_PANEL)));
panelConfigs.add(new PanelConfig(PanelType.BOOKMARKS,
mContext.getString(R.string.bookmarks_title)));
mContext.getString(R.string.bookmarks_title),
BOOKMARKS_PANEL_ID));
// We disable reader mode support on low memory devices. Hence the
// reading list panel should not show up on such devices.
if (!HardwareUtils.isLowMemoryPlatform()) {
panelConfigs.add(new PanelConfig(PanelType.READING_LIST,
mContext.getString(R.string.reading_list_title)));
mContext.getString(R.string.reading_list_title),
READING_LIST_PANEL_ID));
}
final PanelConfig historyEntry = new PanelConfig(PanelType.HISTORY,
mContext.getString(R.string.home_history_title));
mContext.getString(R.string.home_history_title),
HISTORY_PANEL_ID);
// On tablets, the history panel is the last.
// On phones, the history panel is the first one.

Просмотреть файл

@ -210,6 +210,7 @@ gbjar.sources += [
'home/BookmarksListView.java',
'home/BookmarksPanel.java',
'home/BrowserSearch.java',
'home/DynamicPanel.java',
'home/FadedTextView.java',
'home/HistoryPanel.java',
'home/HomeAdapter.java',
@ -222,7 +223,6 @@ gbjar.sources += [
'home/HomePager.java',
'home/HomePagerTabStrip.java',
'home/LastTabsPanel.java',
'home/ListPanel.java',
'home/MostRecentPanel.java',
'home/MultiTypeCursorAdapter.java',
'home/PanelManager.java',

Просмотреть файл

@ -0,0 +1,8 @@
<?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 xmlns:android="http://schemas.android.com/apk/res/android">
<style name="FxAccountTheme" parent="@style/Gecko" />
</resources>

Просмотреть файл

@ -1,12 +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/. -->
<sync-adapter xmlns:android="http://schemas.android.com/apk/res/android"
android:accountType="@string/moz_android_shared_fxaccount_type"
android:contentAuthority="@string/content_authority_db_formhistory"
android:isAlwaysSyncable="true"
android:supportsUploading="true"
android:userVisible="true"
/>

Просмотреть файл

@ -1,12 +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/. -->
<sync-adapter xmlns:android="http://schemas.android.com/apk/res/android"
android:accountType="@string/moz_android_shared_fxaccount_type"
android:contentAuthority="@string/content_authority_db_passwords"
android:isAlwaysSyncable="true"
android:supportsUploading="true"
android:userVisible="true"
/>

Просмотреть файл

@ -1,12 +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/. -->
<sync-adapter xmlns:android="http://schemas.android.com/apk/res/android"
android:accountType="@string/moz_android_shared_fxaccount_type"
android:contentAuthority="@string/content_authority_db_tabs"
android:isAlwaysSyncable="true"
android:supportsUploading="true"
android:userVisible="true"
/>

Просмотреть файл

@ -67,7 +67,7 @@ public class UpgradeReceiver extends BroadcastReceiver {
final String product = GlobalConstants.BROWSER_INTENT_PACKAGE;
final String username = params.username;
final String serverURL = params.serverURL;
final String profile = Constants.DEFAULT_PROFILE;
final String profile = "default";
try {
ConfigurationMigrator.ensurePrefsAreVersion(SyncConfiguration.CURRENT_PREFS_VERSION, context, accountManager, account,
product, username, serverURL, profile);

Просмотреть файл

@ -11,45 +11,12 @@
</service>
<service
android:exported="false"
android:name="org.mozilla.gecko.fxa.sync.FxAccountBookmarksSyncService" >
android:name="org.mozilla.gecko.fxa.sync.FxAccountSyncService" >
<intent-filter >
<action android:name="android.content.SyncAdapter" />
</intent-filter>
<meta-data
android:name="android.content.SyncAdapter"
android:resource="@xml/fxaccount_bookmarks_syncadapter" />
</service>
<service
android:exported="false"
android:name="org.mozilla.gecko.fxa.sync.FxAccountHistorySyncService" >
<intent-filter >
<action android:name="android.content.SyncAdapter" />
</intent-filter>
<meta-data
android:name="android.content.SyncAdapter"
android:resource="@xml/fxaccount_history_syncadapter" />
</service>
<service
android:exported="false"
android:name="org.mozilla.gecko.fxa.sync.FxAccountPasswordsSyncService" >
<intent-filter >
<action android:name="android.content.SyncAdapter" />
</intent-filter>
<meta-data
android:name="android.content.SyncAdapter"
android:resource="@xml/fxaccount_passwords_syncadapter" />
</service>
<service
android:exported="false"
android:name="org.mozilla.gecko.fxa.sync.FxAccountTabsSyncService" >
<intent-filter >
<action android:name="android.content.SyncAdapter" />
</intent-filter>
<meta-data
android:name="android.content.SyncAdapter"
android:resource="@xml/fxaccount_tabs_syncadapter" />
android:resource="@xml/fxaccount_syncadapter" />
</service>

Просмотреть файл

@ -508,7 +508,7 @@ class Marionette(object):
gecko_path=gecko_path,
busybox=busybox)
def __del__(self):
def cleanup(self):
if self.emulator:
self.emulator.close()
if self.instance:
@ -516,6 +516,9 @@ class Marionette(object):
for qemu in self.extra_emulators:
qemu.emulator.close()
def __del__(self):
self.cleanup()
@staticmethod
def is_port_available(port, host=''):
port = int(port)

Просмотреть файл

@ -746,7 +746,9 @@ class BaseMarionetteTestRunner(object):
if self.marionette.instance:
self.marionette.instance.close()
self.marionette.instance = None
del self.marionette
self.marionette.cleanup()
for run_tests in self.mixin_run_tests:
run_tests(tests)

Просмотреть файл

@ -17,6 +17,7 @@
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <gdk/gdkkeysyms.h>
#include <algorithm>
#include <string>
@ -27,6 +28,10 @@
#include "crashreporter.h"
#include "crashreporter_gtk_common.h"
#ifndef GDK_KEY_Escape
#define GDK_KEY_Escape GDK_Escape
#endif
using std::string;
using std::vector;
@ -215,14 +220,25 @@ gpointer SendThread(gpointer args)
}
gboolean WindowDeleted(GtkWidget* window,
GdkEvent* event,
gpointer userData)
GdkEvent* event,
gpointer userData)
{
SaveSettings();
gtk_main_quit();
return TRUE;
}
gboolean check_escape(GtkWidget* window,
GdkEventKey* event,
gpointer userData)
{
if (event->keyval == GDK_KEY_Escape) {
gtk_main_quit();
return TRUE;
}
return FALSE;
}
static void MaybeSubmitReport()
{
if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(gSubmitReportCheck))) {

Просмотреть файл

@ -39,6 +39,7 @@ gpointer SendThread(gpointer args);
gboolean WindowDeleted(GtkWidget* window,
GdkEvent* event,
gpointer userData);
gboolean check_escape(GtkWidget* window, GdkEventKey* event, gpointer data);
void SubmitReportChecked(GtkButton* sender, gpointer userData);
void IncludeURLClicked(GtkButton* sender, gpointer userData);
void CloseClicked(GtkButton* button,

Просмотреть файл

@ -396,6 +396,7 @@ bool UIShowCrashUI(const string& dumpfile,
gtk_window_set_position(GTK_WINDOW(gWindow), GTK_WIN_POS_CENTER);
gtk_container_set_border_width(GTK_CONTAINER(gWindow), 12);
g_signal_connect(gWindow, "delete-event", G_CALLBACK(WindowDeleted), 0);
g_signal_connect(gWindow, "key_press_event", G_CALLBACK(check_escape), nullptr);
GtkWidget* vbox = gtk_vbox_new(FALSE, 6);
gtk_container_add(GTK_CONTAINER(gWindow), vbox);

Просмотреть файл

@ -299,16 +299,18 @@
}
var ltk = lastToken.type.keyword;
if (ltk != null
&& ltk != "debugger"
&& ltk != "null"
&& ltk != "true"
&& ltk != "false"
&& ltk != "this"
&& ltk != "break"
&& ltk != "continue"
&& ltk != "default") {
return true;
if (ltk != null) {
if (ltk == "break" || ltk == "continue") {
return token.type.type != ";";
}
if (ltk != "debugger"
&& ltk != "null"
&& ltk != "true"
&& ltk != "false"
&& ltk != "this"
&& ltk != "default") {
return true;
}
}
if (ltt == ")" && (token.type.type != ")"

Просмотреть файл

@ -218,7 +218,7 @@ var testCases = [
{
name: "Continue/break statements",
input: "while(1){if(x){continue}if(y){break}}",
input: "while(1){if(x){continue}if(y){break}if(z){break foo}}",
output: "while (1) {\n" +
" if (x) {\n" +
" continue\n" +
@ -226,6 +226,9 @@ var testCases = [
" if (y) {\n" +
" break\n" +
" }\n" +
" if (z) {\n" +
" break foo\n" +
" }\n" +
"}\n"
},

Просмотреть файл

@ -180,26 +180,39 @@ let HighlighterActor = protocol.ActorClass({
return this._walker.attachElement(node);
},
/**
* Get the right target for listening to mouse events while in pick mode.
* - On a firefox desktop content page: tabActor is a BrowserTabActor from
* which the browser property will give us a target we can use to listen to
* events, even in nested iframes.
* - On B2G: tabActor is a ContentAppActor which doesn't have a browser but
* since it overrides BrowserTabActor, it does get a browser property
* anyway, which points to its window object.
* - When using the Browser Toolbox (to inspect firefox desktop): tabActor is
* the RootActor, in which case, the window property can be used to listen
* to events
*/
_getPickerListenerTarget: function() {
let actor = this._tabActor;
return actor.isRootActor ? actor.window : actor.browser;
},
_startPickerListeners: function() {
// Note that on b2g devices, tabActor.browser actually returns a window
// object since the browser is in a separate process anyway.
// In any case, adding the event listener will work, although it won't
// fire for elements nested inside iframes
let browser = this._tabActor.browser;
browser.addEventListener("mousemove", this._onHovered, true);
browser.addEventListener("click", this._onPick, true);
browser.addEventListener("mousedown", this._preventContentEvent, true);
browser.addEventListener("mouseup", this._preventContentEvent, true);
browser.addEventListener("dblclick", this._preventContentEvent, true);
let target = this._getPickerListenerTarget();
target.addEventListener("mousemove", this._onHovered, true);
target.addEventListener("click", this._onPick, true);
target.addEventListener("mousedown", this._preventContentEvent, true);
target.addEventListener("mouseup", this._preventContentEvent, true);
target.addEventListener("dblclick", this._preventContentEvent, true);
},
_stopPickerListeners: function() {
let browser = this._tabActor.browser;
browser.removeEventListener("mousemove", this._onHovered, true);
browser.removeEventListener("click", this._onPick, true);
browser.removeEventListener("mousedown", this._preventContentEvent, true);
browser.removeEventListener("mouseup", this._preventContentEvent, true);
browser.removeEventListener("dblclick", this._preventContentEvent, true);
let target = this._getPickerListenerTarget();
target.removeEventListener("mousemove", this._onHovered, true);
target.removeEventListener("click", this._onPick, true);
target.removeEventListener("mousedown", this._preventContentEvent, true);
target.removeEventListener("mouseup", this._preventContentEvent, true);
target.removeEventListener("dblclick", this._preventContentEvent, true);
},
cancelPick: method(function() {

Просмотреть файл

@ -17,6 +17,10 @@
#include "nsIAppStartup.h"
#include "nsToolkitCompsCID.h"
#include <shellapi.h>
#include "nsIDOMWakeLockListener.h"
#include "nsIPowerManagerService.h"
#include "mozilla/StaticPtr.h"
#include <windows.system.display.h>
using namespace mozilla;
using namespace mozilla::widget;
@ -46,6 +50,33 @@ namespace widget {
extern UINT sAppShellGeckoMsgId;
} }
class WakeLockListener : public nsIDOMMozWakeLockListener {
public:
NS_DECL_ISUPPORTS;
private:
ComPtr<ABI::Windows::System::Display::IDisplayRequest> mDisplayRequest;
NS_IMETHOD Callback(const nsAString& aTopic, const nsAString& aState) {
if (!mDisplayRequest) {
if (FAILED(ActivateGenericInstance(RuntimeClass_Windows_System_Display_DisplayRequest, mDisplayRequest))) {
NS_WARNING("Failed to instantiate IDisplayRequest, wakelocks will be broken!");
return NS_OK;
}
}
if (aState.Equals(NS_LITERAL_STRING("locked-foreground"))) {
mDisplayRequest->RequestActive();
} else {
mDisplayRequest->RequestRelease();
}
return NS_OK;
}
};
NS_IMPL_ISUPPORTS1(WakeLockListener, nsIDOMMozWakeLockListener)
StaticRefPtr<WakeLockListener> sWakeLockListener;
static ComPtr<ICoreWindowStatic> sCoreStatic;
static bool sIsDispatching = false;
static bool sShouldPurgeThreadQueue = false;
@ -196,11 +227,27 @@ MetroAppShell::Run(void)
rv = NS_ERROR_NOT_IMPLEMENTED;
break;
case GeckoProcessType_Default: {
nsCOMPtr<nsIPowerManagerService> sPowerManagerService = do_GetService(POWERMANAGERSERVICE_CONTRACTID);
if (sPowerManagerService) {
sWakeLockListener = new WakeLockListener();
sPowerManagerService->AddWakeLockListener(sWakeLockListener);
}
else {
NS_WARNING("Failed to retrieve PowerManagerService, wakelocks will be broken!");
}
mozilla::widget::StartAudioSession();
sFrameworkView->ActivateView();
rv = nsBaseAppShell::Run();
mozilla::widget::StopAudioSession();
if (sPowerManagerService) {
sPowerManagerService->RemoveWakeLockListener(sWakeLockListener);
sPowerManagerService = nullptr;
sWakeLockListener = nullptr;
}
nsCOMPtr<nsIAppStartup> appStartup (do_GetService(NS_APPSTARTUP_CONTRACTID));
bool restartingInMetro = false, restartingInDesktop = false;

Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше