Merge m-c to inbound.
|
@ -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};
|
||||
}
|
||||
};
|
||||
})();
|
|
@ -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("-");
|
||||
})();
|
|
@ -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 == "<" ? "<" : "&"; });
|
||||
}
|
||||
|
||||
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 |
После Ширина: | Высота: | Размер: 1.8 KiB |
После Ширина: | Высота: | Размер: 2.1 KiB |
После Ширина: | Высота: | Размер: 943 B |
После Ширина: | Высота: | Размер: 2.1 KiB |
После Ширина: | Высота: | Размер: 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;
|
||||
|
||||
|
|