merge fx-team to mozilla-central

This commit is contained in:
Carsten "Tomcat" Book 2014-04-23 14:54:09 +02:00
commit f212e35ef0
100 changed files with 1896 additions and 1056 deletions

View File

@ -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);

View File

@ -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);

View File

@ -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");

View File

@ -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) {

View File

@ -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');

View File

@ -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";

View File

@ -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;

View File

@ -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");

View File

@ -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");

View File

@ -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");

View File

@ -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,

View File

@ -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");

View File

@ -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);

View File

@ -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");

View File

@ -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

View File

@ -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);

View File

@ -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"

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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";

View File

@ -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

View File

@ -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]

View File

@ -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");

View File

@ -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);

View File

@ -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");

View File

@ -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];

View File

@ -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");

View File

@ -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");

View File

@ -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.

View File

@ -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);
});
}

View File

@ -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);
});
}

View File

@ -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.");

View File

@ -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");

View File

@ -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);
}
}

View File

@ -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);

View File

@ -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);

View File

@ -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();

View File

@ -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);

View File

@ -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>

View File

@ -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";

View File

@ -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

View File

@ -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);
},

View File

@ -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);

File diff suppressed because it is too large Load Diff

View File

@ -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);

Binary file not shown.

After

Width:  |  Height:  |  Size: 384 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 871 B

View File

@ -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);
}

View File

@ -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>

View File

@ -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--;

View File

@ -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

View File

@ -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.

View File

@ -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

View File

@ -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;

View File

@ -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")) {

View File

@ -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");

View File

@ -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

View File

@ -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);
}
}

View File

@ -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);
}

View File

@ -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;
}

View File

@ -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;

View File

@ -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();

View File

@ -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>

View File

@ -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)

View File

@ -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');
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 380 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 435 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 627 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 195 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 286 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 389 B

View File

@ -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)

View File

@ -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;
}

View File

@ -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();
});
});

View File

@ -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);

View File

@ -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",

View 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);

View File

@ -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:

View File

@ -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

View File

@ -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.

View File

@ -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")
};

View File

@ -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;
}
},
};

View File

@ -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");

View File

@ -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");

View File

@ -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]

View 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();
});
}

View 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>

View File

@ -0,0 +1,9 @@
<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8">
</head>
<body>
Second
</body>
</html>

View File

@ -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;
}
}

View File

@ -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", {});