mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
merge fx-team to mozilla-central
This commit is contained in:
commit
10cb29314e
@ -779,4 +779,11 @@ const CustomizableWidgets = [{
|
||||
};
|
||||
CustomizableUI.addListener(listener);
|
||||
}
|
||||
}, {
|
||||
id: "email-link-button",
|
||||
removable: true,
|
||||
onCommand: function(aEvent) {
|
||||
let win = aEvent.view;
|
||||
win.MailIntegration.sendLinkForWindow(win.content);
|
||||
}
|
||||
}];
|
||||
|
@ -15,6 +15,7 @@ const kAboutURI = "about:customizing";
|
||||
const kDragDataTypePrefix = "text/toolbarwrapper-id/";
|
||||
const kPlaceholderClass = "panel-customization-placeholder";
|
||||
const kSkipSourceNodePref = "browser.uiCustomization.skipSourceNodeCheck";
|
||||
const kMaxTransitionDurationMs = 2000;
|
||||
|
||||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
Cu.import("resource:///modules/CustomizableUI.jsm");
|
||||
@ -322,9 +323,11 @@ CustomizeMode.prototype = {
|
||||
let deck = this.document.getElementById("tab-view-deck");
|
||||
|
||||
let customizeTransitionEnd = function(aEvent) {
|
||||
if (aEvent.originalTarget != deck || aEvent.propertyName != "padding-bottom") {
|
||||
if (aEvent != "timedout" &&
|
||||
(aEvent.originalTarget != deck || aEvent.propertyName != "padding-bottom")) {
|
||||
return;
|
||||
}
|
||||
this.window.clearTimeout(catchAllTimeout);
|
||||
deck.removeEventListener("transitionend", customizeTransitionEnd);
|
||||
|
||||
if (!aEntering) {
|
||||
@ -350,6 +353,9 @@ CustomizeMode.prototype = {
|
||||
this.document.documentElement.setAttribute("customize-exiting", true);
|
||||
this.document.documentElement.removeAttribute("customize-entered");
|
||||
}
|
||||
|
||||
let catchAll = () => customizeTransitionEnd("timedout");
|
||||
let catchAllTimeout = this.window.setTimeout(catchAll, kMaxTransitionDurationMs);
|
||||
return deferred.promise;
|
||||
},
|
||||
|
||||
@ -359,7 +365,17 @@ CustomizeMode.prototype = {
|
||||
let result = this.window.gNavToolbox.dispatchEvent(evt);
|
||||
},
|
||||
|
||||
_getCustomizableChildForNode: function(aNode) {
|
||||
let area = this._getCustomizableParent(aNode);
|
||||
area = area.customizationTarget || area;
|
||||
while (aNode && aNode.parentNode != area) {
|
||||
aNode = aNode.parentNode;
|
||||
}
|
||||
return aNode;
|
||||
},
|
||||
|
||||
addToToolbar: function(aNode) {
|
||||
aNode = this._getCustomizableChildForNode(aNode);
|
||||
if (aNode.localName == "toolbarpaletteitem" && aNode.firstChild) {
|
||||
aNode = aNode.firstChild;
|
||||
}
|
||||
@ -367,6 +383,7 @@ CustomizeMode.prototype = {
|
||||
},
|
||||
|
||||
addToPanel: function(aNode) {
|
||||
aNode = this._getCustomizableChildForNode(aNode);
|
||||
if (aNode.localName == "toolbarpaletteitem" && aNode.firstChild) {
|
||||
aNode = aNode.firstChild;
|
||||
}
|
||||
@ -374,6 +391,7 @@ CustomizeMode.prototype = {
|
||||
},
|
||||
|
||||
removeFromArea: function(aNode) {
|
||||
aNode = this._getCustomizableChildForNode(aNode);
|
||||
if (aNode.localName == "toolbarpaletteitem" && aNode.firstChild) {
|
||||
aNode = aNode.firstChild;
|
||||
}
|
||||
@ -539,7 +557,13 @@ CustomizeMode.prototype = {
|
||||
deferredUnwrapToolbarItem: function(aWrapper) {
|
||||
let deferred = Promise.defer();
|
||||
dispatchFunction(function() {
|
||||
deferred.resolve(this.unwrapToolbarItem(aWrapper));
|
||||
let item = null;
|
||||
try {
|
||||
item = this.unwrapToolbarItem(aWrapper);
|
||||
} catch (ex) {
|
||||
Cu.reportError(ex);
|
||||
}
|
||||
deferred.resolve(item);
|
||||
}.bind(this));
|
||||
return deferred.promise;
|
||||
},
|
||||
|
@ -71,6 +71,32 @@ let gTests = [
|
||||
},
|
||||
teardown: null
|
||||
},
|
||||
{
|
||||
desc: "Right-click on the searchbar and moving it to the menu and back should move the search-container instead.",
|
||||
run: function() {
|
||||
let searchbar = document.getElementById("searchbar");
|
||||
gCustomizeMode.addToPanel(searchbar);
|
||||
let placement = CustomizableUI.getPlacementOfWidget("search-container");
|
||||
is(placement.area, CustomizableUI.AREA_PANEL, "Should be in panel");
|
||||
|
||||
let shownPanelPromise = promisePanelShown(window);
|
||||
PanelUI.toggle({type: "command"});
|
||||
yield shownPanelPromise;
|
||||
let hiddenPanelPromise = promisePanelHidden(window);
|
||||
PanelUI.toggle({type: "command"});
|
||||
yield hiddenPanelPromise;
|
||||
|
||||
gCustomizeMode.addToToolbar(searchbar);
|
||||
placement = CustomizableUI.getPlacementOfWidget("search-container");
|
||||
is(placement.area, CustomizableUI.AREA_NAVBAR, "Should be in navbar");
|
||||
gCustomizeMode.removeFromArea(searchbar);
|
||||
placement = CustomizableUI.getPlacementOfWidget("search-container");
|
||||
is(placement, null, "Should be in palette");
|
||||
CustomizableUI.reset();
|
||||
placement = CustomizableUI.getPlacementOfWidget("search-container");
|
||||
is(placement.area, CustomizableUI.AREA_NAVBAR, "Should be in navbar");
|
||||
}
|
||||
},
|
||||
{
|
||||
desc: "Right-click on an item within the menu panel should show a context menu with options to move it.",
|
||||
setup: null,
|
||||
|
@ -39,6 +39,14 @@
|
||||
background: rgba(255,0,0,0.2);
|
||||
}
|
||||
|
||||
.CodeMirror {
|
||||
cursor: text;
|
||||
}
|
||||
|
||||
.CodeMirror-gutters {
|
||||
cursor: default;
|
||||
}
|
||||
|
||||
/* This is to avoid the fake horizontal scrollbar div of codemirror to go 0
|
||||
height when floating scrollbars are active. Make sure that this value is equal
|
||||
to the maximum of `min-height` specific to the `scrollbar[orient="horizontal"]`
|
||||
|
@ -122,20 +122,23 @@ function Editor(config) {
|
||||
|
||||
this.version = null;
|
||||
this.config = {
|
||||
value: "",
|
||||
mode: Editor.modes.text,
|
||||
indentUnit: tabSize,
|
||||
tabSize: tabSize,
|
||||
contextMenu: null,
|
||||
matchBrackets: true,
|
||||
extraKeys: {},
|
||||
indentWithTabs: useTabs,
|
||||
styleActiveLine: true,
|
||||
theme: "mozilla"
|
||||
value: "",
|
||||
mode: Editor.modes.text,
|
||||
indentUnit: tabSize,
|
||||
tabSize: tabSize,
|
||||
contextMenu: null,
|
||||
matchBrackets: true,
|
||||
extraKeys: {},
|
||||
indentWithTabs: useTabs,
|
||||
styleActiveLine: true,
|
||||
autoCloseBrackets: true,
|
||||
theme: "mozilla"
|
||||
};
|
||||
|
||||
// Additional shortcuts.
|
||||
this.config.extraKeys[Editor.keyFor("jumpToLine")] = (cm) => this.jumpToLine(cm);
|
||||
this.config.extraKeys[Editor.keyFor("moveLineUp")] = (cm) => this.moveLineUp();
|
||||
this.config.extraKeys[Editor.keyFor("moveLineDown")] = (cm) => this.moveLineDown();
|
||||
this.config.extraKeys[Editor.keyFor("toggleComment")] = "toggleComment";
|
||||
|
||||
// Disable ctrl-[ and ctrl-] because toolbox uses those shortcuts.
|
||||
@ -636,6 +639,65 @@ Editor.prototype = {
|
||||
this.openDialog(div, (line) => this.setCursor({ line: line - 1, ch: 0 }));
|
||||
},
|
||||
|
||||
/**
|
||||
* Moves the content of the current line or the lines selected up a line.
|
||||
*/
|
||||
moveLineUp: function () {
|
||||
let cm = editors.get(this);
|
||||
let start = cm.getCursor("start");
|
||||
let end = cm.getCursor("end");
|
||||
|
||||
if (start.line === 0)
|
||||
return;
|
||||
|
||||
// Get the text in the lines selected or the current line of the cursor
|
||||
// and append the text of the previous line.
|
||||
let value;
|
||||
if (start.line !== end.line) {
|
||||
value = cm.getRange({ line: start.line, ch: 0 },
|
||||
{ line: end.line, ch: cm.getLine(end.line).length }) + "\n";
|
||||
} else {
|
||||
value = cm.getLine(start.line) + "\n";
|
||||
}
|
||||
value += cm.getLine(start.line - 1);
|
||||
|
||||
// Replace the previous line and the currently selected lines with the new
|
||||
// value and maintain the selection of the text.
|
||||
cm.replaceRange(value, { line: start.line - 1, ch: 0 },
|
||||
{ line: end.line, ch: cm.getLine(end.line).length });
|
||||
cm.setSelection({ line: start.line - 1, ch: start.ch },
|
||||
{ line: end.line - 1, ch: end.ch });
|
||||
},
|
||||
|
||||
/**
|
||||
* Moves the content of the current line or the lines selected down a line.
|
||||
*/
|
||||
moveLineDown: function () {
|
||||
let cm = editors.get(this);
|
||||
let start = cm.getCursor("start");
|
||||
let end = cm.getCursor("end");
|
||||
|
||||
if (end.line + 1 === cm.lineCount())
|
||||
return;
|
||||
|
||||
// Get the text of next line and append the text in the lines selected
|
||||
// or the current line of the cursor.
|
||||
let value = cm.getLine(end.line + 1) + "\n";
|
||||
if (start.line !== end.line) {
|
||||
value += cm.getRange({ line: start.line, ch: 0 },
|
||||
{ line: end.line, ch: cm.getLine(end.line).length });
|
||||
} else {
|
||||
value += cm.getLine(start.line);
|
||||
}
|
||||
|
||||
// Replace the currently selected lines and the next line with the new
|
||||
// value and maintain the selection of the text.
|
||||
cm.replaceRange(value, { line: start.line, ch: 0 },
|
||||
{ line: end.line + 1, ch: cm.getLine(end.line + 1).length});
|
||||
cm.setSelection({ line: start.line + 1, ch: start.ch },
|
||||
{ line: end.line + 1, ch: end.ch });
|
||||
},
|
||||
|
||||
/**
|
||||
* Extends an instance of the Editor object with additional
|
||||
* functions. Each function will be called with context as
|
||||
|
@ -13,5 +13,6 @@ support-files =
|
||||
[browser_editor_cursor.js]
|
||||
[browser_editor_history.js]
|
||||
[browser_editor_markers.js]
|
||||
[browser_editor_movelines.js]
|
||||
[browser_codemirror.js]
|
||||
[browser_sourceeditor_initialization.js]
|
||||
|
@ -0,0 +1,62 @@
|
||||
/* vim: set ts=2 et sw=2 tw=80: */
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
"use strict";
|
||||
|
||||
function test() {
|
||||
waitForExplicitFinish();
|
||||
setup((ed, win) => {
|
||||
var simpleProg = "function foo() {\n let i = 1;\n let j = 2;\n return bar;\n}";
|
||||
ed.setText(simpleProg);
|
||||
|
||||
// Move first line up
|
||||
ed.setCursor({ line: 0, ch: 0 });
|
||||
ed.moveLineUp();
|
||||
is(ed.getText(0), "function foo() {", "getText(num)");
|
||||
ch(ed.getCursor(), { line: 0, ch: 0 }, "getCursor");
|
||||
|
||||
// Move last line down
|
||||
ed.setCursor({ line: 4, ch: 0 });
|
||||
ed.moveLineDown();
|
||||
is(ed.getText(4), "}", "getText(num)");
|
||||
ch(ed.getCursor(), { line: 4, ch: 0 }, "getCursor");
|
||||
|
||||
// Move line 2 up
|
||||
ed.setCursor({ line: 1, ch: 5});
|
||||
ed.moveLineUp();
|
||||
is(ed.getText(0), " let i = 1;", "getText(num)");
|
||||
is(ed.getText(1), "function foo() {", "getText(num)");
|
||||
ch(ed.getCursor(), { line: 0, ch: 5 }, "getCursor");
|
||||
|
||||
// Undo previous move by moving line 1 down
|
||||
ed.moveLineDown();
|
||||
is(ed.getText(0), "function foo() {", "getText(num)");
|
||||
is(ed.getText(1), " let i = 1;", "getText(num)");
|
||||
ch(ed.getCursor(), { line: 1, ch: 5 }, "getCursor");
|
||||
|
||||
// Move line 2 and 3 up
|
||||
ed.setSelection({ line: 1, ch: 0 }, { line: 2, ch: 0 });
|
||||
ed.moveLineUp();
|
||||
is(ed.getText(0), " let i = 1;", "getText(num)");
|
||||
is(ed.getText(1), " let j = 2;", "getText(num)");
|
||||
is(ed.getText(2), "function foo() {", "getText(num)");
|
||||
ch(ed.getCursor("start"), { line: 0, ch: 0 }, "getCursor(string)");
|
||||
ch(ed.getCursor("end"), { line: 1, ch: 0 }, "getCursor(string)");
|
||||
|
||||
// Move line 1 to 3 down twice
|
||||
ed.dropSelection();
|
||||
ed.setSelection({ line: 0, ch: 7 }, { line: 2, ch: 5 });
|
||||
ed.moveLineDown();
|
||||
ed.moveLineDown();
|
||||
is(ed.getText(0), " return bar;", "getText(num)");
|
||||
is(ed.getText(1), "}", "getText(num)");
|
||||
is(ed.getText(2), " let i = 1;", "getText(num)");
|
||||
is(ed.getText(3), " let j = 2;", "getText(num)");
|
||||
is(ed.getText(4), "function foo() {", "getText(num)");
|
||||
ch(ed.getCursor("start"), { line: 2, ch: 7 }, "getCursor(string)");
|
||||
ch(ed.getCursor("end"), { line: 4, ch: 5 }, "getCursor(string)");
|
||||
|
||||
teardown(ed, win);
|
||||
});
|
||||
}
|
@ -74,3 +74,6 @@ feed-button.tooltiptext = Subscribe to this page…
|
||||
|
||||
characterencoding-button.label = Character Encoding
|
||||
characterencoding-button.tooltiptext = Character encoding
|
||||
|
||||
email-link-button.label = Email Link
|
||||
email-link-button.tooltiptext = Email Link
|
||||
|
@ -73,4 +73,14 @@ indentLess.commandkey=[
|
||||
# the Toolbox to switch between tools
|
||||
#
|
||||
# DO NOT translate this key without proper synchronization with toolbox.dtd.
|
||||
indentMore.commandkey=]
|
||||
indentMore.commandkey=]
|
||||
|
||||
# LOCALIZATION NOTE (moveLineUp.commandkey): This the key to use in
|
||||
# conjunction with accel (Command on Mac or Ctrl on other platforms) to move
|
||||
# the selected lines up.
|
||||
moveLineUp.commandkey=Alt-Up
|
||||
|
||||
# LOCALIZATION NOTE (moveLineDown.commandkey): This the key to use in
|
||||
# conjunction with accel (Command on Mac or Ctrl on other platforms) to move
|
||||
# the selected lines down.
|
||||
moveLineDown.commandkey=Alt-Down
|
||||
|
@ -15,7 +15,7 @@
|
||||
|
||||
<content>
|
||||
<xul:stack>
|
||||
<xul:toolbarbutton anonid="progressButton" class="circularprogressindicator-progressButton appbar-secondary"/>
|
||||
<xul:toolbarbutton anonid="progressButton" class="circularprogressindicator-progressButton"/>
|
||||
<html:div anonid="progressTrack" xbl:inherits="progress" class="circularprogressindicator-progressTrack"></html:div>
|
||||
<html:canvas anonid="progressRing" xbl:inherits="progress" class="circularprogressindicator-progressRing" width="40" height="40"></html:canvas>
|
||||
</xul:stack>
|
||||
|
@ -432,7 +432,7 @@ let Content = {
|
||||
aRect.height,
|
||||
presShellId.value,
|
||||
viewId].join(",");
|
||||
Services.obs.notifyObservers(null, "Metro:ZoomToRect", zoomData);
|
||||
Services.obs.notifyObservers(null, "apzc-zoom-to-rect", zoomData);
|
||||
},
|
||||
|
||||
_shouldZoomToElement: function(aElement) {
|
||||
|
@ -35,6 +35,9 @@ var StartUI = {
|
||||
|
||||
this.chromeWin.addEventListener("MozPrecisePointer", this, true);
|
||||
this.chromeWin.addEventListener("MozImprecisePointer", this, true);
|
||||
this.chromeWin.addEventListener("MozAfterPaint", this, true);
|
||||
this.chromeWin.Elements.panelUI.addEventListener("ToolPanelHidden", this, false);
|
||||
|
||||
Services.obs.addObserver(this, "metro_viewstate_changed", false);
|
||||
},
|
||||
|
||||
@ -107,6 +110,15 @@ var StartUI = {
|
||||
aEvent.preventDefault();
|
||||
aEvent.stopPropagation();
|
||||
break;
|
||||
case "ToolPanelHidden":
|
||||
// After opening panel UI (console) set disableZoom again.
|
||||
this.chromeWin.addEventListener("MozAfterPaint", this, true);
|
||||
break;
|
||||
|
||||
case "MozAfterPaint":
|
||||
this._disableZoom();
|
||||
this.chromeWin.removeEventListener("MozAfterPaint", this, true);
|
||||
break;
|
||||
}
|
||||
},
|
||||
|
||||
@ -116,5 +128,24 @@ var StartUI = {
|
||||
this._adjustDOMforViewState(aData);
|
||||
break;
|
||||
}
|
||||
},
|
||||
|
||||
_disableZoom: function() {
|
||||
let utils = Util.getWindowUtils(window);
|
||||
let viewId;
|
||||
try {
|
||||
viewId = utils.getViewId(document.documentElement);
|
||||
} catch(e) {
|
||||
return;
|
||||
}
|
||||
|
||||
let presShellId = {};
|
||||
utils.getPresShellId(presShellId);
|
||||
|
||||
let notificationData = [
|
||||
presShellId.value,
|
||||
viewId].join(",");
|
||||
|
||||
Services.obs.notifyObservers(null, "apzc-disable-zoom", notificationData);
|
||||
}
|
||||
};
|
||||
|
@ -746,13 +746,16 @@ documenttab[selected] .documenttab-selection {
|
||||
}
|
||||
|
||||
#download-progress {
|
||||
-moz-image-region: rect(0px, 40px, 40px, 0px) !important;
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
list-style-image: url(chrome://browser/skin/images/navbar-download.png);
|
||||
-moz-image-region: rect(0px, 40px, 40px, 0px);
|
||||
}
|
||||
#download-progress:hover {
|
||||
-moz-image-region: rect(40px, 40px, 80px, 0px) !important;
|
||||
-moz-image-region: rect(0px, 80px, 40px, 40px);
|
||||
}
|
||||
#download-progress:active {
|
||||
-moz-image-region: rect(80px, 40px, 120px, 0px) !important;
|
||||
-moz-image-region: rect(0px, 120px, 40px, 80px);
|
||||
}
|
||||
|
||||
#pin-button {
|
||||
@ -768,6 +771,10 @@ documenttab[selected] .documenttab-selection {
|
||||
}
|
||||
|
||||
@media (min-resolution: @min_res_140pc@) {
|
||||
#download-progress {
|
||||
list-style-image: url(chrome://browser/skin/images/navbar-download@1.4x.png);
|
||||
}
|
||||
|
||||
#pin-button {
|
||||
list-style-image: url(chrome://browser/skin/images/navbar-pin@1.4x.png);
|
||||
}
|
||||
@ -782,6 +789,10 @@ documenttab[selected] .documenttab-selection {
|
||||
}
|
||||
|
||||
@media (min-resolution: @min_res_180pc@) {
|
||||
#download-progress {
|
||||
list-style-image: url(chrome://browser/skin/images/navbar-download@1.8x.png);
|
||||
}
|
||||
|
||||
#pin-button {
|
||||
list-style-image: url(chrome://browser/skin/images/navbar-pin@1.8x.png);
|
||||
}
|
||||
|
BIN
browser/metro/theme/images/navbar-download.png
Normal file
BIN
browser/metro/theme/images/navbar-download.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.5 KiB |
BIN
browser/metro/theme/images/navbar-download@1.4x.png
Normal file
BIN
browser/metro/theme/images/navbar-download@1.4x.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 2.1 KiB |
BIN
browser/metro/theme/images/navbar-download@1.8x.png
Normal file
BIN
browser/metro/theme/images/navbar-download@1.8x.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 3.0 KiB |
@ -27,6 +27,9 @@ chrome.jar:
|
||||
skin/images/navbar-back.png (images/navbar-back.png)
|
||||
skin/images/navbar-back@1.4x.png (images/navbar-back@1.4x.png)
|
||||
skin/images/navbar-back@1.8x.png (images/navbar-back@1.8x.png)
|
||||
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-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)
|
||||
|
@ -588,6 +588,10 @@ toolbar .toolbarbutton-1:not([type="menu-button"]),
|
||||
-moz-image-region: rect(36px, 612px, 54px, 594px);
|
||||
}
|
||||
|
||||
#email-link-button@toolbarButtonPressed@ {
|
||||
-moz-image-region: rect(18px, 306px, 36px, 288px);
|
||||
}
|
||||
|
||||
/**
|
||||
* OSX has a unique set of icons when fullscreen is in the checked state.
|
||||
*/
|
||||
@ -737,6 +741,14 @@ toolbar .toolbarbutton-1:not([type="menu-button"]),
|
||||
-moz-image-region: rect(36px, 612px, 72px, 576px);
|
||||
}
|
||||
|
||||
#email-link-button[cui-areatype="toolbar"] {
|
||||
-moz-image-region: rect(0, 612px, 36px, 576px);
|
||||
}
|
||||
|
||||
#email-link-button[cui-areatype="toolbar"]:hover:active:not([disabled="true"]) {
|
||||
-moz-image-region: rect(36px, 612px, 72px, 576px);
|
||||
}
|
||||
|
||||
#characterencoding-button[cui-areatype="toolbar"] {
|
||||
-moz-image-region: rect(0, 648px, 36px, 612px);
|
||||
}
|
||||
@ -1009,6 +1021,16 @@ toolbar .toolbarbutton-1:not([type="menu-button"]),
|
||||
-moz-image-region: rect(0px, 1536px, 64px, 1472px);
|
||||
}
|
||||
|
||||
#email-link-button[cui-areatype="menu-panel"],
|
||||
toolbarpaletteitem[place="palette"] > #email-link-button {
|
||||
-moz-image-region: rect(0px, 896px, 64px, 832px);
|
||||
}
|
||||
|
||||
/* This is temporary until we have an email-link icon (Bug 932235) */
|
||||
#email-link-button > image {
|
||||
transform: scale(-1, -1);
|
||||
}
|
||||
|
||||
/* Footer and wide panel control icons */
|
||||
#edit-controls@inAnyPanel@ > toolbarbutton,
|
||||
#zoom-controls@inAnyPanel@ > toolbarbutton,
|
||||
|
@ -1,4 +1,4 @@
|
||||
%filter substitution
|
||||
|
||||
%define primaryToolbarButtons #back-button, #forward-button, #home-button, #print-button, #downloads-button, #bookmarks-menu-button, #new-tab-button, #new-window-button, #cut-button, #copy-button, #paste-button, #fullscreen-button, #zoom-out-button, #zoom-reset-button, #zoom-in-button, #sync-button, #feed-button, #tabview-button, #webrtc-status-button, #social-share-button, #open-file-button, #find-button, #developer-button, #preferences-button, #privatebrowsing-button, #save-page-button, #add-ons-button, #history-panelmenu, #nav-bar-overflow-button, #PanelUI-menu-button, #characterencoding-button
|
||||
%define primaryToolbarButtons #back-button, #forward-button, #home-button, #print-button, #downloads-button, #bookmarks-menu-button, #new-tab-button, #new-window-button, #cut-button, #copy-button, #paste-button, #fullscreen-button, #zoom-out-button, #zoom-reset-button, #zoom-in-button, #sync-button, #feed-button, #tabview-button, #webrtc-status-button, #social-share-button, #open-file-button, #find-button, #developer-button, #preferences-button, #privatebrowsing-button, #save-page-button, #add-ons-button, #history-panelmenu, #nav-bar-overflow-button, #PanelUI-menu-button, #characterencoding-button, #email-link-button
|
||||
%define inAnyPanel :-moz-any(:not([cui-areatype="toolbar"]),.overflowedItem)
|
||||
|
@ -60,6 +60,17 @@ toolbarpaletteitem[place="palette"] > #social-share-button {
|
||||
-moz-image-region: rect(0px, 448px, 32px, 416px);
|
||||
}
|
||||
|
||||
#email-link-button[cui-areatype="menu-panel"],
|
||||
toolbarpaletteitem[place="palette"] > #email-link-button {
|
||||
-moz-image-region: rect(0, 448px, 32px, 416px);
|
||||
}
|
||||
|
||||
/* This is temporary until we have an email-link icon (Bug 932235) */
|
||||
#email-link-button[cui-areatype="menu-panel"] > image,
|
||||
toolbarpaletteitem[place="palette"] > #email-link-button > image {
|
||||
transform: scale(-1, -1);
|
||||
}
|
||||
|
||||
#characterencoding-button[cui-areatype="menu-panel"],
|
||||
toolbarpaletteitem[place="palette"] > #characterencoding-button {
|
||||
-moz-image-region: rect(0px, 480px, 32px, 448px);
|
||||
|
@ -69,6 +69,12 @@
|
||||
-moz-image-region: rect(0px, 306px, 18px, 288px);
|
||||
}
|
||||
|
||||
#email-link-button[cui-areatype="toolbar"] {
|
||||
-moz-image-region: rect(0, 306px, 18px, 288px);
|
||||
/* This is temporary until we have an email-link icon (Bug 932235) */
|
||||
transform: scale(-1, -1);
|
||||
}
|
||||
|
||||
#characterencoding-button[cui-areatype="toolbar"]{
|
||||
-moz-image-region: rect(0, 324px, 18px, 306px);
|
||||
}
|
||||
|
@ -95,6 +95,11 @@ public class GeckoNetworkManager extends BroadcastReceiver {
|
||||
NETWORK_UNKNOWN
|
||||
}
|
||||
|
||||
private enum InfoType {
|
||||
MCC,
|
||||
MNC
|
||||
}
|
||||
|
||||
private Context mApplicationContext;
|
||||
private NetworkType mNetworkType = NetworkType.NETWORK_NONE;
|
||||
private IntentFilter mNetworkFilter = new IntentFilter();
|
||||
@ -322,4 +327,32 @@ public class GeckoNetworkManager extends BroadcastReceiver {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private static int getNetworkOperator(InfoType type) {
|
||||
TelephonyManager tel = (TelephonyManager)sInstance.mApplicationContext.getSystemService(Context.TELEPHONY_SERVICE);
|
||||
if (tel == null) {
|
||||
Log.e(LOGTAG, "Telephony service does not exist");
|
||||
return -1;
|
||||
}
|
||||
|
||||
String networkOperator = tel.getNetworkOperator();
|
||||
if (networkOperator == null || networkOperator.length() <= 3) {
|
||||
return -1;
|
||||
}
|
||||
if (type == InfoType.MNC) {
|
||||
return Integer.parseInt(networkOperator.substring(3));
|
||||
} else if (type == InfoType.MCC) {
|
||||
return Integer.parseInt(networkOperator.substring(0, 3));
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
public static int getMCC() {
|
||||
return getNetworkOperator(InfoType.MCC);
|
||||
}
|
||||
|
||||
public static int getMNC() {
|
||||
return getNetworkOperator(InfoType.MNC);
|
||||
}
|
||||
}
|
||||
|
@ -58,6 +58,7 @@ skip-if = processor == "x86"
|
||||
[testSessionOOMSave]
|
||||
[testSessionOOMRestore]
|
||||
[testSettingsMenuItems]
|
||||
[testMozPay]
|
||||
[testSharedPreferences]
|
||||
# [testShareLink] # see bug 915897
|
||||
[testSystemPages]
|
||||
|
25
mobile/android/base/tests/roboextender/paymentsUI.html
Normal file
25
mobile/android/base/tests/roboextender/paymentsUI.html
Normal file
@ -0,0 +1,25 @@
|
||||
<html>
|
||||
<head>
|
||||
<script type="text/javascript">
|
||||
function start() {
|
||||
if (!mozPaymentProvider)
|
||||
window.close();
|
||||
|
||||
// We don't have a way to mock these values yet. This check just makes sure the world
|
||||
// doesn't crash if we ask for them.
|
||||
var mcc = mozPaymentProvider.mcc;
|
||||
var mnc = mozPaymentProvider.mnc;
|
||||
|
||||
// We use the jwt passed in here to test calling paymentFailed/Success
|
||||
if (window.location.hash == "#pass")
|
||||
mozPaymentProvider.paymentSuccess("PAID CORRECTLY");
|
||||
else if (window.location.hash == "#fail")
|
||||
mozPaymentProvider.paymentFailed("FAILED CORRECTLY");
|
||||
else
|
||||
mozPaymentProvider.paymentFailed("invalid hash " + window.location.hash);
|
||||
}
|
||||
|
||||
document.addEventListener("DOMContentLoaded", start);
|
||||
</script>
|
||||
</head>
|
||||
</html>
|
10
mobile/android/base/tests/testMozPay.java
Normal file
10
mobile/android/base/tests/testMozPay.java
Normal file
@ -0,0 +1,10 @@
|
||||
package org.mozilla.gecko.tests;
|
||||
|
||||
import org.mozilla.gecko.*;
|
||||
|
||||
|
||||
public class testMozPay extends JavascriptTest {
|
||||
public testMozPay() {
|
||||
super("testMozPay.js");
|
||||
}
|
||||
}
|
102
mobile/android/base/tests/testMozPay.js
Normal file
102
mobile/android/base/tests/testMozPay.js
Normal file
@ -0,0 +1,102 @@
|
||||
// -*- Mode: js2; tab-width: 2; indent-tabs-mode: nil; js2-basic-offset: 2; js2-skip-preprocessor-directives: t; -*-
|
||||
/* 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/. */
|
||||
|
||||
let Cc = Components.classes;
|
||||
let Ci = Components.interfaces;
|
||||
let Cu = Components.utils;
|
||||
|
||||
Components.utils.import("resource://gre/modules/SharedPreferences.jsm");
|
||||
Components.utils.import("resource://gre/modules/commonjs/sdk/core/promise.js");
|
||||
|
||||
let ppmm = Cc["@mozilla.org/parentprocessmessagemanager;1"].getService(Ci.nsIMessageListenerManager);
|
||||
let deferred = 0;
|
||||
let shouldPass = true;
|
||||
let reqId = 0;
|
||||
function getRequestId(increment) {
|
||||
reqId += increment;
|
||||
return "Request" + reqId;
|
||||
}
|
||||
|
||||
let paymentSuccess = {
|
||||
receiveMessage: function(aMsg) {
|
||||
let msg = aMsg.json;
|
||||
if (shouldPass) {
|
||||
do_check_eq(msg.requestId, getRequestId(0));
|
||||
} else {
|
||||
do_throw("Test should not have passed");
|
||||
}
|
||||
deferred.resolve();
|
||||
}
|
||||
}
|
||||
|
||||
let paymentFailed = {
|
||||
receiveMessage: function(aMsg) {
|
||||
let msg = aMsg.json;
|
||||
if (shouldPass) {
|
||||
do_throw("Test should not have failed: " + msg.errorMsg);
|
||||
} else {
|
||||
do_check_eq(msg.requestId, getRequestId(0));
|
||||
do_check_eq(msg.errorMsg, "FAILED CORRECTLY");
|
||||
}
|
||||
deferred.resolve();
|
||||
}
|
||||
}
|
||||
|
||||
add_task(function test_get_set() {
|
||||
let ui = Cc["@mozilla.org/payment/ui-glue;1"].getService(Ci.nsIPaymentUIGlue);
|
||||
deferred = Promise.defer();
|
||||
let id = getRequestId(1);
|
||||
ui.confirmPaymentRequest(id,
|
||||
[{ wrappedJSObject: { type: "Fake Provider" } }],
|
||||
function(aRequestId, type) {
|
||||
do_check_eq(type, "Fake Provider");
|
||||
deferred.resolve();
|
||||
},
|
||||
function(id, msg) {
|
||||
do_throw("confirmPaymentRequest should not have failed");
|
||||
deferred.resolve();
|
||||
});
|
||||
yield deferred.promise;
|
||||
});
|
||||
|
||||
add_task(function test_default() {
|
||||
ppmm.addMessageListener("Payment:Success", paymentSuccess);
|
||||
ppmm.addMessageListener("Payment:Failed", paymentFailed);
|
||||
|
||||
let ui = Cc["@mozilla.org/payment/ui-glue;1"].getService(Ci.nsIPaymentUIGlue);
|
||||
deferred = Promise.defer();
|
||||
let id = getRequestId(1);
|
||||
shouldPass = true;
|
||||
ui.showPaymentFlow(id,
|
||||
{
|
||||
uri: "chrome://roboextender/content/paymentsUI.html",
|
||||
jwt: "#pass"
|
||||
},
|
||||
function(id, msg) {
|
||||
do_throw("confirmPaymentRequest should not have failed");
|
||||
deferred.resolve();
|
||||
});
|
||||
yield deferred.promise;
|
||||
|
||||
deferred = Promise.defer();
|
||||
let id = getRequestId(1);
|
||||
shouldPass = false;
|
||||
ui.showPaymentFlow(id,
|
||||
{
|
||||
uri: "chrome://roboextender/content/paymentsUI.html",
|
||||
jwt: "#fail"
|
||||
},
|
||||
function(id, msg) {
|
||||
do_throw("confirmPaymentRequest should not have failed");
|
||||
deferred.resolve();
|
||||
});
|
||||
|
||||
yield deferred.promise;
|
||||
|
||||
ppmm.removeMessageListener("Payment:Success", paymentSuccess);
|
||||
ppmm.removeMessageListener("Payment:Failed", paymentFailed);
|
||||
});
|
||||
|
||||
run_next_test();
|
@ -961,7 +961,12 @@ public class ActivityChooserModel extends DataSetObservable {
|
||||
for (int i = 0; i < activityCount; i++) {
|
||||
ActivityResolveInfo activity = activities.get(i);
|
||||
activity.weight = 0.0f;
|
||||
String packageName = activity.resolveInfo.activityInfo.packageName;
|
||||
|
||||
// Make sure we're using a non-ambiguous name here
|
||||
ComponentName chosenName = new ComponentName(
|
||||
activity.resolveInfo.activityInfo.packageName,
|
||||
activity.resolveInfo.activityInfo.name);
|
||||
String packageName = chosenName.flattenToString();
|
||||
packageNameToActivityMap.put(packageName, activity);
|
||||
}
|
||||
|
||||
@ -969,7 +974,7 @@ public class ActivityChooserModel extends DataSetObservable {
|
||||
float nextRecordWeight = 1;
|
||||
for (int i = lastShareIndex; i >= 0; i--) {
|
||||
HistoricalRecord historicalRecord = historicalRecords.get(i);
|
||||
String packageName = historicalRecord.activity.getPackageName();
|
||||
String packageName = historicalRecord.activity.flattenToString();
|
||||
ActivityResolveInfo activity = packageNameToActivityMap.get(packageName);
|
||||
if (activity != null) {
|
||||
activity.weight += historicalRecord.weight * nextRecordWeight;
|
||||
|
@ -8,6 +8,7 @@ const { classes: Cc, interfaces: Ci, utils: Cu } = Components;
|
||||
|
||||
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
Cu.import("resource://gre/modules/JNI.jsm");
|
||||
|
||||
XPCOMUtils.defineLazyServiceGetter(this, "cpmm",
|
||||
"@mozilla.org/childprocessmessagemanager;1",
|
||||
@ -32,9 +33,17 @@ function paymentFailed(aRequestId) {
|
||||
}
|
||||
|
||||
let paymentTabs = {};
|
||||
|
||||
let cancelTabCallbacks = {};
|
||||
function paymentCanceled(aRequestId) {
|
||||
return function() {
|
||||
paymentFailed(aRequestId)();
|
||||
}
|
||||
}
|
||||
function closePaymentTab(aId, aCallback) {
|
||||
if (paymentTabs[aId]) {
|
||||
paymentTabs[aId].browser.removeEventListener("TabClose", cancelTabCallbacks[aId]);
|
||||
delete cancelTabCallbacks[aId];
|
||||
|
||||
// We ask the UI to close the selected payment flow.
|
||||
let content = Services.wm.getMostRecentWindow("navigator:browser");
|
||||
if (content) {
|
||||
@ -127,8 +136,39 @@ PaymentUI.prototype = {
|
||||
tab.browser.addEventListener("DOMContentLoaded", function loadPaymentShim() {
|
||||
let frame = tab.browser.contentDocument.defaultView;
|
||||
try {
|
||||
frame.wrappedJSObject.paymentSuccess = paymentSuccess(aRequestId);
|
||||
frame.wrappedJSObject.paymentFailed = paymentFailed(aRequestId);
|
||||
frame.wrappedJSObject.mozPaymentProvider = {
|
||||
__exposedProps__: {
|
||||
paymentSuccess: 'r',
|
||||
paymentFailed: 'r',
|
||||
mnc: 'r',
|
||||
mcc: 'r',
|
||||
},
|
||||
|
||||
_getNetworkInfo: function(type) {
|
||||
let jni = new JNI();
|
||||
let cls = jni.findClass("org/mozilla/gecko/GeckoNetworkManager");
|
||||
let method = jni.getStaticMethodID(cls, "get" + type.toUpperCase(), "()I");
|
||||
let val = jni.callStaticIntMethod(cls, method);
|
||||
jni.close();
|
||||
|
||||
if (val < 0)
|
||||
return null;
|
||||
return val;
|
||||
},
|
||||
|
||||
get mnc() {
|
||||
delete this.mnc;
|
||||
return this.mnc = this._getNetworkInfo("mnc");
|
||||
},
|
||||
|
||||
get mcc() {
|
||||
delete this.mcc;
|
||||
return this.mcc = this._getNetworkInfo("mcc");
|
||||
},
|
||||
|
||||
paymentSuccess: paymentSuccess(aRequestId),
|
||||
paymentFailed: paymentFailed(aRequestId)
|
||||
};
|
||||
} catch (e) {
|
||||
_error(aRequestId, "ERROR_ADDING_METHODS");
|
||||
} finally {
|
||||
@ -136,13 +176,12 @@ PaymentUI.prototype = {
|
||||
}
|
||||
}, true);
|
||||
|
||||
// fail the payment if the tab is closed on its own
|
||||
tab.browser.addEventListener("TabClose", function paymentCanceled() {
|
||||
paymentFailed(aRequestId)();
|
||||
});
|
||||
|
||||
// Store a reference to the tab so that we can close it when the payment succeeds or fails.
|
||||
paymentTabs[aRequestId] = tab;
|
||||
cancelTabCallbacks[aRequestId] = paymentCanceled(aRequestId);
|
||||
|
||||
// Fail the payment if the tab is closed on its own
|
||||
tab.browser.addEventListener("TabClose", cancelTabCallbacks[aRequestId]);
|
||||
},
|
||||
|
||||
cleanup: function cleanup() {
|
||||
|
@ -160,9 +160,7 @@ function eventSource(aProto) {
|
||||
listener.apply(null, arguments);
|
||||
} catch (e) {
|
||||
// Prevent a bad listener from interfering with the others.
|
||||
let msg = e + ": " + e.stack;
|
||||
Cu.reportError(msg);
|
||||
dumpn(msg);
|
||||
DevToolsUtils.reportException("notify event '" + name + "'", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -322,10 +320,7 @@ DebuggerClient.requester = function DC_requester(aPacketSkeleton, { telemetry,
|
||||
try {
|
||||
thisCallback(aResponse);
|
||||
} catch (e) {
|
||||
let msg = "Error executing callback passed to debugger client: "
|
||||
+ e + "\n" + e.stack;
|
||||
dumpn(msg);
|
||||
Cu.reportError(msg);
|
||||
DevToolsUtils.reportException("DebuggerClient.requester callback", e);
|
||||
}
|
||||
}
|
||||
|
||||
@ -650,10 +645,10 @@ DebuggerClient.prototype = {
|
||||
|
||||
resolve(packet).then(aPacket => {
|
||||
if (!aPacket.from) {
|
||||
let msg = "Server did not specify an actor, dropping packet: " +
|
||||
JSON.stringify(aPacket);
|
||||
Cu.reportError(msg);
|
||||
dumpn(msg);
|
||||
DevToolsUtils.reportException(
|
||||
"onPacket",
|
||||
new Error("Server did not specify an actor, dropping packet: " +
|
||||
JSON.stringify(aPacket)));
|
||||
return;
|
||||
}
|
||||
|
||||
@ -703,8 +698,7 @@ DebuggerClient.prototype = {
|
||||
|
||||
this._sendRequests();
|
||||
}, function (ex) {
|
||||
dumpn("Error handling response: " + ex + " - stack:\n" + ex.stack);
|
||||
Cu.reportError(ex.message + "\n" + ex.stack);
|
||||
DevToolsUtils.reportException("onPacket handler", ex);
|
||||
});
|
||||
},
|
||||
|
||||
@ -830,14 +824,13 @@ ProtocolCompatibility.prototype = {
|
||||
this.rejectFeature(feature.name);
|
||||
break;
|
||||
default:
|
||||
Cu.reportError(new Error(
|
||||
"Bad return value from `onPacketTest` for feature '"
|
||||
+ feature.name + "'"));
|
||||
DevToolsUtils.reportException(
|
||||
"PC__detectFeatures",
|
||||
new Error("Bad return value from `onPacketTest` for feature '"
|
||||
+ feature.name + "'"));
|
||||
}
|
||||
} catch (ex) {
|
||||
Cu.reportError("Error detecting support for feature '"
|
||||
+ feature.name + "':" + ex.message + "\n"
|
||||
+ ex.stack);
|
||||
DevToolsUtils.reportException("PC__detectFeatures", ex);
|
||||
}
|
||||
}
|
||||
},
|
||||
@ -1700,11 +1693,6 @@ function TraceClient(aClient, aActor) {
|
||||
this._activeTraces = new Set();
|
||||
this._waitingPackets = new Map();
|
||||
this._expectedPacket = 0;
|
||||
|
||||
this.onPacket = this.onPacket.bind(this);
|
||||
this._client.addListener(UnsolicitedNotifications.enteredFrame, this.onPacket);
|
||||
this._client.addListener(UnsolicitedNotifications.exitedFrame, this.onPacket);
|
||||
|
||||
this.request = this._client.request;
|
||||
}
|
||||
|
||||
@ -1777,32 +1765,9 @@ TraceClient.prototype = {
|
||||
return aResponse;
|
||||
},
|
||||
telemetry: "STOPTRACE"
|
||||
}),
|
||||
|
||||
/**
|
||||
* Called when the trace actor notifies that a frame has been
|
||||
* entered or exited.
|
||||
*
|
||||
* @param aEvent string
|
||||
* The type of the unsolicited packet (enteredFrame|exitedFrame).
|
||||
*
|
||||
* @param aPacket object
|
||||
* Packet received over the RDP from the trace actor.
|
||||
*/
|
||||
onPacket: function JSTC_onPacket(aEvent, aPacket) {
|
||||
this._waitingPackets.set(aPacket.sequence, aPacket);
|
||||
|
||||
while (this._waitingPackets.has(this._expectedPacket)) {
|
||||
let packet = this._waitingPackets.get(this._expectedPacket);
|
||||
this._waitingPackets.delete(this._expectedPacket);
|
||||
this.notify(packet.type, packet);
|
||||
this._expectedPacket++;
|
||||
}
|
||||
}
|
||||
})
|
||||
};
|
||||
|
||||
eventSource(TraceClient.prototype);
|
||||
|
||||
/**
|
||||
* Grip clients are used to retrieve information about the relevant object.
|
||||
*
|
||||
@ -2224,9 +2189,7 @@ this.debuggerSocketConnect = function debuggerSocketConnect(aHost, aPort)
|
||||
transport = new DebuggerTransport(s.openInputStream(0, 0, 0),
|
||||
s.openOutputStream(0, 0, 0));
|
||||
} catch(e) {
|
||||
let msg = e + ": " + e.stack;
|
||||
Cu.reportError(msg);
|
||||
dumpn(msg);
|
||||
DevToolsUtils.reportException("debuggerSocketConnect", e);
|
||||
throw e;
|
||||
}
|
||||
return transport;
|
||||
|
@ -14,6 +14,39 @@ const { DebuggerServer } = Cu.import("resource://gre/modules/devtools/dbg-server
|
||||
Cu.import("resource://gre/modules/jsdebugger.jsm");
|
||||
addDebuggerToGlobal(this);
|
||||
|
||||
const { setTimeout } = require("sdk/timers");
|
||||
|
||||
/**
|
||||
* The number of milliseconds we should buffer frame enter/exit packets before
|
||||
* sending.
|
||||
*/
|
||||
const BUFFER_SEND_DELAY = 50;
|
||||
|
||||
/**
|
||||
* The maximum number of arguments we will send for any single function call.
|
||||
*/
|
||||
const MAX_ARGUMENTS = 5;
|
||||
|
||||
/**
|
||||
* The maximum number of an object's properties we will serialize.
|
||||
*/
|
||||
const MAX_PROPERTIES = 5;
|
||||
|
||||
/**
|
||||
* The complete set of trace types supported.
|
||||
*/
|
||||
const TRACE_TYPES = new Set([
|
||||
"time",
|
||||
"return",
|
||||
"throw",
|
||||
"yield",
|
||||
"name",
|
||||
"location",
|
||||
"callsite",
|
||||
"parameterNames",
|
||||
"arguments"
|
||||
]);
|
||||
|
||||
/**
|
||||
* Creates a TraceActor. TraceActor provides a stream of function
|
||||
* call/return packets to a remote client gathering a full trace.
|
||||
@ -24,11 +57,18 @@ function TraceActor(aConn, aParentActor)
|
||||
this._activeTraces = new MapStack();
|
||||
this._totalTraces = 0;
|
||||
this._startTime = 0;
|
||||
|
||||
// Keep track of how many different trace requests have requested what kind of
|
||||
// tracing info. This way we can minimize the amount of data we are collecting
|
||||
// at any given time.
|
||||
this._requestsForTraceType = Object.create(null);
|
||||
for (let type of TraceTypes.types) {
|
||||
for (let type of TRACE_TYPES) {
|
||||
this._requestsForTraceType[type] = 0;
|
||||
}
|
||||
|
||||
this._sequence = 0;
|
||||
this._bufferSendTimer = null;
|
||||
this._buffer = [];
|
||||
|
||||
this.global = aParentActor.window.wrappedJSObject;
|
||||
}
|
||||
@ -41,24 +81,19 @@ TraceActor.prototype = {
|
||||
get tracing() { return this._attached && this._activeTraces.size > 0; },
|
||||
|
||||
/**
|
||||
* Handle a TraceTypes.Events event by calling each handler which has been
|
||||
* requested by an active trace and adding its result to the packet.
|
||||
*
|
||||
* @param aEvent string
|
||||
* The event to dispatch.
|
||||
*
|
||||
* @param aPacket object
|
||||
* The debugger protocol packet.
|
||||
*
|
||||
* @param aArgs object
|
||||
* The arguments object for the handler.
|
||||
* Buffer traces and only send them every BUFFER_SEND_DELAY milliseconds.
|
||||
*/
|
||||
_handleEvent: function(aEvent, aPacket, aArgs) {
|
||||
let handlersForEvent = TraceTypes.handlers[aEvent];
|
||||
for (let traceType in handlersForEvent) {
|
||||
if (this._requestsForTraceType[traceType]) {
|
||||
aPacket[traceType] = handlersForEvent[traceType].call(null, aArgs);
|
||||
}
|
||||
_send: function(aPacket) {
|
||||
this._buffer.push(aPacket);
|
||||
if (this._bufferSendTimer === null) {
|
||||
this._bufferSendTimer = setTimeout(() => {
|
||||
this.conn.send({
|
||||
from: this.actorID,
|
||||
type: "traces",
|
||||
traces: this._buffer.splice(0, this._buffer.length)
|
||||
});
|
||||
this._bufferSendTimer = null;
|
||||
}, BUFFER_SEND_DELAY);
|
||||
}
|
||||
},
|
||||
|
||||
@ -151,7 +186,11 @@ TraceActor.prototype = {
|
||||
|
||||
this._attached = true;
|
||||
|
||||
return { type: "attached", traceTypes: TraceTypes.types };
|
||||
return {
|
||||
type: "attached",
|
||||
traceTypes: Object.keys(this._requestsForTraceType)
|
||||
.filter(k => !!this._requestsForTraceType[k])
|
||||
};
|
||||
},
|
||||
|
||||
/**
|
||||
@ -168,7 +207,7 @@ TraceActor.prototype = {
|
||||
this.dbg = null;
|
||||
|
||||
this._attached = false;
|
||||
this.conn.send({ from: this.actorID, type: "detached" });
|
||||
return { type: "detached" };
|
||||
},
|
||||
|
||||
/**
|
||||
@ -179,7 +218,7 @@ TraceActor.prototype = {
|
||||
*/
|
||||
onStartTrace: function(aRequest) {
|
||||
for (let traceType of aRequest.trace) {
|
||||
if (TraceTypes.types.indexOf(traceType) < 0) {
|
||||
if (!TRACE_TYPES.has(traceType)) {
|
||||
return {
|
||||
error: "badParameterType",
|
||||
message: "No such trace type: " + traceType
|
||||
@ -190,7 +229,7 @@ TraceActor.prototype = {
|
||||
if (this.idle) {
|
||||
this.dbg.enabled = true;
|
||||
this._sequence = 0;
|
||||
this._startTime = +new Date;
|
||||
this._startTime = Date.now();
|
||||
}
|
||||
|
||||
// Start recording all requested trace types.
|
||||
@ -257,19 +296,61 @@ TraceActor.prototype = {
|
||||
onEnterFrame: function(aFrame) {
|
||||
let callee = aFrame.callee;
|
||||
let packet = {
|
||||
from: this.actorID,
|
||||
type: "enteredFrame",
|
||||
sequence: this._sequence++
|
||||
};
|
||||
|
||||
this._handleEvent(TraceTypes.Events.enterFrame, packet, {
|
||||
frame: aFrame,
|
||||
startTime: this._startTime
|
||||
});
|
||||
if (this._requestsForTraceType.name) {
|
||||
packet.name = aFrame.callee
|
||||
? aFrame.callee.displayName || "(anonymous function)"
|
||||
: "(" + aFrame.type + ")";
|
||||
}
|
||||
|
||||
if (this._requestsForTraceType.location && aFrame.script) {
|
||||
// We should return the location of the start of the script, but
|
||||
// Debugger.Script does not provide complete start locations (bug
|
||||
// 901138). Instead, return the current offset (the location of the first
|
||||
// statement in the function).
|
||||
packet.location = {
|
||||
url: aFrame.script.url,
|
||||
line: aFrame.script.getOffsetLine(aFrame.offset),
|
||||
column: getOffsetColumn(aFrame.offset, aFrame.script)
|
||||
};
|
||||
}
|
||||
|
||||
if (this._requestsForTraceType.callsite
|
||||
&& aFrame.older
|
||||
&& aFrame.older.script) {
|
||||
let older = aFrame.older;
|
||||
packet.callsite = {
|
||||
url: older.script.url,
|
||||
line: older.script.getOffsetLine(older.offset),
|
||||
column: getOffsetColumn(older.offset, older.script)
|
||||
};
|
||||
}
|
||||
|
||||
if (this._requestsForTraceType.time) {
|
||||
packet.time = Date.now() - this._startTime;
|
||||
}
|
||||
|
||||
if (this._requestsForTraceType.parameterNames && aFrame.callee) {
|
||||
packet.parameterNames = aFrame.callee.parameterNames;
|
||||
}
|
||||
|
||||
if (this._requestsForTraceType.arguments && aFrame.arguments) {
|
||||
packet.arguments = [];
|
||||
let i = 0;
|
||||
for (let arg of aFrame.arguments) {
|
||||
if (i++ > MAX_ARGUMENTS) {
|
||||
break;
|
||||
}
|
||||
packet.arguments.push(createValueGrip(arg, true));
|
||||
}
|
||||
}
|
||||
|
||||
aFrame.onPop = this.onExitFrame.bind(this);
|
||||
|
||||
this.conn.send(packet);
|
||||
this._send(packet);
|
||||
},
|
||||
|
||||
/**
|
||||
@ -281,7 +362,6 @@ TraceActor.prototype = {
|
||||
*/
|
||||
onExitFrame: function(aCompletion) {
|
||||
let packet = {
|
||||
from: this.actorID,
|
||||
type: "exitedFrame",
|
||||
sequence: this._sequence++,
|
||||
};
|
||||
@ -296,12 +376,25 @@ TraceActor.prototype = {
|
||||
packet.why = "throw";
|
||||
}
|
||||
|
||||
this._handleEvent(TraceTypes.Events.exitFrame, packet, {
|
||||
value: aCompletion,
|
||||
startTime: this._startTime
|
||||
});
|
||||
if (this._requestsForTraceType.time) {
|
||||
packet.time = Date.now() - this._startTime;
|
||||
}
|
||||
|
||||
this.conn.send(packet);
|
||||
if (aCompletion) {
|
||||
if (this._requestsForTraceType.return) {
|
||||
packet.return = createValueGrip(aCompletion.return, true);
|
||||
}
|
||||
|
||||
if (this._requestsForTraceType.throw) {
|
||||
packet.throw = createValueGrip(aCompletion.throw, true);
|
||||
}
|
||||
|
||||
if (this._requestsForTraceType.yield) {
|
||||
packet.yield = createValueGrip(aCompletion.yield, true);
|
||||
}
|
||||
}
|
||||
|
||||
this._send(packet);
|
||||
}
|
||||
};
|
||||
|
||||
@ -419,91 +512,6 @@ MapStack.prototype = {
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* TraceTypes is a collection of handlers which generate optional trace
|
||||
* information. Handlers are associated with an event (from TraceTypes.Event)
|
||||
* and a trace type, and return a value to be embedded in the packet associated
|
||||
* with that event.
|
||||
*/
|
||||
let TraceTypes = {
|
||||
handlers: {},
|
||||
types: [],
|
||||
|
||||
register: function(aType, aEvent, aHandler) {
|
||||
if (!this.handlers[aEvent]) {
|
||||
this.handlers[aEvent] = {};
|
||||
}
|
||||
this.handlers[aEvent][aType] = aHandler;
|
||||
if (this.types.indexOf(aType) < 0) {
|
||||
this.types.push(aType);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
TraceTypes.Events = {
|
||||
"enterFrame": "enterFrame",
|
||||
"exitFrame": "exitFrame"
|
||||
};
|
||||
|
||||
TraceTypes.register("name", TraceTypes.Events.enterFrame, function({ frame }) {
|
||||
return frame.callee
|
||||
? frame.callee.displayName || "(anonymous function)"
|
||||
: "(" + frame.type + ")";
|
||||
});
|
||||
|
||||
TraceTypes.register("location", TraceTypes.Events.enterFrame, function({ frame }) {
|
||||
if (!frame.script) {
|
||||
return undefined;
|
||||
}
|
||||
// We should return the location of the start of the script, but
|
||||
// Debugger.Script does not provide complete start locations
|
||||
// (bug 901138). Instead, return the current offset (the location of
|
||||
// the first statement in the function).
|
||||
return {
|
||||
url: frame.script.url,
|
||||
line: frame.script.getOffsetLine(frame.offset),
|
||||
column: getOffsetColumn(frame.offset, frame.script)
|
||||
};
|
||||
});
|
||||
|
||||
TraceTypes.register("callsite", TraceTypes.Events.enterFrame, function({ frame }) {
|
||||
let older = frame.older;
|
||||
if (!older || !older.script) {
|
||||
return undefined;
|
||||
}
|
||||
return {
|
||||
url: older.script.url,
|
||||
line: older.script.getOffsetLine(older.offset),
|
||||
column: getOffsetColumn(older.offset, older.script)
|
||||
};
|
||||
});
|
||||
|
||||
TraceTypes.register("time", TraceTypes.Events.enterFrame, timeSinceTraceStarted);
|
||||
TraceTypes.register("time", TraceTypes.Events.exitFrame, timeSinceTraceStarted);
|
||||
|
||||
TraceTypes.register("parameterNames", TraceTypes.Events.enterFrame, function({ frame }) {
|
||||
return frame.callee ? frame.callee.parameterNames : undefined;
|
||||
});
|
||||
|
||||
TraceTypes.register("arguments", TraceTypes.Events.enterFrame, function({ frame }) {
|
||||
if (!frame.arguments) {
|
||||
return undefined;
|
||||
}
|
||||
let args = Array.prototype.slice.call(frame.arguments);
|
||||
return args.map(arg => createValueGrip(arg, true));
|
||||
});
|
||||
|
||||
TraceTypes.register("return", TraceTypes.Events.exitFrame,
|
||||
serializeCompletionValue.bind(null, "return"));
|
||||
|
||||
TraceTypes.register("throw", TraceTypes.Events.exitFrame,
|
||||
serializeCompletionValue.bind(null, "throw"));
|
||||
|
||||
TraceTypes.register("yield", TraceTypes.Events.exitFrame,
|
||||
serializeCompletionValue.bind(null, "yield"));
|
||||
|
||||
|
||||
// TODO bug 863089: use Debugger.Script.prototype.getOffsetColumn when
|
||||
// it is implemented.
|
||||
function getOffsetColumn(aOffset, aScript) {
|
||||
@ -530,27 +538,6 @@ function getOffsetColumn(aOffset, aScript) {
|
||||
return bestOffsetMapping.columnNumber;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns elapsed time since the given start time.
|
||||
*/
|
||||
function timeSinceTraceStarted({ startTime }) {
|
||||
return +new Date - startTime;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a value grip for the given completion value, to be
|
||||
* serialized by JSON.stringify.
|
||||
*
|
||||
* @param aType string
|
||||
* The type of completion value to serialize (return, throw, or yield).
|
||||
*/
|
||||
function serializeCompletionValue(aType, { value }) {
|
||||
if (!Object.hasOwnProperty.call(value, aType)) {
|
||||
return undefined;
|
||||
}
|
||||
return createValueGrip(value[aType], true);
|
||||
}
|
||||
|
||||
|
||||
// Serialization helper functions. Largely copied from script.js and modified
|
||||
// for use in serialization rather than object actor requests.
|
||||
@ -657,24 +644,27 @@ function objectGrip(aObject) {
|
||||
function objectDescriptor(aObject) {
|
||||
let desc = objectGrip(aObject);
|
||||
let ownProperties = Object.create(null);
|
||||
let names;
|
||||
try {
|
||||
names = aObject.getOwnPropertyNames();
|
||||
} catch(ex) {
|
||||
// The above can throw if aObject points to a dead object.
|
||||
// TODO: we should use Cu.isDeadWrapper() - see bug 885800.
|
||||
|
||||
if (Cu.isDeadWrapper(aObject)) {
|
||||
desc.prototype = createValueGrip(null);
|
||||
desc.ownProperties = ownProperties;
|
||||
desc.safeGetterValues = Object.create(null);
|
||||
return desc;
|
||||
}
|
||||
|
||||
const names = aObject.getOwnPropertyNames();
|
||||
let i = 0;
|
||||
for (let name of names) {
|
||||
ownProperties[name] = propertyDescriptor(name, aObject);
|
||||
if (i++ > MAX_PROPERTIES) {
|
||||
break;
|
||||
}
|
||||
let desc = propertyDescriptor(name, aObject);
|
||||
if (desc) {
|
||||
ownProperties[name] = desc;
|
||||
}
|
||||
}
|
||||
|
||||
desc.prototype = createValueGrip(aObject.proto);
|
||||
desc.ownProperties = ownProperties;
|
||||
desc.safeGetterValues = findSafeGetterValues(ownProperties, aObject);
|
||||
|
||||
return desc;
|
||||
}
|
||||
@ -708,7 +698,8 @@ function propertyDescriptor(aName, aObject) {
|
||||
};
|
||||
}
|
||||
|
||||
if (!desc) {
|
||||
// Skip objects since we only support shallow objects anyways.
|
||||
if (!desc || typeof desc.value == "object" && desc.value !== null) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
@ -730,104 +721,3 @@ function propertyDescriptor(aName, aObject) {
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
|
||||
/**
|
||||
* Find the safe getter values for the given Debugger.Object.
|
||||
*
|
||||
* @param aOwnProperties object
|
||||
* The object that holds the list of known ownProperties for |aObject|.
|
||||
*
|
||||
* @param Debugger.Object object
|
||||
* The object to find safe getter values for.
|
||||
*
|
||||
* @return object
|
||||
* An object that maps property names to safe getter descriptors.
|
||||
*/
|
||||
function findSafeGetterValues(aOwnProperties, aObject) {
|
||||
let safeGetterValues = Object.create(null);
|
||||
let obj = aObject;
|
||||
let level = 0;
|
||||
|
||||
while (obj) {
|
||||
let getters = findSafeGetters(obj);
|
||||
for (let name of getters) {
|
||||
// Avoid overwriting properties from prototypes closer to this.obj. Also
|
||||
// avoid providing safeGetterValues from prototypes if property |name|
|
||||
// is already defined as an own property.
|
||||
if (name in safeGetterValues ||
|
||||
(obj != aObject && name in aOwnProperties)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
let desc = null, getter = null;
|
||||
try {
|
||||
desc = obj.getOwnPropertyDescriptor(name);
|
||||
getter = desc.get;
|
||||
} catch (ex) {
|
||||
// The above can throw if the cache becomes stale.
|
||||
}
|
||||
if (!getter) {
|
||||
continue;
|
||||
}
|
||||
|
||||
let result = getter.call(aObject);
|
||||
if (result && !("throw" in result)) {
|
||||
let getterValue = undefined;
|
||||
if ("return" in result) {
|
||||
getterValue = result.return;
|
||||
} else if ("yield" in result) {
|
||||
getterValue = result.yield;
|
||||
}
|
||||
// WebIDL attributes specified with the LenientThis extended attribute
|
||||
// return undefined and should be ignored.
|
||||
if (getterValue !== undefined) {
|
||||
safeGetterValues[name] = {
|
||||
getterValue: createValueGrip(getterValue),
|
||||
getterPrototypeLevel: level,
|
||||
enumerable: desc.enumerable,
|
||||
writable: level == 0 ? desc.writable : true,
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
obj = obj.proto;
|
||||
level++;
|
||||
}
|
||||
|
||||
return safeGetterValues;
|
||||
}
|
||||
|
||||
/**
|
||||
* Find the safe getters for a given Debugger.Object. Safe getters are native
|
||||
* getters which are safe to execute.
|
||||
*
|
||||
* @param Debugger.Object aObject
|
||||
* The Debugger.Object where you want to find safe getters.
|
||||
*
|
||||
* @return Set
|
||||
* A Set of names of safe getters.
|
||||
*/
|
||||
function findSafeGetters(aObject) {
|
||||
let getters = new Set();
|
||||
for (let name of aObject.getOwnPropertyNames()) {
|
||||
let desc = null;
|
||||
try {
|
||||
desc = aObject.getOwnPropertyDescriptor(name);
|
||||
} catch (e) {
|
||||
// Calling getOwnPropertyDescriptor on wrapped native prototypes is not
|
||||
// allowed (bug 560072).
|
||||
}
|
||||
if (!desc || desc.value !== undefined || !("get" in desc)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
let fn = desc.get;
|
||||
if (fn && fn.callable && fn.class == "Function" &&
|
||||
fn.script === undefined) {
|
||||
getters.add(name);
|
||||
}
|
||||
}
|
||||
|
||||
return getters;
|
||||
}
|
||||
|
@ -31,43 +31,50 @@ function run_test()
|
||||
|
||||
function test_enter_exit_frame()
|
||||
{
|
||||
let packetsSeen = 0;
|
||||
let packetNames = [];
|
||||
let tracesSeen = 0;
|
||||
let traceNames = [];
|
||||
let traceStopped = defer();
|
||||
|
||||
gTraceClient.addListener("enteredFrame", function(aEvent, aPacket) {
|
||||
packetsSeen++;
|
||||
do_check_eq(aPacket.type, "enteredFrame",
|
||||
'enteredFrame response should have type "enteredFrame"');
|
||||
do_check_eq(typeof aPacket.sequence, "number",
|
||||
'enteredFrame response should have sequence number');
|
||||
do_check_true(!isNaN(aPacket.sequence),
|
||||
'enteredFrame sequence should be a number');
|
||||
do_check_eq(typeof aPacket.name, "string",
|
||||
'enteredFrame response should have function name');
|
||||
packetNames[aPacket.sequence] = aPacket.name;
|
||||
});
|
||||
gClient.addListener("traces", function onTraces(aEvent, { traces }) {
|
||||
for (let t of traces) {
|
||||
tracesSeen++;
|
||||
|
||||
gTraceClient.addListener("exitedFrame", function(aEvent, aPacket) {
|
||||
packetsSeen++;
|
||||
do_check_eq(aPacket.type, "exitedFrame",
|
||||
'exitedFrame response should have type "exitedFrame"');
|
||||
do_check_eq(typeof aPacket.sequence, "number",
|
||||
'exitedFrame response should have sequence number');
|
||||
do_check_true(!isNaN(aPacket.sequence),
|
||||
'exitedFrame sequence should be a number');
|
||||
if (t.type == "enteredFrame") {
|
||||
do_check_eq(t.type, "enteredFrame",
|
||||
'enteredFrame response should have type "enteredFrame"');
|
||||
do_check_eq(typeof t.sequence, "number",
|
||||
'enteredFrame response should have sequence number');
|
||||
do_check_true(!isNaN(t.sequence),
|
||||
'enteredFrame sequence should be a number');
|
||||
do_check_eq(typeof t.name, "string",
|
||||
'enteredFrame response should have function name');
|
||||
traceNames[t.sequence] = t.name;
|
||||
} else {
|
||||
do_check_eq(t.type, "exitedFrame",
|
||||
'exitedFrame response should have type "exitedFrame"');
|
||||
do_check_eq(typeof t.sequence, "number",
|
||||
'exitedFrame response should have sequence number');
|
||||
do_check_true(!isNaN(t.sequence),
|
||||
'exitedFrame sequence should be a number');
|
||||
}
|
||||
|
||||
if (tracesSeen == 10) {
|
||||
gClient.removeListener("traces", onTraces);
|
||||
traceStopped.resolve();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
start_trace()
|
||||
.then(eval_code)
|
||||
.then(() => traceStopped.promise)
|
||||
.then(stop_trace)
|
||||
.then(function() {
|
||||
do_check_eq(packetsSeen, 10,
|
||||
'Should have seen two packets for each of 5 stack frames');
|
||||
do_check_eq(packetNames[2], "baz",
|
||||
do_check_eq(traceNames[2], "baz",
|
||||
'Should have entered "baz" frame in third packet');
|
||||
do_check_eq(packetNames[3], "bar",
|
||||
do_check_eq(traceNames[3], "bar",
|
||||
'Should have entered "bar" frame in fourth packet');
|
||||
do_check_eq(packetNames[4], "foo",
|
||||
do_check_eq(traceNames[4], "foo",
|
||||
'Should have entered "foo" frame in fifth packet');
|
||||
finishClient(gClient);
|
||||
});
|
||||
|
@ -6,7 +6,7 @@
|
||||
* "arguments", and "return" trace types.
|
||||
*/
|
||||
|
||||
let {defer} = devtools.require("sdk/core/promise");
|
||||
let { defer } = devtools.require("sdk/core/promise");
|
||||
|
||||
var gDebuggee;
|
||||
var gClient;
|
||||
@ -28,106 +28,90 @@ function run_test()
|
||||
do_test_pending();
|
||||
}
|
||||
|
||||
function check_number(value, name)
|
||||
function check_number(value)
|
||||
{
|
||||
do_check_eq(typeof value, "number", name + ' should be a number');
|
||||
do_check_true(!isNaN(value), name + ' should be a number');
|
||||
do_check_eq(typeof value, "number");
|
||||
do_check_true(!isNaN(value));
|
||||
}
|
||||
|
||||
function check_location(actual, expected, name)
|
||||
function check_location(actual, expected)
|
||||
{
|
||||
do_check_eq(typeof actual, "object",
|
||||
name + ' missing expected source location');
|
||||
do_check_eq(typeof actual, "object");
|
||||
|
||||
check_number(actual.line, name + ' line');
|
||||
check_number(actual.column, name + ' column');
|
||||
check_number(actual.line);
|
||||
check_number(actual.column);
|
||||
|
||||
do_check_eq(actual.url, expected.url,
|
||||
name + ' location should have url ' + expected.url);
|
||||
do_check_eq(actual.line, expected.line,
|
||||
name + ' location should have source line of ' + expected.line);
|
||||
do_check_eq(actual.column, expected.column,
|
||||
name + ' location should have source column of ' + expected.line);
|
||||
do_check_eq(actual.url, expected.url);
|
||||
do_check_eq(actual.line, expected.line);
|
||||
do_check_eq(actual.column, expected.column);
|
||||
|
||||
}
|
||||
|
||||
function test_enter_exit_frame()
|
||||
{
|
||||
let packets = [];
|
||||
let traces = [];
|
||||
let traceStopped = defer();
|
||||
|
||||
gTraceClient.addListener("enteredFrame", function(aEvent, aPacket) {
|
||||
do_check_eq(aPacket.type, "enteredFrame",
|
||||
'enteredFrame response should have type "enteredFrame"');
|
||||
do_check_eq(typeof aPacket.name, "string",
|
||||
'enteredFrame response should have function name');
|
||||
do_check_eq(typeof aPacket.location, "object",
|
||||
'enteredFrame response should have source location');
|
||||
gClient.addListener("traces", function(aEvent, aPacket) {
|
||||
for (let t of aPacket.traces) {
|
||||
if (t.type == "enteredFrame") {
|
||||
do_check_eq(typeof t.name, "string");
|
||||
do_check_eq(typeof t.location, "object");
|
||||
|
||||
check_number(aPacket.sequence, 'enteredFrame sequence');
|
||||
check_number(aPacket.time, 'enteredFrame time');
|
||||
check_number(aPacket.location.line, 'enteredFrame source line');
|
||||
check_number(aPacket.location.column, 'enteredFrame source column');
|
||||
if (aPacket.callsite) {
|
||||
check_number(aPacket.callsite.line, 'enteredFrame callsite line');
|
||||
check_number(aPacket.callsite.column, 'enteredFrame callsite column');
|
||||
check_number(t.sequence);
|
||||
check_number(t.time);
|
||||
check_number(t.location.line);
|
||||
check_number(t.location.column);
|
||||
if (t.callsite) {
|
||||
check_number(t.callsite.line);
|
||||
check_number(t.callsite.column);
|
||||
}
|
||||
} else {
|
||||
check_number(t.sequence);
|
||||
check_number(t.time);
|
||||
}
|
||||
|
||||
traces[t.sequence] = t;
|
||||
if (traces.length === 4) {
|
||||
traceStopped.resolve();
|
||||
}
|
||||
}
|
||||
|
||||
packets[aPacket.sequence] = aPacket;
|
||||
});
|
||||
|
||||
gTraceClient.addListener("exitedFrame", function(aEvent, aPacket) {
|
||||
do_check_eq(aPacket.type, "exitedFrame",
|
||||
'exitedFrame response should have type "exitedFrame"');
|
||||
|
||||
check_number(aPacket.sequence, 'exitedFrame sequence');
|
||||
check_number(aPacket.time, 'exitedFrame time');
|
||||
|
||||
packets[aPacket.sequence] = aPacket;
|
||||
});
|
||||
|
||||
start_trace()
|
||||
.then(eval_code)
|
||||
.then(() => traceStopped.promise)
|
||||
.then(stop_trace)
|
||||
.then(function() {
|
||||
let url = getFileUrl("tracerlocations.js");
|
||||
|
||||
check_location(packets[0].location, { url: url, line: 1, column: 0 },
|
||||
'global entry packet');
|
||||
check_location(traces[0].location, { url: url, line: 1, column: 0 });
|
||||
|
||||
do_check_eq(packets[1].name, "foo",
|
||||
'Second packet in sequence should be entry to "foo" frame');
|
||||
do_check_eq(traces[1].name, "foo");
|
||||
|
||||
// foo's definition is at tracerlocations.js:3:0, but
|
||||
// Debugger.Script does not provide complete definition
|
||||
// locations (bug 901138). tracerlocations.js:4:2 is the first
|
||||
// statement in the function (used as an approximation).
|
||||
check_location(packets[1].location, { url: url, line: 4, column: 2 },
|
||||
'foo source');
|
||||
check_location(packets[1].callsite, { url: url, line: 8, column: 0 },
|
||||
'foo callsite');
|
||||
check_location(traces[1].location, { url: url, line: 4, column: 2 });
|
||||
check_location(traces[1].callsite, { url: url, line: 8, column: 0 });
|
||||
|
||||
do_check_eq(typeof packets[1].parameterNames, "object",
|
||||
'foo entry packet should have parameterNames');
|
||||
do_check_eq(packets[1].parameterNames.length, 1,
|
||||
'foo should have only one formal parameter');
|
||||
do_check_eq(packets[1].parameterNames[0], "x",
|
||||
'foo should have formal parameter "x"');
|
||||
do_check_eq(typeof traces[1].parameterNames, "object");
|
||||
do_check_eq(traces[1].parameterNames.length, 1);
|
||||
do_check_eq(traces[1].parameterNames[0], "x");
|
||||
|
||||
do_check_eq(typeof packets[1].arguments, "object",
|
||||
'foo entry packet should have arguments');
|
||||
do_check_true(Array.isArray(packets[1].arguments),
|
||||
'foo entry packet arguments should be an array');
|
||||
do_check_eq(packets[1].arguments.length, 1,
|
||||
'foo should have only one actual parameter');
|
||||
do_check_eq(packets[1].arguments[0], 42,
|
||||
'foo should have actual parameter 42');
|
||||
do_check_eq(typeof traces[1].arguments, "object");
|
||||
do_check_true(Array.isArray(traces[1].arguments));
|
||||
do_check_eq(traces[1].arguments.length, 1);
|
||||
do_check_eq(traces[1].arguments[0], 42);
|
||||
|
||||
do_check_eq(typeof packets[2].return, "string",
|
||||
'Fourth packet in sequence should be exit from "foo" frame');
|
||||
do_check_eq(packets[2].return, "bar",
|
||||
'foo should return "bar"');
|
||||
do_check_eq(typeof traces[2].return, "string");
|
||||
do_check_eq(traces[2].return, "bar");
|
||||
|
||||
finishClient(gClient);
|
||||
}, error => {
|
||||
DevToolsUtils.reportException("test_trace_actor-05.js", error);
|
||||
do_check_true(false);
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -6,7 +6,7 @@
|
||||
* and exitedFrame packets.
|
||||
*/
|
||||
|
||||
let {defer} = devtools.require("sdk/core/promise");
|
||||
let { defer } = devtools.require("sdk/core/promise");
|
||||
|
||||
var gDebuggee;
|
||||
var gClient;
|
||||
@ -30,11 +30,20 @@ function run_test()
|
||||
|
||||
function test_enter_exit_frame()
|
||||
{
|
||||
gTraceClient.addListener("enteredFrame", check_packet);
|
||||
gTraceClient.addListener("exitedFrame", check_packet);
|
||||
const traceStopped = defer();
|
||||
|
||||
gClient.addListener("traces", (aEvent, { traces }) => {
|
||||
for (let t of traces) {
|
||||
check_trace(t);
|
||||
if (t.sequence === 27) {
|
||||
traceStopped.resolve();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
start_trace()
|
||||
.then(eval_code)
|
||||
.then(() => traceStopped.promise)
|
||||
.then(stop_trace)
|
||||
.then(function() {
|
||||
finishClient(gClient);
|
||||
@ -58,17 +67,23 @@ function eval_code()
|
||||
let circular = {};
|
||||
circular.self = circular;
|
||||
|
||||
// Make sure there is only 5 properties per object because that is the value
|
||||
// of MAX_PROPERTIES in the server.
|
||||
let obj = {
|
||||
num: 0,
|
||||
str: "foo",
|
||||
bool: false,
|
||||
undef: undefined,
|
||||
nil: null,
|
||||
nil: null
|
||||
};
|
||||
let obj2 = {
|
||||
inf: Infinity,
|
||||
ninf: -Infinity,
|
||||
nan: NaN,
|
||||
nzero: -0,
|
||||
obj: circular,
|
||||
obj: circular
|
||||
};
|
||||
let obj3 = {
|
||||
arr: [1,2,3,4,5]
|
||||
};
|
||||
|
||||
@ -83,6 +98,8 @@ function eval_code()
|
||||
identity(NaN);
|
||||
identity(-0);
|
||||
identity(obj);
|
||||
identity(obj2);
|
||||
identity(obj3);
|
||||
} + ")()");
|
||||
}
|
||||
|
||||
@ -93,17 +110,15 @@ function stop_trace()
|
||||
return deferred.promise;
|
||||
}
|
||||
|
||||
function check_packet(aEvent, aPacket)
|
||||
function check_trace(aTrace)
|
||||
{
|
||||
let value = (aPacket.type === "enteredFrame" && aPacket.arguments)
|
||||
? aPacket.arguments[0]
|
||||
: aPacket.return;
|
||||
switch(aPacket.sequence) {
|
||||
let value = (aTrace.type === "enteredFrame" && aTrace.arguments)
|
||||
? aTrace.arguments[0]
|
||||
: aTrace.return;
|
||||
switch(aTrace.sequence) {
|
||||
case 2:
|
||||
do_check_eq(typeof aPacket.arguments, "object",
|
||||
"zero-argument function call should send arguments list");
|
||||
do_check_eq(aPacket.arguments.length, 0,
|
||||
"zero-argument function call should send zero-length arguments list");
|
||||
do_check_eq(typeof aTrace.arguments, "object");
|
||||
do_check_eq(aTrace.arguments.length, 0);
|
||||
break;
|
||||
case 3:
|
||||
check_value(value, "object", "undefined");
|
||||
@ -146,8 +161,15 @@ function check_packet(aEvent, aPacket)
|
||||
break;
|
||||
case 22:
|
||||
case 23:
|
||||
check_object(aPacket.type, value);
|
||||
check_obj(aTrace.type, value);
|
||||
break;
|
||||
case 24:
|
||||
case 25:
|
||||
check_obj2(aTrace.type, value);
|
||||
break;
|
||||
case 26:
|
||||
case 27:
|
||||
check_obj3(aTrace.type, value);
|
||||
}
|
||||
}
|
||||
|
||||
@ -157,67 +179,50 @@ function check_value(aActual, aExpectedType, aExpectedValue)
|
||||
do_check_eq(aExpectedType === "object" ? aActual.type : aActual, aExpectedValue);
|
||||
}
|
||||
|
||||
function check_object(aType, aObj) {
|
||||
do_check_eq(typeof aObj, "object",
|
||||
'serialized object should be present in packet');
|
||||
do_check_eq(typeof aObj.prototype, "object",
|
||||
'serialized object should have prototype');
|
||||
do_check_eq(typeof aObj.ownProperties, "object",
|
||||
'serialized object should have ownProperties list');
|
||||
do_check_eq(typeof aObj.safeGetterValues, "object",
|
||||
'serialized object should have safeGetterValues');
|
||||
function check_obj(aType, aObj) {
|
||||
do_check_eq(typeof aObj, "object");
|
||||
do_check_eq(typeof aObj.ownProperties, "object");
|
||||
|
||||
do_check_eq(typeof aObj.ownProperties.num, "object",
|
||||
'serialized object should have property "num"');
|
||||
do_check_eq(typeof aObj.ownProperties.str, "object",
|
||||
'serialized object should have property "str"');
|
||||
do_check_eq(typeof aObj.ownProperties.bool, "object",
|
||||
'serialized object should have property "bool"');
|
||||
do_check_eq(typeof aObj.ownProperties.undef, "object",
|
||||
'serialized object should have property "undef"');
|
||||
do_check_eq(typeof aObj.ownProperties.undef.value, "object",
|
||||
'serialized object property "undef" should be a grip');
|
||||
do_check_eq(typeof aObj.ownProperties.nil, "object",
|
||||
'serialized object should have property "nil"');
|
||||
do_check_eq(typeof aObj.ownProperties.nil.value, "object",
|
||||
'serialized object property "nil" should be a grip');
|
||||
do_check_eq(typeof aObj.ownProperties.obj, "object",
|
||||
'serialized object should have property "aObj"');
|
||||
do_check_eq(typeof aObj.ownProperties.obj.value, "object",
|
||||
'serialized object property "aObj" should be a grip');
|
||||
do_check_eq(typeof aObj.ownProperties.arr, "object",
|
||||
'serialized object should have property "arr"');
|
||||
do_check_eq(typeof aObj.ownProperties.arr.value, "object",
|
||||
'serialized object property "arr" should be a grip');
|
||||
do_check_eq(typeof aObj.ownProperties.inf, "object",
|
||||
'serialized object should have property "inf"');
|
||||
do_check_eq(typeof aObj.ownProperties.inf.value, "object",
|
||||
'serialized object property "inf" should be a grip');
|
||||
do_check_eq(typeof aObj.ownProperties.ninf, "object",
|
||||
'serialized object should have property "ninf"');
|
||||
do_check_eq(typeof aObj.ownProperties.ninf.value, "object",
|
||||
'serialized object property "ninf" should be a grip');
|
||||
do_check_eq(typeof aObj.ownProperties.nan, "object",
|
||||
'serialized object should have property "nan"');
|
||||
do_check_eq(typeof aObj.ownProperties.nan.value, "object",
|
||||
'serialized object property "nan" should be a grip');
|
||||
do_check_eq(typeof aObj.ownProperties.nzero, "object",
|
||||
'serialized object should have property "nzero"');
|
||||
do_check_eq(typeof aObj.ownProperties.nzero.value, "object",
|
||||
'serialized object property "nzero" should be a grip');
|
||||
|
||||
do_check_eq(aObj.prototype.type, "object");
|
||||
do_check_eq(typeof aObj.ownProperties.num, "object");
|
||||
do_check_eq(aObj.ownProperties.num.value, 0);
|
||||
|
||||
do_check_eq(typeof aObj.ownProperties.str, "object");
|
||||
do_check_eq(aObj.ownProperties.str.value, "foo");
|
||||
|
||||
do_check_eq(typeof aObj.ownProperties.bool, "object");
|
||||
do_check_eq(aObj.ownProperties.bool.value, false);
|
||||
|
||||
do_check_eq(typeof aObj.ownProperties.undef, "object");
|
||||
do_check_eq(typeof aObj.ownProperties.undef.value, "object");
|
||||
do_check_eq(aObj.ownProperties.undef.value.type, "undefined");
|
||||
|
||||
do_check_eq(typeof aObj.ownProperties.nil, "object");
|
||||
do_check_eq(typeof aObj.ownProperties.nil.value, "object");
|
||||
do_check_eq(aObj.ownProperties.nil.value.type, "null");
|
||||
do_check_eq(aObj.ownProperties.obj.value.type, "object");
|
||||
do_check_eq(aObj.ownProperties.obj.value.class, "Object");
|
||||
do_check_eq(aObj.ownProperties.arr.value.type, "object");
|
||||
do_check_eq(aObj.ownProperties.arr.value.class, "Array");
|
||||
do_check_eq(aObj.ownProperties.inf.value.type, "Infinity");
|
||||
do_check_eq(aObj.ownProperties.ninf.value.type, "-Infinity");
|
||||
do_check_eq(aObj.ownProperties.nan.value.type, "NaN");
|
||||
do_check_eq(aObj.ownProperties.nzero.value.type, "-0");
|
||||
}
|
||||
|
||||
function check_obj2(aType, aObj) {
|
||||
do_check_eq(typeof aObj.ownProperties.inf, "object");
|
||||
do_check_eq(typeof aObj.ownProperties.inf.value, "object");
|
||||
do_check_eq(aObj.ownProperties.inf.value.type, "Infinity");
|
||||
|
||||
do_check_eq(typeof aObj.ownProperties.ninf, "object");
|
||||
do_check_eq(typeof aObj.ownProperties.ninf.value, "object");
|
||||
do_check_eq(aObj.ownProperties.ninf.value.type, "-Infinity");
|
||||
|
||||
do_check_eq(typeof aObj.ownProperties.nan, "object");
|
||||
do_check_eq(typeof aObj.ownProperties.nan.value, "object");
|
||||
do_check_eq(aObj.ownProperties.nan.value.type, "NaN");
|
||||
|
||||
do_check_eq(typeof aObj.ownProperties.nzero, "object");
|
||||
do_check_eq(typeof aObj.ownProperties.nzero.value, "object");
|
||||
do_check_eq(aObj.ownProperties.nzero.value.type, "-0");
|
||||
|
||||
// Sub-objects aren't added.
|
||||
do_check_eq(typeof aObj.ownProperties.obj, "undefined");
|
||||
}
|
||||
|
||||
function check_obj3(aType, aObj) {
|
||||
// Sub-objects aren't added.
|
||||
do_check_eq(typeof aObj.ownProperties.arr, "undefined");
|
||||
}
|
||||
|
@ -29,7 +29,13 @@ function run_test()
|
||||
|
||||
function test_exit_frame_whys()
|
||||
{
|
||||
gTraceClient.addListener("exitedFrame", check_packet);
|
||||
gClient.addListener("traces", (aEvent, { traces }) => {
|
||||
for (let t of traces) {
|
||||
if (t.type == "exitedFrame") {
|
||||
check_trace(t);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
start_trace()
|
||||
.then(eval_code)
|
||||
@ -83,7 +89,7 @@ function stop_trace()
|
||||
return deferred.promise;
|
||||
}
|
||||
|
||||
function check_packet(aEvent, { sequence, why })
|
||||
function check_trace(aEvent, { sequence, why })
|
||||
{
|
||||
switch(sequence) {
|
||||
case 3:
|
||||
|
@ -1,101 +0,0 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
/**
|
||||
* Tests that TraceClient emits enteredFrame and exitedFrame events in
|
||||
* order when receiving packets out of order.
|
||||
*/
|
||||
|
||||
let {defer, resolve} = devtools.require("sdk/core/promise");
|
||||
|
||||
var gDebuggee;
|
||||
var gClient;
|
||||
var gTraceClient;
|
||||
|
||||
function run_test()
|
||||
{
|
||||
initTestTracerServer();
|
||||
gDebuggee = addTestGlobal("test-tracer-actor");
|
||||
gClient = new DebuggerClient(DebuggerServer.connectPipe());
|
||||
gClient.connect(function() {
|
||||
attachTestTab(gClient, "test-tracer-actor", function(aResponse, aTabClient) {
|
||||
gClient.attachTracer(aResponse.traceActor, function(aResponse, aTraceClient) {
|
||||
gTraceClient = aTraceClient;
|
||||
test_packet_order();
|
||||
});
|
||||
});
|
||||
});
|
||||
do_test_pending();
|
||||
}
|
||||
|
||||
function test_packet_order()
|
||||
{
|
||||
let sequence = 0;
|
||||
|
||||
function check_packet(aEvent, aPacket) {
|
||||
do_check_eq(aPacket.sequence, sequence,
|
||||
'packet should have sequence number ' + sequence);
|
||||
sequence++;
|
||||
}
|
||||
|
||||
gTraceClient.addListener("enteredFrame", check_packet);
|
||||
gTraceClient.addListener("exitedFrame", check_packet);
|
||||
|
||||
start_trace()
|
||||
.then(mock_packets)
|
||||
.then(start_trace)
|
||||
.then(mock_packets.bind(null, 14))
|
||||
.then(stop_trace)
|
||||
.then(stop_trace)
|
||||
.then(function() {
|
||||
// All traces were stopped, so the sequence number resets
|
||||
sequence = 0;
|
||||
return resolve();
|
||||
})
|
||||
.then(start_trace)
|
||||
.then(mock_packets)
|
||||
.then(stop_trace)
|
||||
.then(function() {
|
||||
finishClient(gClient);
|
||||
});
|
||||
}
|
||||
|
||||
function start_trace()
|
||||
{
|
||||
let deferred = defer();
|
||||
gTraceClient.startTrace([], null, function() { deferred.resolve(); });
|
||||
return deferred.promise;
|
||||
}
|
||||
|
||||
function stop_trace()
|
||||
{
|
||||
let deferred = defer();
|
||||
gTraceClient.stopTrace(null, function() { deferred.resolve(); });
|
||||
return deferred.promise;
|
||||
}
|
||||
|
||||
function mock_packets(s = 0)
|
||||
{
|
||||
gTraceClient.onPacket("", { type: "exitedFrame", sequence: s + 5 });
|
||||
gTraceClient.onPacket("", { type: "enteredFrame", sequence: s + 3 });
|
||||
gTraceClient.onPacket("", { type: "exitedFrame", sequence: s + 2 });
|
||||
gTraceClient.onPacket("", { type: "enteredFrame", sequence: s + 4 });
|
||||
gTraceClient.onPacket("", { type: "enteredFrame", sequence: s + 1 });
|
||||
|
||||
gTraceClient.onPacket("", { type: "enteredFrame", sequence: s + 7 });
|
||||
gTraceClient.onPacket("", { type: "enteredFrame", sequence: s + 8 });
|
||||
|
||||
// Triggers 0-5
|
||||
gTraceClient.onPacket("", { type: "enteredFrame", sequence: s + 0 });
|
||||
|
||||
gTraceClient.onPacket("", { type: "exitedFrame", sequence: s + 9 });
|
||||
gTraceClient.onPacket("", { type: "exitedFrame", sequence: s + 10 });
|
||||
|
||||
// Triggers 6-10
|
||||
gTraceClient.onPacket("", { type: "exitedFrame", sequence: s + 6 });
|
||||
|
||||
// Each following packet is expected; event is fired immediately
|
||||
gTraceClient.onPacket("", { type: "enteredFrame", sequence: s + 11 });
|
||||
gTraceClient.onPacket("", { type: "exitedFrame", sequence: s + 12 });
|
||||
gTraceClient.onPacket("", { type: "exitedFrame", sequence: s + 13 });
|
||||
}
|
@ -190,4 +190,3 @@ reason = bug 820380
|
||||
[test_trace_actor-06.js]
|
||||
[test_trace_actor-07.js]
|
||||
[test_ignore_caught_exceptions.js]
|
||||
[test_trace_client-01.js]
|
||||
|
@ -517,7 +517,7 @@ if (IS_WIN) {
|
||||
function lockDirectory(aDir) {
|
||||
var file = aDir.clone();
|
||||
file.append(kLockFileName);
|
||||
file.create(file.NORMAL_FILE_TYPE, 4 * 64 + 4 * 8 + 4); // 0444
|
||||
file.create(file.NORMAL_FILE_TYPE, 0o444);
|
||||
file.QueryInterface(AUS_Ci.nsILocalFileWin);
|
||||
file.fileAttributesWin |= file.WFA_READONLY;
|
||||
file.fileAttributesWin &= ~file.WFA_READWRITE;
|
||||
@ -577,7 +577,7 @@ function copyMinimumAppFiles(aSrcDir, aDestDir, aDestLeafName) {
|
||||
deplibsFile.append("dependentlibs.list");
|
||||
let istream = AUS_Cc["@mozilla.org/network/file-input-stream;1"].
|
||||
createInstance(AUS_Ci.nsIFileInputStream);
|
||||
istream.init(deplibsFile, 0x01, 4 * 64 + 4 * 8 + 4, 0); // 0444
|
||||
istream.init(deplibsFile, 0x01, 0o444, 0);
|
||||
istream.QueryInterface(AUS_Ci.nsILineInputStream);
|
||||
|
||||
let hasMore;
|
||||
@ -723,21 +723,6 @@ function shouldRunServiceTest(aFirstTest) {
|
||||
// the newer bin that we have.
|
||||
attemptServiceInstall();
|
||||
|
||||
const REG_PATH = "SOFTWARE\\Mozilla\\MaintenanceService\\" +
|
||||
"3932ecacee736d366d6436db0f55bce4";
|
||||
|
||||
let key = AUS_Cc["@mozilla.org/windows-registry-key;1"].
|
||||
createInstance(AUS_Ci.nsIWindowsRegKey);
|
||||
try {
|
||||
key.open(AUS_Ci.nsIWindowsRegKey.ROOT_KEY_LOCAL_MACHINE, REG_PATH,
|
||||
AUS_Ci.nsIWindowsRegKey.ACCESS_READ | key.WOW64_64);
|
||||
}
|
||||
catch (e) {
|
||||
logTestInfo("this test can only run on the buildbot build system at this " +
|
||||
"time.");
|
||||
return false;
|
||||
}
|
||||
|
||||
let binDir = getGREDir();
|
||||
let updaterBin = binDir.clone();
|
||||
updaterBin.append(FILE_UPDATER_BIN);
|
||||
@ -750,6 +735,29 @@ function shouldRunServiceTest(aFirstTest) {
|
||||
updaterBinPath = '"' + updaterBinPath + '"';
|
||||
}
|
||||
|
||||
const REG_PATH = "SOFTWARE\\Mozilla\\MaintenanceService\\" +
|
||||
"3932ecacee736d366d6436db0f55bce4";
|
||||
|
||||
let key = AUS_Cc["@mozilla.org/windows-registry-key;1"].
|
||||
createInstance(AUS_Ci.nsIWindowsRegKey);
|
||||
try {
|
||||
key.open(AUS_Ci.nsIWindowsRegKey.ROOT_KEY_LOCAL_MACHINE, REG_PATH,
|
||||
AUS_Ci.nsIWindowsRegKey.ACCESS_READ | key.WOW64_64);
|
||||
}
|
||||
catch (e) {
|
||||
#ifndef DISABLE_UPDATER_AUTHENTICODE_CHECK
|
||||
// The build system could sign the files and not have the test registry key
|
||||
// in which case we should fail the test by throwing so it can be fixed.
|
||||
if (isBinarySigned(updaterBinPath)) {
|
||||
do_throw("binary is signed but the test registry key does not exists!");
|
||||
}
|
||||
#endif
|
||||
|
||||
logTestInfo("this test can only run on the buildbot build system at this " +
|
||||
"time.");
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check to make sure the service is installed
|
||||
let helperBin = getTestDirFile(FILE_HELPER_BIN);
|
||||
let args = ["wait-for-service-stop", "MozillaMaintenance", "10"];
|
||||
@ -759,8 +767,8 @@ function shouldRunServiceTest(aFirstTest) {
|
||||
logTestInfo("Checking if the service exists on this machine.");
|
||||
process.run(true, args, args.length);
|
||||
if (process.exitValue == 0xEE) {
|
||||
logTestInfo("this test can only run when the service is installed.");
|
||||
return false;
|
||||
do_throw("test registry key exists but this test can only run on systems " +
|
||||
"with the maintenance service installed.");
|
||||
} else {
|
||||
logTestInfo("Service exists, return value: " + process.exitValue);
|
||||
}
|
||||
@ -773,23 +781,34 @@ function shouldRunServiceTest(aFirstTest) {
|
||||
process.exitValue);
|
||||
}
|
||||
|
||||
#ifdef DISABLE_UPDATER_AUTHENTICODE_CHECK
|
||||
// We won't be performing signature checks.
|
||||
#ifndef DISABLE_UPDATER_AUTHENTICODE_CHECK
|
||||
if (!isBinarySigned(updaterBinPath)) {
|
||||
logTestInfo("this test can only run on builds with signed binaries.");
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
return true;
|
||||
#else
|
||||
// Make sure the binaries are signed
|
||||
args = ["check-signature", updaterBinPath];
|
||||
process = AUS_Cc["@mozilla.org/process/util;1"].
|
||||
createInstance(AUS_Ci.nsIProcess);
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper function to check whether the a binary is signed.
|
||||
*
|
||||
* @param aBinPath The path to the file to check if it is signed.
|
||||
* @return true if the file is signed and false if it isn't.
|
||||
*/
|
||||
function isBinarySigned(aBinPath) {
|
||||
let helperBin = getTestDirFile(FILE_HELPER_BIN);
|
||||
let args = ["check-signature", aBinPath];
|
||||
let process = AUS_Cc["@mozilla.org/process/util;1"].
|
||||
createInstance(AUS_Ci.nsIProcess);
|
||||
process.init(helperBin);
|
||||
process.run(true, args, args.length);
|
||||
if (process.exitValue == 0) {
|
||||
return true;
|
||||
if (process.exitValue != 0) {
|
||||
logTestInfo("binary is not signed. " + FILE_HELPER_BIN + " returned " +
|
||||
process.exitValue + " for file " + aBinPath);
|
||||
return false;
|
||||
}
|
||||
logTestInfo("this test can only run on builds with signed binaries. " +
|
||||
FILE_HELPER_BIN + " returned " + process.exitValue)
|
||||
return false;
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -817,7 +836,7 @@ function copyBinToApplyToDir(filename) {
|
||||
* This is useful for XP where we have permission to upgrade in case an
|
||||
* older service installer exists. Also if the user manually installed into
|
||||
* a unprivileged location.
|
||||
*/
|
||||
*/
|
||||
function attemptServiceInstall() {
|
||||
var version = AUS_Cc["@mozilla.org/system-info;1"]
|
||||
.getService(AUS_Ci.nsIPropertyBag2)
|
||||
|
@ -280,7 +280,8 @@ MetroWidget::Destroy()
|
||||
nsCOMPtr<nsIObserverService> observerService = do_GetService("@mozilla.org/observer-service;1", &rv);
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
observerService->RemoveObserver(this, "apzc-scroll-offset-changed");
|
||||
observerService->RemoveObserver(this, "Metro:ZoomToRect");
|
||||
observerService->RemoveObserver(this, "apzc-zoom-to-rect");
|
||||
observerService->RemoveObserver(this, "apzc-disable-zoom");
|
||||
}
|
||||
}
|
||||
|
||||
@ -991,7 +992,8 @@ CompositorParent* MetroWidget::NewCompositorParent(int aSurfaceWidth, int aSurfa
|
||||
nsCOMPtr<nsIObserverService> observerService = do_GetService("@mozilla.org/observer-service;1", &rv);
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
observerService->AddObserver(this, "apzc-scroll-offset-changed", false);
|
||||
observerService->AddObserver(this, "Metro:ZoomToRect", false);
|
||||
observerService->AddObserver(this, "apzc-zoom-to-rect", false);
|
||||
observerService->AddObserver(this, "apzc-disable-zoom", false);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1601,7 +1603,7 @@ MetroWidget::Observe(nsISupports *subject, const char *topic, const PRUnichar *d
|
||||
mController->UpdateScrollOffset(ScrollableLayerGuid(mRootLayerTreeId, presShellId, scrollId),
|
||||
scrollOffset);
|
||||
}
|
||||
else if (!strcmp(topic, "Metro:ZoomToRect")) {
|
||||
else if (!strcmp(topic, "apzc-zoom-to-rect")) {
|
||||
CSSRect rect = CSSRect();
|
||||
uint64_t viewId = 0;
|
||||
int32_t presShellId = 0;
|
||||
@ -1610,12 +1612,25 @@ MetroWidget::Observe(nsISupports *subject, const char *topic, const PRUnichar *d
|
||||
&rect.x, &rect.y, &rect.width, &rect.height,
|
||||
&presShellId, &viewId);
|
||||
if(reScan != 6) {
|
||||
NS_WARNING("Malformed Metro:ZoomToRect message");
|
||||
NS_WARNING("Malformed apzc-zoom-to-rect message");
|
||||
}
|
||||
|
||||
ScrollableLayerGuid guid = ScrollableLayerGuid(mRootLayerTreeId, presShellId, viewId);
|
||||
APZController::sAPZC->ZoomToRect(guid, rect);
|
||||
}
|
||||
else if (!strcmp(topic, "apzc-disable-zoom")) {
|
||||
uint64_t viewId = 0;
|
||||
int32_t presShellId = 0;
|
||||
|
||||
int reScan = swscanf(data, L"%d,%llu",
|
||||
&presShellId, &viewId);
|
||||
if (reScan != 2) {
|
||||
NS_WARNING("Malformed apzc-disable-zoom message");
|
||||
}
|
||||
|
||||
ScrollableLayerGuid guid = ScrollableLayerGuid(mRootLayerTreeId, presShellId, viewId);
|
||||
APZController::sAPZC->UpdateZoomConstraints(guid, false, CSSToScreenScale(1.0f), CSSToScreenScale(1.0f));
|
||||
}
|
||||
else {
|
||||
return NS_OK;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user