merge fx-team to mozilla-central
@ -284,7 +284,7 @@ const CustomizableWidgets = [{
|
||||
}, {
|
||||
id: "save-page-button",
|
||||
shortcutId: "key_savePage",
|
||||
tooltiptext: "save-page-button.tooltiptext2",
|
||||
tooltiptext: "save-page-button.tooltiptext3",
|
||||
defaultArea: CustomizableUI.AREA_PANEL,
|
||||
onCommand: function(aEvent) {
|
||||
let win = aEvent.target &&
|
||||
@ -297,7 +297,7 @@ const CustomizableWidgets = [{
|
||||
}, {
|
||||
id: "find-button",
|
||||
shortcutId: "key_find",
|
||||
tooltiptext: "find-button.tooltiptext2",
|
||||
tooltiptext: "find-button.tooltiptext3",
|
||||
defaultArea: CustomizableUI.AREA_PANEL,
|
||||
onCommand: function(aEvent) {
|
||||
let win = aEvent.target &&
|
||||
@ -310,7 +310,7 @@ const CustomizableWidgets = [{
|
||||
}, {
|
||||
id: "open-file-button",
|
||||
shortcutId: "openFileKb",
|
||||
tooltiptext: "open-file-button.tooltiptext2",
|
||||
tooltiptext: "open-file-button.tooltiptext3",
|
||||
defaultArea: CustomizableUI.AREA_PANEL,
|
||||
onCommand: function(aEvent) {
|
||||
let win = aEvent.target
|
||||
@ -325,6 +325,7 @@ const CustomizableWidgets = [{
|
||||
type: "view",
|
||||
viewId: "PanelUI-developer",
|
||||
shortcutId: "key_devToolboxMenuItem",
|
||||
tooltiptext: "developer-button.tooltiptext2",
|
||||
defaultArea: CustomizableUI.AREA_PANEL,
|
||||
onViewShowing: function(aEvent) {
|
||||
// Populate the subview with whatever menuitems are in the developer
|
||||
@ -350,6 +351,7 @@ const CustomizableWidgets = [{
|
||||
id: "sidebar-button",
|
||||
type: "view",
|
||||
viewId: "PanelUI-sidebar",
|
||||
tooltiptext: "sidebar-button.tooltiptext2",
|
||||
onViewShowing: function(aEvent) {
|
||||
// Largely duplicated from the developer-button above with a couple minor
|
||||
// alterations.
|
||||
@ -377,7 +379,7 @@ const CustomizableWidgets = [{
|
||||
}, {
|
||||
id: "add-ons-button",
|
||||
shortcutId: "key_openAddons",
|
||||
tooltiptext: "add-ons-button.tooltiptext2",
|
||||
tooltiptext: "add-ons-button.tooltiptext3",
|
||||
defaultArea: CustomizableUI.AREA_PANEL,
|
||||
onCommand: function(aEvent) {
|
||||
let win = aEvent.target &&
|
||||
@ -412,6 +414,7 @@ const CustomizableWidgets = [{
|
||||
}, {
|
||||
id: "zoom-controls",
|
||||
type: "custom",
|
||||
tooltiptext: "zoom-controls.tooltiptext2",
|
||||
defaultArea: CustomizableUI.AREA_PANEL,
|
||||
onBuild: function(aDocument) {
|
||||
const kPanelId = "PanelUI-popup";
|
||||
@ -584,6 +587,7 @@ const CustomizableWidgets = [{
|
||||
}, {
|
||||
id: "edit-controls",
|
||||
type: "custom",
|
||||
tooltiptext: "edit-controls.tooltiptext2",
|
||||
defaultArea: CustomizableUI.AREA_PANEL,
|
||||
onBuild: function(aDocument) {
|
||||
let buttons = [{
|
||||
@ -675,6 +679,7 @@ const CustomizableWidgets = [{
|
||||
id: "feed-button",
|
||||
type: "view",
|
||||
viewId: "PanelUI-feeds",
|
||||
tooltiptext: "feed-button.tooltiptext2",
|
||||
defaultArea: CustomizableUI.AREA_PANEL,
|
||||
onClick: function(aEvent) {
|
||||
let win = aEvent.target.ownerDocument.defaultView;
|
||||
@ -877,7 +882,7 @@ const CustomizableWidgets = [{
|
||||
}
|
||||
}, {
|
||||
id: "email-link-button",
|
||||
tooltiptext: "email-link-button.tooltiptext2",
|
||||
tooltiptext: "email-link-button.tooltiptext3",
|
||||
onCommand: function(aEvent) {
|
||||
let win = aEvent.view;
|
||||
win.MailIntegration.sendLinkForWindow(win.content);
|
||||
|
@ -1,6 +1,6 @@
|
||||
const {Cc,Ci,Cu} = require("chrome");
|
||||
const ObservableObject = require("devtools/shared/observable-object");
|
||||
const promise = require("sdk/core/promise");
|
||||
const promise = require("devtools/toolkit/deprecated-sync-thenables");
|
||||
|
||||
const {EventEmitter} = Cu.import("resource://gre/modules/devtools/event-emitter.js");
|
||||
const {generateUUID} = Cc['@mozilla.org/uuid-generator;1'].getService(Ci.nsIUUIDGenerator);
|
||||
|
@ -4,7 +4,7 @@
|
||||
"use strict";
|
||||
|
||||
let {Ci,Cu,CC} = require("chrome");
|
||||
const promise = require("sdk/core/promise");
|
||||
const promise = require("devtools/toolkit/deprecated-sync-thenables");
|
||||
|
||||
const {FileUtils} = Cu.import("resource://gre/modules/FileUtils.jsm");
|
||||
const {Services} = Cu.import("resource://gre/modules/Services.jsm");
|
||||
|
@ -17,7 +17,7 @@ const {getTargetForApp, launchApp, closeApp}
|
||||
= require("devtools/app-actor-front");
|
||||
const DeviceStore = require("devtools/app-manager/device-store");
|
||||
const WebappsStore = require("devtools/app-manager/webapps-store");
|
||||
const promise = require("sdk/core/promise");
|
||||
const promise = require("devtools/toolkit/deprecated-sync-thenables");
|
||||
const DEFAULT_APP_ICON = "chrome://browser/skin/devtools/app-manager/default-app-icon.png";
|
||||
|
||||
window.addEventListener("message", function(event) {
|
||||
|
@ -7,7 +7,7 @@ Cu.import("resource:///modules/devtools/gDevTools.jsm");
|
||||
const {devtools} = Cu.import("resource://gre/modules/devtools/Loader.jsm", {});
|
||||
const {require} = devtools;
|
||||
const {ConnectionManager, Connection} = require("devtools/client/connection-manager");
|
||||
const promise = require("sdk/core/promise");
|
||||
const promise = require("devtools/toolkit/deprecated-sync-thenables");
|
||||
const prefs = require('sdk/preferences/service');
|
||||
|
||||
|
||||
|
@ -18,7 +18,7 @@ const {installHosted, installPackaged, getTargetForApp,
|
||||
reloadApp, launchApp, closeApp} = require("devtools/app-actor-front");
|
||||
const {EventEmitter} = Cu.import("resource://gre/modules/devtools/event-emitter.js");
|
||||
|
||||
const promise = require("sdk/core/promise");
|
||||
const promise = require("devtools/toolkit/deprecated-sync-thenables");
|
||||
|
||||
const MANIFEST_EDITOR_ENABLED = "devtools.appmanager.manifestEditor.enabled";
|
||||
|
||||
|
@ -5,7 +5,7 @@
|
||||
const {utils: Cu, classes: Cc, interfaces: Ci} = Components;
|
||||
|
||||
const {Promise: promise} =
|
||||
Cu.import("resource://gre/modules/commonjs/sdk/core/promise.js", {});
|
||||
Cu.import("resource://gre/modules/devtools/deprecated-sync-thenables.js", {});
|
||||
const {devtools} =
|
||||
Cu.import("resource://gre/modules/devtools/Loader.jsm", {});
|
||||
const {require} = devtools;
|
||||
|
@ -3,7 +3,7 @@
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
const ObservableObject = require("devtools/shared/observable-object");
|
||||
const promise = require("sdk/core/promise");
|
||||
const promise = require("devtools/toolkit/deprecated-sync-thenables");
|
||||
const {Connection} = require("devtools/client/connection-manager");
|
||||
|
||||
const {Cu} = require("chrome");
|
||||
|
@ -98,7 +98,7 @@ Cu.import("resource:///modules/devtools/VariablesViewController.jsm");
|
||||
Cu.import("resource:///modules/devtools/ViewHelpers.jsm");
|
||||
|
||||
const require = Cu.import("resource://gre/modules/devtools/Loader.jsm", {}).devtools.require;
|
||||
const promise = require("sdk/core/promise");
|
||||
const promise = require("devtools/toolkit/deprecated-sync-thenables");
|
||||
const Editor = require("devtools/sourceeditor/editor");
|
||||
const DebuggerEditor = require("devtools/sourceeditor/debugger.js");
|
||||
const {Tooltip} = require("devtools/shared/widgets/Tooltip");
|
||||
|
@ -4,7 +4,7 @@
|
||||
const TEST_BASE = "chrome://mochitests/content/browser/browser/devtools/eyedropper/test/";
|
||||
const TEST_HOST = 'mochi.test:8888';
|
||||
|
||||
const promise = Cu.import("resource://gre/modules/commonjs/sdk/core/promise.js").Promise;
|
||||
const promise = Cu.import("resource://gre/modules/devtools/deprecated-sync-thenables.js").Promise;
|
||||
const require = Cu.import("resource://gre/modules/devtools/Loader.jsm", {}).devtools.require;
|
||||
const { Eyedropper } = require("devtools/eyedropper/eyedropper");
|
||||
|
||||
|
@ -16,7 +16,7 @@ Cu.import("resource:///modules/devtools/ViewHelpers.jsm");
|
||||
const ELLIPSIS = Services.prefs.getComplexValue("intl.ellipsis", Ci.nsIPrefLocalizedString).data;
|
||||
const MAX_LABEL_LENGTH = 40;
|
||||
|
||||
let promise = require("sdk/core/promise");
|
||||
let promise = require("devtools/toolkit/deprecated-sync-thenables");
|
||||
|
||||
const LOW_PRIORITY_ELEMENTS = {
|
||||
"HEAD": true,
|
||||
|
@ -8,7 +8,7 @@ const {Cc, Ci, Cu, Cr} = require("chrome");
|
||||
|
||||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
|
||||
let promise = require("sdk/core/promise");
|
||||
let promise = require("devtools/toolkit/deprecated-sync-thenables");
|
||||
let EventEmitter = require("devtools/toolkit/event-emitter");
|
||||
let {CssLogic} = require("devtools/styleinspector/css-logic");
|
||||
|
||||
|
@ -4,7 +4,7 @@
|
||||
|
||||
"use strict";
|
||||
|
||||
const promise = require("sdk/core/promise");
|
||||
const promise = require("devtools/toolkit/deprecated-sync-thenables");
|
||||
|
||||
loader.lazyGetter(this, "AutocompletePopup", () => require("devtools/shared/autocomplete-popup").AutocompletePopup);
|
||||
|
||||
|
@ -20,7 +20,7 @@ const {UndoStack} = require("devtools/shared/undo");
|
||||
const {editableField, InplaceEditor} = require("devtools/shared/inplace-editor");
|
||||
const {gDevTools} = Cu.import("resource:///modules/devtools/gDevTools.jsm", {});
|
||||
const {HTMLEditor} = require("devtools/markupview/html-editor");
|
||||
const promise = require("sdk/core/promise");
|
||||
const promise = require("devtools/toolkit/deprecated-sync-thenables");
|
||||
const {Tooltip} = require("devtools/shared/widgets/Tooltip");
|
||||
const EventEmitter = require("devtools/toolkit/event-emitter");
|
||||
|
||||
|
@ -6,7 +6,7 @@ const Cu = Components.utils;
|
||||
let {devtools} = Cu.import("resource://gre/modules/devtools/Loader.jsm", {});
|
||||
let TargetFactory = devtools.TargetFactory;
|
||||
let {console} = Cu.import("resource://gre/modules/devtools/Console.jsm", {});
|
||||
let promise = devtools.require("sdk/core/promise");
|
||||
let promise = devtools.require("devtools/toolkit/deprecated-sync-thenables");
|
||||
let {getInplaceEditorForSpan: inplaceEditor} = devtools.require("devtools/shared/inplace-editor");
|
||||
|
||||
// All test are asynchronous
|
||||
|
@ -394,6 +394,7 @@ RequestsMenuView.prototype = Heritage.extend(WidgetMethods, {
|
||||
$("#requests-menu-perf-notice-button").addEventListener("command", this._onContextPerfCommand, false);
|
||||
$("#requests-menu-network-summary-button").addEventListener("command", this._onContextPerfCommand, false);
|
||||
$("#requests-menu-network-summary-label").addEventListener("click", this._onContextPerfCommand, false);
|
||||
$("#network-statistics-back-button").addEventListener("command", this._onContextPerfCommand, false);
|
||||
} else {
|
||||
$("#notice-perf-message").hidden = true;
|
||||
$("#request-menu-context-perf").hidden = true;
|
||||
@ -428,6 +429,7 @@ RequestsMenuView.prototype = Heritage.extend(WidgetMethods, {
|
||||
$("#requests-menu-perf-notice-button").removeEventListener("command", this._onContextPerfCommand, false);
|
||||
$("#requests-menu-network-summary-button").removeEventListener("command", this._onContextPerfCommand, false);
|
||||
$("#requests-menu-network-summary-label").removeEventListener("click", this._onContextPerfCommand, false);
|
||||
$("#network-statistics-back-button").removeEventListener("command", this._onContextPerfCommand, false);
|
||||
|
||||
$("#custom-request-send-button").removeEventListener("click", this.sendCustomRequestEvent, false);
|
||||
$("#custom-request-close-button").removeEventListener("click", this.closeCustomRequestEvent, false);
|
||||
|
@ -516,7 +516,6 @@
|
||||
class="devtools-toolbar">
|
||||
<button id="network-statistics-back-button"
|
||||
class="devtools-toolbarbutton"
|
||||
onclick="NetMonitorView.toggleFrontendMode()"
|
||||
label="&netmonitorUI.backButton;"/>
|
||||
</toolbar>
|
||||
<box id="network-statistics-charts"
|
||||
|
@ -7,7 +7,7 @@ const TEST_URI = "data:text/html;charset=utf-8,<p>browser_telemetry_button_paint
|
||||
// opened we make use of setTimeout() to create tool active times.
|
||||
const TOOL_DELAY = 200;
|
||||
|
||||
let promise = Cu.import("resource://gre/modules/commonjs/sdk/core/promise.js", {}).Promise;
|
||||
let promise = Cu.import("resource://gre/modules/devtools/deprecated-sync-thenables.js", {}).Promise;
|
||||
let {Services} = Cu.import("resource://gre/modules/Services.jsm", {});
|
||||
|
||||
let require = Cu.import("resource://gre/modules/devtools/Loader.jsm", {}).devtools.require;
|
||||
|
@ -7,7 +7,7 @@ const TEST_URI = "data:text/html;charset=utf-8,<p>browser_telemetry_button_respo
|
||||
// opened we make use of setTimeout() to create tool active times.
|
||||
const TOOL_DELAY = 200;
|
||||
|
||||
let promise = Cu.import("resource://gre/modules/commonjs/sdk/core/promise.js", {}).Promise;
|
||||
let promise = Cu.import("resource://gre/modules/devtools/deprecated-sync-thenables.js", {}).Promise;
|
||||
let {Services} = Cu.import("resource://gre/modules/Services.jsm", {});
|
||||
|
||||
let require = Cu.import("resource://gre/modules/devtools/Loader.jsm", {}).devtools.require;
|
||||
|
@ -7,7 +7,7 @@ const TEST_URI = "data:text/html;charset=utf-8,<p>browser_telemetry_button_scrat
|
||||
// opened we make use of setTimeout() to create tool active times.
|
||||
const TOOL_DELAY = 200;
|
||||
|
||||
let promise = Cu.import("resource://gre/modules/commonjs/sdk/core/promise.js", {}).Promise;
|
||||
let promise = Cu.import("resource://gre/modules/devtools/deprecated-sync-thenables.js", {}).Promise;
|
||||
let {Services} = Cu.import("resource://gre/modules/Services.jsm", {});
|
||||
|
||||
let require = Cu.import("resource://gre/modules/devtools/Loader.jsm", {}).devtools.require;
|
||||
|
@ -7,7 +7,7 @@ const TEST_URI = "data:text/html;charset=utf-8,<p>browser_telemetry_button_tilt.
|
||||
// opened we make use of setTimeout() to create tool active times.
|
||||
const TOOL_DELAY = 200;
|
||||
|
||||
let promise = Cu.import("resource://gre/modules/commonjs/sdk/core/promise.js", {}).Promise;
|
||||
let promise = Cu.import("resource://gre/modules/devtools/deprecated-sync-thenables.js", {}).Promise;
|
||||
let {Services} = Cu.import("resource://gre/modules/Services.jsm", {});
|
||||
|
||||
let require = Cu.import("resource://gre/modules/devtools/Loader.jsm", {}).devtools.require;
|
||||
|
@ -7,7 +7,7 @@ const TEST_URI = "data:text/html;charset=utf-8,<p>browser_telemetry_sidebar.js</
|
||||
// opened we make use of setTimeout() to create tool active times.
|
||||
const TOOL_DELAY = 200;
|
||||
|
||||
let {Promise: promise} = Cu.import("resource://gre/modules/commonjs/sdk/core/promise.js", {});
|
||||
let {Promise: promise} = Cu.import("resource://gre/modules/devtools/deprecated-sync-thenables.js", {});
|
||||
let {Services} = Cu.import("resource://gre/modules/Services.jsm", {});
|
||||
|
||||
let require = Cu.import("resource://gre/modules/devtools/Loader.jsm", {}).devtools.require;
|
||||
|
@ -7,7 +7,7 @@ const TEST_URI = "data:text/html;charset=utf-8,<p>browser_telemetry_toolboxtabs_
|
||||
// opened we make use of setTimeout() to create tool active times.
|
||||
const TOOL_DELAY = 200;
|
||||
|
||||
let {Promise: promise} = Cu.import("resource://gre/modules/commonjs/sdk/core/promise.js", {});
|
||||
let {Promise: promise} = Cu.import("resource://gre/modules/devtools/deprecated-sync-thenables.js", {});
|
||||
let {Services} = Cu.import("resource://gre/modules/Services.jsm", {});
|
||||
|
||||
let require = Cu.import("resource://gre/modules/devtools/Loader.jsm", {}).devtools.require;
|
||||
|
@ -7,7 +7,7 @@ const TEST_URI = "data:text/html;charset=utf-8,<p>browser_telemetry_toolboxtabs_
|
||||
// opened we make use of setTimeout() to create tool active times.
|
||||
const TOOL_DELAY = 200;
|
||||
|
||||
let {Promise: promise} = Cu.import("resource://gre/modules/commonjs/sdk/core/promise.js", {});
|
||||
let {Promise: promise} = Cu.import("resource://gre/modules/devtools/deprecated-sync-thenables.js", {});
|
||||
let {Services} = Cu.import("resource://gre/modules/Services.jsm", {});
|
||||
|
||||
let require = Cu.import("resource://gre/modules/devtools/Loader.jsm", {}).devtools.require;
|
||||
|
@ -7,7 +7,7 @@ const TEST_URI = "data:text/html;charset=utf-8,<p>browser_telemetry_toolboxtabs_
|
||||
// opened we make use of setTimeout() to create tool active times.
|
||||
const TOOL_DELAY = 200;
|
||||
|
||||
let {Promise: promise} = Cu.import("resource://gre/modules/commonjs/sdk/core/promise.js", {});
|
||||
let {Promise: promise} = Cu.import("resource://gre/modules/devtools/deprecated-sync-thenables.js", {});
|
||||
let {Services} = Cu.import("resource://gre/modules/Services.jsm", {});
|
||||
|
||||
let require = Cu.import("resource://gre/modules/devtools/Loader.jsm", {}).devtools.require;
|
||||
|
@ -7,7 +7,7 @@ const TEST_URI = "data:text/html;charset=utf-8,<p>browser_telemetry_toolboxtabs_
|
||||
// opened we make use of setTimeout() to create tool active times.
|
||||
const TOOL_DELAY = 200;
|
||||
|
||||
let {Promise: promise} = Cu.import("resource://gre/modules/commonjs/sdk/core/promise.js", {});
|
||||
let {Promise: promise} = Cu.import("resource://gre/modules/devtools/deprecated-sync-thenables.js", {});
|
||||
let {Services} = Cu.import("resource://gre/modules/Services.jsm", {});
|
||||
|
||||
let require = Cu.import("resource://gre/modules/devtools/Loader.jsm", {}).devtools.require;
|
||||
|
@ -7,7 +7,7 @@ const TEST_URI = "data:text/html;charset=utf-8,<p>browser_telemetry_toolboxtabs_
|
||||
// opened we make use of setTimeout() to create tool active times.
|
||||
const TOOL_DELAY = 200;
|
||||
|
||||
let {Promise: promise} = Cu.import("resource://gre/modules/commonjs/sdk/core/promise.js", {});
|
||||
let {Promise: promise} = Cu.import("resource://gre/modules/devtools/deprecated-sync-thenables.js", {});
|
||||
let {Services} = Cu.import("resource://gre/modules/Services.jsm", {});
|
||||
|
||||
let require = Cu.import("resource://gre/modules/devtools/Loader.jsm", {}).devtools.require;
|
||||
|
@ -7,7 +7,7 @@ const TEST_URI = "data:text/html;charset=utf-8,<p>browser_telemetry_toolboxtabs_
|
||||
// opened we make use of setTimeout() to create tool active times.
|
||||
const TOOL_DELAY = 200;
|
||||
|
||||
let {Promise: promise} = Cu.import("resource://gre/modules/commonjs/sdk/core/promise.js", {});
|
||||
let {Promise: promise} = Cu.import("resource://gre/modules/devtools/deprecated-sync-thenables.js", {});
|
||||
let {Services} = Cu.import("resource://gre/modules/Services.jsm", {});
|
||||
|
||||
let require = Cu.import("resource://gre/modules/devtools/Loader.jsm", {}).devtools.require;
|
||||
|
@ -7,7 +7,7 @@ const TEST_URI = "data:text/html;charset=utf-8,<p>browser_telemetry_toolboxtabs_
|
||||
// opened we make use of setTimeout() to create tool active times.
|
||||
const TOOL_DELAY = 200;
|
||||
|
||||
let {Promise: promise} = Cu.import("resource://gre/modules/commonjs/sdk/core/promise.js", {});
|
||||
let {Promise: promise} = Cu.import("resource://gre/modules/devtools/deprecated-sync-thenables.js", {});
|
||||
let {Services} = Cu.import("resource://gre/modules/Services.jsm", {});
|
||||
|
||||
let require = Cu.import("resource://gre/modules/devtools/Loader.jsm", {}).devtools.require;
|
||||
|
@ -9,7 +9,7 @@
|
||||
* We should endevour to keep the source in sync.
|
||||
*/
|
||||
|
||||
var promise = Cu.import("resource://gre/modules/commonjs/sdk/core/promise.js", {}).Promise;
|
||||
var promise = Cu.import("resource://gre/modules/devtools/deprecated-sync-thenables.js", {}).Promise;
|
||||
var template = Cu.import("resource://gre/modules/devtools/Templater.jsm", {}).template;
|
||||
|
||||
const TEST_URI = "http://example.com/browser/browser/devtools/shared/test/browser_templater_basic.html";
|
||||
|
@ -870,7 +870,7 @@ Messages.Simple.prototype = Heritage.extend(Messages.BaseMessage.prototype,
|
||||
_renderBody: function()
|
||||
{
|
||||
let body = this.document.createElementNS(XHTML_NS, "span");
|
||||
body.className = "body devtools-monospace";
|
||||
body.className = "message-body-wrapper message-body devtools-monospace";
|
||||
|
||||
let anchor, container = body;
|
||||
if (this._link || this._linkCallback) {
|
||||
@ -1223,6 +1223,7 @@ Messages.ConsoleGeneric = function(packet)
|
||||
line: packet.lineNumber,
|
||||
},
|
||||
};
|
||||
|
||||
switch (packet.level) {
|
||||
case "count": {
|
||||
let counter = packet.counter, label = counter.label;
|
||||
@ -1239,12 +1240,30 @@ Messages.ConsoleGeneric = function(packet)
|
||||
|
||||
this._repeatID.consoleApiLevel = packet.level;
|
||||
this._repeatID.styles = packet.styles;
|
||||
this._stacktrace = this._repeatID.stacktrace = packet.stacktrace;
|
||||
this._styles = packet.styles || [];
|
||||
|
||||
this._onClickCollapsible = this._onClickCollapsible.bind(this);
|
||||
};
|
||||
|
||||
Messages.ConsoleGeneric.prototype = Heritage.extend(Messages.Extended.prototype,
|
||||
{
|
||||
_styles: null,
|
||||
_stacktrace: null,
|
||||
|
||||
/**
|
||||
* Tells if the message can be expanded/collapsed.
|
||||
* @type boolean
|
||||
*/
|
||||
collapsible: false,
|
||||
|
||||
/**
|
||||
* Getter that tells if this message is collapsed - no details are shown.
|
||||
* @type boolean
|
||||
*/
|
||||
get collapsed() {
|
||||
return this.collapsible && this.element && !this.element.hasAttribute("open");
|
||||
},
|
||||
|
||||
_renderBodyPieceSeparator: function()
|
||||
{
|
||||
@ -1253,13 +1272,84 @@ Messages.ConsoleGeneric.prototype = Heritage.extend(Messages.Extended.prototype,
|
||||
|
||||
render: function()
|
||||
{
|
||||
let lastStyle = null;
|
||||
let msg = this.document.createElementNS(XHTML_NS, "span");
|
||||
msg.className = "message-body devtools-monospace";
|
||||
|
||||
this._renderBodyPieces(msg);
|
||||
|
||||
let repeatNode = Messages.Simple.prototype._renderRepeatNode.call(this);
|
||||
let location = Messages.Simple.prototype._renderLocation.call(this);
|
||||
if (location) {
|
||||
location.target = "jsdebugger";
|
||||
}
|
||||
|
||||
let stack = null;
|
||||
let twisty = null;
|
||||
if (this._stacktrace && this._stacktrace.length > 0) {
|
||||
stack = new Widgets.Stacktrace(this, this._stacktrace).render().element;
|
||||
|
||||
twisty = this.document.createElementNS(XHTML_NS, "a");
|
||||
twisty.className = "theme-twisty";
|
||||
twisty.href = "#";
|
||||
twisty.title = l10n.getStr("messageToggleDetails");
|
||||
twisty.addEventListener("click", this._onClickCollapsible);
|
||||
}
|
||||
|
||||
let flex = this.document.createElementNS(XHTML_NS, "span");
|
||||
flex.className = "message-flex-body";
|
||||
|
||||
if (twisty) {
|
||||
flex.appendChild(twisty);
|
||||
}
|
||||
|
||||
flex.appendChild(msg);
|
||||
|
||||
if (repeatNode) {
|
||||
flex.appendChild(repeatNode);
|
||||
}
|
||||
if (location) {
|
||||
flex.appendChild(location);
|
||||
}
|
||||
|
||||
let result = this.document.createDocumentFragment();
|
||||
result.appendChild(flex);
|
||||
|
||||
if (stack) {
|
||||
result.appendChild(this.document.createTextNode("\n"));
|
||||
result.appendChild(stack);
|
||||
}
|
||||
|
||||
this._message = result;
|
||||
this._stacktrace = null;
|
||||
|
||||
Messages.Simple.prototype.render.call(this);
|
||||
|
||||
if (stack) {
|
||||
this.collapsible = true;
|
||||
this.element.setAttribute("collapsible", true);
|
||||
|
||||
let icon = this.element.querySelector(".icon");
|
||||
icon.addEventListener("click", this._onClickCollapsible);
|
||||
}
|
||||
|
||||
return this;
|
||||
},
|
||||
|
||||
_renderBody: function()
|
||||
{
|
||||
let body = Messages.Simple.prototype._renderBody.apply(this, arguments);
|
||||
body.classList.remove("devtools-monospace", "message-body");
|
||||
return body;
|
||||
},
|
||||
|
||||
_renderBodyPieces: function(container)
|
||||
{
|
||||
let lastStyle = null;
|
||||
|
||||
for (let i = 0; i < this._messagePieces.length; i++) {
|
||||
let separator = i > 0 ? this._renderBodyPieceSeparator() : null;
|
||||
if (separator) {
|
||||
result.appendChild(separator);
|
||||
container.appendChild(separator);
|
||||
}
|
||||
|
||||
let piece = this._messagePieces[i];
|
||||
@ -1270,13 +1360,11 @@ Messages.ConsoleGeneric.prototype = Heritage.extend(Messages.Extended.prototype,
|
||||
lastStyle = this.cleanupStyle(style);
|
||||
}
|
||||
|
||||
result.appendChild(this._renderBodyPiece(piece, lastStyle));
|
||||
container.appendChild(this._renderBodyPiece(piece, lastStyle));
|
||||
}
|
||||
|
||||
this._message = result;
|
||||
this._messagePieces = null;
|
||||
this._styles = null;
|
||||
return Messages.Simple.prototype.render.call(this);
|
||||
},
|
||||
|
||||
_renderBodyPiece: function(piece, style)
|
||||
@ -1298,6 +1386,41 @@ Messages.ConsoleGeneric.prototype = Heritage.extend(Messages.Extended.prototype,
|
||||
return result;
|
||||
},
|
||||
|
||||
// no-op for the message location and .repeats elements.
|
||||
// |this.render()| handles customized message output.
|
||||
_renderLocation: function() { },
|
||||
_renderRepeatNode: function() { },
|
||||
|
||||
/**
|
||||
* Expand/collapse message details.
|
||||
*/
|
||||
toggleDetails: function()
|
||||
{
|
||||
let twisty = this.element.querySelector(".theme-twisty");
|
||||
if (this.element.hasAttribute("open")) {
|
||||
this.element.removeAttribute("open");
|
||||
twisty.removeAttribute("open");
|
||||
} else {
|
||||
this.element.setAttribute("open", true);
|
||||
twisty.setAttribute("open", true);
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* The click event handler for the message expander arrow element. This method
|
||||
* toggles the display of message details.
|
||||
*
|
||||
* @private
|
||||
* @param nsIDOMEvent ev
|
||||
* The DOM event object.
|
||||
* @see this.toggleDetails()
|
||||
*/
|
||||
_onClickCollapsible: function(ev)
|
||||
{
|
||||
ev.preventDefault();
|
||||
this.toggleDetails();
|
||||
},
|
||||
|
||||
/**
|
||||
* Given a style attribute value, return a cleaned up version of the string
|
||||
* such that:
|
||||
@ -1355,7 +1478,7 @@ Messages.ConsoleGeneric.prototype = Heritage.extend(Messages.Extended.prototype,
|
||||
Messages.ConsoleTrace = function(packet)
|
||||
{
|
||||
let options = {
|
||||
className: "consoleTrace cm-s-mozilla",
|
||||
className: "cm-s-mozilla",
|
||||
timestamp: packet.timeStamp,
|
||||
category: "webdev",
|
||||
severity: CONSOLE_API_LEVELS_TO_SEVERITIES[packet.level],
|
||||
@ -1412,6 +1535,13 @@ Messages.ConsoleTrace.prototype = Heritage.extend(Messages.Simple.prototype,
|
||||
return result;
|
||||
},
|
||||
|
||||
render: function()
|
||||
{
|
||||
Messages.Simple.prototype.render.apply(this, arguments);
|
||||
this.element.setAttribute("open", true);
|
||||
return this;
|
||||
},
|
||||
|
||||
/**
|
||||
* Render the stack frames.
|
||||
*
|
||||
@ -1429,7 +1559,7 @@ Messages.ConsoleTrace.prototype = Heritage.extend(Messages.Simple.prototype,
|
||||
cmprop.textContent = "trace";
|
||||
|
||||
let title = this.document.createElementNS(XHTML_NS, "span");
|
||||
title.className = "title devtools-monospace";
|
||||
title.className = "message-body devtools-monospace";
|
||||
title.appendChild(cmvar);
|
||||
title.appendChild(this.document.createTextNode("."));
|
||||
title.appendChild(cmprop);
|
||||
@ -1443,7 +1573,8 @@ Messages.ConsoleTrace.prototype = Heritage.extend(Messages.Simple.prototype,
|
||||
|
||||
let widget = new Widgets.Stacktrace(this, this._stacktrace).render();
|
||||
|
||||
let body = this.document.createElementNS(XHTML_NS, "div");
|
||||
let body = this.document.createElementNS(XHTML_NS, "span");
|
||||
body.className = "message-flex-body";
|
||||
body.appendChild(title);
|
||||
if (repeatNode) {
|
||||
body.appendChild(repeatNode);
|
||||
@ -1463,7 +1594,7 @@ Messages.ConsoleTrace.prototype = Heritage.extend(Messages.Simple.prototype,
|
||||
_renderBody: function()
|
||||
{
|
||||
let body = Messages.Simple.prototype._renderBody.apply(this, arguments);
|
||||
body.classList.remove("devtools-monospace");
|
||||
body.classList.remove("devtools-monospace", "message-body");
|
||||
return body;
|
||||
},
|
||||
|
||||
@ -2722,7 +2853,6 @@ Widgets.Stacktrace.prototype = Heritage.extend(Widgets.BaseWidget.prototype,
|
||||
|
||||
return elem;
|
||||
},
|
||||
|
||||
}); // Widgets.Stacktrace.prototype
|
||||
|
||||
|
||||
|
@ -113,6 +113,7 @@ support-files =
|
||||
test-bug-609872-cd-iframe-parent.html
|
||||
test-bug-609872-cd-iframe-child.html
|
||||
test-bug-989025-iframe-parent.html
|
||||
test-console-api-stackframe.html
|
||||
|
||||
[browser_bug664688_sandbox_update_after_navigation.js]
|
||||
[browser_bug_638949_copy_link_location.js]
|
||||
@ -283,3 +284,4 @@ run-if = os == "mac"
|
||||
[browser_webconsole_cd_iframe.js]
|
||||
[browser_webconsole_autocomplete_crossdomain_iframe.js]
|
||||
[browser_webconsole_console_custom_styles.js]
|
||||
[browser_webconsole_console_api_stackframe.js]
|
||||
|
@ -67,6 +67,7 @@ function onConsoleMessage(aResults) {
|
||||
|
||||
// Test that the "Copy Link Location" menu item is hidden for non-network
|
||||
// messages.
|
||||
message.scrollIntoView();
|
||||
waitForContextMenu(menu, message, () => {
|
||||
let isHidden = menu.querySelector(CONTEXT_MENU_ID).hidden;
|
||||
ok(isHidden, CONTEXT_MENU_ID + " is hidden");
|
||||
@ -107,6 +108,7 @@ function onNetworkMessage(aResults) {
|
||||
function testMenuWithNetActivity() {
|
||||
// Test that the "Copy Link Location" menu item is visible for network-related
|
||||
// messages.
|
||||
message.scrollIntoView();
|
||||
waitForContextMenu(menu, message, () => {
|
||||
let isVisible = !menu.querySelector(CONTEXT_MENU_ID).hidden;
|
||||
ok(isVisible, CONTEXT_MENU_ID + " is visible");
|
||||
|
@ -53,7 +53,7 @@ function checkMessages([result])
|
||||
if (msg) {
|
||||
ok(msg, "message element #" + m);
|
||||
|
||||
let clickable = msg.querySelector(".body a");
|
||||
let clickable = msg.querySelector(".message-body a");
|
||||
ok(clickable, "clickable object #" + m);
|
||||
|
||||
msg.scrollIntoView(false);
|
||||
|
@ -23,7 +23,7 @@ function test()
|
||||
ok(msg, "output message found");
|
||||
|
||||
let anchor = msg.querySelector("a");
|
||||
let body = msg.querySelector(".body");
|
||||
let body = msg.querySelector(".message-body");
|
||||
ok(anchor, "object anchor");
|
||||
ok(body, "message body");
|
||||
ok(body.textContent.contains('testProp: "testValue"'), "message text check");
|
||||
@ -59,7 +59,7 @@ function test()
|
||||
msg = yield execute("window.location");
|
||||
ok(msg, "output message found");
|
||||
|
||||
body = msg.querySelector(".body");
|
||||
body = msg.querySelector(".message-body");
|
||||
ok(body, "message body");
|
||||
anchor = msg.querySelector("a");
|
||||
ok(anchor, "object anchor");
|
||||
|
@ -47,7 +47,7 @@ function onConsoleMessage(aResults)
|
||||
let msg = [...aResults[0].matched][0];
|
||||
ok(msg, "message element");
|
||||
|
||||
let body = msg.querySelector(".body");
|
||||
let body = msg.querySelector(".message-body");
|
||||
ok(body, "message body");
|
||||
|
||||
let clickable = aResults[0].clickableElements[0];
|
||||
|
@ -25,7 +25,7 @@ function testInputFocus() {
|
||||
}],
|
||||
}).then(([result]) => {
|
||||
let msg = [...result.matched][0];
|
||||
let outputItem = msg.querySelector(".body");
|
||||
let outputItem = msg.querySelector(".message-body");
|
||||
ok(outputItem, "found a logged message");
|
||||
let inputNode = hud.jsterm.inputNode;
|
||||
ok(inputNode.getAttribute("focused"), "input node is focused, first");
|
||||
|
@ -34,7 +34,7 @@ function performTest(hud)
|
||||
}).then(([result]) => {
|
||||
let msg = [...result.matched][0];
|
||||
ok(msg, "message element");
|
||||
let body = msg.querySelector(".body");
|
||||
let body = msg.querySelector(".message-body");
|
||||
ok(body, "message body");
|
||||
let clickable = result.clickableElements[0];
|
||||
ok(clickable, "the console.log() object anchor was found");
|
||||
|
@ -36,7 +36,7 @@ function tabLoad2(aEvent) {
|
||||
}],
|
||||
}).then(([result]) => {
|
||||
let msg = [...result.matched][0];
|
||||
outputItem = msg.querySelector(".body .url");
|
||||
outputItem = msg.querySelector(".message-body .url");
|
||||
ok(outputItem, "found a network message");
|
||||
document.addEventListener("popupshown", networkPanelShown, false);
|
||||
|
||||
@ -102,7 +102,7 @@ function networkPanelHidden(aEvent) {
|
||||
info("jsterm execute 'document' callback");
|
||||
|
||||
HUD.jsterm.once("variablesview-open", onVariablesViewOpen);
|
||||
let outputItem = msg.querySelector(".body a");
|
||||
let outputItem = msg.querySelector(".message-body a");
|
||||
ok(outputItem, "jsterm output message found");
|
||||
|
||||
// Send the mousedown and click events such that the property panel opens.
|
||||
|
@ -66,7 +66,7 @@ function consoleOpened(HUD) {
|
||||
|
||||
jsterm.execute("window._container", (msg) => {
|
||||
jsterm.once("variablesview-fetched", testVariablesView.bind(null, HUD));
|
||||
let anchor = msg.querySelector(".body a");
|
||||
let anchor = msg.querySelector(".message-body a");
|
||||
EventUtils.synthesizeMouse(anchor, 2, 2, {}, HUD.iframeWindow);
|
||||
});
|
||||
}
|
||||
|
@ -75,7 +75,7 @@ function testPropertyPanel()
|
||||
jsterm.clearOutput();
|
||||
jsterm.execute("document", (msg) => {
|
||||
jsterm.once("variablesview-fetched", onVariablesViewReady);
|
||||
let anchor = msg.querySelector(".body a");
|
||||
let anchor = msg.querySelector(".message-body a");
|
||||
EventUtils.synthesizeMouse(anchor, 2, 2, {}, gHUD.iframeWindow);
|
||||
});
|
||||
}
|
||||
|
@ -58,6 +58,7 @@ function onConsoleMessage(aResults) {
|
||||
let isDisabled = !controller || !controller.isCommandEnabled(COMMAND_NAME);
|
||||
ok(isDisabled, COMMAND_NAME + " should be disabled.");
|
||||
|
||||
outputNode.selectedItem.scrollIntoView();
|
||||
waitForContextMenu(contextMenu, outputNode.selectedItem, () => {
|
||||
let isHidden = contextMenu.querySelector(CONTEXT_MENU_ID).hidden;
|
||||
ok(isHidden, CONTEXT_MENU_ID + " should be hidden.");
|
||||
@ -117,6 +118,7 @@ function testOnNetActivity_contextmenu(msg) {
|
||||
outputNode.focus();
|
||||
HUD.ui.output.selectMessage(msg);
|
||||
|
||||
msg.scrollIntoView();
|
||||
waitForContextMenu(contextMenu, msg, () => {
|
||||
let isShown = !contextMenu.querySelector(CONTEXT_MENU_ID).hidden;
|
||||
ok(isShown, CONTEXT_MENU_ID + " should be shown.");
|
||||
|
@ -1,8 +1,12 @@
|
||||
/* vim:set ts=2 sw=2 sts=2 et: */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Any copyright is dedicated to the Public Domain.
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
*/
|
||||
|
||||
// Test that message source links for js errors and console API calls open in
|
||||
// the jsdebugger when clicked.
|
||||
|
||||
"use strict";
|
||||
|
||||
const TEST_URI = "http://example.com/browser/browser/devtools/webconsole/test" +
|
||||
"/test-bug-766001-js-console-links.html";
|
||||
@ -61,10 +65,8 @@ function test() {
|
||||
EventUtils.sendMouseEvent({ type: "click" }, node);
|
||||
});
|
||||
|
||||
yield hud.ui.once("source-in-debugger-opened", checkLine.bind(null, url, line));
|
||||
}
|
||||
yield hud.ui.once("source-in-debugger-opened");
|
||||
|
||||
function* checkLine(url, line) {
|
||||
let toolbox = yield gDevTools.getToolbox(hud.target);
|
||||
let {panelWin: { DebuggerView: view }} = toolbox.getPanel("jsdebugger");
|
||||
is(view.Sources.selectedValue, url, "expected source url");
|
||||
|
@ -0,0 +1,81 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
"use strict";
|
||||
|
||||
// Test that the console API messages for console.error()/exception()/assert()
|
||||
// include a stackframe. See bug 920116.
|
||||
|
||||
function test() {
|
||||
let hud;
|
||||
|
||||
const TEST_URI = "http://example.com/browser/browser/devtools/webconsole/test/test-console-api-stackframe.html";
|
||||
const TEST_FILE = TEST_URI.substr(TEST_URI.lastIndexOf("/"));
|
||||
|
||||
Task.spawn(runner).then(finishTest);
|
||||
|
||||
function* runner() {
|
||||
const {tab} = yield loadTab(TEST_URI);
|
||||
hud = yield openConsole(tab);
|
||||
|
||||
const stack = [{
|
||||
file: TEST_FILE,
|
||||
fn: "thirdCall",
|
||||
line: /\b2[123]\b/, // 21,22,23
|
||||
}, {
|
||||
file: TEST_FILE,
|
||||
fn: "secondCall",
|
||||
line: 16,
|
||||
}, {
|
||||
file: TEST_FILE,
|
||||
fn: "firstCall",
|
||||
line: 12,
|
||||
}];
|
||||
|
||||
let results = yield waitForMessages({
|
||||
webconsole: hud,
|
||||
messages: [{
|
||||
text: "foo-log",
|
||||
category: CATEGORY_WEBDEV,
|
||||
severity: SEVERITY_LOG,
|
||||
collapsible: false,
|
||||
}, {
|
||||
text: "foo-error",
|
||||
category: CATEGORY_WEBDEV,
|
||||
severity: SEVERITY_ERROR,
|
||||
collapsible: true,
|
||||
stacktrace: stack,
|
||||
}, {
|
||||
text: "foo-exception",
|
||||
category: CATEGORY_WEBDEV,
|
||||
severity: SEVERITY_ERROR,
|
||||
collapsible: true,
|
||||
stacktrace: stack,
|
||||
}, {
|
||||
text: "foo-assert",
|
||||
category: CATEGORY_WEBDEV,
|
||||
severity: SEVERITY_ERROR,
|
||||
collapsible: true,
|
||||
stacktrace: stack,
|
||||
}],
|
||||
});
|
||||
|
||||
let elem = [...results[1].matched][0];
|
||||
ok(elem, "message element");
|
||||
|
||||
let msg = elem._messageObject;
|
||||
ok(msg, "message object");
|
||||
|
||||
ok(msg.collapsed, "message is collapsed");
|
||||
|
||||
msg.toggleDetails();
|
||||
|
||||
ok(!msg.collapsed, "message is not collapsed");
|
||||
|
||||
msg.toggleDetails();
|
||||
|
||||
ok(msg.collapsed, "message is collapsed");
|
||||
|
||||
yield closeConsole(tab);
|
||||
}
|
||||
}
|
@ -59,7 +59,7 @@ function test() {
|
||||
let msg = [...result.matched][0];
|
||||
ok(msg, "message element");
|
||||
|
||||
let span = msg.querySelector(".body span[style]");
|
||||
let span = msg.querySelector(".message-body span[style]");
|
||||
ok(span, "span element");
|
||||
|
||||
info("span textContent is: " + span.textContent);
|
||||
|
@ -30,7 +30,7 @@ function checkResult(msg, desc) {
|
||||
category: CATEGORY_OUTPUT,
|
||||
}],
|
||||
}).then(([result]) => {
|
||||
let node = [...result.matched][0].querySelector(".body");
|
||||
let node = [...result.matched][0].querySelector(".message-body");
|
||||
if (typeof msg == "string") {
|
||||
is(node.textContent.trim(), msg,
|
||||
"correct message shown for " + desc);
|
||||
|
@ -3,6 +3,8 @@
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
"use strict";
|
||||
|
||||
let {gDevTools} = Cu.import("resource:///modules/devtools/gDevTools.jsm", {});
|
||||
let {console} = Cu.import("resource://gre/modules/devtools/Console.jsm", {});
|
||||
let {Promise: promise} = Cu.import("resource://gre/modules/Promise.jsm", {});
|
||||
@ -882,6 +884,8 @@ function openDebugger(aOptions = {})
|
||||
* message.
|
||||
* - longString: boolean, set to |true} to match long strings in the
|
||||
* message.
|
||||
* - collapsible: boolean, set to |true| to match messages that can
|
||||
* be collapsed/expanded.
|
||||
* - type: match messages that are instances of the given object. For
|
||||
* example, you can point to Messages.NavigationMarker to match any
|
||||
* such message.
|
||||
@ -890,6 +894,8 @@ function openDebugger(aOptions = {})
|
||||
* - source: object of the shape { url, line }. This is used to
|
||||
* match the source URL and line number of the error message or
|
||||
* console API call.
|
||||
* - stacktrace: array of objects of the form { file, fn, line } that
|
||||
* can match frames in the stacktrace associated with the message.
|
||||
* - groupDepth: number used to check the depth of the message in
|
||||
* a group.
|
||||
* - url: URL to match for network requests.
|
||||
@ -918,7 +924,7 @@ function waitForMessages(aOptions)
|
||||
|
||||
function checkText(aRule, aText)
|
||||
{
|
||||
let result;
|
||||
let result = false;
|
||||
if (Array.isArray(aRule)) {
|
||||
result = aRule.every((s) => checkText(s, aText));
|
||||
}
|
||||
@ -928,6 +934,9 @@ function waitForMessages(aOptions)
|
||||
else if (aRule instanceof RegExp) {
|
||||
result = aRule.test(aText);
|
||||
}
|
||||
else {
|
||||
result = aRule == aText;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@ -940,41 +949,18 @@ function waitForMessages(aOptions)
|
||||
return false;
|
||||
}
|
||||
|
||||
let frame = aElement.querySelector(".stacktrace li:first-child");
|
||||
if (trace.file) {
|
||||
let file = frame.querySelector(".message-location").title;
|
||||
if (!checkText(trace.file, file)) {
|
||||
ok(false, "console.trace() message is missing the file name: " +
|
||||
trace.file);
|
||||
displayErrorContext(aRule, aElement);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (trace.fn) {
|
||||
let fn = frame.querySelector(".function").textContent;
|
||||
if (!checkText(trace.fn, fn)) {
|
||||
ok(false, "console.trace() message is missing the function name: " +
|
||||
trace.fn);
|
||||
displayErrorContext(aRule, aElement);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (trace.line) {
|
||||
let line = frame.querySelector(".message-location").sourceLine;
|
||||
if (!checkText(trace.line, line)) {
|
||||
ok(false, "console.trace() message is missing the line number: " +
|
||||
trace.line);
|
||||
displayErrorContext(aRule, aElement);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
aRule.category = CATEGORY_WEBDEV;
|
||||
aRule.severity = SEVERITY_LOG;
|
||||
aRule.type = Messages.ConsoleTrace;
|
||||
|
||||
if (!aRule.stacktrace && typeof trace == "object" && trace !== true) {
|
||||
if (Array.isArray(trace)) {
|
||||
aRule.stacktrace = trace;
|
||||
} else {
|
||||
aRule.stacktrace = [trace];
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -1058,6 +1044,66 @@ function waitForMessages(aOptions)
|
||||
return true;
|
||||
}
|
||||
|
||||
function checkCollapsible(aRule, aElement)
|
||||
{
|
||||
let msg = aElement._messageObject;
|
||||
if (!msg || !!msg.collapsible != aRule.collapsible) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
function checkStacktrace(aRule, aElement)
|
||||
{
|
||||
let stack = aRule.stacktrace;
|
||||
let frames = aElement.querySelectorAll(".stacktrace > li");
|
||||
if (!frames.length) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (let i = 0; i < stack.length; i++) {
|
||||
let frame = frames[i];
|
||||
let expected = stack[i];
|
||||
if (!frame) {
|
||||
ok(false, "expected frame #" + i + " but didnt find it");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (expected.file) {
|
||||
let file = frame.querySelector(".message-location").title;
|
||||
if (!checkText(expected.file, file)) {
|
||||
ok(false, "frame #" + i + " does not match file name: " +
|
||||
expected.file);
|
||||
displayErrorContext(aRule, aElement);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (expected.fn) {
|
||||
let fn = frame.querySelector(".function").textContent;
|
||||
if (!checkText(expected.fn, fn)) {
|
||||
ok(false, "frame #" + i + " does not match the function name: " +
|
||||
expected.fn);
|
||||
displayErrorContext(aRule, aElement);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (expected.line) {
|
||||
let line = frame.querySelector(".message-location").sourceLine;
|
||||
if (!checkText(expected.line, line)) {
|
||||
ok(false, "frame #" + i + " does not match the line number: " +
|
||||
expected.line);
|
||||
displayErrorContext(aRule, aElement);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
function checkMessage(aRule, aElement)
|
||||
{
|
||||
let elemText = aElement.textContent;
|
||||
@ -1094,6 +1140,10 @@ function waitForMessages(aOptions)
|
||||
return false;
|
||||
}
|
||||
|
||||
if ("collapsible" in aRule && !checkCollapsible(aRule, aElement)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
let partialMatch = !!(aRule.consoleTrace || aRule.consoleTime ||
|
||||
aRule.consoleTimeEnd);
|
||||
|
||||
@ -1129,6 +1179,18 @@ function waitForMessages(aOptions)
|
||||
return false;
|
||||
}
|
||||
|
||||
if (aRule.text) {
|
||||
partialMatch = true;
|
||||
}
|
||||
|
||||
if (aRule.stacktrace && !checkStacktrace(aRule, aElement)) {
|
||||
if (partialMatch) {
|
||||
ok(false, "failed to match stacktrace for rule: " + displayRule(aRule));
|
||||
displayErrorContext(aRule, aElement);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
if (aRule.category == CATEGORY_NETWORK && "url" in aRule &&
|
||||
!checkText(aRule.url, aElement.url)) {
|
||||
return false;
|
||||
@ -1166,7 +1228,7 @@ function waitForMessages(aOptions)
|
||||
}
|
||||
|
||||
if ("objects" in aRule) {
|
||||
let clickables = aElement.querySelectorAll(".body a");
|
||||
let clickables = aElement.querySelectorAll(".message-body a");
|
||||
if (aRule.objects != !!clickables[0]) {
|
||||
if (partialMatch) {
|
||||
is(!!clickables[0], aRule.objects,
|
||||
@ -1410,7 +1472,8 @@ function checkOutputForInputs(hud, inputTests)
|
||||
|
||||
function checkObjectClick(entry, msg)
|
||||
{
|
||||
let body = msg.querySelector(".body a") || msg.querySelector(".body");
|
||||
let body = msg.querySelector(".message-body a") ||
|
||||
msg.querySelector(".message-body");
|
||||
ok(body, "the message body");
|
||||
|
||||
let deferred = promise.defer();
|
||||
|
@ -3,6 +3,8 @@
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/
|
||||
*/
|
||||
|
||||
window.addEventListener("load", function() {
|
||||
function onLoad123() {
|
||||
console.log("Blah Blah");
|
||||
}, false);
|
||||
}
|
||||
|
||||
window.addEventListener("load", onLoad123, false);
|
||||
|
@ -0,0 +1,32 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html dir="ltr" lang="en">
|
||||
<head>
|
||||
<meta charset="utf8">
|
||||
<!--
|
||||
- Any copyright is dedicated to the Public Domain.
|
||||
- http://creativecommons.org/publicdomain/zero/1.0/
|
||||
-->
|
||||
<title>Test for bug 920116 - stacktraces for console API messages</title>
|
||||
<script>
|
||||
function firstCall() {
|
||||
secondCall();
|
||||
}
|
||||
|
||||
function secondCall() {
|
||||
thirdCall();
|
||||
}
|
||||
|
||||
function thirdCall() {
|
||||
console.log("foo-log");
|
||||
console.error("foo-error");
|
||||
console.exception("foo-exception");
|
||||
console.assert("red" == "blue", "foo-assert");
|
||||
}
|
||||
|
||||
window.onload = firstCall;
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
<p>Hello world!</p>
|
||||
</body>
|
||||
</html>
|
@ -1373,7 +1373,7 @@ WebConsoleFrame.prototype = {
|
||||
aScriptError.timeStamp);
|
||||
|
||||
// Select the body of the message node that is displayed in the console
|
||||
let msgBody = node.getElementsByClassName("body")[0];
|
||||
let msgBody = node.getElementsByClassName("message-body")[0];
|
||||
// Add the more info link node to messages that belong to certain categories
|
||||
this.addMoreInfoLink(msgBody, aScriptError);
|
||||
|
||||
@ -2461,7 +2461,7 @@ WebConsoleFrame.prototype = {
|
||||
|
||||
// Create the message body, which contains the actual text of the message.
|
||||
let bodyNode = this.document.createElementNS(XHTML_NS, "span");
|
||||
bodyNode.className = "body devtools-monospace";
|
||||
bodyNode.className = "message-body-wrapper message-body devtools-monospace";
|
||||
|
||||
// Store the body text, since it is needed later for the variables view.
|
||||
let body = aBody;
|
||||
@ -2608,7 +2608,9 @@ WebConsoleFrame.prototype = {
|
||||
|
||||
locationNode.href = isScratchpad || !fullURL ? "#" : fullURL;
|
||||
locationNode.draggable = false;
|
||||
locationNode.target = aTarget;
|
||||
if (aTarget) {
|
||||
locationNode.target = aTarget;
|
||||
}
|
||||
locationNode.setAttribute("title", aSourceURL);
|
||||
locationNode.className = "message-location theme-link devtools-monospace";
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
This is the pdf.js project output, https://github.com/mozilla/pdf.js
|
||||
|
||||
Current extension version is: 1.0.21
|
||||
Current extension version is: 1.0.68
|
||||
|
||||
|
@ -227,7 +227,8 @@ ChromeActions.prototype = {
|
||||
// the original url.
|
||||
var originalUri = NetUtil.newURI(data.originalUrl);
|
||||
var filename = data.filename;
|
||||
if (typeof filename !== 'string' || !/\.pdf$/i.test(filename)) {
|
||||
if (typeof filename !== 'string' ||
|
||||
(!/\.pdf$/i.test(filename) && !data.isAttachment)) {
|
||||
filename = 'document.pdf';
|
||||
}
|
||||
var blobUri = data.blobUrl ? NetUtil.newURI(data.blobUrl) : originalUri;
|
||||
@ -273,7 +274,8 @@ ChromeActions.prototype = {
|
||||
var listener = {
|
||||
extListener: null,
|
||||
onStartRequest: function(aRequest, aContext) {
|
||||
this.extListener = extHelperAppSvc.doContent('application/pdf',
|
||||
this.extListener = extHelperAppSvc.doContent((data.isAttachment ? '' :
|
||||
'application/pdf'),
|
||||
aRequest, frontWindow, false);
|
||||
this.extListener.onStartRequest(aRequest, aContext);
|
||||
},
|
||||
|
@ -21,8 +21,8 @@ if (typeof PDFJS === 'undefined') {
|
||||
(typeof window !== 'undefined' ? window : this).PDFJS = {};
|
||||
}
|
||||
|
||||
PDFJS.version = '1.0.21';
|
||||
PDFJS.build = 'f954cde';
|
||||
PDFJS.version = '1.0.68';
|
||||
PDFJS.build = 'ead4cbf';
|
||||
|
||||
(function pdfjsWrapper() {
|
||||
// Use strict in our context only - users might not want it
|
||||
@ -453,6 +453,28 @@ function string32(value) {
|
||||
(value >> 8) & 0xff, value & 0xff);
|
||||
}
|
||||
|
||||
function log2(x) {
|
||||
var n = 1, i = 0;
|
||||
while (x > n) {
|
||||
n <<= 1;
|
||||
i++;
|
||||
}
|
||||
return i;
|
||||
}
|
||||
|
||||
function readInt8(data, start) {
|
||||
return (data[start] << 24) >> 24;
|
||||
}
|
||||
|
||||
function readUint16(data, offset) {
|
||||
return (data[offset] << 8) | data[offset + 1];
|
||||
}
|
||||
|
||||
function readUint32(data, offset) {
|
||||
return ((data[offset] << 24) | (data[offset + 1] << 16) |
|
||||
(data[offset + 2] << 8) | data[offset + 3]) >>> 0;
|
||||
}
|
||||
|
||||
// Lazy test the endianness of the platform
|
||||
// NOTE: This will be 'true' for simulated TypedArrays
|
||||
function isLittleEndian() {
|
||||
@ -1745,31 +1767,31 @@ var DeviceCmykCS = (function DeviceCmykCSClosure() {
|
||||
var k = src[srcOffset + 3] * srcScale;
|
||||
|
||||
var r =
|
||||
c * (-4.387332384609988 * c + 54.48615194189176 * m +
|
||||
18.82290502165302 * y + 212.25662451639585 * k +
|
||||
-285.2331026137004) +
|
||||
m * (1.7149763477362134 * m - 5.6096736904047315 * y +
|
||||
-17.873870861415444 * k - 5.497006427196366) +
|
||||
y * (-2.5217340131683033 * y - 21.248923337353073 * k +
|
||||
17.5119270841813) +
|
||||
k * (-21.86122147463605 * k - 189.48180835922747) + 255;
|
||||
(c * (-4.387332384609988 * c + 54.48615194189176 * m +
|
||||
18.82290502165302 * y + 212.25662451639585 * k +
|
||||
-285.2331026137004) +
|
||||
m * (1.7149763477362134 * m - 5.6096736904047315 * y +
|
||||
-17.873870861415444 * k - 5.497006427196366) +
|
||||
y * (-2.5217340131683033 * y - 21.248923337353073 * k +
|
||||
17.5119270841813) +
|
||||
k * (-21.86122147463605 * k - 189.48180835922747) + 255) | 0;
|
||||
var g =
|
||||
c * (8.841041422036149 * c + 60.118027045597366 * m +
|
||||
6.871425592049007 * y + 31.159100130055922 * k +
|
||||
-79.2970844816548) +
|
||||
m * (-15.310361306967817 * m + 17.575251261109482 * y +
|
||||
131.35250912493976 * k - 190.9453302588951) +
|
||||
y * (4.444339102852739 * y + 9.8632861493405 * k - 24.86741582555878) +
|
||||
k * (-20.737325471181034 * k - 187.80453709719578) + 255;
|
||||
(c * (8.841041422036149 * c + 60.118027045597366 * m +
|
||||
6.871425592049007 * y + 31.159100130055922 * k +
|
||||
-79.2970844816548) +
|
||||
m * (-15.310361306967817 * m + 17.575251261109482 * y +
|
||||
131.35250912493976 * k - 190.9453302588951) +
|
||||
y * (4.444339102852739 * y + 9.8632861493405 * k - 24.86741582555878) +
|
||||
k * (-20.737325471181034 * k - 187.80453709719578) + 255) | 0;
|
||||
var b =
|
||||
c * (0.8842522430003296 * c + 8.078677503112928 * m +
|
||||
30.89978309703729 * y - 0.23883238689178934 * k +
|
||||
-14.183576799673286) +
|
||||
m * (10.49593273432072 * m + 63.02378494754052 * y +
|
||||
50.606957656360734 * k - 112.23884253719248) +
|
||||
y * (0.03296041114873217 * y + 115.60384449646641 * k +
|
||||
-193.58209356861505) +
|
||||
k * (-22.33816807309886 * k - 180.12613974708367) + 255;
|
||||
(c * (0.8842522430003296 * c + 8.078677503112928 * m +
|
||||
30.89978309703729 * y - 0.23883238689178934 * k +
|
||||
-14.183576799673286) +
|
||||
m * (10.49593273432072 * m + 63.02378494754052 * y +
|
||||
50.606957656360734 * k - 112.23884253719248) +
|
||||
y * (0.03296041114873217 * y + 115.60384449646641 * k +
|
||||
-193.58209356861505) +
|
||||
k * (-22.33816807309886 * k - 180.12613974708367) + 255) | 0;
|
||||
|
||||
dest[destOffset] = r > 255 ? 255 : r < 0 ? 0 : r;
|
||||
dest[destOffset + 1] = g > 255 ? 255 : g < 0 ? 0 : g;
|
||||
@ -2142,7 +2164,6 @@ var PDFFunction = (function PDFFunctionClosure() {
|
||||
constructSampled: function PDFFunction_constructSampled(str, dict) {
|
||||
function toMultiArray(arr) {
|
||||
var inputLength = arr.length;
|
||||
var outputLength = arr.length / 2;
|
||||
var out = [];
|
||||
var index = 0;
|
||||
for (var i = 0; i < inputLength; i += 2) {
|
||||
@ -2213,7 +2234,7 @@ var PDFFunction = (function PDFFunctionClosure() {
|
||||
var samples = IR[5];
|
||||
var size = IR[6];
|
||||
var n = IR[7];
|
||||
var mask = IR[8];
|
||||
//var mask = IR[8];
|
||||
var range = IR[9];
|
||||
|
||||
if (m != args.length) {
|
||||
@ -2884,6 +2905,7 @@ var Annotation = (function AnnotationClosure() {
|
||||
|
||||
this.appearance = getDefaultAppearance(dict);
|
||||
data.hasAppearance = !!this.appearance;
|
||||
data.id = params.ref.num;
|
||||
}
|
||||
|
||||
Annotation.prototype = {
|
||||
@ -2992,8 +3014,6 @@ var Annotation = (function AnnotationClosure() {
|
||||
var matrix = appearanceDict.get('Matrix') || [1, 0, 0, 1, 0 ,0];
|
||||
var transform = getTransformMatrix(data.rect, bbox, matrix);
|
||||
|
||||
var border = data.border;
|
||||
|
||||
resourcesPromise.then(function(resources) {
|
||||
var opList = new OperatorList();
|
||||
opList.addOp(OPS.beginAnnotation, [data.rect, transform, matrix]);
|
||||
@ -3219,7 +3239,6 @@ var TextWidgetAnnotation = (function TextWidgetAnnotationClosure() {
|
||||
}
|
||||
|
||||
|
||||
var parent = WidgetAnnotation.prototype;
|
||||
Util.inherit(TextWidgetAnnotation, WidgetAnnotation, {
|
||||
hasHtml: function TextWidgetAnnotation_hasHtml() {
|
||||
return !this.data.hasAppearance && !!this.data.fieldValue;
|
||||
@ -3242,7 +3261,7 @@ var TextWidgetAnnotation = (function TextWidgetAnnotationClosure() {
|
||||
|
||||
var fontObj = item.fontRefName ?
|
||||
commonObjs.getData(item.fontRefName) : null;
|
||||
var cssRules = setTextStyles(content, item, fontObj);
|
||||
setTextStyles(content, item, fontObj);
|
||||
|
||||
element.appendChild(content);
|
||||
|
||||
@ -3274,7 +3293,6 @@ var TextWidgetAnnotation = (function TextWidgetAnnotationClosure() {
|
||||
var appearanceFnArray = opList.fnArray;
|
||||
var appearanceArgsArray = opList.argsArray;
|
||||
var fnArray = [];
|
||||
var argsArray = [];
|
||||
|
||||
// TODO(mack): Add support for stroke color
|
||||
data.rgb = [0, 0, 0];
|
||||
@ -3490,7 +3508,6 @@ var TextAnnotation = (function TextAnnotationClosure() {
|
||||
}
|
||||
};
|
||||
|
||||
var self = this;
|
||||
image.addEventListener('click', function image_clickHandler() {
|
||||
toggleAnnotation();
|
||||
}, false);
|
||||
@ -3595,7 +3612,6 @@ var LinkAnnotation = (function LinkAnnotationClosure() {
|
||||
container.className = 'annotLink';
|
||||
|
||||
var item = this.data;
|
||||
var rect = item.rect;
|
||||
|
||||
container.style.borderColor = item.colorCssRgb;
|
||||
container.style.borderStyle = 'solid';
|
||||
@ -3850,6 +3866,13 @@ var PDFDocumentProxy = (function PDFDocumentProxyClosure() {
|
||||
getDestinations: function PDFDocumentProxy_getDestinations() {
|
||||
return this.transport.getDestinations();
|
||||
},
|
||||
/**
|
||||
* @return {Promise} A promise that is resolved with a lookup table for
|
||||
* mapping named attachments to their content.
|
||||
*/
|
||||
getAttachments: function PDFDocumentProxy_getAttachments() {
|
||||
return this.transport.getAttachments();
|
||||
},
|
||||
/**
|
||||
* @return {Promise} A promise that is resolved with an array of all the
|
||||
* JavaScript strings in the name tree.
|
||||
@ -4627,6 +4650,16 @@ var WorkerTransport = (function WorkerTransportClosure() {
|
||||
return promise;
|
||||
},
|
||||
|
||||
getAttachments: function WorkerTransport_getAttachments() {
|
||||
var promise = new PDFJS.LegacyPromise();
|
||||
this.messageHandler.send('GetAttachments', null,
|
||||
function transportAttachments(attachments) {
|
||||
promise.resolve(attachments);
|
||||
}
|
||||
);
|
||||
return promise;
|
||||
},
|
||||
|
||||
startCleanup: function WorkerTransport_startCleanup() {
|
||||
this.messageHandler.send('Cleanup', null,
|
||||
function endCleanup() {
|
||||
@ -5421,7 +5454,6 @@ var CanvasGraphics = (function CanvasGraphicsClosure() {
|
||||
// imgData.kind tells us which one this is.
|
||||
if (imgData.kind === ImageKind.GRAYSCALE_1BPP) {
|
||||
// Grayscale, 1 bit per pixel (i.e. black-and-white).
|
||||
var destDataLength = dest.length;
|
||||
var srcLength = src.byteLength;
|
||||
var dest32 = PDFJS.hasCanvasTypedArrays ? new Uint32Array(dest.buffer) :
|
||||
new Uint32ArrayView(dest);
|
||||
@ -5692,7 +5724,6 @@ var CanvasGraphics = (function CanvasGraphicsClosure() {
|
||||
return i;
|
||||
}
|
||||
|
||||
var executionEndIdx;
|
||||
var endTime = Date.now() + EXECUTION_TIME;
|
||||
|
||||
var commonObjs = this.commonObjs;
|
||||
@ -6268,7 +6299,6 @@ var CanvasGraphics = (function CanvasGraphicsClosure() {
|
||||
var vertical = font.vertical;
|
||||
var defaultVMetrics = font.defaultVMetrics;
|
||||
var i, glyph, width;
|
||||
var VERTICAL_TEXT_ROTATION = Math.PI / 2;
|
||||
|
||||
if (fontSize === 0) {
|
||||
return;
|
||||
@ -6396,7 +6426,6 @@ var CanvasGraphics = (function CanvasGraphicsClosure() {
|
||||
}
|
||||
},
|
||||
showSpacedText: function CanvasGraphics_showSpacedText(arr) {
|
||||
var ctx = this.ctx;
|
||||
var current = this.current;
|
||||
var font = current.font;
|
||||
var fontSize = current.fontSize;
|
||||
@ -6472,8 +6501,6 @@ var CanvasGraphics = (function CanvasGraphicsClosure() {
|
||||
var base = cs.base;
|
||||
var color;
|
||||
if (base) {
|
||||
var baseComps = base.numComps;
|
||||
|
||||
color = base.getRgb(args, 0);
|
||||
}
|
||||
pattern = new TilingPattern(IR, color, this.ctx, this.objs,
|
||||
@ -7732,13 +7759,13 @@ var createMeshCanvas = (function createMeshCanvasClosure() {
|
||||
|
||||
ShadingIRs.Mesh = {
|
||||
fromIR: function Mesh_fromIR(raw) {
|
||||
var type = raw[1];
|
||||
//var type = raw[1];
|
||||
var coords = raw[2];
|
||||
var colors = raw[3];
|
||||
var figures = raw[4];
|
||||
var bounds = raw[5];
|
||||
var matrix = raw[6];
|
||||
var bbox = raw[7];
|
||||
//var bbox = raw[7];
|
||||
var background = raw[8];
|
||||
return {
|
||||
type: 'Pattern',
|
||||
@ -7835,7 +7862,6 @@ var TilingPattern = (function TilingPatternClosure() {
|
||||
var color = this.color;
|
||||
var objs = this.objs;
|
||||
var commonObjs = this.commonObjs;
|
||||
var ctx = this.ctx;
|
||||
|
||||
info('TilingType: ' + tilingType);
|
||||
|
||||
|
918
browser/extensions/pdfjs/content/build/pdf.worker.js
vendored
@ -20,7 +20,6 @@
|
||||
|
||||
var FontInspector = (function FontInspectorClosure() {
|
||||
var fonts;
|
||||
var panelWidth = 300;
|
||||
var active = false;
|
||||
var fontAttribute = 'data-font-name';
|
||||
function removeSelection() {
|
||||
@ -327,6 +326,8 @@ var Stepper = (function StepperClosure() {
|
||||
}
|
||||
},
|
||||
updateOperatorList: function updateOperatorList(operatorList) {
|
||||
var self = this;
|
||||
|
||||
function cboxOnClick() {
|
||||
var x = +this.dataset.idx;
|
||||
if (this.checked) {
|
||||
@ -342,7 +343,6 @@ var Stepper = (function StepperClosure() {
|
||||
return;
|
||||
}
|
||||
|
||||
var self = this;
|
||||
var chunk = document.createDocumentFragment();
|
||||
var operatorsToDisplay = Math.min(MAX_OPERATORS_COUNT,
|
||||
operatorList.fnArray.length);
|
||||
|
After Width: | Height: | Size: 384 B |
After Width: | Height: | Size: 871 B |
@ -533,6 +533,9 @@ html[dir='rtl'] .splitToolbarButton > .toolbarButton {
|
||||
0 0 1px hsla(0,0%,0%,.05);
|
||||
z-index: 199;
|
||||
}
|
||||
.splitToolbarButton > .toolbarButton {
|
||||
position: relative;
|
||||
}
|
||||
html[dir='ltr'] .splitToolbarButton > .toolbarButton:first-child,
|
||||
html[dir='rtl'] .splitToolbarButton > .toolbarButton:last-child {
|
||||
position: relative;
|
||||
@ -861,6 +864,10 @@ html[dir="rtl"] #viewOutline.toolbarButton::before {
|
||||
content: url(images/toolbarButton-viewOutline-rtl.png);
|
||||
}
|
||||
|
||||
#viewAttachments.toolbarButton::before {
|
||||
content: url(images/toolbarButton-viewAttachments.png);
|
||||
}
|
||||
|
||||
#viewFind.toolbarButton::before {
|
||||
content: url(images/toolbarButton-search.png);
|
||||
}
|
||||
@ -1070,7 +1077,8 @@ a:focus > .thumbnail > .thumbnailSelectionRing,
|
||||
color: hsla(0,0%,100%,1);
|
||||
}
|
||||
|
||||
#outlineView {
|
||||
#outlineView,
|
||||
#attachmentsView {
|
||||
position: absolute;
|
||||
width: 192px;
|
||||
top: 0;
|
||||
@ -1088,7 +1096,8 @@ html[dir='rtl'] .outlineItem > .outlineItems {
|
||||
margin-right: 20px;
|
||||
}
|
||||
|
||||
.outlineItem > a {
|
||||
.outlineItem > a,
|
||||
.attachmentsItem > a {
|
||||
text-decoration: none;
|
||||
display: inline-block;
|
||||
min-width: 95%;
|
||||
@ -1102,15 +1111,18 @@ html[dir='rtl'] .outlineItem > .outlineItems {
|
||||
white-space: normal;
|
||||
}
|
||||
|
||||
html[dir='ltr'] .outlineItem > a {
|
||||
html[dir='ltr'] .outlineItem > a,
|
||||
html[dir='ltr'] .attachmentsItem > a {
|
||||
padding: 2px 0 5px 10px;
|
||||
}
|
||||
|
||||
html[dir='rtl'] .outlineItem > a {
|
||||
html[dir='rtl'] .outlineItem > a,
|
||||
html[dir='rtl'] .attachmentsItem > a {
|
||||
padding: 2px 10px 5px 0;
|
||||
}
|
||||
|
||||
.outlineItem > a:hover {
|
||||
.outlineItem > a:hover,
|
||||
.attachmentsItem > a:hover {
|
||||
background-color: hsla(0,0%,100%,.02);
|
||||
background-image: linear-gradient(hsla(0,0%,100%,.05), hsla(0,0%,100%,0));
|
||||
background-clip: padding-box;
|
||||
@ -1641,6 +1653,10 @@ html[dir='rtl'] #documentPropertiesContainer .row > * {
|
||||
content: url(images/toolbarButton-viewOutline-rtl@2x.png);
|
||||
}
|
||||
|
||||
#viewAttachments.toolbarButton::before {
|
||||
content: url(images/toolbarButton-viewAttachments@2x.png);
|
||||
}
|
||||
|
||||
#viewFind.toolbarButton::before {
|
||||
content: url(images/toolbarButton-search@2x.png);
|
||||
}
|
||||
|
@ -23,7 +23,7 @@ http://sourceforge.net/adobe/cmap/wiki/License/
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
|
||||
<title>PDF.js viewer</title>
|
||||
|
||||
<!-- This snippet is used in firefox extension, see Makefile -->
|
||||
<!-- This snippet is used in the Firefox extension (included from viewer.html) -->
|
||||
<base href="resource://pdf.js/web/" />
|
||||
<script type="text/javascript" src="l10n.js"></script>
|
||||
<script type="text/javascript" src="../build/pdf.js"></script>
|
||||
@ -53,6 +53,9 @@ http://sourceforge.net/adobe/cmap/wiki/License/
|
||||
<button id="viewOutline" class="toolbarButton group" title="Show Document Outline" tabindex="3" data-l10n-id="outline">
|
||||
<span data-l10n-id="outline_label">Document Outline</span>
|
||||
</button>
|
||||
<button id="viewAttachments" class="toolbarButton group" title="Show Attachments" tabindex="4" data-l10n-id="attachments">
|
||||
<span data-l10n-id="attachments_label">Attachments</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div id="sidebarContent">
|
||||
@ -60,6 +63,8 @@ http://sourceforge.net/adobe/cmap/wiki/License/
|
||||
</div>
|
||||
<div id="outlineView" class="hidden">
|
||||
</div>
|
||||
<div id="attachmentsView" class="hidden">
|
||||
</div>
|
||||
</div>
|
||||
</div> <!-- sidebarContainer -->
|
||||
|
||||
@ -85,53 +90,53 @@ http://sourceforge.net/adobe/cmap/wiki/License/
|
||||
|
||||
<div id="secondaryToolbar" class="secondaryToolbar hidden doorHangerRight">
|
||||
<div id="secondaryToolbarButtonContainer">
|
||||
<button id="secondaryPresentationMode" class="secondaryToolbarButton presentationMode visibleLargeView" title="Switch to Presentation Mode" tabindex="18" data-l10n-id="presentation_mode">
|
||||
<button id="secondaryPresentationMode" class="secondaryToolbarButton presentationMode visibleLargeView" title="Switch to Presentation Mode" tabindex="19" data-l10n-id="presentation_mode">
|
||||
<span data-l10n-id="presentation_mode_label">Presentation Mode</span>
|
||||
</button>
|
||||
|
||||
<button id="secondaryOpenFile" class="secondaryToolbarButton openFile visibleLargeView" title="Open File" tabindex="19" data-l10n-id="open_file">
|
||||
<button id="secondaryOpenFile" class="secondaryToolbarButton openFile visibleLargeView" title="Open File" tabindex="20" data-l10n-id="open_file">
|
||||
<span data-l10n-id="open_file_label">Open</span>
|
||||
</button>
|
||||
|
||||
<button id="secondaryPrint" class="secondaryToolbarButton print visibleMediumView" title="Print" tabindex="20" data-l10n-id="print">
|
||||
<button id="secondaryPrint" class="secondaryToolbarButton print visibleMediumView" title="Print" tabindex="21" data-l10n-id="print">
|
||||
<span data-l10n-id="print_label">Print</span>
|
||||
</button>
|
||||
|
||||
<button id="secondaryDownload" class="secondaryToolbarButton download visibleMediumView" title="Download" tabindex="21" data-l10n-id="download">
|
||||
<button id="secondaryDownload" class="secondaryToolbarButton download visibleMediumView" title="Download" tabindex="22" data-l10n-id="download">
|
||||
<span data-l10n-id="download_label">Download</span>
|
||||
</button>
|
||||
|
||||
<a href="#" id="secondaryViewBookmark" class="secondaryToolbarButton bookmark visibleSmallView" title="Current view (copy or open in new window)" tabindex="22" data-l10n-id="bookmark">
|
||||
<a href="#" id="secondaryViewBookmark" class="secondaryToolbarButton bookmark visibleSmallView" title="Current view (copy or open in new window)" tabindex="23" data-l10n-id="bookmark">
|
||||
<span data-l10n-id="bookmark_label">Current View</span>
|
||||
</a>
|
||||
|
||||
<div class="horizontalToolbarSeparator visibleLargeView"></div>
|
||||
|
||||
<button id="firstPage" class="secondaryToolbarButton firstPage" title="Go to First Page" tabindex="23" data-l10n-id="first_page">
|
||||
<button id="firstPage" class="secondaryToolbarButton firstPage" title="Go to First Page" tabindex="24" data-l10n-id="first_page">
|
||||
<span data-l10n-id="first_page_label">Go to First Page</span>
|
||||
</button>
|
||||
<button id="lastPage" class="secondaryToolbarButton lastPage" title="Go to Last Page" tabindex="24" data-l10n-id="last_page">
|
||||
<button id="lastPage" class="secondaryToolbarButton lastPage" title="Go to Last Page" tabindex="25" data-l10n-id="last_page">
|
||||
<span data-l10n-id="last_page_label">Go to Last Page</span>
|
||||
</button>
|
||||
|
||||
<div class="horizontalToolbarSeparator"></div>
|
||||
|
||||
<button id="pageRotateCw" class="secondaryToolbarButton rotateCw" title="Rotate Clockwise" tabindex="25" data-l10n-id="page_rotate_cw">
|
||||
<button id="pageRotateCw" class="secondaryToolbarButton rotateCw" title="Rotate Clockwise" tabindex="26" data-l10n-id="page_rotate_cw">
|
||||
<span data-l10n-id="page_rotate_cw_label">Rotate Clockwise</span>
|
||||
</button>
|
||||
<button id="pageRotateCcw" class="secondaryToolbarButton rotateCcw" title="Rotate Counterclockwise" tabindex="26" data-l10n-id="page_rotate_ccw">
|
||||
<button id="pageRotateCcw" class="secondaryToolbarButton rotateCcw" title="Rotate Counterclockwise" tabindex="27" data-l10n-id="page_rotate_ccw">
|
||||
<span data-l10n-id="page_rotate_ccw_label">Rotate Counterclockwise</span>
|
||||
</button>
|
||||
|
||||
<div class="horizontalToolbarSeparator"></div>
|
||||
|
||||
<button id="toggleHandTool" class="secondaryToolbarButton handTool" title="Enable hand tool" tabindex="27" data-l10n-id="hand_tool_enable">
|
||||
<button id="toggleHandTool" class="secondaryToolbarButton handTool" title="Enable hand tool" tabindex="28" data-l10n-id="hand_tool_enable">
|
||||
<span data-l10n-id="hand_tool_enable_label">Enable hand tool</span>
|
||||
</button>
|
||||
|
||||
<div class="horizontalToolbarSeparator"></div>
|
||||
|
||||
<button id="documentProperties" class="secondaryToolbarButton documentProperties" title="Document Properties…" tabindex="28" data-l10n-id="document_properties">
|
||||
<button id="documentProperties" class="secondaryToolbarButton documentProperties" title="Document Properties…" tabindex="29" data-l10n-id="document_properties">
|
||||
<span data-l10n-id="document_properties_label">Document Properties…</span>
|
||||
</button>
|
||||
</div>
|
||||
@ -141,77 +146,77 @@ http://sourceforge.net/adobe/cmap/wiki/License/
|
||||
<div id="toolbarContainer">
|
||||
<div id="toolbarViewer">
|
||||
<div id="toolbarViewerLeft">
|
||||
<button id="sidebarToggle" class="toolbarButton" title="Toggle Sidebar" tabindex="4" data-l10n-id="toggle_sidebar">
|
||||
<button id="sidebarToggle" class="toolbarButton" title="Toggle Sidebar" tabindex="5" data-l10n-id="toggle_sidebar">
|
||||
<span data-l10n-id="toggle_sidebar_label">Toggle Sidebar</span>
|
||||
</button>
|
||||
<div class="toolbarButtonSpacer"></div>
|
||||
<button id="viewFind" class="toolbarButton group hiddenSmallView" title="Find in Document" tabindex="5" data-l10n-id="findbar">
|
||||
<button id="viewFind" class="toolbarButton group hiddenSmallView" title="Find in Document" tabindex="6" data-l10n-id="findbar">
|
||||
<span data-l10n-id="findbar_label">Find</span>
|
||||
</button>
|
||||
<div class="splitToolbarButton">
|
||||
<button class="toolbarButton pageUp" title="Previous Page" id="previous" tabindex="6" data-l10n-id="previous">
|
||||
<button class="toolbarButton pageUp" title="Previous Page" id="previous" tabindex="7" data-l10n-id="previous">
|
||||
<span data-l10n-id="previous_label">Previous</span>
|
||||
</button>
|
||||
<div class="splitToolbarButtonSeparator"></div>
|
||||
<button class="toolbarButton pageDown" title="Next Page" id="next" tabindex="7" data-l10n-id="next">
|
||||
<button class="toolbarButton pageDown" title="Next Page" id="next" tabindex="8" data-l10n-id="next">
|
||||
<span data-l10n-id="next_label">Next</span>
|
||||
</button>
|
||||
</div>
|
||||
<label id="pageNumberLabel" class="toolbarLabel" for="pageNumber" data-l10n-id="page_label">Page: </label>
|
||||
<input type="number" id="pageNumber" class="toolbarField pageNumber" value="1" size="4" min="1" tabindex="8">
|
||||
<input type="number" id="pageNumber" class="toolbarField pageNumber" value="1" size="4" min="1" tabindex="9">
|
||||
<span id="numPages" class="toolbarLabel"></span>
|
||||
</div>
|
||||
<div id="toolbarViewerRight">
|
||||
<button id="presentationMode" class="toolbarButton presentationMode hiddenLargeView" title="Switch to Presentation Mode" tabindex="12" data-l10n-id="presentation_mode">
|
||||
<button id="presentationMode" class="toolbarButton presentationMode hiddenLargeView" title="Switch to Presentation Mode" tabindex="13" data-l10n-id="presentation_mode">
|
||||
<span data-l10n-id="presentation_mode_label">Presentation Mode</span>
|
||||
</button>
|
||||
|
||||
<button id="openFile" class="toolbarButton openFile hiddenLargeView" title="Open File" tabindex="13" data-l10n-id="open_file">
|
||||
<button id="openFile" class="toolbarButton openFile hiddenLargeView" title="Open File" tabindex="14" data-l10n-id="open_file">
|
||||
<span data-l10n-id="open_file_label">Open</span>
|
||||
</button>
|
||||
|
||||
<button id="print" class="toolbarButton print hiddenMediumView" title="Print" tabindex="14" data-l10n-id="print">
|
||||
<button id="print" class="toolbarButton print hiddenMediumView" title="Print" tabindex="15" data-l10n-id="print">
|
||||
<span data-l10n-id="print_label">Print</span>
|
||||
</button>
|
||||
|
||||
<button id="download" class="toolbarButton download hiddenMediumView" title="Download" tabindex="15" data-l10n-id="download">
|
||||
<button id="download" class="toolbarButton download hiddenMediumView" title="Download" tabindex="16" data-l10n-id="download">
|
||||
<span data-l10n-id="download_label">Download</span>
|
||||
</button>
|
||||
<!-- <div class="toolbarButtonSpacer"></div> -->
|
||||
<a href="#" id="viewBookmark" class="toolbarButton bookmark hiddenSmallView" title="Current view (copy or open in new window)" tabindex="16" data-l10n-id="bookmark">
|
||||
<a href="#" id="viewBookmark" class="toolbarButton bookmark hiddenSmallView" title="Current view (copy or open in new window)" tabindex="17" data-l10n-id="bookmark">
|
||||
<span data-l10n-id="bookmark_label">Current View</span>
|
||||
</a>
|
||||
|
||||
<div class="verticalToolbarSeparator hiddenSmallView"></div>
|
||||
|
||||
<button id="secondaryToolbarToggle" class="toolbarButton" title="Tools" tabindex="17" data-l10n-id="tools">
|
||||
<button id="secondaryToolbarToggle" class="toolbarButton" title="Tools" tabindex="18" data-l10n-id="tools">
|
||||
<span data-l10n-id="tools_label">Tools</span>
|
||||
</button>
|
||||
</div>
|
||||
<div class="outerCenter">
|
||||
<div class="innerCenter" id="toolbarViewerMiddle">
|
||||
<div class="splitToolbarButton">
|
||||
<button id="zoomOut" class="toolbarButton zoomOut" title="Zoom Out" tabindex="9" data-l10n-id="zoom_out">
|
||||
<button id="zoomOut" class="toolbarButton zoomOut" title="Zoom Out" tabindex="10" data-l10n-id="zoom_out">
|
||||
<span data-l10n-id="zoom_out_label">Zoom Out</span>
|
||||
</button>
|
||||
<div class="splitToolbarButtonSeparator"></div>
|
||||
<button id="zoomIn" class="toolbarButton zoomIn" title="Zoom In" tabindex="10" data-l10n-id="zoom_in">
|
||||
<button id="zoomIn" class="toolbarButton zoomIn" title="Zoom In" tabindex="11" data-l10n-id="zoom_in">
|
||||
<span data-l10n-id="zoom_in_label">Zoom In</span>
|
||||
</button>
|
||||
</div>
|
||||
<span id="scaleSelectContainer" class="dropdownToolbarButton">
|
||||
<select id="scaleSelect" title="Zoom" tabindex="11" data-l10n-id="zoom">
|
||||
<option id="pageAutoOption" value="auto" selected="selected" data-l10n-id="page_scale_auto">Automatic Zoom</option>
|
||||
<option id="pageActualOption" value="page-actual" data-l10n-id="page_scale_actual">Actual Size</option>
|
||||
<option id="pageFitOption" value="page-fit" data-l10n-id="page_scale_fit">Fit Page</option>
|
||||
<option id="pageWidthOption" value="page-width" data-l10n-id="page_scale_width">Full Width</option>
|
||||
<option id="customScaleOption" value="custom"></option>
|
||||
<option value="0.5">50%</option>
|
||||
<option value="0.75">75%</option>
|
||||
<option value="1">100%</option>
|
||||
<option value="1.25">125%</option>
|
||||
<option value="1.5">150%</option>
|
||||
<option value="2">200%</option>
|
||||
<select id="scaleSelect" title="Zoom" tabindex="12" data-l10n-id="zoom">
|
||||
<option id="pageAutoOption" title="" value="auto" selected="selected" data-l10n-id="page_scale_auto">Automatic Zoom</option>
|
||||
<option id="pageActualOption" title="" value="page-actual" data-l10n-id="page_scale_actual">Actual Size</option>
|
||||
<option id="pageFitOption" title="" value="page-fit" data-l10n-id="page_scale_fit">Fit Page</option>
|
||||
<option id="pageWidthOption" title="" value="page-width" data-l10n-id="page_scale_width">Full Width</option>
|
||||
<option id="customScaleOption" title="" value="custom"></option>
|
||||
<option title="" value="0.5">50%</option>
|
||||
<option title="" value="0.75">75%</option>
|
||||
<option title="" value="1">100%</option>
|
||||
<option title="" value="1.25">125%</option>
|
||||
<option title="" value="1.5">150%</option>
|
||||
<option title="" value="2">200%</option>
|
||||
</select>
|
||||
</span>
|
||||
</div>
|
||||
|
@ -520,6 +520,18 @@ var DownloadManager = (function DownloadManagerClosure() {
|
||||
});
|
||||
},
|
||||
|
||||
downloadData: function DownloadManager_downloadData(data, filename,
|
||||
contentType) {
|
||||
var blobUrl = PDFJS.createObjectURL(data, contentType);
|
||||
|
||||
FirefoxCom.request('download', {
|
||||
blobUrl: blobUrl,
|
||||
originalUrl: blobUrl,
|
||||
filename: filename,
|
||||
isAttachment: true
|
||||
});
|
||||
},
|
||||
|
||||
download: function DownloadManager_download(blob, url, filename) {
|
||||
var blobUrl = window.URL.createObjectURL(blob);
|
||||
|
||||
@ -2829,6 +2841,9 @@ var PDFView = {
|
||||
},
|
||||
|
||||
close: function pdfViewClose() {
|
||||
var errorWrapper = document.getElementById('errorWrapper');
|
||||
errorWrapper.setAttribute('hidden', 'true');
|
||||
|
||||
if (!this.pdfDocument) {
|
||||
return;
|
||||
}
|
||||
@ -2836,9 +2851,6 @@ var PDFView = {
|
||||
this.pdfDocument.destroy();
|
||||
this.pdfDocument = null;
|
||||
|
||||
var errorWrapper = document.getElementById('errorWrapper');
|
||||
errorWrapper.setAttribute('hidden', 'true');
|
||||
|
||||
var thumbsView = document.getElementById('thumbnailView');
|
||||
while (thumbsView.hasChildNodes()) {
|
||||
thumbsView.removeChild(thumbsView.lastChild);
|
||||
@ -2862,11 +2874,10 @@ var PDFView = {
|
||||
open: function pdfViewOpen(url, scale, password,
|
||||
pdfDataRangeTransport, args) {
|
||||
if (this.pdfDocument) {
|
||||
this.close();
|
||||
|
||||
// Reload the preferences if a document was previously opened.
|
||||
Preferences.reload();
|
||||
}
|
||||
this.close();
|
||||
|
||||
var parameters = {password: password};
|
||||
if (typeof url === 'string') { // URL
|
||||
@ -3307,6 +3318,10 @@ var PDFView = {
|
||||
});
|
||||
}
|
||||
});
|
||||
pdfDocument.getAttachments().then(function(attachments) {
|
||||
self.attachments = new DocumentAttachmentsView(attachments);
|
||||
document.getElementById('viewAttachments').disabled = !attachments;
|
||||
});
|
||||
});
|
||||
|
||||
pdfDocument.getMetadata().then(function(data) {
|
||||
@ -3548,12 +3563,14 @@ var PDFView = {
|
||||
}
|
||||
if ('pagemode' in params) {
|
||||
var toggle = document.getElementById('sidebarToggle');
|
||||
if (params.pagemode === 'thumbs' || params.pagemode === 'bookmarks') {
|
||||
if (params.pagemode === 'thumbs' || params.pagemode === 'bookmarks' ||
|
||||
params.pagemode === 'attachments') {
|
||||
if (!this.sidebarOpen) {
|
||||
toggle.click();
|
||||
}
|
||||
this.switchSidebarView(params.pagemode === 'thumbs' ?
|
||||
'thumbs' : 'outline');
|
||||
this.switchSidebarView(params.pagemode === 'bookmarks' ?
|
||||
'outline' :
|
||||
params.pagemode);
|
||||
} else if (params.pagemode === 'none' && this.sidebarOpen) {
|
||||
toggle.click();
|
||||
}
|
||||
@ -3569,24 +3586,28 @@ var PDFView = {
|
||||
switchSidebarView: function pdfViewSwitchSidebarView(view) {
|
||||
var thumbsView = document.getElementById('thumbnailView');
|
||||
var outlineView = document.getElementById('outlineView');
|
||||
var attachmentsView = document.getElementById('attachmentsView');
|
||||
|
||||
var thumbsButton = document.getElementById('viewThumbnail');
|
||||
var outlineButton = document.getElementById('viewOutline');
|
||||
var attachmentsButton = document.getElementById('viewAttachments');
|
||||
|
||||
switch (view) {
|
||||
case 'thumbs':
|
||||
var wasOutlineViewVisible = thumbsView.classList.contains('hidden');
|
||||
var wasAnotherViewVisible = thumbsView.classList.contains('hidden');
|
||||
|
||||
thumbsButton.classList.add('toggled');
|
||||
outlineButton.classList.remove('toggled');
|
||||
attachmentsButton.classList.remove('toggled');
|
||||
thumbsView.classList.remove('hidden');
|
||||
outlineView.classList.add('hidden');
|
||||
attachmentsView.classList.add('hidden');
|
||||
|
||||
PDFView.renderHighestPriority();
|
||||
|
||||
if (wasOutlineViewVisible) {
|
||||
if (wasAnotherViewVisible) {
|
||||
// Ensure that the thumbnail of the current page is visible
|
||||
// when switching from the outline view.
|
||||
// when switching from another view.
|
||||
scrollIntoView(document.getElementById('thumbnailContainer' +
|
||||
this.page));
|
||||
}
|
||||
@ -3595,13 +3616,28 @@ var PDFView = {
|
||||
case 'outline':
|
||||
thumbsButton.classList.remove('toggled');
|
||||
outlineButton.classList.add('toggled');
|
||||
attachmentsButton.classList.remove('toggled');
|
||||
thumbsView.classList.add('hidden');
|
||||
outlineView.classList.remove('hidden');
|
||||
attachmentsView.classList.add('hidden');
|
||||
|
||||
if (outlineButton.getAttribute('disabled')) {
|
||||
return;
|
||||
}
|
||||
break;
|
||||
|
||||
case 'attachments':
|
||||
thumbsButton.classList.remove('toggled');
|
||||
outlineButton.classList.remove('toggled');
|
||||
attachmentsButton.classList.add('toggled');
|
||||
thumbsView.classList.add('hidden');
|
||||
outlineView.classList.add('hidden');
|
||||
attachmentsView.classList.remove('hidden');
|
||||
|
||||
if (attachmentsButton.getAttribute('disabled')) {
|
||||
return;
|
||||
}
|
||||
break;
|
||||
}
|
||||
},
|
||||
|
||||
@ -3673,7 +3709,7 @@ var PDFView = {
|
||||
parseQueryString: function pdfViewParseQueryString(query) {
|
||||
var parts = query.split('&');
|
||||
var params = {};
|
||||
for (var i = 0, ii = parts.length; i < parts.length; ++i) {
|
||||
for (var i = 0, ii = parts.length; i < ii; ++i) {
|
||||
var param = parts[i].split('=');
|
||||
var key = param[0];
|
||||
var value = param.length > 1 ? param[1] : null;
|
||||
@ -3864,7 +3900,7 @@ var PageView = function pageView(container, id, scale,
|
||||
}
|
||||
};
|
||||
|
||||
this.reset = function pageViewReset() {
|
||||
this.reset = function pageViewReset(keepAnnotations) {
|
||||
if (this.renderTask) {
|
||||
this.renderTask.cancel();
|
||||
}
|
||||
@ -3877,14 +3913,23 @@ var PageView = function pageView(container, id, scale,
|
||||
var childNodes = div.childNodes;
|
||||
for (var i = div.childNodes.length - 1; i >= 0; i--) {
|
||||
var node = childNodes[i];
|
||||
if (this.zoomLayer && this.zoomLayer === node) {
|
||||
if ((this.zoomLayer && this.zoomLayer === node) ||
|
||||
(keepAnnotations && this.annotationLayer === node)) {
|
||||
continue;
|
||||
}
|
||||
div.removeChild(node);
|
||||
}
|
||||
div.removeAttribute('data-loaded');
|
||||
|
||||
this.annotationLayer = null;
|
||||
if (keepAnnotations) {
|
||||
if (this.annotationLayer) {
|
||||
// Hide annotationLayer until all elements are resized
|
||||
// so they are not displayed on the already-resized page
|
||||
this.annotationLayer.setAttribute('hidden', 'true');
|
||||
}
|
||||
} else {
|
||||
this.annotationLayer = null;
|
||||
}
|
||||
|
||||
delete this.canvas;
|
||||
|
||||
@ -3916,7 +3961,7 @@ var PageView = function pageView(container, id, scale,
|
||||
if (this.zoomLayer) {
|
||||
this.cssTransform(this.zoomLayer.firstChild);
|
||||
}
|
||||
this.reset();
|
||||
this.reset(true);
|
||||
};
|
||||
|
||||
this.cssTransform = function pageCssTransform(canvas) {
|
||||
@ -4065,60 +4110,73 @@ var PageView = function pageView(container, id, scale,
|
||||
}
|
||||
|
||||
pdfPage.getAnnotations().then(function(annotationsData) {
|
||||
if (self.annotationLayer) {
|
||||
// If an annotationLayer already exists, delete it to avoid creating
|
||||
// duplicate annotations when rapidly re-zooming the document.
|
||||
pageDiv.removeChild(self.annotationLayer);
|
||||
self.annotationLayer = null;
|
||||
}
|
||||
viewport = viewport.clone({ dontFlip: true });
|
||||
for (var i = 0; i < annotationsData.length; i++) {
|
||||
var data = annotationsData[i];
|
||||
var annotation = PDFJS.Annotation.fromData(data);
|
||||
if (!annotation || !annotation.hasHtml()) {
|
||||
continue;
|
||||
}
|
||||
var transform = viewport.transform;
|
||||
var transformStr = 'matrix(' + transform.join(',') + ')';
|
||||
var data, element, i, ii;
|
||||
|
||||
var element = annotation.getHtmlElement(pdfPage.commonObjs);
|
||||
mozL10n.translate(element);
|
||||
|
||||
data = annotation.getData();
|
||||
var rect = data.rect;
|
||||
var view = pdfPage.view;
|
||||
rect = PDFJS.Util.normalizeRect([
|
||||
rect[0],
|
||||
view[3] - rect[1] + view[1],
|
||||
rect[2],
|
||||
view[3] - rect[3] + view[1]
|
||||
]);
|
||||
element.style.left = rect[0] + 'px';
|
||||
element.style.top = rect[1] + 'px';
|
||||
element.style.position = 'absolute';
|
||||
|
||||
var transform = viewport.transform;
|
||||
var transformStr = 'matrix(' + transform.join(',') + ')';
|
||||
CustomStyle.setProp('transform', element, transformStr);
|
||||
var transformOriginStr = -rect[0] + 'px ' + -rect[1] + 'px';
|
||||
CustomStyle.setProp('transformOrigin', element, transformOriginStr);
|
||||
|
||||
if (data.subtype === 'Link' && !data.url) {
|
||||
var link = element.getElementsByTagName('a')[0];
|
||||
if (link) {
|
||||
if (data.action) {
|
||||
bindNamedAction(link, data.action);
|
||||
} else {
|
||||
bindLink(link, ('dest' in data) ? data.dest : null);
|
||||
}
|
||||
if (self.annotationLayer) {
|
||||
// If an annotationLayer already exists, refresh its children's
|
||||
// transformation matrices
|
||||
for (i = 0, ii = annotationsData.length; i < ii; i++) {
|
||||
data = annotationsData[i];
|
||||
element = self.annotationLayer.querySelector(
|
||||
'[data-annotation-id="' + data.id + '"]');
|
||||
if (element) {
|
||||
CustomStyle.setProp('transform', element, transformStr);
|
||||
}
|
||||
}
|
||||
// See this.reset()
|
||||
self.annotationLayer.removeAttribute('hidden');
|
||||
} else {
|
||||
for (i = 0, ii = annotationsData.length; i < ii; i++) {
|
||||
data = annotationsData[i];
|
||||
var annotation = PDFJS.Annotation.fromData(data);
|
||||
if (!annotation || !annotation.hasHtml()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!self.annotationLayer) {
|
||||
var annotationLayerDiv = document.createElement('div');
|
||||
annotationLayerDiv.className = 'annotationLayer';
|
||||
pageDiv.appendChild(annotationLayerDiv);
|
||||
self.annotationLayer = annotationLayerDiv;
|
||||
element = annotation.getHtmlElement(pdfPage.commonObjs);
|
||||
element.setAttribute('data-annotation-id', data.id);
|
||||
mozL10n.translate(element);
|
||||
|
||||
data = annotation.getData();
|
||||
var rect = data.rect;
|
||||
var view = pdfPage.view;
|
||||
rect = PDFJS.Util.normalizeRect([
|
||||
rect[0],
|
||||
view[3] - rect[1] + view[1],
|
||||
rect[2],
|
||||
view[3] - rect[3] + view[1]
|
||||
]);
|
||||
element.style.left = rect[0] + 'px';
|
||||
element.style.top = rect[1] + 'px';
|
||||
element.style.position = 'absolute';
|
||||
|
||||
CustomStyle.setProp('transform', element, transformStr);
|
||||
var transformOriginStr = -rect[0] + 'px ' + -rect[1] + 'px';
|
||||
CustomStyle.setProp('transformOrigin', element, transformOriginStr);
|
||||
|
||||
if (data.subtype === 'Link' && !data.url) {
|
||||
var link = element.getElementsByTagName('a')[0];
|
||||
if (link) {
|
||||
if (data.action) {
|
||||
bindNamedAction(link, data.action);
|
||||
} else {
|
||||
bindLink(link, ('dest' in data) ? data.dest : null);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!self.annotationLayer) {
|
||||
var annotationLayerDiv = document.createElement('div');
|
||||
annotationLayerDiv.className = 'annotationLayer';
|
||||
pageDiv.appendChild(annotationLayerDiv);
|
||||
self.annotationLayer = annotationLayerDiv;
|
||||
}
|
||||
|
||||
self.annotationLayer.appendChild(element);
|
||||
}
|
||||
self.annotationLayer.appendChild(element);
|
||||
}
|
||||
});
|
||||
}
|
||||
@ -4254,10 +4312,14 @@ var PageView = function pageView(container, id, scale,
|
||||
var canvas = document.createElement('canvas');
|
||||
canvas.id = 'page' + this.id;
|
||||
canvasWrapper.appendChild(canvas);
|
||||
div.appendChild(canvasWrapper);
|
||||
if (this.annotationLayer) {
|
||||
// annotationLayer needs to stay on top
|
||||
div.insertBefore(canvasWrapper, this.annotationLayer);
|
||||
} else {
|
||||
div.appendChild(canvasWrapper);
|
||||
}
|
||||
this.canvas = canvas;
|
||||
|
||||
var scale = this.scale;
|
||||
var ctx = canvas.getContext('2d');
|
||||
var outputScale = getOutputScale(ctx);
|
||||
|
||||
@ -4283,7 +4345,12 @@ var PageView = function pageView(container, id, scale,
|
||||
textLayerDiv.className = 'textLayer';
|
||||
textLayerDiv.style.width = canvas.style.width;
|
||||
textLayerDiv.style.height = canvas.style.height;
|
||||
div.appendChild(textLayerDiv);
|
||||
if (this.annotationLayer) {
|
||||
// annotationLayer needs to stay on top
|
||||
div.insertBefore(textLayerDiv, this.annotationLayer);
|
||||
} else {
|
||||
div.appendChild(textLayerDiv);
|
||||
}
|
||||
}
|
||||
var textLayer = this.textLayer =
|
||||
textLayerDiv ? new TextLayerBuilder({
|
||||
@ -4425,7 +4492,6 @@ var PageView = function pageView(container, id, scale,
|
||||
canvasWrapper.appendChild(canvas);
|
||||
printContainer.appendChild(canvasWrapper);
|
||||
|
||||
var self = this;
|
||||
canvas.mozPrintCallback = function(obj) {
|
||||
var ctx = obj.context;
|
||||
|
||||
@ -4794,9 +4860,6 @@ var TextLayerBuilder = function textLayerBuilder(options) {
|
||||
var queryLen = (PDFFindController === null ?
|
||||
0 : PDFFindController.state.query.length);
|
||||
|
||||
var lastDivIdx = -1;
|
||||
var pos;
|
||||
|
||||
var ret = [];
|
||||
|
||||
// Loop over all the matches.
|
||||
@ -4987,7 +5050,6 @@ var TextLayerBuilder = function textLayerBuilder(options) {
|
||||
|
||||
var DocumentOutlineView = function documentOutlineView(outline) {
|
||||
var outlineView = document.getElementById('outlineView');
|
||||
var outlineButton = document.getElementById('viewOutline');
|
||||
while (outlineView.firstChild) {
|
||||
outlineView.removeChild(outlineView.firstChild);
|
||||
}
|
||||
@ -5033,6 +5095,44 @@ var DocumentOutlineView = function documentOutlineView(outline) {
|
||||
}
|
||||
};
|
||||
|
||||
var DocumentAttachmentsView = function documentAttachmentsView(attachments) {
|
||||
var attachmentsView = document.getElementById('attachmentsView');
|
||||
while (attachmentsView.firstChild) {
|
||||
attachmentsView.removeChild(attachmentsView.firstChild);
|
||||
}
|
||||
|
||||
if (!attachments) {
|
||||
if (!attachmentsView.classList.contains('hidden')) {
|
||||
PDFView.switchSidebarView('thumbs');
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
function bindItemLink(domObj, item) {
|
||||
domObj.href = '#';
|
||||
domObj.onclick = function documentAttachmentsViewOnclick(e) {
|
||||
var downloadManager = new DownloadManager();
|
||||
downloadManager.downloadData(item.content, getFileName(item.filename),
|
||||
'');
|
||||
return false;
|
||||
};
|
||||
}
|
||||
|
||||
var names = Object.keys(attachments).sort(function(a,b) {
|
||||
return a.toLowerCase().localeCompare(b.toLowerCase());
|
||||
});
|
||||
for (var i = 0, ii = names.length; i < ii; i++) {
|
||||
var item = attachments[names[i]];
|
||||
var div = document.createElement('div');
|
||||
div.className = 'attachmentsItem';
|
||||
var a = document.createElement('a');
|
||||
bindItemLink(a, item);
|
||||
a.textContent = getFileName(item.filename);
|
||||
div.appendChild(a);
|
||||
attachmentsView.appendChild(div);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
function webViewerLoad(evt) {
|
||||
PDFView.initialize().then(webViewerInitialized);
|
||||
@ -5166,6 +5266,11 @@ function webViewerInitialized() {
|
||||
PDFView.switchSidebarView('outline');
|
||||
});
|
||||
|
||||
document.getElementById('viewAttachments').addEventListener('click',
|
||||
function() {
|
||||
PDFView.switchSidebarView('attachments');
|
||||
});
|
||||
|
||||
document.getElementById('previous').addEventListener('click',
|
||||
function() {
|
||||
PDFView.page--;
|
||||
|
@ -11,45 +11,42 @@ privatebrowsing-button.label = New Private Window
|
||||
privatebrowsing-button.tooltiptext = Open a new Private Browsing window (%S)
|
||||
|
||||
save-page-button.label = Save Page
|
||||
# LOCALIZATION NOTE(save-page-button.tooltiptext2): %S is the keyboard shortcut
|
||||
# Use the unicode ellipsis char, \u2026, or use "..." if \u2026 doesn't suit traditions in your locale.
|
||||
save-page-button.tooltiptext2 = Save this page… (%S)
|
||||
# LOCALIZATION NOTE(save-page-button.tooltiptext3): %S is the keyboard shortcut
|
||||
save-page-button.tooltiptext3 = Save this page (%S)
|
||||
|
||||
find-button.label = Find
|
||||
# LOCALIZATION NOTE(find-button.tooltiptext2): %S is the keyboard shortcut.
|
||||
# Use the unicode ellipsis char, \u2026, or use "..." if \u2026 doesn't suit traditions in your locale.
|
||||
find-button.tooltiptext2 = Find in this page… (%S)
|
||||
# LOCALIZATION NOTE(find-button.tooltiptext3): %S is the keyboard shortcut.
|
||||
find-button.tooltiptext3 = Find in this page (%S)
|
||||
|
||||
open-file-button.label = Open File
|
||||
# LOCALIZATION NOTE (open-file-button.tooltiptext2): %S is the keyboard shortcut.
|
||||
# Use the unicode ellipsis char, \u2026, or use "..." if \u2026 doesn't suit traditions in your locale.
|
||||
open-file-button.tooltiptext2 = Open file… (%S)
|
||||
# LOCALIZATION NOTE (open-file-button.tooltiptext3): %S is the keyboard shortcut.
|
||||
open-file-button.tooltiptext3 = Open a file (%S)
|
||||
|
||||
developer-button.label = Developer
|
||||
# LOCALIZATION NOTE(developer-button.tooltiptext): %S is the keyboard shortcut
|
||||
developer-button.tooltiptext = Web Developer Tools (%S)
|
||||
developer-button.tooltiptext2 = Open Web developer tools (%S)
|
||||
|
||||
sidebar-button.label = Sidebars
|
||||
sidebar-button.tooltiptext = Show Sidebars
|
||||
sidebar-button.tooltiptext2 = Show sidebars
|
||||
|
||||
add-ons-button.label = Add-ons
|
||||
# LOCALIZATION NOTE(add-ons-button.tooltiptext2): %S is the keyboard shortcut
|
||||
add-ons-button.tooltiptext2 = Open Add-ons Manager (%S)
|
||||
# LOCALIZATION NOTE(add-ons-button.tooltiptext3): %S is the keyboard shortcut
|
||||
add-ons-button.tooltiptext3 = Manage your add-ons (%S)
|
||||
|
||||
switch-to-metro-button2.label = Windows 8 Touch
|
||||
# LOCALIZATION NOTE(switch-to-metro-button2.tooltiptext): %S is the brand short name
|
||||
switch-to-metro-button2.tooltiptext = Relaunch in %S for Windows 8 Touch
|
||||
|
||||
preferences-button.label = Preferences
|
||||
preferences-button.tooltiptext2 = Open Preferences
|
||||
preferences-button.tooltiptext.withshortcut = Open Preferences (%S)
|
||||
preferences-button.tooltiptext2 = Open preferences
|
||||
preferences-button.tooltiptext.withshortcut = Open preferences (%S)
|
||||
# LOCALIZATION NOTE (preferences-button.labelWin): Windows-only label for Options
|
||||
preferences-button.labelWin = Options
|
||||
# LOCALIZATION NOTE (preferences-button.tooltipWin): Windows-only tooltip for Options
|
||||
preferences-button.tooltipWin2 = Open Options
|
||||
preferences-button.tooltipWin2 = Open options
|
||||
|
||||
zoom-controls.label = Zoom Controls
|
||||
zoom-controls.tooltiptext = Zoom Controls
|
||||
zoom-controls.tooltiptext2 = Zoom controls
|
||||
|
||||
zoom-out-button.label = Zoom out
|
||||
# LOCALIZATION NOTE(zoom-out-button.tooltiptext2): %S is the keyboard shortcut.
|
||||
@ -67,7 +64,7 @@ zoom-in-button.label = Zoom in
|
||||
zoom-in-button.tooltiptext2 = Zoom in (%S)
|
||||
|
||||
edit-controls.label = Edit Controls
|
||||
edit-controls.tooltiptext = Edit Controls
|
||||
edit-controls.tooltiptext2 = Edit controls
|
||||
|
||||
cut-button.label = Cut
|
||||
# LOCALIZATION NOTE(cut-button.tooltiptext2): %S is the keyboard shortcut.
|
||||
@ -81,21 +78,17 @@ paste-button.label = Paste
|
||||
# LOCALIZATION NOTE(paste-button.tooltiptext2): %S is the keyboard shortcut.
|
||||
paste-button.tooltiptext2 = Paste (%S)
|
||||
|
||||
# LOCALIZATION NOTE (feed-button.tooltiptext): Use the unicode ellipsis char,
|
||||
# \u2026, or use "..." if \u2026 doesn't suit traditions in your locale.
|
||||
feed-button.label = Subscribe
|
||||
feed-button.tooltiptext = Subscribe to this page…
|
||||
feed-button.tooltiptext2 = Subscribe to this page
|
||||
|
||||
# LOCALIZATION NOTE (characterencoding-button.label): The \u00ad character at the beginning
|
||||
# of the string is used to disable auto hyphenation on the button text when it is displayed
|
||||
# in the menu panel.
|
||||
characterencoding-button.label = \u00adCharacter Encoding
|
||||
characterencoding-button.tooltiptext2 = Show Character Encoding options
|
||||
characterencoding-button.tooltiptext2 = Show character encoding options
|
||||
|
||||
email-link-button.label = Email Link
|
||||
# LOCALIZATION NOTE (email-link-button.tooltiptext2): Use the unicode ellipsis char,
|
||||
# \u2026, or use "..." if \u2026 doesn't suit traditions in your locale.
|
||||
email-link-button.tooltiptext2 = Email Link…
|
||||
email-link-button.tooltiptext3 = Email a link to this page
|
||||
|
||||
# LOCALIZATION NOTE(quit-button.tooltiptext.linux2): %1$S is the brand name (e.g. Firefox),
|
||||
# %2$S is the keyboard shortcut
|
||||
|
@ -222,3 +222,8 @@ openNodeInInspector=Click to select the node in the inspector
|
||||
# LOCALIZATION NOTE (cdFunctionInvalidArgument): the text that is displayed when
|
||||
# cd() is invoked with an invalid argument.
|
||||
cdFunctionInvalidArgument=Cannot cd() to the given window. Invalid argument.
|
||||
|
||||
# LOCALIZATION NOTE (messageToggleDetails): the text that is displayed when
|
||||
# you hover the arrow for expanding/collapsing the message details. For
|
||||
# console.error() and other messages we show the stacktrace.
|
||||
messageToggleDetails=Show/hide message details.
|
||||
|
@ -89,6 +89,8 @@ toggle_sidebar.title=Toggle Sidebar
|
||||
toggle_sidebar_label=Toggle Sidebar
|
||||
outline.title=Show Document Outline
|
||||
outline_label=Document Outline
|
||||
attachments.title=Show Attachments
|
||||
attachments_label=Attachments
|
||||
thumbs.title=Show Thumbnails
|
||||
thumbs_label=Thumbnails
|
||||
findbar.title=Find in Document
|
||||
|
@ -38,10 +38,8 @@ a {
|
||||
width: 8px;
|
||||
}
|
||||
|
||||
.message > .body {
|
||||
.message > .message-body-wrapper {
|
||||
flex: 1 1 100%;
|
||||
white-space: pre-wrap;
|
||||
word-wrap: break-word;
|
||||
margin-top: 4px;
|
||||
}
|
||||
|
||||
@ -71,7 +69,7 @@ a {
|
||||
align-self: flex-start;
|
||||
justify-content: flex-end;
|
||||
width: 10em;
|
||||
margin-top: 4px;
|
||||
margin: 3px 0;
|
||||
color: -moz-nativehyperlinktext;
|
||||
text-decoration: none;
|
||||
white-space: nowrap;
|
||||
@ -92,6 +90,20 @@ a {
|
||||
flex: 0 0 auto;
|
||||
}
|
||||
|
||||
.message-flex-body {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.message-body {
|
||||
white-space: pre-wrap;
|
||||
word-wrap: break-word;
|
||||
}
|
||||
|
||||
.message-flex-body > .message-body {
|
||||
display: block;
|
||||
flex: 1 1 auto;
|
||||
}
|
||||
|
||||
.jsterm-input-container {
|
||||
border-top-width: 1px;
|
||||
border-top-style: solid;
|
||||
@ -153,6 +165,14 @@ a {
|
||||
border-color: #777;
|
||||
}
|
||||
|
||||
.theme-light .message[severity=error] {
|
||||
background-color: rgba(255, 150, 150, 0.3);
|
||||
}
|
||||
|
||||
.theme-dark .message[severity=error] {
|
||||
background-color: rgba(255, 100, 100, 0.3);
|
||||
}
|
||||
|
||||
.message[category=network] > .icon {
|
||||
-moz-border-start: solid #000 6px;
|
||||
}
|
||||
@ -161,7 +181,7 @@ a {
|
||||
background-image: -moz-image-rect(url(chrome://browser/skin/devtools/webconsole.png), 0, 16, 8, 8);
|
||||
}
|
||||
|
||||
.message[category=network] > .body {
|
||||
.message[category=network] > .message-body {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
@ -284,7 +304,7 @@ a {
|
||||
overflow-x: hidden;
|
||||
}
|
||||
|
||||
.inlined-variables-view .body {
|
||||
.inlined-variables-view .message-body {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
@ -340,27 +360,35 @@ a {
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.consoleTrace .body > div {
|
||||
display: flex;
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
|
||||
.consoleTrace .title {
|
||||
display: block;
|
||||
flex: 1 1 auto;
|
||||
}
|
||||
|
||||
.stacktrace {
|
||||
display: none;
|
||||
list-style: none;
|
||||
padding: 0 1em 0 1.5em;
|
||||
margin: 0;
|
||||
margin: 5px 0 0 0;
|
||||
max-height: 10em;
|
||||
overflow-y: auto;
|
||||
|
||||
border: 1px solid rgba(128, 128, 128, .5);
|
||||
border: 1px solid rgb(200,200,200);
|
||||
border-radius: 3px;
|
||||
}
|
||||
|
||||
.theme-light .message[severity=error] .stacktrace {
|
||||
background-color: rgba(255, 255, 255, 0.5);
|
||||
}
|
||||
|
||||
.theme-dark .message[severity=error] .stacktrace {
|
||||
background-color: rgba(0, 0, 0, 0.5);
|
||||
}
|
||||
|
||||
.message[open] .stacktrace {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.message .theme-twisty {
|
||||
display: inline-block;
|
||||
vertical-align: middle;
|
||||
margin: 2px 3px 0 0;
|
||||
}
|
||||
|
||||
.stacktrace li {
|
||||
display: flex;
|
||||
margin: 0;
|
||||
|
@ -356,16 +356,6 @@ abstract public class BrowserApp extends GeckoApp
|
||||
return super.onKeyDown(keyCode, event);
|
||||
}
|
||||
|
||||
void handleReaderListCountRequest() {
|
||||
ThreadUtils.postToBackgroundThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
final int count = BrowserDB.getReadingListCount(getContentResolver());
|
||||
GeckoAppShell.sendEventToGecko(GeckoEvent.createBroadcastEvent("Reader:ListCountReturn", Integer.toString(count)));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void handleReaderListStatusRequest(final String url) {
|
||||
ThreadUtils.postToBackgroundThread(new Runnable() {
|
||||
@Override
|
||||
@ -402,9 +392,6 @@ abstract public class BrowserApp extends GeckoApp
|
||||
public void run() {
|
||||
BrowserDB.addReadingListItem(getContentResolver(), values);
|
||||
showToast(R.string.reading_list_added, Toast.LENGTH_SHORT);
|
||||
|
||||
final int count = BrowserDB.getReadingListCount(getContentResolver());
|
||||
GeckoAppShell.sendEventToGecko(GeckoEvent.createBroadcastEvent("Reader:ListCountUpdated", Integer.toString(count)));
|
||||
}
|
||||
});
|
||||
}
|
||||
@ -1206,8 +1193,6 @@ abstract public class BrowserApp extends GeckoApp
|
||||
Telemetry.HistogramAdd("PLACES_BOOKMARKS_COUNT", BrowserDB.getCount(getContentResolver(), "bookmarks"));
|
||||
Telemetry.HistogramAdd("FENNEC_FAVICONS_COUNT", BrowserDB.getCount(getContentResolver(), "favicons"));
|
||||
Telemetry.HistogramAdd("FENNEC_THUMBNAILS_COUNT", BrowserDB.getCount(getContentResolver(), "thumbnails"));
|
||||
} else if (event.equals("Reader:ListCountRequest")) {
|
||||
handleReaderListCountRequest();
|
||||
} else if (event.equals("Reader:ListStatusRequest")) {
|
||||
handleReaderListStatusRequest(message.getString("url"));
|
||||
} else if (event.equals("Reader:Added")) {
|
||||
|
@ -1572,7 +1572,6 @@ public abstract class GeckoApp
|
||||
|
||||
//register for events
|
||||
registerEventListener("log");
|
||||
registerEventListener("Reader:ListCountRequest");
|
||||
registerEventListener("Reader:ListStatusRequest");
|
||||
registerEventListener("Reader:Added");
|
||||
registerEventListener("Reader:Removed");
|
||||
@ -2107,7 +2106,6 @@ public abstract class GeckoApp
|
||||
public void onDestroy()
|
||||
{
|
||||
unregisterEventListener("log");
|
||||
unregisterEventListener("Reader:ListCountRequest");
|
||||
unregisterEventListener("Reader:ListStatusRequest");
|
||||
unregisterEventListener("Reader:Added");
|
||||
unregisterEventListener("Reader:Removed");
|
||||
|
@ -146,7 +146,7 @@ public class BrowserToolbar extends ThemedRelativeLayout
|
||||
private OnStartEditingListener startEditingListener;
|
||||
private OnStopEditingListener stopEditingListener;
|
||||
|
||||
final private BrowserApp activity;
|
||||
private final BrowserApp activity;
|
||||
private boolean hasSoftMenuButton;
|
||||
|
||||
private UIMode uiMode;
|
||||
@ -581,7 +581,7 @@ public class BrowserToolbar extends ThemedRelativeLayout
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isVisible() {
|
||||
private boolean isVisible() {
|
||||
return ViewHelper.getTranslationY(this) == 0;
|
||||
}
|
||||
|
||||
@ -1200,7 +1200,7 @@ public class BrowserToolbar extends ThemedRelativeLayout
|
||||
contentAnimator.start();
|
||||
}
|
||||
|
||||
public void setButtonEnabled(ImageButton button, boolean enabled) {
|
||||
private void setButtonEnabled(ImageButton button, boolean enabled) {
|
||||
final Drawable drawable = button.getDrawable();
|
||||
if (drawable != null) {
|
||||
// This alpha value has to be in sync with the one used
|
||||
|
@ -13,17 +13,17 @@ import android.graphics.PorterDuffXfermode;
|
||||
import android.graphics.Shader;
|
||||
import android.os.Build;
|
||||
|
||||
public class CanvasDelegate {
|
||||
class CanvasDelegate {
|
||||
Paint mPaint;
|
||||
PorterDuffXfermode mMode;
|
||||
DrawManager mDrawManager;
|
||||
|
||||
// DrawManager would do a default draw of the background.
|
||||
public static interface DrawManager {
|
||||
static interface DrawManager {
|
||||
public void defaultDraw(Canvas cavas);
|
||||
}
|
||||
|
||||
public CanvasDelegate(DrawManager drawManager, Mode mode) {
|
||||
CanvasDelegate(DrawManager drawManager, Mode mode) {
|
||||
mDrawManager = drawManager;
|
||||
|
||||
// DST_IN masks, DST_OUT clips.
|
||||
@ -35,7 +35,7 @@ public class CanvasDelegate {
|
||||
mPaint.setStrokeWidth(0.0f);
|
||||
}
|
||||
|
||||
public void draw(Canvas canvas, Path path, int width, int height) {
|
||||
void draw(Canvas canvas, Path path, int width, int height) {
|
||||
// Save the canvas. All PorterDuff operations should be done in a offscreen bitmap.
|
||||
int count = canvas.saveLayer(0, 0, width, height, null,
|
||||
Canvas.MATRIX_SAVE_FLAG |
|
||||
@ -70,7 +70,7 @@ public class CanvasDelegate {
|
||||
canvas.restoreToCount(count);
|
||||
}
|
||||
|
||||
public void setShader(Shader shader) {
|
||||
void setShader(Shader shader) {
|
||||
mPaint.setShader(shader);
|
||||
}
|
||||
}
|
||||
|
@ -64,7 +64,7 @@ public class PageActionLayout extends LinearLayout implements GeckoEventListener
|
||||
registerEventListener("PageActions:Remove");
|
||||
}
|
||||
|
||||
public void setNumberShown(int count) {
|
||||
private void setNumberShown(int count) {
|
||||
mMaxVisiblePageActions = count;
|
||||
|
||||
for(int index = 0; index < count; index++) {
|
||||
@ -118,7 +118,7 @@ public class PageActionLayout extends LinearLayout implements GeckoEventListener
|
||||
}
|
||||
}
|
||||
|
||||
public void addPageAction(final String id, final String title, final String imageData, final OnPageActionClickListeners mOnPageActionClickListeners, boolean mImportant) {
|
||||
private void addPageAction(final String id, final String title, final String imageData, final OnPageActionClickListeners mOnPageActionClickListeners, boolean mImportant) {
|
||||
final PageAction pageAction = new PageAction(id, title, null, mOnPageActionClickListeners, mImportant);
|
||||
|
||||
int insertAt = mPageActionList.size();
|
||||
@ -138,7 +138,7 @@ public class PageActionLayout extends LinearLayout implements GeckoEventListener
|
||||
});
|
||||
}
|
||||
|
||||
public void removePageAction(String id) {
|
||||
private void removePageAction(String id) {
|
||||
for(int i = 0; i < mPageActionList.size(); i++) {
|
||||
if (mPageActionList.get(i).getID().equals(id)) {
|
||||
mPageActionList.remove(i);
|
||||
@ -291,7 +291,7 @@ public class PageActionLayout extends LinearLayout implements GeckoEventListener
|
||||
mPageActionsMenu.show();
|
||||
}
|
||||
|
||||
public static interface OnPageActionClickListeners {
|
||||
private static interface OnPageActionClickListeners {
|
||||
public void onClick(String id);
|
||||
public boolean onLongClick(String id);
|
||||
}
|
||||
|
@ -67,7 +67,7 @@ public class TabCounter extends ThemedTextSwitcher
|
||||
}
|
||||
}
|
||||
|
||||
public void setCountWithAnimation(int count) {
|
||||
void setCountWithAnimation(int count) {
|
||||
// Don't animate from initial state
|
||||
if (mCount == 0) {
|
||||
setCount(count);
|
||||
@ -97,7 +97,7 @@ public class TabCounter extends ThemedTextSwitcher
|
||||
mCount = count;
|
||||
}
|
||||
|
||||
public void setCount(int count) {
|
||||
void setCount(int count) {
|
||||
setCurrentText(String.valueOf(count));
|
||||
mCount = count;
|
||||
}
|
||||
|
@ -95,7 +95,7 @@ public class ToolbarDisplayLayout extends ThemedLinearLayout
|
||||
public void onTitleChange(CharSequence title);
|
||||
}
|
||||
|
||||
final private BrowserApp mActivity;
|
||||
private final BrowserApp mActivity;
|
||||
|
||||
private UIMode mUiMode;
|
||||
|
||||
|
@ -11,8 +11,8 @@ import org.mozilla.gecko.Tabs;
|
||||
import org.mozilla.gecko.util.ThreadUtils;
|
||||
|
||||
class ToolbarTitlePrefs {
|
||||
public static final String PREF_TITLEBAR_MODE = "browser.chrome.titlebarMode";
|
||||
public static final String PREF_TRIM_URLS = "browser.urlbar.trimURLs";
|
||||
static final String PREF_TITLEBAR_MODE = "browser.chrome.titlebarMode";
|
||||
static final String PREF_TRIM_URLS = "browser.urlbar.trimURLs";
|
||||
|
||||
interface OnChangeListener {
|
||||
public void onChange();
|
||||
|
@ -34,7 +34,6 @@
|
||||
<ul id="color-scheme-buttons" class="segmented-button"></ul>
|
||||
</li>
|
||||
</ul>
|
||||
<li><a id="list-button" class="button list-button" href="#"></a></li>
|
||||
<li><a id="toggle-button" class="button toggle-button" href="#"></a></li>
|
||||
</ul>
|
||||
|
||||
|
@ -7,9 +7,6 @@ let Ci = Components.interfaces, Cc = Components.classes, Cu = Components.utils;
|
||||
Cu.import("resource://gre/modules/Services.jsm")
|
||||
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
|
||||
// Panel ID defined in HomeConfig.java.
|
||||
const READING_LIST_PANEL_ID = "20f4549a-64ad-4c32-93e4-1dcef792733b";
|
||||
|
||||
XPCOMUtils.defineLazyGetter(window, "gChromeWin", function ()
|
||||
window.QueryInterface(Ci.nsIInterfaceRequestor)
|
||||
.getInterface(Ci.nsIWebNavigation)
|
||||
@ -34,8 +31,6 @@ let AboutReader = function(doc, win) {
|
||||
Services.obs.addObserver(this, "Reader:FaviconReturn", false);
|
||||
Services.obs.addObserver(this, "Reader:Add", false);
|
||||
Services.obs.addObserver(this, "Reader:Remove", false);
|
||||
Services.obs.addObserver(this, "Reader:ListCountReturn", false);
|
||||
Services.obs.addObserver(this, "Reader:ListCountUpdated", false);
|
||||
Services.obs.addObserver(this, "Reader:ListStatusReturn", false);
|
||||
|
||||
this._article = null;
|
||||
@ -64,7 +59,6 @@ let AboutReader = function(doc, win) {
|
||||
|
||||
this._setupAllDropdowns();
|
||||
this._setupButton("toggle-button", this._onReaderToggle.bind(this));
|
||||
this._setupButton("list-button", this._onList.bind(this));
|
||||
this._setupButton("share-button", this._onShare.bind(this));
|
||||
|
||||
let colorSchemeOptions = [
|
||||
@ -127,11 +121,6 @@ let AboutReader = function(doc, win) {
|
||||
this._isReadingListItem = -1;
|
||||
this._updateToggleButton();
|
||||
|
||||
// Track status of reader toolbar list button
|
||||
this._readingListCount = -1;
|
||||
this._updateListButton();
|
||||
this._requestReadingListCount();
|
||||
|
||||
let url = queryArgs.url;
|
||||
let tabId = queryArgs.tabId;
|
||||
if (tabId) {
|
||||
@ -215,27 +204,6 @@ AboutReader.prototype = {
|
||||
break;
|
||||
}
|
||||
|
||||
case "Reader:ListCountReturn":
|
||||
case "Reader:ListCountUpdated": {
|
||||
let count = parseInt(aData);
|
||||
if (this._readingListCount != count) {
|
||||
let isInitialStateChange = (this._readingListCount == -1);
|
||||
this._readingListCount = count;
|
||||
this._updateListButton();
|
||||
|
||||
// Display the toolbar when all its initial component states are known
|
||||
if (isInitialStateChange) {
|
||||
this._setToolbarVisibility(true);
|
||||
}
|
||||
|
||||
// Initial readinglist count is requested before any page is displayed
|
||||
if (this._article) {
|
||||
this._requestReadingListStatus();
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case "Reader:ListStatusReturn": {
|
||||
let args = JSON.parse(aData);
|
||||
if (args.url == this._article.url) {
|
||||
@ -289,8 +257,6 @@ AboutReader.prototype = {
|
||||
case "unload":
|
||||
Services.obs.removeObserver(this, "Reader:Add");
|
||||
Services.obs.removeObserver(this, "Reader:Remove");
|
||||
Services.obs.removeObserver(this, "Reader:ListCountReturn");
|
||||
Services.obs.removeObserver(this, "Reader:ListCountUpdated");
|
||||
Services.obs.removeObserver(this, "Reader:ListStatusReturn");
|
||||
break;
|
||||
}
|
||||
@ -306,20 +272,6 @@ AboutReader.prototype = {
|
||||
}
|
||||
},
|
||||
|
||||
_updateListButton: function Reader_updateListButton() {
|
||||
let classes = this._doc.getElementById("list-button").classList;
|
||||
|
||||
if (this._readingListCount > 0) {
|
||||
classes.add("on");
|
||||
} else {
|
||||
classes.remove("on");
|
||||
}
|
||||
},
|
||||
|
||||
_requestReadingListCount: function Reader_requestReadingListCount() {
|
||||
gChromeWin.sendMessageToJava({ type: "Reader:ListCountRequest" });
|
||||
},
|
||||
|
||||
_requestReadingListStatus: function Reader_requestReadingListStatus() {
|
||||
gChromeWin.sendMessageToJava({
|
||||
type: "Reader:ListStatusRequest",
|
||||
@ -361,13 +313,6 @@ AboutReader.prototype = {
|
||||
}
|
||||
},
|
||||
|
||||
_onList: function Reader_onList() {
|
||||
if (!this._article || this._readingListCount < 1)
|
||||
return;
|
||||
|
||||
gChromeWin.BrowserApp.loadURI("about:home?panel=" + READING_LIST_PANEL_ID);
|
||||
},
|
||||
|
||||
_onShare: function Reader_onShare() {
|
||||
if (!this._article)
|
||||
return;
|
||||
@ -494,7 +439,7 @@ AboutReader.prototype = {
|
||||
return;
|
||||
|
||||
// Don't allow visible toolbar until banner state is known
|
||||
if (this._readingListCount == -1 || this._isReadingListItem == -1)
|
||||
if (this._isReadingListItem == -1)
|
||||
return;
|
||||
|
||||
if (this._getToolbarVisibility() === visible)
|
||||
|
@ -346,7 +346,7 @@ body {
|
||||
|
||||
.toolbar > * {
|
||||
float: right;
|
||||
width: 25%;
|
||||
width: 33%;
|
||||
}
|
||||
|
||||
.button {
|
||||
@ -496,14 +496,6 @@ body {
|
||||
background-image: url('chrome://browser/skin/images/reader-toggle-off-icon-mdpi.png');
|
||||
}
|
||||
|
||||
.list-button.on {
|
||||
background-image: url('chrome://browser/skin/images/reader-list-on-icon-mdpi.png');
|
||||
}
|
||||
|
||||
.list-button {
|
||||
background-image: url('chrome://browser/skin/images/reader-list-off-icon-mdpi.png');
|
||||
}
|
||||
|
||||
.share-button {
|
||||
background-image: url('chrome://browser/skin/images/reader-share-icon-mdpi.png');
|
||||
}
|
||||
@ -533,14 +525,6 @@ body {
|
||||
background-image: url('chrome://browser/skin/images/reader-toggle-off-icon-hdpi.png');
|
||||
}
|
||||
|
||||
.list-button.on {
|
||||
background-image: url('chrome://browser/skin/images/reader-list-on-icon-hdpi.png');
|
||||
}
|
||||
|
||||
.list-button {
|
||||
background-image: url('chrome://browser/skin/images/reader-list-off-icon-hdpi.png');
|
||||
}
|
||||
|
||||
.share-button {
|
||||
background-image: url('chrome://browser/skin/images/reader-share-icon-hdpi.png');
|
||||
}
|
||||
@ -571,14 +555,6 @@ body {
|
||||
background-image: url('chrome://browser/skin/images/reader-toggle-off-icon-xhdpi.png');
|
||||
}
|
||||
|
||||
.list-button.on {
|
||||
background-image: url('chrome://browser/skin/images/reader-list-on-icon-xhdpi.png');
|
||||
}
|
||||
|
||||
.list-button {
|
||||
background-image: url('chrome://browser/skin/images/reader-list-off-icon-xhdpi.png');
|
||||
}
|
||||
|
||||
.share-button {
|
||||
background-image: url('chrome://browser/skin/images/reader-share-icon-xhdpi.png');
|
||||
}
|
||||
|
Before Width: | Height: | Size: 380 B |
Before Width: | Height: | Size: 435 B |
Before Width: | Height: | Size: 627 B |
Before Width: | Height: | Size: 195 B |
Before Width: | Height: | Size: 286 B |
Before Width: | Height: | Size: 389 B |
@ -79,12 +79,6 @@ chrome.jar:
|
||||
skin/images/reader-dropdown-arrow-mdpi.png (images/reader-dropdown-arrow-mdpi.png)
|
||||
skin/images/reader-dropdown-arrow-hdpi.png (images/reader-dropdown-arrow-hdpi.png)
|
||||
skin/images/reader-dropdown-arrow-xhdpi.png (images/reader-dropdown-arrow-xhdpi.png)
|
||||
skin/images/reader-list-on-icon-mdpi.png (images/reader-list-on-icon-mdpi.png)
|
||||
skin/images/reader-list-on-icon-hdpi.png (images/reader-list-on-icon-hdpi.png)
|
||||
skin/images/reader-list-on-icon-xhdpi.png (images/reader-list-on-icon-xhdpi.png)
|
||||
skin/images/reader-list-off-icon-mdpi.png (images/reader-list-off-icon-mdpi.png)
|
||||
skin/images/reader-list-off-icon-hdpi.png (images/reader-list-off-icon-hdpi.png)
|
||||
skin/images/reader-list-off-icon-xhdpi.png (images/reader-list-off-icon-xhdpi.png)
|
||||
skin/images/reader-toggle-on-icon-mdpi.png (images/reader-toggle-on-icon-mdpi.png)
|
||||
skin/images/reader-toggle-on-icon-hdpi.png (images/reader-toggle-on-icon-hdpi.png)
|
||||
skin/images/reader-toggle-on-icon-xhdpi.png (images/reader-toggle-on-icon-xhdpi.png)
|
||||
|
@ -545,27 +545,33 @@ FxAccountsInternal.prototype = {
|
||||
*/
|
||||
getKeys: function() {
|
||||
let currentState = this.currentAccountState;
|
||||
return currentState.getUserAccountData().then((data) => {
|
||||
if (!data) {
|
||||
return currentState.getUserAccountData().then((userData) => {
|
||||
if (!userData) {
|
||||
throw new Error("Can't get keys; User is not signed in");
|
||||
}
|
||||
if (data.kA && data.kB) {
|
||||
return data;
|
||||
if (userData.kA && userData.kB) {
|
||||
return userData;
|
||||
}
|
||||
if (!currentState.whenKeysReadyDeferred) {
|
||||
currentState.whenKeysReadyDeferred = Promise.defer();
|
||||
this.fetchAndUnwrapKeys(data.keyFetchToken).then(
|
||||
data => {
|
||||
if (!data.kA || !data.kB) {
|
||||
currentState.whenKeysReadyDeferred.reject(
|
||||
new Error("user data missing kA or kB")
|
||||
);
|
||||
return;
|
||||
if (userData.keyFetchToken) {
|
||||
this.fetchAndUnwrapKeys(userData.keyFetchToken).then(
|
||||
(dataWithKeys) => {
|
||||
if (!dataWithKeys.kA || !dataWithKeys.kB) {
|
||||
currentState.whenKeysReadyDeferred.reject(
|
||||
new Error("user data missing kA or kB")
|
||||
);
|
||||
return;
|
||||
}
|
||||
currentState.whenKeysReadyDeferred.resolve(dataWithKeys);
|
||||
},
|
||||
(err) => {
|
||||
currentState.whenKeysReadyDeferred.reject(err);
|
||||
}
|
||||
currentState.whenKeysReadyDeferred.resolve(data);
|
||||
},
|
||||
err => currentState.whenKeysReadyDeferred.reject(err)
|
||||
);
|
||||
);
|
||||
} else {
|
||||
currentState.whenKeysReadyDeferred.reject('No keyFetchToken');
|
||||
}
|
||||
}
|
||||
return currentState.whenKeysReadyDeferred.promise;
|
||||
}).then(result => currentState.resolve(result));
|
||||
@ -577,6 +583,7 @@ FxAccountsInternal.prototype = {
|
||||
return Task.spawn(function* task() {
|
||||
// Sign out if we don't have a key fetch token.
|
||||
if (!keyFetchToken) {
|
||||
log.warn("improper fetchAndUnwrapKeys() call: token missing");
|
||||
yield this.signOut();
|
||||
return null;
|
||||
}
|
||||
|
@ -305,8 +305,8 @@ add_test(function test_getKeys() {
|
||||
});
|
||||
});
|
||||
|
||||
// getKeys with no keyFetchToken should trigger signOut
|
||||
add_test(function test_getKeys_no_token() {
|
||||
// fetchAndUnwrapKeys with no keyFetchToken should trigger signOut
|
||||
add_test(function test_fetchAndUnwrapKeys_no_token() {
|
||||
do_test_pending();
|
||||
|
||||
let fxa = new MockFxAccounts();
|
||||
@ -314,7 +314,7 @@ add_test(function test_getKeys_no_token() {
|
||||
delete user.keyFetchToken
|
||||
|
||||
makeObserver(ONLOGOUT_NOTIFICATION, function() {
|
||||
log.debug("test_getKeys_no_token observed logout");
|
||||
log.debug("test_fetchAndUnwrapKeys_no_token observed logout");
|
||||
fxa.internal.getUserAccountData().then(user => {
|
||||
do_test_finished();
|
||||
run_next_test();
|
||||
@ -322,7 +322,7 @@ add_test(function test_getKeys_no_token() {
|
||||
});
|
||||
|
||||
fxa.setSignedInUser(user).then((user) => {
|
||||
fxa.internal.getKeys();
|
||||
fxa.internal.fetchAndUnwrapKeys();
|
||||
});
|
||||
});
|
||||
|
||||
|
@ -560,6 +560,7 @@ add_task(function test_getKeysMissing() {
|
||||
// try and fetch them.
|
||||
delete identityConfig.fxaccount.user.kA;
|
||||
delete identityConfig.fxaccount.user.kB;
|
||||
identityConfig.fxaccount.user.keyFetchToken = 'keyFetchToken';
|
||||
|
||||
configureFxAccountIdentity(browseridManager, identityConfig);
|
||||
|
||||
|
@ -29,7 +29,7 @@ Cu.import("resource://gre/modules/NetUtil.jsm");
|
||||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
Cu.import("resource://gre/modules/Timer.jsm");
|
||||
|
||||
let promise = Cu.import("resource://gre/modules/commonjs/sdk/core/promise.js").Promise;
|
||||
let promise = Cu.import("resource://gre/modules/devtools/deprecated-sync-thenables.js").Promise;
|
||||
const { defer, resolve, reject } = promise;
|
||||
|
||||
XPCOMUtils.defineLazyServiceGetter(this, "socketTransportService",
|
||||
|
119
toolkit/devtools/deprecated-sync-thenables.js
Normal file
@ -0,0 +1,119 @@
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
/**
|
||||
* THIS MODULE IS DEPRECATED. IMPORT "Promise.jsm" INSTEAD.
|
||||
*/
|
||||
|
||||
"use strict";
|
||||
|
||||
this.Promise = {};
|
||||
|
||||
if (typeof(require) === "function") {
|
||||
module.exports = Promise;
|
||||
} else {
|
||||
this.EXPORTED_SYMBOLS = ["Promise"];
|
||||
}
|
||||
|
||||
function fulfilled(value) {
|
||||
return { then: function then(fulfill) { fulfill(value); } };
|
||||
}
|
||||
|
||||
function rejected(reason) {
|
||||
return { then: function then(fulfill, reject) { reject(reason); } };
|
||||
}
|
||||
|
||||
function isPromise(value) {
|
||||
return value && typeof(value.then) === 'function';
|
||||
}
|
||||
|
||||
function defer() {
|
||||
var observers = [];
|
||||
var result = null;
|
||||
var promise = {
|
||||
then: function then(onFulfill, onError) {
|
||||
var deferred = defer();
|
||||
|
||||
function resolve(value) {
|
||||
try {
|
||||
deferred.resolve(onFulfill ? onFulfill(value) : value);
|
||||
} catch (error) {
|
||||
deferred.resolve(rejected(error));
|
||||
}
|
||||
}
|
||||
|
||||
function reject(reason) {
|
||||
try {
|
||||
if (onError) deferred.resolve(onError(reason));
|
||||
else deferred.resolve(rejected(reason));
|
||||
} catch (error) {
|
||||
deferred.resolve(rejected(error));
|
||||
}
|
||||
}
|
||||
|
||||
if (observers) {
|
||||
observers.push({ resolve: resolve, reject: reject });
|
||||
} else {
|
||||
result.then(resolve, reject);
|
||||
}
|
||||
|
||||
return deferred.promise;
|
||||
}
|
||||
};
|
||||
|
||||
var deferred = {
|
||||
promise: promise,
|
||||
resolve: function resolve(value) {
|
||||
if (!result) {
|
||||
result = isPromise(value) ? value : fulfilled(value);
|
||||
while (observers.length) {
|
||||
var observer = observers.shift();
|
||||
result.then(observer.resolve, observer.reject);
|
||||
}
|
||||
observers = null;
|
||||
}
|
||||
},
|
||||
reject: function reject(reason) {
|
||||
deferred.resolve(rejected(reason));
|
||||
}
|
||||
};
|
||||
|
||||
return deferred;
|
||||
}
|
||||
Promise.defer = defer;
|
||||
|
||||
function resolve(value) {
|
||||
var deferred = defer();
|
||||
deferred.resolve(value);
|
||||
return deferred.promise;
|
||||
}
|
||||
Promise.resolve = resolve;
|
||||
|
||||
function reject(reason) {
|
||||
var deferred = defer();
|
||||
deferred.reject(reason);
|
||||
return deferred.promise;
|
||||
}
|
||||
Promise.reject = reject;
|
||||
|
||||
var promised = (function() {
|
||||
var call = Function.call;
|
||||
var concat = Array.prototype.concat;
|
||||
function execute(args) { return call.apply(call, args) }
|
||||
function promisedConcat(promises, unknown) {
|
||||
return promises.then(function(values) {
|
||||
return resolve(unknown).then(function(value) {
|
||||
return values.concat([ value ]);
|
||||
});
|
||||
});
|
||||
}
|
||||
return function promised(f) {
|
||||
return function promised() {
|
||||
return concat.apply([ f, this ], arguments).
|
||||
reduce(promisedConcat, resolve([])).
|
||||
then(execute);
|
||||
};
|
||||
}
|
||||
})();
|
||||
Promise.all = promised(Array);
|
@ -18,7 +18,7 @@
|
||||
|
||||
var Cu = require('chrome').Cu;
|
||||
module.exports = exports =
|
||||
Cu.import('resource://gre/modules/commonjs/sdk/core/promise.js', {}).Promise;
|
||||
Cu.import('resource://gre/modules/devtools/deprecated-sync-thenables.js', {}).Promise;
|
||||
|
||||
// When we've solved the debugger/sdk/promise/gcli/helpers/overlap problem then
|
||||
// we should use this instead:
|
||||
|
@ -22,6 +22,7 @@
|
||||
*/
|
||||
function ContentActor(connection, chromeGlobal)
|
||||
{
|
||||
this._chromeGlobal = chromeGlobal;
|
||||
TabActor.call(this, connection, chromeGlobal);
|
||||
this.traits.reconfigure = false;
|
||||
}
|
||||
@ -32,7 +33,7 @@ ContentActor.prototype.constructor = ContentActor;
|
||||
|
||||
Object.defineProperty(ContentActor.prototype, "docShell", {
|
||||
get: function() {
|
||||
return this.chromeEventHandler.docShell;
|
||||
return this._chromeGlobal.docShell;
|
||||
},
|
||||
enumerable: true,
|
||||
configurable: false
|
||||
|
@ -775,64 +775,6 @@ let traversalMethod = {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* We need to know when a document is navigating away so that we can kill
|
||||
* the nodes underneath it. We also need to know when a document is
|
||||
* navigated to so that we can send a mutation event for the iframe node.
|
||||
*
|
||||
* The nsIWebProgressListener is the easiest/best way to watch these
|
||||
* loads that works correctly with the bfcache.
|
||||
*
|
||||
* See nsIWebProgressListener for details
|
||||
* https://developer.mozilla.org/en-US/docs/XPCOM_Interface_Reference/nsIWebProgressListener
|
||||
*/
|
||||
var ProgressListener = Class({
|
||||
extends: Unknown,
|
||||
interfaces: ["nsIWebProgressListener", "nsISupportsWeakReference"],
|
||||
|
||||
initialize: function(tabActor) {
|
||||
Unknown.prototype.initialize.call(this);
|
||||
this.webProgress = tabActor.webProgress;
|
||||
this.webProgress.addProgressListener(
|
||||
this, Ci.nsIWebProgress.NOTIFY_ALL
|
||||
);
|
||||
},
|
||||
|
||||
destroy: function() {
|
||||
try {
|
||||
this.webProgress.removeProgressListener(this);
|
||||
} catch(ex) {
|
||||
// This can throw during browser shutdown.
|
||||
}
|
||||
this.webProgress = null;
|
||||
},
|
||||
|
||||
onStateChange: makeInfallible(function stateChange(progress, request, flags, status) {
|
||||
if (!this.webProgress) {
|
||||
console.warn("got an onStateChange after destruction");
|
||||
return;
|
||||
}
|
||||
|
||||
let isWindow = flags & Ci.nsIWebProgressListener.STATE_IS_WINDOW;
|
||||
let isDocument = flags & Ci.nsIWebProgressListener.STATE_IS_DOCUMENT;
|
||||
if (!(isWindow || isDocument)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (isDocument && (flags & Ci.nsIWebProgressListener.STATE_START)) {
|
||||
events.emit(this, "windowchange-start", progress.DOMWindow);
|
||||
}
|
||||
if (isWindow && (flags & Ci.nsIWebProgressListener.STATE_STOP)) {
|
||||
events.emit(this, "windowchange-stop", progress.DOMWindow);
|
||||
}
|
||||
}),
|
||||
|
||||
onProgressChange: function() {},
|
||||
onSecurityChange: function() {},
|
||||
onStatusChange: function() {},
|
||||
onLocationChange: function() {},
|
||||
});
|
||||
|
||||
/**
|
||||
* Server side of the DOM walker.
|
||||
*/
|
||||
@ -889,10 +831,8 @@ var WalkerActor = protocol.ActorClass({
|
||||
this.onFrameLoad = this.onFrameLoad.bind(this);
|
||||
this.onFrameUnload = this.onFrameUnload.bind(this);
|
||||
|
||||
this.progressListener = ProgressListener(tabActor);
|
||||
|
||||
events.on(this.progressListener, "windowchange-start", this.onFrameUnload);
|
||||
events.on(this.progressListener, "windowchange-stop", this.onFrameLoad);
|
||||
events.on(tabActor, "will-navigate", this.onFrameUnload);
|
||||
events.on(tabActor, "navigate", this.onFrameLoad);
|
||||
|
||||
// Ensure that the root document node actor is ready and
|
||||
// managed.
|
||||
@ -915,7 +855,6 @@ var WalkerActor = protocol.ActorClass({
|
||||
this._hoveredNode = null;
|
||||
this.clearPseudoClassLocks();
|
||||
this._activePseudoClassLocks = null;
|
||||
this.progressListener.destroy();
|
||||
this.rootDoc = null;
|
||||
events.emit(this, "destroyed");
|
||||
protocol.Actor.prototype.destroy.call(this);
|
||||
@ -1966,10 +1905,8 @@ var WalkerActor = protocol.ActorClass({
|
||||
}
|
||||
},
|
||||
|
||||
onFrameLoad: function(window) {
|
||||
let frame = this.layoutHelpers.getFrameElement(window);
|
||||
let isTopLevel = this.layoutHelpers.isTopLevelWindow(window);
|
||||
if (!frame && !this.rootDoc && isTopLevel) {
|
||||
onFrameLoad: function({ window, isTopLevel }) {
|
||||
if (!this.rootDoc && isTopLevel) {
|
||||
this.rootDoc = window.document;
|
||||
this.rootNode = this.document();
|
||||
this.queueMutation({
|
||||
@ -1977,6 +1914,7 @@ var WalkerActor = protocol.ActorClass({
|
||||
target: this.rootNode.form()
|
||||
});
|
||||
}
|
||||
let frame = this.layoutHelpers.getFrameElement(window);
|
||||
let frameActor = this._refMap.get(frame);
|
||||
if (!frameActor) {
|
||||
return;
|
||||
@ -2008,7 +1946,7 @@ var WalkerActor = protocol.ActorClass({
|
||||
return false;
|
||||
},
|
||||
|
||||
onFrameUnload: function(window) {
|
||||
onFrameUnload: function({ window }) {
|
||||
// Any retained orphans that belong to this document
|
||||
// or its children need to be released, and a mutation sent
|
||||
// to notify of that.
|
||||
|
@ -10,6 +10,13 @@ let {Cu} = require("chrome");
|
||||
let {Promise: promise} = Cu.import("resource://gre/modules/Promise.jsm", {});
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "AddonManager", "resource://gre/modules/AddonManager.jsm");
|
||||
|
||||
// Assumptions on events module:
|
||||
// events needs to be dispatched synchronously,
|
||||
// by calling the listeners in the order or registration.
|
||||
XPCOMUtils.defineLazyGetter(this, "events", () => {
|
||||
return devtools.require("sdk/event/core");
|
||||
});
|
||||
|
||||
/**
|
||||
* Browser-specific actors.
|
||||
*/
|
||||
@ -485,15 +492,13 @@ BrowserTabList.prototype.onCloseWindow = DevToolsUtils.makeInfallible(function(a
|
||||
* @param aChromeEventHandler
|
||||
* An object on which listen for DOMWindowCreated and pageshow events.
|
||||
*/
|
||||
function TabActor(aConnection, aChromeEventHandler)
|
||||
function TabActor(aConnection)
|
||||
{
|
||||
this.conn = aConnection;
|
||||
this._chromeEventHandler = aChromeEventHandler;
|
||||
this._tabActorPool = null;
|
||||
// A map of actor names to actor instances provided by extensions.
|
||||
this._extraActors = {};
|
||||
|
||||
this._onWindowCreated = this.onWindowCreated.bind(this);
|
||||
this._exited = false;
|
||||
|
||||
this.traits = { reconfigure: true };
|
||||
}
|
||||
@ -504,7 +509,7 @@ function TabActor(aConnection, aChromeEventHandler)
|
||||
TabActor.prototype = {
|
||||
traits: null,
|
||||
|
||||
get exited() { return !this._chromeEventHandler; },
|
||||
get exited() { return this._exited; },
|
||||
get attached() { return !!this._attached; },
|
||||
|
||||
_tabPool: null,
|
||||
@ -522,7 +527,10 @@ TabActor.prototype = {
|
||||
* An object on which listen for DOMWindowCreated and pageshow events.
|
||||
*/
|
||||
get chromeEventHandler() {
|
||||
return this._chromeEventHandler;
|
||||
// TODO: bug 992778, fix docShell.chromeEventHandler in child processes
|
||||
return this.docShell.chromeEventHandler ||
|
||||
this.docShell.QueryInterface(Ci.nsIInterfaceRequestor)
|
||||
.getInterface(Ci.nsIContentFrameMessageManager);
|
||||
},
|
||||
|
||||
/**
|
||||
@ -631,7 +639,7 @@ TabActor.prototype = {
|
||||
disconnect: function BTA_disconnect() {
|
||||
this._detach();
|
||||
this._extraActors = null;
|
||||
this._chromeEventHandler = null;
|
||||
this._exited = true;
|
||||
},
|
||||
|
||||
/**
|
||||
@ -647,7 +655,7 @@ TabActor.prototype = {
|
||||
type: "tabDetached" });
|
||||
}
|
||||
|
||||
this._chromeEventHandler = null;
|
||||
this._exited = true;
|
||||
},
|
||||
|
||||
/* Support for DebuggerServer.addTabActor. */
|
||||
@ -670,10 +678,8 @@ TabActor.prototype = {
|
||||
// ... and a pool for context-lifetime actors.
|
||||
this._pushContext();
|
||||
|
||||
// Watch for globals being created in this tab.
|
||||
this.chromeEventHandler.addEventListener("DOMWindowCreated", this._onWindowCreated, true);
|
||||
this.chromeEventHandler.addEventListener("pageshow", this._onWindowCreated, true);
|
||||
this._progressListener = new DebuggerProgressListener(this);
|
||||
this._progressListener.watch(this.docShell);
|
||||
|
||||
this._attached = true;
|
||||
},
|
||||
@ -715,10 +721,12 @@ TabActor.prototype = {
|
||||
return false;
|
||||
}
|
||||
|
||||
this._progressListener.destroy();
|
||||
|
||||
this.chromeEventHandler.removeEventListener("DOMWindowCreated", this._onWindowCreated, true);
|
||||
this.chromeEventHandler.removeEventListener("pageshow", this._onWindowCreated, true);
|
||||
// Check for docShell availability, as it can be already gone
|
||||
// during Firefox shutdown.
|
||||
if (this.docShell) {
|
||||
this._progressListener.unwatch(this.docShell);
|
||||
}
|
||||
this._progressListener = null;
|
||||
|
||||
this._popContext();
|
||||
|
||||
@ -909,28 +917,116 @@ TabActor.prototype = {
|
||||
* debugging, which may have been disabled temporarily by the
|
||||
* DebuggerProgressListener.
|
||||
*/
|
||||
onWindowCreated:
|
||||
DevToolsUtils.makeInfallible(function BTA_onWindowCreated(evt) {
|
||||
// pageshow events for non-persisted pages have already been handled by a
|
||||
// prior DOMWindowCreated event.
|
||||
if (!this._attached || (evt.type == "pageshow" && !evt.persisted)) {
|
||||
return;
|
||||
}
|
||||
if (evt.target === this.contentDocument) {
|
||||
this.threadActor.clearDebuggees();
|
||||
if (this.threadActor.dbg) {
|
||||
this.threadActor.dbg.enabled = true;
|
||||
this.threadActor.global = evt.target.defaultView;
|
||||
this.threadActor.maybePauseOnExceptions();
|
||||
_windowReady: function (window) {
|
||||
let isTopLevel = window == this.window;
|
||||
dumpn("window-ready: " + window.location + " isTopLevel:" + isTopLevel);
|
||||
|
||||
events.emit(this, "window-ready", {
|
||||
window: window,
|
||||
isTopLevel: isTopLevel
|
||||
});
|
||||
|
||||
// TODO bug 997119: move that code to ThreadActor by listening to window-ready
|
||||
let threadActor = this.threadActor;
|
||||
if (isTopLevel) {
|
||||
threadActor.clearDebuggees();
|
||||
if (threadActor.dbg) {
|
||||
threadActor.dbg.enabled = true;
|
||||
threadActor.global = window;
|
||||
threadActor.maybePauseOnExceptions();
|
||||
}
|
||||
}
|
||||
|
||||
// Refresh the debuggee list when a new window object appears (top window or
|
||||
// iframe).
|
||||
if (this.threadActor.attached) {
|
||||
this.threadActor.findGlobals();
|
||||
if (threadActor.attached) {
|
||||
threadActor.findGlobals();
|
||||
}
|
||||
}, "TabActor.prototype.onWindowCreated"),
|
||||
},
|
||||
|
||||
/**
|
||||
* Start notifying server codebase and client about a new document
|
||||
* being loaded in the currently targeted context.
|
||||
*/
|
||||
_willNavigate: function (window, newURI, request) {
|
||||
let isTopLevel = window == this.window;
|
||||
|
||||
// will-navigate event needs to be dispatched synchronously,
|
||||
// by calling the listeners in the order or registration.
|
||||
// This event fires once navigation starts,
|
||||
// (all pending user prompts are dealt with),
|
||||
// but before the first request starts.
|
||||
events.emit(this, "will-navigate", {
|
||||
window: window,
|
||||
isTopLevel: isTopLevel,
|
||||
newURI: newURI,
|
||||
request: request
|
||||
});
|
||||
|
||||
|
||||
// We don't do anything for inner frames in TabActor.
|
||||
// (we will only update thread actor on window-ready)
|
||||
if (!isTopLevel) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Proceed normally only if the debuggee is not paused.
|
||||
// TODO bug 997119: move that code to ThreadActor by listening to will-navigate
|
||||
let threadActor = this.threadActor;
|
||||
if (request && threadActor.state == "paused") {
|
||||
request.suspend();
|
||||
threadActor.onResume();
|
||||
threadActor.dbg.enabled = false;
|
||||
this._pendingNavigation = request;
|
||||
}
|
||||
threadActor.disableAllBreakpoints();
|
||||
|
||||
this.conn.send({
|
||||
from: this.actorID,
|
||||
type: "tabNavigated",
|
||||
url: newURI,
|
||||
nativeConsoleAPI: true,
|
||||
state: "start"
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* Notify server and client about a new document done loading in the current
|
||||
* targeted context.
|
||||
*/
|
||||
_navigate: function (window) {
|
||||
let isTopLevel = window == this.window;
|
||||
|
||||
// navigate event needs to be dispatched synchronously,
|
||||
// by calling the listeners in the order or registration.
|
||||
// This event is fired once the document is loaded,
|
||||
// after the load event, it's document ready-state is 'complete'.
|
||||
events.emit(this, "navigate", {
|
||||
window: window,
|
||||
isTopLevel: isTopLevel
|
||||
});
|
||||
|
||||
// We don't do anything for inner frames in TabActor.
|
||||
// (we will only update thread actor on window-ready)
|
||||
if (!isTopLevel) {
|
||||
return;
|
||||
}
|
||||
|
||||
// TODO bug 997119: move that code to ThreadActor by listening to navigate
|
||||
let threadActor = this.threadActor;
|
||||
if (threadActor.state == "running") {
|
||||
threadActor.dbg.enabled = true;
|
||||
}
|
||||
|
||||
this.conn.send({
|
||||
from: this.actorID,
|
||||
type: "tabNavigated",
|
||||
url: this.url,
|
||||
title: this.title,
|
||||
nativeConsoleAPI: this.hasNativeConsoleAPI(this.window),
|
||||
state: "stop"
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* Tells if the window.console object is native or overwritten by script in
|
||||
@ -999,12 +1095,15 @@ Object.defineProperty(BrowserTabActor.prototype, "messageManager", {
|
||||
|
||||
Object.defineProperty(BrowserTabActor.prototype, "title", {
|
||||
get: function() {
|
||||
let title = this.contentDocument.contentTitle;
|
||||
let title = this.contentDocument.title || this._browser.contentTitle;
|
||||
// If contentTitle is empty (e.g. on a not-yet-restored tab), but there is a
|
||||
// tabbrowser (i.e. desktop Firefox, but not Fennec), we can use the label
|
||||
// as the title.
|
||||
if (!title && this._tabbrowser) {
|
||||
title = this._tabbrowser._getTabForContentWindow(this.window).label;
|
||||
let tab = this._tabbrowser._getTabForContentWindow(this.window);
|
||||
if (tab) {
|
||||
title = tab.label;
|
||||
}
|
||||
}
|
||||
return title;
|
||||
},
|
||||
@ -1254,9 +1353,7 @@ BrowserAddonActor.prototype.requestTypes = {
|
||||
*/
|
||||
function DebuggerProgressListener(aTabActor) {
|
||||
this._tabActor = aTabActor;
|
||||
this._tabActor.webProgress.addProgressListener(this, Ci.nsIWebProgress.NOTIFY_STATE_ALL);
|
||||
let EventEmitter = devtools.require("devtools/toolkit/event-emitter");
|
||||
EventEmitter.decorate(this);
|
||||
this._onWindowCreated = this.onWindowCreated.bind(this);
|
||||
}
|
||||
|
||||
DebuggerProgressListener.prototype = {
|
||||
@ -1266,70 +1363,76 @@ DebuggerProgressListener.prototype = {
|
||||
Ci.nsISupports,
|
||||
]),
|
||||
|
||||
onStateChange:
|
||||
DevToolsUtils.makeInfallible(function DPL_onStateChange(aProgress, aRequest, aFlag, aStatus) {
|
||||
let isStart = aFlag & Ci.nsIWebProgressListener.STATE_START;
|
||||
let isStop = aFlag & Ci.nsIWebProgressListener.STATE_STOP;
|
||||
let isDocument = aFlag & Ci.nsIWebProgressListener.STATE_IS_DOCUMENT;
|
||||
let isNetwork = aFlag & Ci.nsIWebProgressListener.STATE_IS_NETWORK;
|
||||
let isRequest = aFlag & Ci.nsIWebProgressListener.STATE_IS_REQUEST;
|
||||
let isWindow = aFlag & Ci.nsIWebProgressListener.STATE_IS_WINDOW;
|
||||
watch: function DPL_watch(docShell) {
|
||||
let webProgress = docShell.QueryInterface(Ci.nsIInterfaceRequestor)
|
||||
.getInterface(Ci.nsIWebProgress);
|
||||
webProgress.addProgressListener(this, Ci.nsIWebProgress.NOTIFY_STATUS |
|
||||
Ci.nsIWebProgress.NOTIFY_STATE_WINDOW |
|
||||
Ci.nsIWebProgress.NOTIFY_STATE_DOCUMENT);
|
||||
|
||||
// Skip non-interesting states.
|
||||
if (!isWindow || !isNetwork ||
|
||||
aProgress.DOMWindow != this._tabActor.window) {
|
||||
// TODO: fix docShell.chromeEventHandler in child processes!
|
||||
let chromeEventHandler = docShell.chromeEventHandler ||
|
||||
docShell.QueryInterface(Ci.nsIInterfaceRequestor)
|
||||
.getInterface(Ci.nsIContentFrameMessageManager);
|
||||
|
||||
// Watch for globals being created in this docshell tree.
|
||||
chromeEventHandler.addEventListener("DOMWindowCreated",
|
||||
this._onWindowCreated, true);
|
||||
chromeEventHandler.addEventListener("pageshow",
|
||||
this._onWindowCreated, true);
|
||||
},
|
||||
|
||||
unwatch: function DPL_unwatch(docShell) {
|
||||
let webProgress = docShell.QueryInterface(Ci.nsIInterfaceRequestor)
|
||||
.getInterface(Ci.nsIWebProgress);
|
||||
webProgress.removeProgressListener(this);
|
||||
|
||||
// TODO: fix docShell.chromeEventHandler in child processes!
|
||||
let chromeEventHandler = docShell.chromeEventHandler ||
|
||||
docShell.QueryInterface(Ci.nsIInterfaceRequestor)
|
||||
.getInterface(Ci.nsIContentFrameMessageManager);
|
||||
chromeEventHandler.removeEventListener("DOMWindowCreated",
|
||||
this._onWindowCreated, true);
|
||||
chromeEventHandler.removeEventListener("pageshow",
|
||||
this._onWindowCreated, true);
|
||||
},
|
||||
|
||||
onWindowCreated:
|
||||
DevToolsUtils.makeInfallible(function DPL_onWindowCreated(evt) {
|
||||
// Ignore any event if the tab actor isn't attached.
|
||||
if (!this._tabActor.attached) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (isStart && aRequest instanceof Ci.nsIChannel) {
|
||||
// Proceed normally only if the debuggee is not paused.
|
||||
if (this._tabActor.threadActor.state == "paused") {
|
||||
aRequest.suspend();
|
||||
this._tabActor.threadActor.onResume();
|
||||
this._tabActor.threadActor.dbg.enabled = false;
|
||||
this._tabActor._pendingNavigation = aRequest;
|
||||
}
|
||||
|
||||
let packet = {
|
||||
from: this._tabActor.actorID,
|
||||
type: "tabNavigated",
|
||||
url: aRequest.URI.spec,
|
||||
nativeConsoleAPI: true,
|
||||
state: "start"
|
||||
};
|
||||
this._tabActor.threadActor.disableAllBreakpoints();
|
||||
this._tabActor.conn.send(packet);
|
||||
this.emit("will-navigate", packet);
|
||||
} else if (isStop) {
|
||||
if (this._tabActor.threadActor.state == "running") {
|
||||
this._tabActor.threadActor.dbg.enabled = true;
|
||||
}
|
||||
|
||||
let window = this._tabActor.window;
|
||||
let packet = {
|
||||
from: this._tabActor.actorID,
|
||||
type: "tabNavigated",
|
||||
url: this._tabActor.url,
|
||||
title: this._tabActor.title,
|
||||
nativeConsoleAPI: this._tabActor.hasNativeConsoleAPI(window),
|
||||
state: "stop"
|
||||
};
|
||||
this._tabActor.conn.send(packet);
|
||||
this.emit("navigate", packet);
|
||||
}
|
||||
}, "DebuggerProgressListener.prototype.onStateChange"),
|
||||
|
||||
/**
|
||||
* Destroy the progress listener instance.
|
||||
*/
|
||||
destroy: function DPL_destroy() {
|
||||
try {
|
||||
this._tabActor.webProgress.removeProgressListener(this);
|
||||
} catch (ex) {
|
||||
// This can throw during browser shutdown.
|
||||
// pageshow events for non-persisted pages have already been handled by a
|
||||
// prior DOMWindowCreated event.
|
||||
if (evt.type == "pageshow" && !evt.persisted) {
|
||||
return;
|
||||
}
|
||||
|
||||
this._tabActor._progressListener = null;
|
||||
this._tabActor = null;
|
||||
}
|
||||
let window = evt.target.defaultView;
|
||||
this._tabActor._windowReady(window);
|
||||
}, "DebuggerProgressListener.prototype.onWindowCreated"),
|
||||
|
||||
onStateChange:
|
||||
DevToolsUtils.makeInfallible(function DPL_onStateChange(aProgress, aRequest, aFlag, aStatus) {
|
||||
// Ignore any event if the tab actor isn't attached.
|
||||
if (!this._tabActor.attached) {
|
||||
return;
|
||||
}
|
||||
|
||||
let isStart = aFlag & Ci.nsIWebProgressListener.STATE_START;
|
||||
let isStop = aFlag & Ci.nsIWebProgressListener.STATE_STOP;
|
||||
let isDocument = aFlag & Ci.nsIWebProgressListener.STATE_IS_DOCUMENT;
|
||||
let isWindow = aFlag & Ci.nsIWebProgressListener.STATE_IS_WINDOW;
|
||||
|
||||
let window = aProgress.DOMWindow;
|
||||
if (isDocument && isStart) {
|
||||
let newURI = aRequest instanceof Ci.nsIChannel ? aRequest.URI.spec : null;
|
||||
this._tabActor._willNavigate(window, newURI, aRequest);
|
||||
}
|
||||
if (isWindow && isStop) {
|
||||
this._tabActor._navigate(window);
|
||||
}
|
||||
}, "DebuggerProgressListener.prototype.onStateChange")
|
||||
};
|
||||
|
@ -237,8 +237,8 @@ WebConsoleActor.prototype =
|
||||
set evalWindow(aWindow) {
|
||||
this._evalWindow = aWindow;
|
||||
|
||||
if (!this._progressListenerActive && this.parentActor._progressListener) {
|
||||
this.parentActor._progressListener.once("will-navigate", this._onWillNavigate);
|
||||
if (!this._progressListenerActive) {
|
||||
events.on(this.parentActor, "will-navigate", this._onWillNavigate);
|
||||
this._progressListenerActive = true;
|
||||
}
|
||||
},
|
||||
@ -1374,10 +1374,13 @@ WebConsoleActor.prototype =
|
||||
* The "will-navigate" progress listener. This is used to clear the current
|
||||
* eval scope.
|
||||
*/
|
||||
_onWillNavigate: function WCA__onWillNavigate()
|
||||
_onWillNavigate: function WCA__onWillNavigate({ window, isTopLevel })
|
||||
{
|
||||
this._evalWindow = null;
|
||||
this._progressListenerActive = false;
|
||||
if (isTopLevel) {
|
||||
this._evalWindow = null;
|
||||
events.off(this.parentActor, "will-navigate", this._onWillNavigate);
|
||||
this._progressListenerActive = false;
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
|
@ -47,7 +47,7 @@ Cu.import("resource://gre/modules/reflect.jsm");
|
||||
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
dumpn.wantLogging = Services.prefs.getBoolPref("devtools.debugger.log");
|
||||
|
||||
Cu.import("resource://gre/modules/commonjs/sdk/core/promise.js");
|
||||
Cu.import("resource://gre/modules/devtools/deprecated-sync-thenables.js");
|
||||
|
||||
function loadSubScript(aURL)
|
||||
{
|
||||
@ -66,11 +66,10 @@ function loadSubScript(aURL)
|
||||
}
|
||||
|
||||
let events = require("sdk/event/core");
|
||||
let {defer, resolve, reject, promised, all} = require("sdk/core/promise");
|
||||
let {defer, resolve, reject, all} = require("devtools/toolkit/deprecated-sync-thenables");
|
||||
this.defer = defer;
|
||||
this.resolve = resolve;
|
||||
this.reject = reject;
|
||||
this.promised = promised;
|
||||
this.all = all;
|
||||
|
||||
Cu.import("resource://gre/modules/devtools/SourceMap.jsm");
|
||||
|
@ -6,7 +6,7 @@
|
||||
|
||||
let {Cu} = require("chrome");
|
||||
let Services = require("Services");
|
||||
let promise = require("sdk/core/promise");
|
||||
let promise = require("devtools/toolkit/deprecated-sync-thenables");
|
||||
let {Class} = require("sdk/core/heritage");
|
||||
let {EventTarget} = require("sdk/event/target");
|
||||
let events = require("sdk/event/core");
|
||||
|
@ -8,7 +8,10 @@ support-files =
|
||||
storage-unsecured-iframe.html
|
||||
storage-updates.html
|
||||
storage-secured-iframe.html
|
||||
navigate-first.html
|
||||
navigate-second.html
|
||||
|
||||
[browser_storage_dynamic_windows.js]
|
||||
[browser_storage_listings.js]
|
||||
[browser_storage_updates.js]
|
||||
[browser_navigateEvents.js]
|
||||
|
169
toolkit/devtools/server/tests/browser/browser_navigateEvents.js
Normal file
@ -0,0 +1,169 @@
|
||||
|
||||
let Cu = Components.utils;
|
||||
let Cc = Components.classes;
|
||||
let Ci = Components.interfaces;
|
||||
|
||||
const URL1 = MAIN_DOMAIN + "navigate-first.html";
|
||||
const URL2 = MAIN_DOMAIN + "navigate-second.html";
|
||||
|
||||
let { DebuggerClient } = Cu.import("resource://gre/modules/devtools/dbg-client.jsm", {});
|
||||
let { DebuggerServer } = Cu.import("resource://gre/modules/devtools/dbg-server.jsm", {});
|
||||
|
||||
let devtools = Cu.import("resource://gre/modules/devtools/Loader.jsm", {}).devtools;
|
||||
let events = devtools.require("sdk/event/core");
|
||||
|
||||
let client;
|
||||
|
||||
// State machine to check events order
|
||||
let i = 0;
|
||||
function assertEvent(event, data) {
|
||||
let x = 0;
|
||||
switch(i++) {
|
||||
case x++:
|
||||
is(event, "request", "Get first page load");
|
||||
is(data, URL1);
|
||||
break;
|
||||
case x++:
|
||||
is(event, "load-new-document", "Ask to load the second page");
|
||||
break;
|
||||
case x++:
|
||||
is(event, "unload-dialog", "We get the dialog on first page unload");
|
||||
break;
|
||||
case x++:
|
||||
is(event, "will-navigate", "The very first event is will-navigate on server side");
|
||||
is(data.newURI, URL2, "newURI property is correct");
|
||||
break;
|
||||
case x++:
|
||||
is(event, "tabNavigated", "Right after will-navigate, the client receive tabNavigated");
|
||||
is(data.state, "start", "state is start");
|
||||
is(data.url, URL2, "url property is correct");
|
||||
break;
|
||||
case x++:
|
||||
is(event, "request", "Given that locally, the Debugger protocol is sync, the request happens after tabNavigated");
|
||||
is(data, URL2);
|
||||
break;
|
||||
case x++:
|
||||
is(event, "DOMContentLoaded");
|
||||
is(content.document.readyState, "interactive");
|
||||
break;
|
||||
case x++:
|
||||
is(event, "load");
|
||||
is(content.document.readyState, "complete");
|
||||
break;
|
||||
case x++:
|
||||
is(event, "navigate", "Then once the second doc is loaded, we get the navigate event");
|
||||
is(content.document.readyState, "complete", "navigate is emitted only once the document is fully loaded");
|
||||
break;
|
||||
case x++:
|
||||
is(event, "tabNavigated", "Finally, the receive the client event");
|
||||
is(data.state, "stop", "state is stop");
|
||||
is(data.url, URL2, "url property is correct");
|
||||
|
||||
// End of test!
|
||||
cleanup();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
function waitForOnBeforeUnloadDialog(browser, callback) {
|
||||
browser.addEventListener("DOMWillOpenModalDialog", function onModalDialog() {
|
||||
browser.removeEventListener("DOMWillOpenModalDialog", onModalDialog, true);
|
||||
|
||||
executeSoon(() => {
|
||||
let stack = browser.parentNode;
|
||||
let dialogs = stack.getElementsByTagName("tabmodalprompt");
|
||||
let {button0, button1} = dialogs[0].ui;
|
||||
callback(button0, button1);
|
||||
});
|
||||
}, true);
|
||||
}
|
||||
|
||||
let httpObserver = function (subject, topic, state) {
|
||||
let channel = subject.QueryInterface(Ci.nsIHttpChannel);
|
||||
let url = channel.URI.spec;
|
||||
// Only listen for our document request, as many other requests can happen
|
||||
if (url == URL1 || url == URL2) {
|
||||
assertEvent("request", url);
|
||||
}
|
||||
};
|
||||
Services.obs.addObserver(httpObserver, "http-on-modify-request", false);
|
||||
|
||||
function onDOMContentLoaded() {
|
||||
assertEvent("DOMContentLoaded");
|
||||
}
|
||||
function onLoad() {
|
||||
assertEvent("load");
|
||||
}
|
||||
|
||||
function getServerTabActor(callback) {
|
||||
// Ensure having a minimal server
|
||||
if (!DebuggerServer.initialized) {
|
||||
DebuggerServer.init(function () { return true; });
|
||||
DebuggerServer.addBrowserActors();
|
||||
}
|
||||
|
||||
// Connect to this tab
|
||||
let transport = DebuggerServer.connectPipe();
|
||||
client = new DebuggerClient(transport);
|
||||
client.connect(function onConnect() {
|
||||
client.listTabs(function onListTabs(aResponse) {
|
||||
// Fetch the BrowserTabActor for this tab
|
||||
let actorID = aResponse.tabs[aResponse.selected].actor;
|
||||
client.attachTab(actorID, function(aResponse, aTabClient) {
|
||||
// !Hack! Retrieve a server side object, the BrowserTabActor instance
|
||||
let conn = transport._serverConnection;
|
||||
let tabActor = conn.getActor(actorID);
|
||||
callback(tabActor);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
client.addListener("tabNavigated", function (aEvent, aPacket) {
|
||||
assertEvent("tabNavigated", aPacket);
|
||||
});
|
||||
}
|
||||
|
||||
function test() {
|
||||
waitForExplicitFinish();
|
||||
|
||||
// Open a test tab
|
||||
addTab(URL1, function(doc) {
|
||||
getServerTabActor(function (tabActor) {
|
||||
// In order to listen to internal will-navigate/navigate events
|
||||
events.on(tabActor, "will-navigate", function (data) {
|
||||
assertEvent("will-navigate", data);
|
||||
});
|
||||
events.on(tabActor, "navigate", function (data) {
|
||||
assertEvent("navigate", data);
|
||||
});
|
||||
|
||||
// Start listening for page load events
|
||||
let browser = gBrowser.selectedTab.linkedBrowser;
|
||||
browser.addEventListener("DOMContentLoaded", onDOMContentLoaded, true);
|
||||
browser.addEventListener("load", onLoad, true);
|
||||
|
||||
// Listen for alert() call being made in navigate-first during unload
|
||||
waitForOnBeforeUnloadDialog(browser, function (btnLeave, btnStay) {
|
||||
assertEvent("unload-dialog");
|
||||
// accept to quit this page to another
|
||||
btnLeave.click();
|
||||
});
|
||||
|
||||
// Load another document in this doc to dispatch these events
|
||||
assertEvent("load-new-document");
|
||||
content.location = URL2;
|
||||
});
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
function cleanup() {
|
||||
let browser = gBrowser.selectedTab.linkedBrowser;
|
||||
browser.removeEventListener("DOMContentLoaded", onDOMContentLoaded);
|
||||
browser.removeEventListener("load", onLoad);
|
||||
client.close(function () {
|
||||
Services.obs.addObserver(httpObserver, "http-on-modify-request", false);
|
||||
DebuggerServer.destroy();
|
||||
finish();
|
||||
});
|
||||
}
|
15
toolkit/devtools/server/tests/browser/navigate-first.html
Normal file
@ -0,0 +1,15 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
</head>
|
||||
<body>
|
||||
First
|
||||
<script>
|
||||
|
||||
window.onbeforeunload=function(e){
|
||||
e.returnValue="?";
|
||||
};
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
@ -0,0 +1,9 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
</head>
|
||||
<body>
|
||||
Second
|
||||
</body>
|
||||
</html>
|
@ -61,12 +61,14 @@ function attachURL(url, callback) {
|
||||
for (let tab of response.tabs) {
|
||||
if (tab.url === url) {
|
||||
window.removeEventListener("message", loadListener, false);
|
||||
try {
|
||||
callback(null, client, tab, win.document);
|
||||
} catch(ex) {
|
||||
Cu.reportError(ex);
|
||||
dump(ex);
|
||||
}
|
||||
client.attachTab(tab.actor, function(aResponse, aTabClient) {
|
||||
try {
|
||||
callback(null, client, tab, win.document);
|
||||
} catch(ex) {
|
||||
Cu.reportError(ex);
|
||||
dump(ex);
|
||||
}
|
||||
});
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -23,7 +23,7 @@
|
||||
|
||||
const { utils: Cu } = Components;
|
||||
const { Promise: promise } =
|
||||
Cu.import("resource://gre/modules/commonjs/sdk/core/promise.js", {});
|
||||
Cu.import("resource://gre/modules/devtools/deprecated-sync-thenables.js", {});
|
||||
const { EventEmitter } =
|
||||
Cu.import("resource://gre/modules/devtools/event-emitter.js", {});
|
||||
const { Task } = Cu.import("resource://gre/modules/Task.jsm", {});
|
||||
|