Merge m-c to graphics

This commit is contained in:
Ryan Hunt 2017-01-27 10:07:37 -06:00
commit 3fe2c02ee1
521 changed files with 7938 additions and 4605 deletions

View File

@ -46,6 +46,18 @@ public:
bool IsShutdown() const { return mShutdown; }
/**
* Mark this actor as shutdown without doing any cleanup. This should only
* be called on actors that have just been initialized, so probably only from
* RecvPDocAccessibleConstructor.
*/
void MarkAsShutdown()
{
MOZ_ASSERT(mChildDocs.IsEmpty());
MOZ_ASSERT(mAccessibles.Count() == 0);
mShutdown = true;
}
/*
* Called when a message from a document in a child process notifies the main
* process it is firing an event.

View File

@ -38,7 +38,7 @@ support-files =
[browser_treeupdate_gencontent.js]
[browser_treeupdate_hidden.js]
[browser_treeupdate_imagemap.js]
skip-if = (os == 'mac' && debug && e10s) # Bug 1318569
skip-if = e10s # Bug 1318569
[browser_treeupdate_list.js]
[browser_treeupdate_list_editabledoc.js]
[browser_treeupdate_listener.js]

View File

@ -1029,8 +1029,12 @@ pref("security.sandbox.content.tempDirSuffix", "");
#if defined(MOZ_SANDBOX)
// This pref determines if messages relevant to sandbox violations are
// logged.
#if defined(XP_WIN)
pref("security.sandbox.logging.enabled", false);
#else
pref("security.sandbox.logging.enabled", true);
#endif
#endif
// This pref governs whether we attempt to work around problems caused by
// plugins using OS calls to manipulate the cursor while running out-of-

View File

@ -296,6 +296,7 @@ var FullScreen = {
this._fullScrToggler = document.getElementById("fullscr-toggler");
this._fullScrToggler.addEventListener("mouseover", this._expandCallback);
this._fullScrToggler.addEventListener("dragenter", this._expandCallback);
this._fullScrToggler.addEventListener("touchmove", this._expandCallback, {passive: true});
}
if (enterFS) {

View File

@ -92,24 +92,18 @@ var security = {
break;
}
// Select status text to display for Certificate Transparency.
// Select the status text to display for Certificate Transparency.
// Since we do not yet enforce the CT Policy on secure connections,
// we must not complain on policy discompliance (it might be viewed
// as a security issue by the user).
switch (status.certificateTransparencyStatus) {
case nsISSLStatus.CERTIFICATE_TRANSPARENCY_NOT_APPLICABLE:
// CT compliance checks were not performed,
// do not display any status text.
case nsISSLStatus.CERTIFICATE_TRANSPARENCY_POLICY_NOT_ENOUGH_SCTS:
case nsISSLStatus.CERTIFICATE_TRANSPARENCY_POLICY_NOT_DIVERSE_SCTS:
retval.certificateTransparency = null;
break;
case nsISSLStatus.CERTIFICATE_TRANSPARENCY_NONE:
retval.certificateTransparency = "None";
break;
case nsISSLStatus.CERTIFICATE_TRANSPARENCY_OK:
retval.certificateTransparency = "OK";
break;
case nsISSLStatus.CERTIFICATE_TRANSPARENCY_UNKNOWN_LOG:
retval.certificateTransparency = "UnknownLog";
break;
case nsISSLStatus.CERTIFICATE_TRANSPARENCY_INVALID:
retval.certificateTransparency = "Invalid";
case nsISSLStatus.CERTIFICATE_TRANSPARENCY_POLICY_COMPLIANT:
retval.certificateTransparency = "Compliant";
break;
}

View File

@ -27,6 +27,7 @@ function checkIdentityPopup(icon) {
}
add_task(function* () {
yield BrowserTestUtils.openNewForegroundTab(gBrowser);
// check that a warning is shown when loading a page with mixed content and an overridden certificate
yield loadBadCertPage(MIXED_CONTENT_URL);
@ -47,5 +48,7 @@ add_task(function* () {
let certOverrideService = Cc["@mozilla.org/security/certoverride;1"]
.getService(Ci.nsICertOverrideService);
certOverrideService.clearValidityOverride("self-signed.example.com", -1);
yield BrowserTestUtils.removeTab(gBrowser.selectedTab);
});

View File

@ -1015,16 +1015,9 @@ function* loadBadCertPage(url) {
"cert-exception-ui-ready", false);
});
// Sometimes clearing the cert override is not immediately picked up,
// so we reload until we are on an actual cert error page.
yield BrowserTestUtils.waitForCondition(function*() {
yield BrowserTestUtils.loadURI(gBrowser.selectedBrowser, url);
yield promiseErrorPageLoaded(gBrowser.selectedBrowser);
let isErrorPage = yield ContentTask.spawn(gBrowser.selectedBrowser, null, function*() {
return content.document.documentURI.startsWith("about:certerror");
});
return isErrorPage;
}, "Could not load error page", 1000);
let loaded = BrowserTestUtils.waitForErrorPage(gBrowser.selectedBrowser);
yield BrowserTestUtils.loadURI(gBrowser.selectedBrowser, url);
yield loaded;
yield ContentTask.spawn(gBrowser.selectedBrowser, null, function*() {
content.document.getElementById("exceptionDialogButton").click();

View File

@ -39,13 +39,14 @@ var gTests = [
info("request audio+video and check if there is no prompt");
yield promiseRequestDevice(true, true, null, null, win.gBrowser.selectedBrowser);
yield promiseObserverCalled("getUserMedia:request");
yield promiseNoPopupNotification("webRTC-shareDevices");
yield expectObserverCalled("getUserMedia:response:allow");
yield expectObserverCalled("recording-device-events");
let promises = [promiseNoPopupNotification("webRTC-shareDevices"),
promiseObserverCalled("getUserMedia:response:allow"),
promiseObserverCalled("recording-device-events")];
yield Promise.all(promises);
let promises = [promiseObserverCalled("recording-device-events"),
promiseObserverCalled("recording-device-events"),
promiseObserverCalled("recording-window-ended")];
promises = [promiseObserverCalled("recording-device-events"),
promiseObserverCalled("recording-device-events"),
promiseObserverCalled("recording-window-ended")];
yield BrowserTestUtils.closeWindow(win);
yield Promise.all(promises);

View File

@ -320,7 +320,7 @@ extensions.registerSchemaAPI("bookmarks", "addon_parent", context => {
onCreated: new SingletonEventManager(context, "bookmarks.onCreated", fire => {
let listener = (event, bookmark) => {
context.runSafe(fire, bookmark.id, bookmark);
fire.sync(bookmark.id, bookmark);
};
observer.on("created", listener);
@ -333,7 +333,7 @@ extensions.registerSchemaAPI("bookmarks", "addon_parent", context => {
onRemoved: new SingletonEventManager(context, "bookmarks.onRemoved", fire => {
let listener = (event, data) => {
context.runSafe(fire, data.guid, data.info);
fire.sync(data.guid, data.info);
};
observer.on("removed", listener);
@ -346,7 +346,7 @@ extensions.registerSchemaAPI("bookmarks", "addon_parent", context => {
onChanged: new SingletonEventManager(context, "bookmarks.onChanged", fire => {
let listener = (event, data) => {
context.runSafe(fire, data.guid, data.info);
fire.sync(data.guid, data.info);
};
observer.on("changed", listener);
@ -359,7 +359,7 @@ extensions.registerSchemaAPI("bookmarks", "addon_parent", context => {
onMoved: new SingletonEventManager(context, "bookmarks.onMoved", fire => {
let listener = (event, data) => {
context.runSafe(fire, data.guid, data.info);
fire.sync(data.guid, data.info);
};
observer.on("moved", listener);

View File

@ -18,7 +18,7 @@ Cu.import("resource://gre/modules/ExtensionUtils.jsm");
Cu.import("resource://gre/modules/Task.jsm");
var {
EventManager,
SingletonEventManager,
IconDetails,
} = ExtensionUtils;
@ -446,10 +446,10 @@ extensions.registerSchemaAPI("browserAction", "addon_parent", context => {
let {extension} = context;
return {
browserAction: {
onClicked: new EventManager(context, "browserAction.onClicked", fire => {
onClicked: new SingletonEventManager(context, "browserAction.onClicked", fire => {
let listener = () => {
let tab = TabManager.activeTab;
fire(TabManager.convert(extension, tab));
fire.async(TabManager.convert(extension, tab));
};
BrowserAction.for(extension).on("click", listener);
return () => {

View File

@ -5,7 +5,6 @@
Cu.import("resource://gre/modules/ExtensionUtils.jsm");
var {
runSafeSyncWithoutClone,
SingletonEventManager,
} = ExtensionUtils;
@ -14,7 +13,7 @@ extensions.registerSchemaAPI("omnibox", "addon_child", context => {
omnibox: {
onInputChanged: new SingletonEventManager(context, "omnibox.onInputChanged", fire => {
let listener = (text, id) => {
runSafeSyncWithoutClone(fire, text, suggestions => {
fire.asyncWithoutClone(text, suggestions => {
// TODO: Switch to using callParentFunctionNoReturn once bug 1314903 is fixed.
context.childManager.callParentAsyncFunction("omnibox_internal.addSuggestions", [
id,

View File

@ -6,7 +6,7 @@ Cu.import("resource://devtools/shared/event-emitter.js");
Cu.import("resource://gre/modules/ExtensionUtils.jsm");
var {
EventManager,
SingletonEventManager,
PlatformInfo,
} = ExtensionUtils;
@ -245,9 +245,9 @@ extensions.registerSchemaAPI("commands", "addon_parent", context => {
});
}));
},
onCommand: new EventManager(context, "commands.onCommand", fire => {
onCommand: new SingletonEventManager(context, "commands.onCommand", fire => {
let listener = (eventName, commandName) => {
fire(commandName);
fire.async(commandName);
};
commandsMap.get(extension).on("command", listener);
return () => {

View File

@ -8,9 +8,9 @@ Cu.import("resource://gre/modules/Services.jsm");
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
var {
EventManager,
ExtensionError,
IconDetails,
SingletonEventManager,
} = ExtensionUtils;
const ACTION_MENU_TOP_LEVEL_LIMIT = 6;
@ -625,9 +625,9 @@ extensions.registerSchemaAPI("contextMenus", "addon_parent", context => {
}
},
onClicked: new EventManager(context, "contextMenus.onClicked", fire => {
onClicked: new SingletonEventManager(context, "contextMenus.onClicked", fire => {
let listener = (event, info, tab) => {
fire(info, tab);
fire.async(info, tab);
};
extension.on("webext-contextmenu-menuitem-click", listener);

View File

@ -222,7 +222,7 @@ extensions.registerSchemaAPI("history", "addon_parent", context => {
onVisited: new SingletonEventManager(context, "history.onVisited", fire => {
let listener = (event, data) => {
context.runSafe(fire, data);
fire.sync(data);
};
getObserver().on("visited", listener);
@ -233,7 +233,7 @@ extensions.registerSchemaAPI("history", "addon_parent", context => {
onVisitRemoved: new SingletonEventManager(context, "history.onVisitRemoved", fire => {
let listener = (event, data) => {
context.runSafe(fire, data);
fire.sync(data);
};
getObserver().on("visitRemoved", listener);

View File

@ -50,7 +50,7 @@ extensions.registerSchemaAPI("omnibox", "addon_parent", context => {
onInputStarted: new SingletonEventManager(context, "omnibox.onInputStarted", fire => {
let listener = (eventName) => {
fire();
fire.sync();
};
extension.on(ExtensionSearchHandler.MSG_INPUT_STARTED, listener);
return () => {
@ -60,7 +60,7 @@ extensions.registerSchemaAPI("omnibox", "addon_parent", context => {
onInputCancelled: new SingletonEventManager(context, "omnibox.onInputCancelled", fire => {
let listener = (eventName) => {
fire();
fire.sync();
};
extension.on(ExtensionSearchHandler.MSG_INPUT_CANCELLED, listener);
return () => {
@ -70,7 +70,7 @@ extensions.registerSchemaAPI("omnibox", "addon_parent", context => {
onInputEntered: new SingletonEventManager(context, "omnibox.onInputEntered", fire => {
let listener = (eventName, text, disposition) => {
fire(text, disposition);
fire.sync(text, disposition);
};
extension.on(ExtensionSearchHandler.MSG_INPUT_ENTERED, listener);
return () => {
@ -92,7 +92,7 @@ extensions.registerSchemaAPI("omnibox", "addon_parent", context => {
onInputChanged: new SingletonEventManager(context, "omnibox_internal.onInputChanged", fire => {
let listener = (eventName, text, id) => {
fire(text, id);
fire.sync(text, id);
};
extension.on(ExtensionSearchHandler.MSG_INPUT_CHANGED, listener);
return () => {

View File

@ -5,7 +5,7 @@
Cu.import("resource://gre/modules/Task.jsm");
Cu.import("resource://gre/modules/ExtensionUtils.jsm");
var {
EventManager,
SingletonEventManager,
IconDetails,
} = ExtensionUtils;
@ -244,9 +244,9 @@ extensions.registerSchemaAPI("pageAction", "addon_parent", context => {
let {extension} = context;
return {
pageAction: {
onClicked: new EventManager(context, "pageAction.onClicked", fire => {
onClicked: new SingletonEventManager(context, "pageAction.onClicked", fire => {
let listener = (evt, tab) => {
fire(TabManager.convert(extension, tab));
fire.async(TabManager.convert(extension, tab));
};
let pageAction = PageAction.for(extension);

View File

@ -94,7 +94,7 @@ extensions.registerSchemaAPI("sessions", "addon_parent", context => {
onChanged: new SingletonEventManager(context, "sessions.onChanged", fire => {
let observer = () => {
context.runSafe(fire);
fire.async();
};
Services.obs.addObserver(observer, SS_ON_CLOSED_OBJECTS_CHANGED, false);

View File

@ -18,7 +18,7 @@ XPCOMUtils.defineLazyModuleGetter(this, "Services",
Cu.import("resource://gre/modules/ExtensionUtils.jsm");
var {
EventManager,
SingletonEventManager,
ignoreEvent,
} = ExtensionUtils;
@ -283,12 +283,12 @@ extensions.registerSchemaAPI("tabs", "addon_parent", context => {
let tab = event.originalTarget;
let tabId = TabManager.getId(tab);
let windowId = WindowManager.getId(tab.ownerGlobal);
fire({tabId, windowId});
fire.async({tabId, windowId});
}).api(),
onCreated: new EventManager(context, "tabs.onCreated", fire => {
onCreated: new SingletonEventManager(context, "tabs.onCreated", fire => {
let listener = (eventName, event) => {
fire(TabManager.convert(extension, event.tab));
fire.async(TabManager.convert(extension, event.tab));
};
tabListener.on("tab-created", listener);
@ -307,12 +307,12 @@ extensions.registerSchemaAPI("tabs", "addon_parent", context => {
let tab = event.originalTarget;
let tabIds = [TabManager.getId(tab)];
let windowId = WindowManager.getId(tab.ownerGlobal);
fire({tabIds, windowId});
fire.async({tabIds, windowId});
}).api(),
onAttached: new EventManager(context, "tabs.onAttached", fire => {
onAttached: new SingletonEventManager(context, "tabs.onAttached", fire => {
let listener = (eventName, event) => {
fire(event.tabId, {newWindowId: event.newWindowId, newPosition: event.newPosition});
fire.async(event.tabId, {newWindowId: event.newWindowId, newPosition: event.newPosition});
};
tabListener.on("tab-attached", listener);
@ -321,9 +321,9 @@ extensions.registerSchemaAPI("tabs", "addon_parent", context => {
};
}).api(),
onDetached: new EventManager(context, "tabs.onDetached", fire => {
onDetached: new SingletonEventManager(context, "tabs.onDetached", fire => {
let listener = (eventName, event) => {
fire(event.tabId, {oldWindowId: event.oldWindowId, oldPosition: event.oldPosition});
fire.async(event.tabId, {oldWindowId: event.oldWindowId, oldPosition: event.oldPosition});
};
tabListener.on("tab-detached", listener);
@ -332,9 +332,9 @@ extensions.registerSchemaAPI("tabs", "addon_parent", context => {
};
}).api(),
onRemoved: new EventManager(context, "tabs.onRemoved", fire => {
onRemoved: new SingletonEventManager(context, "tabs.onRemoved", fire => {
let listener = (eventName, event) => {
fire(event.tabId, {windowId: event.windowId, isWindowClosing: event.isWindowClosing});
fire.async(event.tabId, {windowId: event.windowId, isWindowClosing: event.isWindowClosing});
};
tabListener.on("tab-removed", listener);
@ -345,7 +345,7 @@ extensions.registerSchemaAPI("tabs", "addon_parent", context => {
onReplaced: ignoreEvent(context, "tabs.onReplaced"),
onMoved: new EventManager(context, "tabs.onMoved", fire => {
onMoved: new SingletonEventManager(context, "tabs.onMoved", fire => {
// There are certain circumstances where we need to ignore a move event.
//
// Namely, the first time the tab is moved after it's created, we need
@ -373,7 +373,7 @@ extensions.registerSchemaAPI("tabs", "addon_parent", context => {
return;
}
fire(TabManager.getId(tab), {
fire.async(TabManager.getId(tab), {
windowId: WindowManager.getId(tab.ownerGlobal),
fromIndex: event.detail,
toIndex: tab._tPos,
@ -388,7 +388,7 @@ extensions.registerSchemaAPI("tabs", "addon_parent", context => {
};
}).api(),
onUpdated: new EventManager(context, "tabs.onUpdated", fire => {
onUpdated: new SingletonEventManager(context, "tabs.onUpdated", fire => {
const restricted = ["url", "favIconUrl", "title"];
function sanitize(extension, changeInfo) {
@ -410,7 +410,7 @@ extensions.registerSchemaAPI("tabs", "addon_parent", context => {
let tabElem = gBrowser.getTabForBrowser(browser);
let tab = TabManager.convert(extension, tabElem);
fire(tab.id, changeInfo, tab);
fire.async(tab.id, changeInfo, tab);
}
};
@ -447,7 +447,7 @@ extensions.registerSchemaAPI("tabs", "addon_parent", context => {
for (let prop of needed) {
changeInfo[prop] = tab[prop];
}
fire(tab.id, changeInfo, tab);
fire.async(tab.id, changeInfo, tab);
}
};
let progressListener = {
@ -1025,7 +1025,7 @@ extensions.registerSchemaAPI("tabs", "addon_parent", context => {
return Promise.resolve();
},
onZoomChange: new EventManager(context, "tabs.onZoomChange", fire => {
onZoomChange: new SingletonEventManager(context, "tabs.onZoomChange", fire => {
let getZoomLevel = browser => {
let {ZoomManager} = browser.ownerGlobal;
@ -1075,7 +1075,7 @@ extensions.registerSchemaAPI("tabs", "addon_parent", context => {
zoomLevels.set(browser, newZoomFactor);
let tabId = TabManager.getId(tab);
fire({
fire.async({
tabId,
oldZoomFactor,
newZoomFactor,

View File

@ -28,8 +28,8 @@ const XUL_NS = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
var {
DefaultWeakMap,
EventManager,
promiseEvent,
SingletonEventManager,
} = ExtensionUtils;
// This file provides some useful code for the |tabs| and |windows|
@ -1281,16 +1281,16 @@ global.AllWindowEvents = {
AllWindowEvents.openListener = AllWindowEvents.openListener.bind(AllWindowEvents);
// Subclass of EventManager where we just need to call
// Subclass of SingletonEventManager where we just need to call
// add/removeEventListener on each XUL window.
global.WindowEventManager = function(context, name, event, listener) {
EventManager.call(this, context, name, fire => {
let listener2 = (...args) => listener(fire, ...args);
AllWindowEvents.addListener(event, listener2);
return () => {
AllWindowEvents.removeListener(event, listener2);
};
});
global.WindowEventManager = class extends SingletonEventManager {
constructor(context, name, event, listener) {
super(context, name, fire => {
let listener2 = (...args) => listener(fire, ...args);
AllWindowEvents.addListener(event, listener2);
return () => {
AllWindowEvents.removeListener(event, listener2);
};
});
}
};
WindowEventManager.prototype = Object.create(EventManager.prototype);

View File

@ -12,7 +12,7 @@ XPCOMUtils.defineLazyModuleGetter(this, "PrivateBrowsingUtils",
Cu.import("resource://gre/modules/ExtensionUtils.jsm");
var {
EventManager,
SingletonEventManager,
promiseObserved,
} = ExtensionUtils;
@ -26,15 +26,15 @@ extensions.registerSchemaAPI("windows", "addon_parent", context => {
windows: {
onCreated:
new WindowEventManager(context, "windows.onCreated", "domwindowopened", (fire, window) => {
fire(WindowManager.convert(extension, window));
fire.async(WindowManager.convert(extension, window));
}).api(),
onRemoved:
new WindowEventManager(context, "windows.onRemoved", "domwindowclosed", (fire, window) => {
fire(WindowManager.getId(window));
fire.async(WindowManager.getId(window));
}).api(),
onFocusChanged: new EventManager(context, "windows.onFocusChanged", fire => {
onFocusChanged: new SingletonEventManager(context, "windows.onFocusChanged", fire => {
// Keep track of the last windowId used to fire an onFocusChanged event
let lastOnFocusChangedWindowId;
@ -45,7 +45,7 @@ extensions.registerSchemaAPI("windows", "addon_parent", context => {
let window = Services.focus.activeWindow;
let windowId = window ? WindowManager.getId(window) : WindowManager.WINDOW_ID_NONE;
if (windowId !== lastOnFocusChangedWindowId) {
fire(windowId);
fire.async(windowId);
lastOnFocusChangedWindowId = windowId;
}
});

View File

@ -4,8 +4,11 @@ module.exports = { // eslint-disable-line no-undef
"extends": "../../.eslintrc.js",
"globals": {
"addMessageListener": false,
"Components": true,
"dump": true,
"removeMessageListener": false,
"sendAsyncMessage": false,
"TextDecoder": false,
"TextEncoder": false,
},

View File

@ -56,6 +56,7 @@ let FormAutofillParent = {
let mm = Cc["@mozilla.org/globalmessagemanager;1"]
.getService(Ci.nsIMessageListenerManager);
mm.addMessageListener("FormAutofill:PopulateFieldValues", this);
mm.addMessageListener("FormAutofill:GetProfiles", this);
},
/**
@ -70,6 +71,9 @@ let FormAutofillParent = {
case "FormAutofill:PopulateFieldValues":
this._populateFieldValues(data, target);
break;
case "FormAutofill:GetProfiles":
this._getProfiles(data, target);
break;
}
},
@ -98,6 +102,7 @@ let FormAutofillParent = {
let mm = Cc["@mozilla.org/globalmessagemanager;1"]
.getService(Ci.nsIMessageListenerManager);
mm.removeMessageListener("FormAutofill:PopulateFieldValues", this);
mm.removeMessageListener("FormAutofill:GetProfiles", this);
},
/**
@ -118,6 +123,29 @@ let FormAutofillParent = {
target.sendAsyncMessage("FormAutofill:fillForm", {fields});
},
/**
* Get the profile data from profile store and return profiles back to content process.
*
* @private
* @param {string} data.searchString
* The typed string for filtering out the matched profile.
* @param {string} data.info
* The input autocomplete property's information.
* @param {nsIFrameMessageManager} target
* Content's message manager.
*/
_getProfiles({searchString, info}, target) {
let profiles = [];
if (info && info.fieldName) {
profiles = this._profileStore.getByFilter({searchString, info});
} else {
profiles = this._profileStore.getAll();
}
target.messageManager.sendAsyncMessage("FormAutofill:Profiles", profiles);
},
/**
* Transforms a word with hyphen into camel case.
* (e.g. transforms "address-type" into "addressType".)

View File

@ -66,6 +66,20 @@ const VALID_FIELDS = [
"email",
];
// TODO: Remove this once we can add profile from preference.
const MOCK_MODE = false;
const MOCK_STORAGE = [{
guid: "test-guid-1",
organization: "Sesame Street",
streetAddress: "123 Sesame Street.",
tel: "1-345-345-3456",
}, {
guid: "test-guid-2",
organization: "Mozilla",
streetAddress: "331 E. Evelyn Avenue",
tel: "1-650-903-0800",
}];
function ProfileStorage(path) {
this._path = path;
}
@ -210,6 +224,19 @@ ProfileStorage.prototype = {
return this._store.data.profiles.map(this._clone);
},
/**
* Returns the filtered profiles based on input's information and searchString.
*
* @returns {Array.<Profile>}
* An array containing clones of matched profiles.
*/
getByFilter({info, searchString}) {
this._store.ensureDataReady();
// Profiles are cloned to avoid accidental modifications from outside.
return this._findByFilter({info, searchString}).map(this._clone);
},
_clone(profile) {
return Object.assign({}, profile);
},
@ -218,6 +245,23 @@ ProfileStorage.prototype = {
return this._store.data.profiles.find(profile => profile.guid == guid);
},
_findByFilter({info, searchString}) {
let profiles = MOCK_MODE ? MOCK_STORAGE : this._store.data.profiles;
let lcSearchString = searchString.toLowerCase();
return profiles.filter(profile => {
// Return true if string is not provided and field exists.
// TODO: We'll need to check if the address is for billing or shipping.
let name = profile[info.fieldName];
if (!searchString) {
return !!name;
}
return name.toLowerCase().startsWith(lcSearchString);
});
},
_normalizeProfile(profile) {
let result = {};
for (let key in profile) {

View File

@ -2,6 +2,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/. */
/* eslint-disable no-use-before-define */
/*
* Form Autofill frame script.
*/
@ -227,28 +229,74 @@ AutofillProfileAutoCompleteSearch.prototype = {
* @param {Object} listener the listener to notify when the search is complete
*/
startSearch(searchString, searchParam, previousResult, listener) {
// TODO: These mock data should be replaced by form autofill API
let fieldName = "name";
let profiles = [{
guid: "test-guid-1",
organization: "Sesame Street",
streetAddress: "123 Sesame Street.",
tel: "1-345-345-3456.",
}, {
guid: "test-guid-2",
organization: "Mozilla",
streetAddress: "331 E. Evelyn Avenue",
tel: "1-650-903-0800",
}];
let result = new ProfileAutoCompleteResult(searchString, fieldName, profiles, {});
this.forceStop = false;
let info = this.getInputDetails();
listener.onSearchResult(this, result);
this.getProfiles({info, searchString}).then((profiles) => {
if (this.forceStop) {
return;
}
// TODO: Set formInfo for ProfileAutoCompleteResult
// let formInfo = this.getFormDetails();
let result = new ProfileAutoCompleteResult(searchString, info, profiles, {});
listener.onSearchResult(this, result);
});
},
/**
* Stops an asynchronous search that is in progress
*/
stopSearch() {
this.forceStop = true;
},
/**
* Get the profile data from parent process for AutoComplete result.
*
* @private
* @param {Object} data
* Parameters for querying the corresponding result.
* @param {string} data.searchString
* The typed string for filtering out the matched profile.
* @param {string} data.info
* The input autocomplete property's information.
* @returns {Promise}
* Promise that resolves when profiles returned from parent process.
*/
getProfiles(data) {
return new Promise((resolve) => {
addMessageListener("FormAutofill:Profiles", function getResult(result) {
removeMessageListener("FormAutofill:Profiles", getResult);
resolve(result.data);
});
sendAsyncMessage("FormAutofill:GetProfiles", data);
});
},
/**
* Get the input's information from FormAutofillContent's cache.
*
* @returns {Object}
* Target input's information that cached in FormAutofillContent.
*/
getInputDetails() {
// TODO: Maybe we'll need to wait for cache ready if detail is empty.
return FormAutofillContent.getInputDetails(formFillController.getFocusedInput());
},
/**
* Get the form's information from FormAutofillContent's cache.
*
* @returns {Array<Object>}
* Array of the inputs' information for the target form.
*/
getFormDetails() {
// TODO: Maybe we'll need to wait for cache ready if details is empty.
return FormAutofillContent.getFormDetails(formFillController.getFocusedInput());
},
};
@ -307,11 +355,69 @@ var FormAutofillContent = {
}
},
/**
* Get the input's information from cache which is created after page identified.
*
* @param {HTMLInputElement} element Focused input which triggered profile searching
* @returns {Object|null}
* Return target input's information that cloned from content cache
* (or return null if the information is not found in the cache).
*/
getInputDetails(element) {
for (let formDetails of this._formsDetails) {
for (let detail of formDetails) {
if (element == detail.element) {
return this._serializeInfo(detail);
}
}
}
return null;
},
/**
* Get the form's information from cache which is created after page identified.
*
* @param {HTMLInputElement} element Focused input which triggered profile searching
* @returns {Array<Object>|null}
* Return target form's information that cloned from content cache
* (or return null if the information is not found in the cache).
*
*/
getFormDetails(element) {
for (let formDetails of this._formsDetails) {
if (formDetails.some((detail) => detail.element == element)) {
return formDetails.map((detail) => this._serializeInfo(detail));
}
}
return null;
},
/**
* Create a clone the information object without element reference.
*
* @param {Object} detail Profile autofill information for specific input.
* @returns {Object}
* Return a copy of cached information object without element reference
* since it's not needed for creating result.
*/
_serializeInfo(detail) {
let info = Object.assign({}, detail);
delete info.element;
return info;
},
_identifyAutofillFields(doc) {
let forms = [];
this._formsDetails = [];
// Collects root forms from inputs.
for (let field of doc.getElementsByTagName("input")) {
// We only consider text-like fields for now until we support radio and
// checkbox buttons in the future.
if (!field.mozIsTextField(true)) {
continue;
}
let formLike = FormLikeFactory.createFromField(field);
if (!forms.some(form => form.rootElement === formLike.rootElement)) {
forms.push(formLike);
@ -327,6 +433,7 @@ var FormAutofillContent = {
return;
}
this._formsDetails.push(formHandler.fieldDetails);
formHandler.fieldDetails.forEach(
detail => this._markAsAutofillField(detail.element));
});
@ -337,4 +444,5 @@ var FormAutofillContent = {
},
};
FormAutofillContent.init();

View File

@ -0,0 +1,90 @@
"use strict";
let {FormAutofillContent} = loadFormAutofillContent();
const TESTCASES = [
{
description: "Form containing 5 fields with autocomplete attribute.",
document: `<form>
<input id="street-addr" autocomplete="street-address">
<input id="city" autocomplete="address-level2">
<input id="country" autocomplete="country">
<input id="email" autocomplete="email">
<input id="tel" autocomplete="tel">
</form>`,
targetInput: ["street-addr", "country"],
expectedResult: [{
input: {"section": "", "addressType": "", "contactType": "", "fieldName": "street-address"},
form: [
{"section": "", "addressType": "", "contactType": "", "fieldName": "street-address"},
{"section": "", "addressType": "", "contactType": "", "fieldName": "address-level2"},
{"section": "", "addressType": "", "contactType": "", "fieldName": "country"},
{"section": "", "addressType": "", "contactType": "", "fieldName": "email"},
{"section": "", "addressType": "", "contactType": "", "fieldName": "tel"},
],
},
{
input: {"section": "", "addressType": "", "contactType": "", "fieldName": "country"},
form: [
{"section": "", "addressType": "", "contactType": "", "fieldName": "street-address"},
{"section": "", "addressType": "", "contactType": "", "fieldName": "address-level2"},
{"section": "", "addressType": "", "contactType": "", "fieldName": "country"},
{"section": "", "addressType": "", "contactType": "", "fieldName": "email"},
{"section": "", "addressType": "", "contactType": "", "fieldName": "tel"},
],
}],
},
{
description: "2 forms that are able to be auto filled",
document: `<form>
<input id="home-addr" autocomplete="street-address">
<input id="city" autocomplete="address-level2">
<input id="country" autocomplete="country">
</form>
<form>
<input id="office-addr" autocomplete="street-address">
<input id="email" autocomplete="email">
<input id="tel" autocomplete="tel">
</form>`,
targetInput: ["home-addr", "office-addr"],
expectedResult: [{
input: {"section": "", "addressType": "", "contactType": "", "fieldName": "street-address"},
form: [
{"section": "", "addressType": "", "contactType": "", "fieldName": "street-address"},
{"section": "", "addressType": "", "contactType": "", "fieldName": "address-level2"},
{"section": "", "addressType": "", "contactType": "", "fieldName": "country"},
],
},
{
input: {"section": "", "addressType": "", "contactType": "", "fieldName": "street-address"},
form: [
{"section": "", "addressType": "", "contactType": "", "fieldName": "street-address"},
{"section": "", "addressType": "", "contactType": "", "fieldName": "email"},
{"section": "", "addressType": "", "contactType": "", "fieldName": "tel"},
],
}],
},
];
TESTCASES.forEach(testcase => {
add_task(function* () {
do_print("Starting testcase: " + testcase.description);
let doc = MockDocument.createTestDocument(
"http://localhost:8080/test/", testcase.document);
FormAutofillContent._identifyAutofillFields(doc);
for (let i in testcase.targetInput) {
let input = doc.getElementById(testcase.targetInput[i]);
Assert.deepEqual(FormAutofillContent.getInputDetails(input),
testcase.expectedResult[i].input,
"Check if returned input information is correct.");
Assert.deepEqual(FormAutofillContent.getFormDetails(input),
testcase.expectedResult[i].form,
"Check if returned form information is correct.");
}
});
});

View File

@ -109,6 +109,38 @@ add_task(function* test_get() {
/No matching profile\./);
});
add_task(function* test_getByFilter() {
let path = getTempFile(TEST_STORE_FILE_NAME).path;
yield prepareTestProfiles(path);
let profileStorage = new ProfileStorage(path);
yield profileStorage.initialize();
let filter = {info: {fieldName: "streetAddress"}, searchString: "Some"};
let profiles = profileStorage.getByFilter(filter);
do_check_eq(profiles.length, 1);
do_check_profile_matches(profiles[0], TEST_PROFILE_2);
filter = {info: {fieldName: "country"}, searchString: "u"};
profiles = profileStorage.getByFilter(filter);
do_check_eq(profiles.length, 2);
do_check_profile_matches(profiles[0], TEST_PROFILE_1);
do_check_profile_matches(profiles[1], TEST_PROFILE_2);
filter = {info: {fieldName: "streetAddress"}, searchString: "test"};
profiles = profileStorage.getByFilter(filter);
do_check_eq(profiles.length, 0);
filter = {info: {fieldName: "streetAddress"}, searchString: ""};
profiles = profileStorage.getByFilter(filter);
do_check_eq(profiles.length, 2);
// Check if the filtering logic is free from searching special chars.
filter = {info: {fieldName: "streetAddress"}, searchString: ".*"};
profiles = profileStorage.getByFilter(filter);
do_check_eq(profiles.length, 0);
});
add_task(function* test_add() {
let path = getTempFile(TEST_STORE_FILE_NAME).path;
yield prepareTestProfiles(path);

View File

@ -5,6 +5,7 @@ support-files =
[test_autofillFormFields.js]
[test_collectFormFields.js]
[test_getFormInputDetails.js]
[test_markAsAutofillField.js]
[test_populateFieldValues.js]
[test_profileAutocompleteResult.js]

View File

@ -1,3 +1,3 @@
This is the pdf.js project output, https://github.com/mozilla/pdf.js
Current extension version is: 1.6.467
Current extension version is: 1.7.227

View File

@ -21,30 +21,14 @@ Components.utils.import('resource://gre/modules/Services.jsm');
var EXPORTED_SYMBOLS = ['NetworkManager'];
function log(aMsg) {
var msg = 'network.js: ' + (aMsg.join ? aMsg.join('') : aMsg);
var msg = 'PdfJsNetwork.jsm: ' + (aMsg.join ? aMsg.join('') : aMsg);
Services.console.logStringMessage(msg);
}
var NetworkManager = (function NetworkManagerClosure() {
var OK_RESPONSE = 200;
var PARTIAL_CONTENT_RESPONSE = 206;
function NetworkManager(url, args) {
this.url = url;
args = args || {};
this.isHttp = /^https?:/i.test(url);
this.httpHeaders = (this.isHttp && args.httpHeaders) || {};
this.withCredentials = args.withCredentials || false;
this.getXhr = args.getXhr ||
function NetworkManager_getXhr() {
return new XMLHttpRequest();
};
this.currXhrId = 0;
this.pendingRequests = Object.create(null);
this.loadedRequests = Object.create(null);
}
const OK_RESPONSE = 200;
const PARTIAL_CONTENT_RESPONSE = 206;
function getArrayBuffer(xhr) {
var data = xhr.response;
@ -59,27 +43,43 @@ var NetworkManager = (function NetworkManagerClosure() {
return array.buffer;
}
NetworkManager.prototype = {
requestRange: function NetworkManager_requestRange(begin, end, listeners) {
class NetworkManagerClass {
constructor(url, args) {
this.url = url;
args = args || {};
this.isHttp = /^https?:/i.test(url);
this.httpHeaders = (this.isHttp && args.httpHeaders) || {};
this.withCredentials = args.withCredentials || false;
this.getXhr = args.getXhr ||
function NetworkManager_getXhr() {
return new XMLHttpRequest();
};
this.currXhrId = 0;
this.pendingRequests = Object.create(null);
this.loadedRequests = Object.create(null);
}
requestRange(begin, end, listeners) {
var args = {
begin: begin,
end: end
begin,
end,
};
for (var prop in listeners) {
args[prop] = listeners[prop];
}
return this.request(args);
},
}
requestFull: function NetworkManager_requestFull(listeners) {
requestFull(listeners) {
return this.request(listeners);
},
}
request: function NetworkManager_request(args) {
request(args) {
var xhr = this.getXhr();
var xhrId = this.currXhrId++;
var pendingRequest = this.pendingRequests[xhrId] = {
xhr: xhr
xhr,
};
xhr.open('GET', this.url);
@ -124,9 +124,9 @@ var NetworkManager = (function NetworkManagerClosure() {
xhr.send(null);
return xhrId;
},
}
onProgress: function NetworkManager_onProgress(xhrId, evt) {
onProgress(xhrId, evt) {
var pendingRequest = this.pendingRequests[xhrId];
if (!pendingRequest) {
// Maybe abortRequest was called...
@ -142,9 +142,9 @@ var NetworkManager = (function NetworkManagerClosure() {
if (onProgress) {
onProgress(evt);
}
},
}
onStateChange: function NetworkManager_onStateChange(xhrId, evt) {
onStateChange(xhrId, evt) {
var pendingRequest = this.pendingRequests[xhrId];
if (!pendingRequest) {
// Maybe abortRequest was called...
@ -201,57 +201,57 @@ var NetworkManager = (function NetworkManagerClosure() {
var matches = /bytes (\d+)-(\d+)\/(\d+)/.exec(rangeHeader);
var begin = parseInt(matches[1], 10);
pendingRequest.onDone({
begin: begin,
chunk: chunk
begin,
chunk,
});
} else if (pendingRequest.onProgressiveData) {
pendingRequest.onDone(null);
} else if (chunk) {
pendingRequest.onDone({
begin: 0,
chunk: chunk
chunk,
});
} else if (pendingRequest.onError) {
pendingRequest.onError(xhr.status);
}
},
}
hasPendingRequests: function NetworkManager_hasPendingRequests() {
hasPendingRequests() {
for (var xhrId in this.pendingRequests) {
return true;
}
return false;
},
}
getRequestXhr: function NetworkManager_getXhr(xhrId) {
getRequestXhr(xhrId) {
return this.pendingRequests[xhrId].xhr;
},
}
isStreamingRequest: function NetworkManager_isStreamingRequest(xhrId) {
isStreamingRequest(xhrId) {
return !!(this.pendingRequests[xhrId].onProgressiveData);
},
}
isPendingRequest: function NetworkManager_isPendingRequest(xhrId) {
isPendingRequest(xhrId) {
return xhrId in this.pendingRequests;
},
}
isLoadedRequest: function NetworkManager_isLoadedRequest(xhrId) {
isLoadedRequest(xhrId) {
return xhrId in this.loadedRequests;
},
}
abortAllRequests: function NetworkManager_abortAllRequests() {
abortAllRequests() {
for (var xhrId in this.pendingRequests) {
this.abortRequest(xhrId | 0);
}
},
}
abortRequest: function NetworkManager_abortRequest(xhrId) {
abortRequest(xhrId) {
var xhr = this.pendingRequests[xhrId].xhr;
delete this.pendingRequests[xhrId];
xhr.abort();
}
};
}
return NetworkManager;
return NetworkManagerClass;
})();

View File

@ -23,47 +23,47 @@ const Cu = Components.utils;
Cu.import('resource://gre/modules/Services.jsm');
this.PdfJsTelemetry = {
onViewerIsUsed: function () {
onViewerIsUsed() {
let histogram = Services.telemetry.getHistogramById('PDF_VIEWER_USED');
histogram.add(true);
},
onFallback: function () {
onFallback() {
let histogram = Services.telemetry.getHistogramById('PDF_VIEWER_FALLBACK_SHOWN');
histogram.add(true);
},
onDocumentSize: function (size) {
onDocumentSize(size) {
let histogram = Services.telemetry.getHistogramById('PDF_VIEWER_DOCUMENT_SIZE_KB');
histogram.add(size / 1024);
},
onDocumentVersion: function (versionId) {
onDocumentVersion(versionId) {
let histogram = Services.telemetry.getHistogramById('PDF_VIEWER_DOCUMENT_VERSION');
histogram.add(versionId);
},
onDocumentGenerator: function (generatorId) {
onDocumentGenerator(generatorId) {
let histogram = Services.telemetry.getHistogramById('PDF_VIEWER_DOCUMENT_GENERATOR');
histogram.add(generatorId);
},
onEmbed: function (isObject) {
onEmbed(isObject) {
let histogram = Services.telemetry.getHistogramById('PDF_VIEWER_EMBED');
histogram.add(isObject);
},
onFontType: function (fontTypeId) {
onFontType(fontTypeId) {
let histogram = Services.telemetry.getHistogramById('PDF_VIEWER_FONT_TYPES');
histogram.add(fontTypeId);
},
onForm: function (isAcroform) {
onForm(isAcroform) {
let histogram = Services.telemetry.getHistogramById('PDF_VIEWER_FORM');
histogram.add(isAcroform);
},
onPrint: function () {
onPrint() {
let histogram = Services.telemetry.getHistogramById('PDF_VIEWER_PRINT');
histogram.add(true);
},
onStreamType: function (streamTypeId) {
onStreamType(streamTypeId) {
let histogram = Services.telemetry.getHistogramById('PDF_VIEWER_STREAM_TYPES');
histogram.add(streamTypeId);
},
onTimeToView: function (ms) {
onTimeToView(ms) {
let histogram = Services.telemetry.getHistogramById('PDF_VIEWER_TIME_TO_VIEW_MS');
histogram.add(ms);
}

View File

@ -190,7 +190,7 @@ PdfDataListener.prototype = {
this.oncompleteCallback(null, errorCode);
}
},
onprogress: function() {},
onprogress() {},
get oncomplete() {
return this.oncompleteCallback;
},
@ -205,24 +205,27 @@ PdfDataListener.prototype = {
}
};
// All the priviledged actions.
function ChromeActions(domWindow, contentDispositionFilename) {
this.domWindow = domWindow;
this.contentDispositionFilename = contentDispositionFilename;
this.telemetryState = {
documentInfo: false,
firstPageInfo: false,
streamTypesUsed: [],
fontTypesUsed: [],
startAt: Date.now()
};
}
/**
* All the privileged actions.
*/
class ChromeActions {
constructor(domWindow, contentDispositionFilename) {
this.domWindow = domWindow;
this.contentDispositionFilename = contentDispositionFilename;
this.telemetryState = {
documentInfo: false,
firstPageInfo: false,
streamTypesUsed: [],
fontTypesUsed: [],
startAt: Date.now()
};
}
ChromeActions.prototype = {
isInPrivateBrowsing: function() {
isInPrivateBrowsing() {
return PrivateBrowsingUtils.isContentWindowPrivate(this.domWindow);
},
download: function(data, sendResponse) {
}
download(data, sendResponse) {
var self = this;
var originalUrl = data.originalUrl;
var blobUrl = data.blobUrl || originalUrl;
@ -279,7 +282,7 @@ ChromeActions.prototype = {
var listener = {
extListener: null,
onStartRequest: function(aRequest, aContext) {
onStartRequest(aRequest, aContext) {
var loadContext = self.domWindow
.QueryInterface(Ci.nsIInterfaceRequestor)
.getInterface(Ci.nsIWebNavigation)
@ -290,7 +293,7 @@ ChromeActions.prototype = {
aRequest, loadContext, false);
this.extListener.onStartRequest(aRequest, aContext);
},
onStopRequest: function(aRequest, aContext, aStatusCode) {
onStopRequest(aRequest, aContext, aStatusCode) {
if (this.extListener) {
this.extListener.onStopRequest(aRequest, aContext, aStatusCode);
}
@ -299,20 +302,21 @@ ChromeActions.prototype = {
sendResponse(false);
}
},
onDataAvailable: function(aRequest, aContext, aInputStream, aOffset,
aCount) {
this.extListener.onDataAvailable(aRequest, aContext, aInputStream,
onDataAvailable(aRequest, aContext, aDataInputStream, aOffset, aCount) {
this.extListener.onDataAvailable(aRequest, aContext, aDataInputStream,
aOffset, aCount);
}
};
channel.asyncOpen2(listener);
});
},
getLocale: function() {
}
getLocale() {
return getStringPref('general.useragent.locale', 'en-US');
},
getStrings: function(data) {
}
getStrings(data) {
try {
// Lazy initialization of localizedStrings
if (!('localizedStrings' in this)) {
@ -324,8 +328,9 @@ ChromeActions.prototype = {
log('Unable to retrieve localized strings: ' + e);
return 'null';
}
},
supportsIntegratedFind: function() {
}
supportsIntegratedFind() {
// Integrated find is only supported when we're not in a frame
if (this.domWindow.frameElement !== null) {
return false;
@ -339,22 +344,26 @@ ChromeActions.prototype = {
// ... or when the new find events code exists.
var findBar = getFindBar(this.domWindow);
return !!findBar && ('updateControlState' in findBar);
},
supportsDocumentFonts: function() {
}
supportsDocumentFonts() {
var prefBrowser = getIntPref('browser.display.use_document_fonts', 1);
var prefGfx = getBoolPref('gfx.downloadable_fonts.enabled', true);
return (!!prefBrowser && prefGfx);
},
supportsDocumentColors: function() {
}
supportsDocumentColors() {
return getIntPref('browser.display.document_color_use', 0) !== 2;
},
supportedMouseWheelZoomModifierKeys: function() {
}
supportedMouseWheelZoomModifierKeys() {
return {
ctrlKey: getIntPref('mousewheel.with_control.action', 3) === 3,
metaKey: getIntPref('mousewheel.with_meta.action', 1) === 3,
};
},
reportTelemetry: function (data) {
}
reportTelemetry(data) {
var probeInfo = JSON.parse(data);
switch (probeInfo.type) {
case 'documentInfo':
@ -409,12 +418,15 @@ ChromeActions.prototype = {
PdfJsTelemetry.onPrint();
break;
}
},
fallback: function(args, sendResponse) {
var featureId = args.featureId;
var url = args.url;
}
/**
* @param {Object} args - Object with `featureId` and `url` properties.
* @param {function} sendResponse - Callback function.
*/
fallback(args, sendResponse) {
var featureId = args.featureId;
var self = this;
var domWindow = this.domWindow;
var strings = getLocalizedStrings('chrome.properties');
var message;
@ -441,8 +453,9 @@ ChromeActions.prototype = {
winmm.removeMessageListener('PDFJS:Child:fallbackDownload',
fallbackDownload);
});
},
updateFindControlState: function(data) {
}
updateFindControlState(data) {
if (!this.supportsIntegratedFind()) {
return;
}
@ -461,8 +474,9 @@ ChromeActions.prototype = {
.getInterface(Ci.nsIContentFrameMessageManager);
winmm.sendAsyncMessage('PDFJS:Parent:updateControlState', data);
},
setPreferences: function(prefs, sendResponse) {
}
setPreferences(prefs, sendResponse) {
var defaultBranch = Services.prefs.getDefaultBranch(PREF_PREFIX + '.');
var numberOfPrefs = 0;
var prefValue, prefName;
@ -496,8 +510,9 @@ ChromeActions.prototype = {
if (sendResponse) {
sendResponse(true);
}
},
getPreferences: function(prefs, sendResponse) {
}
getPreferences(prefs, sendResponse) {
var defaultBranch = Services.prefs.getDefaultBranch(PREF_PREFIX + '.');
var currentPrefs = {}, numberOfPrefs = 0;
var prefValue, prefName;
@ -529,17 +544,16 @@ ChromeActions.prototype = {
return JSON.stringify(currentPrefs);
}
}
};
}
var RangedChromeActions = (function RangedChromeActionsClosure() {
/**
* This is for range requests
*/
function RangedChromeActions(
domWindow, contentDispositionFilename, originalRequest,
/**
* This is for range requests.
*/
class RangedChromeActions extends ChromeActions {
constructor(domWindow, contentDispositionFilename, originalRequest,
rangeEnabled, streamingEnabled, dataListener) {
ChromeActions.call(this, domWindow, contentDispositionFilename);
super(domWindow, contentDispositionFilename);
this.dataListener = dataListener;
this.originalRequest = originalRequest;
this.rangeEnabled = rangeEnabled;
@ -551,7 +565,7 @@ var RangedChromeActions = (function RangedChromeActionsClosure() {
// Pass all the headers from the original request through
var httpHeaderVisitor = {
headers: {},
visitHeader: function(aHeader, aValue) {
visitHeader(aHeader, aValue) {
if (aHeader === 'Range') {
// When loading the PDF from cache, firefox seems to set the Range
// request header to fetch only the unfetched portions of the file
@ -587,7 +601,7 @@ var RangedChromeActions = (function RangedChromeActionsClosure() {
this.networkManager = new NetworkManager(this.pdfUrl, {
httpHeaders: httpHeaderVisitor.headers,
getXhr: getXhr
getXhr,
});
// If we are in range request mode, this means we manually issued xhr
@ -598,12 +612,7 @@ var RangedChromeActions = (function RangedChromeActionsClosure() {
});
}
RangedChromeActions.prototype = Object.create(ChromeActions.prototype);
var proto = RangedChromeActions.prototype;
proto.constructor = RangedChromeActions;
proto.initPassiveLoading = function RangedChromeActions_initPassiveLoading() {
var self = this;
initPassiveLoading() {
var data;
if (!this.streamingEnabled) {
this.originalRequest.cancel(Cr.NS_BINDING_ABORTED);
@ -613,16 +622,16 @@ var RangedChromeActions = (function RangedChromeActionsClosure() {
} else {
data = this.dataListener.readData();
this.dataListener.onprogress = function (loaded, total) {
self.domWindow.postMessage({
this.dataListener.onprogress = (loaded, total) => {
this.domWindow.postMessage({
pdfjsLoadAction: 'progressiveRead',
loaded: loaded,
total: total,
chunk: self.dataListener.readData()
loaded,
total,
chunk: this.dataListener.readData(),
}, '*');
};
this.dataListener.oncomplete = function () {
self.dataListener = null;
this.dataListener.oncomplete = () => {
this.dataListener = null;
};
}
@ -632,13 +641,13 @@ var RangedChromeActions = (function RangedChromeActionsClosure() {
streamingEnabled: this.streamingEnabled,
pdfUrl: this.pdfUrl,
length: this.contentLength,
data: data
data,
}, '*');
return true;
};
}
proto.requestDataRange = function RangedChromeActions_requestDataRange(args) {
requestDataRange(args) {
if (!this.rangeEnabled) {
return;
}
@ -650,11 +659,11 @@ var RangedChromeActions = (function RangedChromeActionsClosure() {
// errors from chrome code for non-range requests, so this doesn't
// seem high-pri
this.networkManager.requestRange(begin, end, {
onDone: function RangedChromeActions_onDone(args) {
onDone: function RangedChromeActions_onDone(aArgs) {
domWindow.postMessage({
pdfjsLoadAction: 'range',
begin: args.begin,
chunk: args.chunk
begin: aArgs.begin,
chunk: aArgs.chunk,
}, '*');
},
onProgress: function RangedChromeActions_onProgress(evt) {
@ -664,162 +673,155 @@ var RangedChromeActions = (function RangedChromeActionsClosure() {
}, '*');
}
});
};
}
proto.abortLoading = function RangedChromeActions_abortLoading() {
abortLoading() {
this.networkManager.abortAllRequests();
if (this.originalRequest) {
this.originalRequest.cancel(Cr.NS_BINDING_ABORTED);
this.originalRequest = null;
}
this.dataListener = null;
};
}
}
return RangedChromeActions;
})();
var StandardChromeActions = (function StandardChromeActionsClosure() {
/**
* This is for a single network stream
*/
function StandardChromeActions(domWindow, contentDispositionFilename,
originalRequest, dataListener) {
ChromeActions.call(this, domWindow, contentDispositionFilename);
/**
* This is for a single network stream.
*/
class StandardChromeActions extends ChromeActions {
constructor(domWindow, contentDispositionFilename, originalRequest,
dataListener) {
super(domWindow, contentDispositionFilename);
this.originalRequest = originalRequest;
this.dataListener = dataListener;
}
StandardChromeActions.prototype = Object.create(ChromeActions.prototype);
var proto = StandardChromeActions.prototype;
proto.constructor = StandardChromeActions;
proto.initPassiveLoading =
function StandardChromeActions_initPassiveLoading() {
initPassiveLoading() {
if (!this.dataListener) {
return false;
}
var self = this;
this.dataListener.onprogress = function ChromeActions_dataListenerProgress(
loaded, total) {
self.domWindow.postMessage({
this.dataListener.onprogress = (loaded, total) => {
this.domWindow.postMessage({
pdfjsLoadAction: 'progress',
loaded: loaded,
total: total
loaded,
total,
}, '*');
};
this.dataListener.oncomplete =
function StandardChromeActions_dataListenerComplete(data, errorCode) {
self.domWindow.postMessage({
this.dataListener.oncomplete = (data, errorCode) => {
this.domWindow.postMessage({
pdfjsLoadAction: 'complete',
data: data,
errorCode: errorCode
data,
errorCode,
}, '*');
self.dataListener = null;
self.originalRequest = null;
this.dataListener = null;
this.originalRequest = null;
};
return true;
};
}
proto.abortLoading = function StandardChromeActions_abortLoading() {
abortLoading() {
if (this.originalRequest) {
this.originalRequest.cancel(Cr.NS_BINDING_ABORTED);
this.originalRequest = null;
}
this.dataListener = null;
};
return StandardChromeActions;
})();
// Event listener to trigger chrome privileged code.
function RequestListener(actions) {
this.actions = actions;
}
// Receive an event and synchronously or asynchronously responds.
RequestListener.prototype.receive = function(event) {
var message = event.target;
var doc = message.ownerDocument;
var action = event.detail.action;
var data = event.detail.data;
var sync = event.detail.sync;
var actions = this.actions;
if (!(action in actions)) {
log('Unknown action: ' + action);
return;
}
var response;
if (sync) {
response = actions[action].call(this.actions, data);
event.detail.response = Cu.cloneInto(response, doc.defaultView);
} else {
if (!event.detail.responseExpected) {
doc.documentElement.removeChild(message);
response = null;
} else {
response = function sendResponse(response) {
try {
var listener = doc.createEvent('CustomEvent');
let detail = Cu.cloneInto({ response: response }, doc.defaultView);
listener.initCustomEvent('pdf.js.response', true, false, detail);
return message.dispatchEvent(listener);
} catch (e) {
// doc is no longer accessible because the requestor is already
// gone. unloaded content cannot receive the response anyway.
return false;
}
};
}
/**
* Event listener to trigger chrome privileged code.
*/
class RequestListener {
constructor(actions) {
this.actions = actions;
}
// Receive an event and synchronously or asynchronously responds.
receive(event) {
var message = event.target;
var doc = message.ownerDocument;
var action = event.detail.action;
var data = event.detail.data;
var sync = event.detail.sync;
var actions = this.actions;
if (!(action in actions)) {
log('Unknown action: ' + action);
return;
}
var response;
if (sync) {
response = actions[action].call(this.actions, data);
event.detail.response = Cu.cloneInto(response, doc.defaultView);
} else {
if (!event.detail.responseExpected) {
doc.documentElement.removeChild(message);
response = null;
} else {
response = function sendResponse(aResponse) {
try {
var listener = doc.createEvent('CustomEvent');
let detail = Cu.cloneInto({ response: aResponse }, doc.defaultView);
listener.initCustomEvent('pdf.js.response', true, false, detail);
return message.dispatchEvent(listener);
} catch (e) {
// doc is no longer accessible because the requestor is already
// gone. unloaded content cannot receive the response anyway.
return false;
}
};
}
actions[action].call(this.actions, data, response);
}
actions[action].call(this.actions, data, response);
}
};
// Forwards events from the eventElement to the contentWindow only if the
// content window matches the currently selected browser window.
function FindEventManager(contentWindow) {
this.contentWindow = contentWindow;
this.winmm = contentWindow.QueryInterface(Ci.nsIInterfaceRequestor)
.getInterface(Ci.nsIDocShell)
.QueryInterface(Ci.nsIInterfaceRequestor)
.getInterface(Ci.nsIContentFrameMessageManager);
}
FindEventManager.prototype.bind = function() {
var unload = function(e) {
this.unbind();
this.contentWindow.removeEventListener(e.type, unload);
}.bind(this);
this.contentWindow.addEventListener('unload', unload);
/**
* Forwards events from the eventElement to the contentWindow only if the
* content window matches the currently selected browser window.
*/
class FindEventManager {
constructor(contentWindow) {
this.contentWindow = contentWindow;
this.winmm = contentWindow.QueryInterface(Ci.nsIInterfaceRequestor)
.getInterface(Ci.nsIDocShell)
.QueryInterface(Ci.nsIInterfaceRequestor)
.getInterface(Ci.nsIContentFrameMessageManager);
}
// We cannot directly attach listeners to for the find events
// since the FindBar is in the parent process. Instead we're
// asking the PdfjsChromeUtils to do it for us and forward
// all the find events to us.
this.winmm.sendAsyncMessage('PDFJS:Parent:addEventListener');
this.winmm.addMessageListener('PDFJS:Child:handleEvent', this);
};
bind() {
var unload = function(e) {
this.unbind();
this.contentWindow.removeEventListener(e.type, unload);
}.bind(this);
this.contentWindow.addEventListener('unload', unload);
FindEventManager.prototype.receiveMessage = function(msg) {
var detail = msg.data.detail;
var type = msg.data.type;
var contentWindow = this.contentWindow;
// We cannot directly attach listeners to for the find events
// since the FindBar is in the parent process. Instead we're
// asking the PdfjsChromeUtils to do it for us and forward
// all the find events to us.
this.winmm.sendAsyncMessage('PDFJS:Parent:addEventListener');
this.winmm.addMessageListener('PDFJS:Child:handleEvent', this);
}
detail = Cu.cloneInto(detail, contentWindow);
var forward = contentWindow.document.createEvent('CustomEvent');
forward.initCustomEvent(type, true, true, detail);
contentWindow.dispatchEvent(forward);
};
receiveMessage(msg) {
var detail = msg.data.detail;
var type = msg.data.type;
var contentWindow = this.contentWindow;
FindEventManager.prototype.unbind = function() {
this.winmm.sendAsyncMessage('PDFJS:Parent:removeEventListener');
};
detail = Cu.cloneInto(detail, contentWindow);
var forward = contentWindow.document.createEvent('CustomEvent');
forward.initCustomEvent(type, true, true, detail);
contentWindow.dispatchEvent(forward);
}
unbind() {
this.winmm.sendAsyncMessage('PDFJS:Parent:removeEventListener');
}
}
function PdfStreamConverter() {
}
@ -858,18 +860,18 @@ PdfStreamConverter.prototype = {
*/
// nsIStreamConverter::convert
convert: function(aFromStream, aFromType, aToType, aCtxt) {
convert(aFromStream, aFromType, aToType, aCtxt) {
throw Cr.NS_ERROR_NOT_IMPLEMENTED;
},
// nsIStreamConverter::asyncConvertData
asyncConvertData: function(aFromType, aToType, aListener, aCtxt) {
asyncConvertData(aFromType, aToType, aListener, aCtxt) {
// Store the listener passed to us
this.listener = aListener;
},
// nsIStreamListener::onDataAvailable
onDataAvailable: function(aRequest, aContext, aInputStream, aOffset, aCount) {
onDataAvailable(aRequest, aContext, aInputStream, aOffset, aCount) {
if (!this.dataListener) {
return;
}
@ -881,7 +883,7 @@ PdfStreamConverter.prototype = {
},
// nsIRequestObserver::onStartRequest
onStartRequest: function(aRequest, aContext) {
onStartRequest(aRequest, aContext) {
// Setup the request so we can use it below.
var isHttpRequest = false;
try {
@ -960,14 +962,14 @@ PdfStreamConverter.prototype = {
// request(aRequest) below so we don't overwrite the original channel and
// trigger an assertion.
var proxy = {
onStartRequest: function(request, context) {
onStartRequest(request, context) {
listener.onStartRequest(aRequest, aContext);
},
onDataAvailable: function(request, context, inputStream, offset, count) {
onDataAvailable(request, context, inputStream, offset, count) {
listener.onDataAvailable(aRequest, aContext, inputStream,
offset, count);
},
onStopRequest: function(request, context, statusCode) {
onStopRequest(request, context, statusCode) {
// We get the DOM window here instead of before the request since it
// may have changed during a redirect.
var domWindow = getDOMWindow(channel);
@ -1017,7 +1019,7 @@ PdfStreamConverter.prototype = {
},
// nsIRequestObserver::onStopRequest
onStopRequest: function(aRequest, aContext, aStatusCode) {
onStopRequest(aRequest, aContext, aStatusCode) {
if (!this.dataListener) {
// Do nothing
return;

View File

@ -67,7 +67,7 @@ var PdfjsChromeUtils = {
* Public API
*/
init: function () {
init() {
this._browsers = new WeakSet();
if (!this._ppmm) {
// global parent process message manager (PPMM)
@ -94,7 +94,7 @@ var PdfjsChromeUtils = {
}
},
uninit: function () {
uninit() {
if (this._ppmm) {
this._ppmm.removeMessageListener('PDFJS:Parent:clearUserPref', this);
this._ppmm.removeMessageListener('PDFJS:Parent:setIntPref', this);
@ -123,7 +123,7 @@ var PdfjsChromeUtils = {
* instruct the child to refresh its configuration and (possibly)
* the module's registration.
*/
notifyChildOfSettingsChange: function () {
notifyChildOfSettingsChange() {
if (Services.appinfo.processType ===
Services.appinfo.PROCESS_TYPE_DEFAULT && this._ppmm) {
// XXX kinda bad, we want to get the parent process mm associated
@ -139,13 +139,13 @@ var PdfjsChromeUtils = {
* Events
*/
observe: function(aSubject, aTopic, aData) {
observe(aSubject, aTopic, aData) {
if (aTopic === 'quit-application') {
this.uninit();
}
},
receiveMessage: function (aMsg) {
receiveMessage(aMsg) {
switch (aMsg.name) {
case 'PDFJS:Parent:clearUserPref':
this._clearUserPref(aMsg.data.name);
@ -182,20 +182,20 @@ var PdfjsChromeUtils = {
* Internal
*/
_findbarFromMessage: function(aMsg) {
_findbarFromMessage(aMsg) {
let browser = aMsg.target;
let tabbrowser = browser.getTabBrowser();
let tab = tabbrowser.getTabForBrowser(browser);
return tabbrowser.getFindBar(tab);
},
_updateControlState: function (aMsg) {
_updateControlState(aMsg) {
let data = aMsg.data;
this._findbarFromMessage(aMsg)
.updateControlState(data.result, data.findPrevious);
},
handleEvent: function(aEvent) {
handleEvent(aEvent) {
// To avoid forwarding the message as a CPOW, create a structured cloneable
// version of the event for both performance, and ease of usage, reasons.
let type = aEvent.type;
@ -213,8 +213,7 @@ var PdfjsChromeUtils = {
}
// Only forward the events if the current browser is a registered browser.
let mm = browser.messageManager;
mm.sendAsyncMessage('PDFJS:Child:handleEvent',
{ type: type, detail: detail });
mm.sendAsyncMessage('PDFJS:Child:handleEvent', { type, detail, });
aEvent.preventDefault();
},
@ -223,7 +222,7 @@ var PdfjsChromeUtils = {
'findhighlightallchange',
'findcasesensitivitychange'],
_addEventListener: function (aMsg) {
_addEventListener(aMsg) {
let browser = aMsg.target;
if (this._browsers.has(browser)) {
throw new Error('FindEventManager was bound 2nd time ' +
@ -242,7 +241,7 @@ var PdfjsChromeUtils = {
}
},
_removeEventListener: function (aMsg) {
_removeEventListener(aMsg) {
let browser = aMsg.target;
if (!this._browsers.has(browser)) {
throw new Error('FindEventManager was unbound without binding it first.');
@ -258,7 +257,7 @@ var PdfjsChromeUtils = {
}
},
_ensurePreferenceAllowed: function (aPrefName) {
_ensurePreferenceAllowed(aPrefName) {
let unPrefixedName = aPrefName.split(PREF_PREFIX + '.');
if (unPrefixedName[0] !== '' ||
this._allowedPrefNames.indexOf(unPrefixedName[1]) === -1) {
@ -268,27 +267,27 @@ var PdfjsChromeUtils = {
}
},
_clearUserPref: function (aPrefName) {
_clearUserPref(aPrefName) {
this._ensurePreferenceAllowed(aPrefName);
Services.prefs.clearUserPref(aPrefName);
},
_setIntPref: function (aPrefName, aPrefValue) {
_setIntPref(aPrefName, aPrefValue) {
this._ensurePreferenceAllowed(aPrefName);
Services.prefs.setIntPref(aPrefName, aPrefValue);
},
_setBoolPref: function (aPrefName, aPrefValue) {
_setBoolPref(aPrefName, aPrefValue) {
this._ensurePreferenceAllowed(aPrefName);
Services.prefs.setBoolPref(aPrefName, aPrefValue);
},
_setCharPref: function (aPrefName, aPrefValue) {
_setCharPref(aPrefName, aPrefValue) {
this._ensurePreferenceAllowed(aPrefName);
Services.prefs.setCharPref(aPrefName, aPrefValue);
},
_setStringPref: function (aPrefName, aPrefValue) {
_setStringPref(aPrefName, aPrefValue) {
this._ensurePreferenceAllowed(aPrefName);
let str = Cc['@mozilla.org/supports-string;1']
.createInstance(Ci.nsISupportsString);
@ -301,7 +300,7 @@ var PdfjsChromeUtils = {
* we bounce this pdfjs enabled configuration check over to the
* parent.
*/
isDefaultHandlerApp: function () {
isDefaultHandlerApp() {
var handlerInfo = Svc.mime.getFromTypeAndExtension(PDF_CONTENT_TYPE, 'pdf');
return (!handlerInfo.alwaysAskBeforeHandling &&
handlerInfo.preferredAction === Ci.nsIHandlerInfo.handleInternally);
@ -311,7 +310,7 @@ var PdfjsChromeUtils = {
* Display a notification warning when the renderer isn't sure
* a pdf displayed correctly.
*/
_displayWarning: function (aMsg) {
_displayWarning(aMsg) {
let data = aMsg.data;
let browser = aMsg.target;
@ -324,13 +323,12 @@ var PdfjsChromeUtils = {
let messageSent = false;
function sendMessage(download) {
let mm = browser.messageManager;
mm.sendAsyncMessage('PDFJS:Child:fallbackDownload',
{ download: download });
mm.sendAsyncMessage('PDFJS:Child:fallbackDownload', { download, });
}
let buttons = [{
label: data.label,
accessKey: data.accessKey,
callback: function() {
callback() {
messageSent = true;
sendMessage(true);
}

View File

@ -38,7 +38,7 @@ var PdfjsContentUtils = {
Services.appinfo.PROCESS_TYPE_CONTENT);
},
init: function () {
init() {
// child *process* mm, or when loaded into the parent for in-content
// support the psuedo child process mm 'child PPMM'.
if (!this._mm) {
@ -49,7 +49,7 @@ var PdfjsContentUtils = {
}
},
uninit: function () {
uninit() {
if (this._mm) {
this._mm.removeMessageListener('PDFJS:Child:refreshSettings', this);
Services.obs.removeObserver(this, 'quit-application');
@ -63,34 +63,34 @@ var PdfjsContentUtils = {
* approved pdfjs prefs in chrome utils.
*/
clearUserPref: function (aPrefName) {
clearUserPref(aPrefName) {
this._mm.sendSyncMessage('PDFJS:Parent:clearUserPref', {
name: aPrefName
});
},
setIntPref: function (aPrefName, aPrefValue) {
setIntPref(aPrefName, aPrefValue) {
this._mm.sendSyncMessage('PDFJS:Parent:setIntPref', {
name: aPrefName,
value: aPrefValue
});
},
setBoolPref: function (aPrefName, aPrefValue) {
setBoolPref(aPrefName, aPrefValue) {
this._mm.sendSyncMessage('PDFJS:Parent:setBoolPref', {
name: aPrefName,
value: aPrefValue
});
},
setCharPref: function (aPrefName, aPrefValue) {
setCharPref(aPrefName, aPrefValue) {
this._mm.sendSyncMessage('PDFJS:Parent:setCharPref', {
name: aPrefName,
value: aPrefValue
});
},
setStringPref: function (aPrefName, aPrefValue) {
setStringPref(aPrefName, aPrefValue) {
this._mm.sendSyncMessage('PDFJS:Parent:setStringPref', {
name: aPrefName,
value: aPrefValue
@ -101,7 +101,7 @@ var PdfjsContentUtils = {
* Forwards default app query to the parent where we check various
* handler app settings only available in the parent process.
*/
isDefaultHandlerApp: function () {
isDefaultHandlerApp() {
return this._mm.sendSyncMessage('PDFJS:Parent:isDefaultHandlerApp')[0];
},
@ -109,7 +109,7 @@ var PdfjsContentUtils = {
* Request the display of a notification warning in the associated window
* when the renderer isn't sure a pdf displayed correctly.
*/
displayWarning: function (aWindow, aMessage, aLabel, accessKey) {
displayWarning(aWindow, aMessage, aLabel, aAccessKey) {
// the child's dom frame mm associated with the window.
let winmm = aWindow.QueryInterface(Ci.nsIInterfaceRequestor)
.getInterface(Ci.nsIDocShell)
@ -118,7 +118,7 @@ var PdfjsContentUtils = {
winmm.sendAsyncMessage('PDFJS:Parent:displayWarning', {
message: aMessage,
label: aLabel,
accessKey: accessKey
accessKey: aAccessKey,
});
},
@ -126,13 +126,13 @@ var PdfjsContentUtils = {
* Events
*/
observe: function(aSubject, aTopic, aData) {
observe(aSubject, aTopic, aData) {
if (aTopic === 'quit-application') {
this.uninit();
}
},
receiveMessage: function (aMsg) {
receiveMessage(aMsg) {
switch (aMsg.name) {
case 'PDFJS:Child:refreshSettings':
// Only react to this if we are remote.

View File

@ -23,8 +23,8 @@
}
}(this, function (exports) {
'use strict';
var pdfjsVersion = '1.6.467';
var pdfjsBuild = '54d55e8b';
var pdfjsVersion = '1.7.227';
var pdfjsBuild = 'e132fa97';
var pdfjsFilePath = typeof document !== 'undefined' && document.currentScript ? document.currentScript.src : null;
var pdfjsLibs = {};
(function pdfjsWrapper() {
@ -1434,6 +1434,7 @@
var warn = sharedUtil.warn;
var deprecated = sharedUtil.deprecated;
var createValidAbsoluteUrl = sharedUtil.createValidAbsoluteUrl;
var DEFAULT_LINK_REL = 'noopener noreferrer nofollow';
var CustomStyle = function CustomStyleClosure() {
var prefixes = [
'ms',
@ -1559,7 +1560,7 @@
globalSettings.externalLinkTarget = LinkTarget.NONE;
return LinkTarget.NONE;
case 'externalLinkRel':
return globalSettings ? globalSettings.externalLinkRel : 'noreferrer';
return globalSettings ? globalSettings.externalLinkRel : DEFAULT_LINK_REL;
case 'enableStats':
return !!(globalSettings && globalSettings.enableStats);
default:
@ -1591,6 +1592,7 @@
exports.LinkTarget = LinkTarget;
exports.hasCanvasTypedArrays = hasCanvasTypedArrays;
exports.getDefaultSetting = getDefaultSetting;
exports.DEFAULT_LINK_REL = DEFAULT_LINK_REL;
}));
(function (root, factory) {
factory(root.pdfjsDisplayFontLoader = {}, root.pdfjsSharedUtil);
@ -5084,15 +5086,13 @@
}
return pattern;
},
setStrokeColorN: function CanvasGraphics_setStrokeColorN()
{
this.current.strokeColor = this.getColorN_Pattern(arguments);
},
setFillColorN: function CanvasGraphics_setFillColorN()
{
this.current.fillColor = this.getColorN_Pattern(arguments);
this.current.patternFill = true;
},
setStrokeColorN: function CanvasGraphics_setStrokeColorN() {
this.current.strokeColor = this.getColorN_Pattern(arguments);
},
setFillColorN: function CanvasGraphics_setFillColorN() {
this.current.fillColor = this.getColorN_Pattern(arguments);
this.current.patternFill = true;
},
setStrokeRGBColor: function CanvasGraphics_setStrokeRGBColor(r, g, b) {
var color = Util.makeCssRgb(r, g, b);
this.ctx.strokeStyle = color;
@ -6824,7 +6824,7 @@
return;
}
if (this.task.onContinue) {
this.task.onContinue.call(this.task, this._scheduleNextBound);
this.task.onContinue(this._scheduleNextBound);
} else {
this._scheduleNext();
}
@ -6886,6 +6886,7 @@
var deprecated = sharedUtil.deprecated;
var warn = sharedUtil.warn;
var LinkTarget = displayDOMUtils.LinkTarget;
var DEFAULT_LINK_REL = displayDOMUtils.DEFAULT_LINK_REL;
var isWorker = typeof window === 'undefined';
if (!globalScope.PDFJS) {
globalScope.PDFJS = {};
@ -6953,7 +6954,7 @@
PDFJS.disableCreateObjectURL = PDFJS.disableCreateObjectURL === undefined ? false : PDFJS.disableCreateObjectURL;
PDFJS.disableWebGL = PDFJS.disableWebGL === undefined ? true : PDFJS.disableWebGL;
PDFJS.externalLinkTarget = PDFJS.externalLinkTarget === undefined ? LinkTarget.NONE : PDFJS.externalLinkTarget;
PDFJS.externalLinkRel = PDFJS.externalLinkRel === undefined ? 'noreferrer' : PDFJS.externalLinkRel;
PDFJS.externalLinkRel = PDFJS.externalLinkRel === undefined ? DEFAULT_LINK_REL : PDFJS.externalLinkRel;
PDFJS.isEvalSupported = PDFJS.isEvalSupported === undefined ? true : PDFJS.isEvalSupported;
PDFJS.getDocument = displayAPI.getDocument;
PDFJS.PDFDataRangeTransport = displayAPI.PDFDataRangeTransport;

View File

@ -23,8 +23,8 @@
}
}(this, function (exports) {
'use strict';
var pdfjsVersion = '1.6.467';
var pdfjsBuild = '54d55e8b';
var pdfjsVersion = '1.7.227';
var pdfjsBuild = 'e132fa97';
var pdfjsFilePath = typeof document !== 'undefined' && document.currentScript ? document.currentScript.src : null;
var pdfjsLibs = {};
(function pdfjsWrapper() {
@ -38197,7 +38197,7 @@
var stackDelta = op <= 0x8E ? TTOpsStackDeltas[op] : op >= 0xC0 && op <= 0xDF ? -1 : op >= 0xE0 ? -2 : 0;
if (op >= 0x71 && op <= 0x75) {
n = stack.pop();
if (n === n) {
if (!isNaN(n)) {
stackDelta = -n * 2;
}
}

View File

@ -1,617 +0,0 @@
/* Copyright 2012 Mozilla Foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
// NOTE: Be careful what goes in this file, as it is also used from the context
// of the addon. So using warn/error in here will break the addon.
'use strict';
(function (root, factory) {
if (typeof define === 'function' && define.amd) {
define('pdfjs/core/network', ['exports', 'pdfjs/shared/util',
'pdfjs/core/worker'], factory);
} else if (typeof exports !== 'undefined') {
factory(exports, require('../shared/util.js'), require('./worker.js'));
} else {
factory((root.pdfjsCoreNetwork = {}), root.pdfjsSharedUtil,
root.pdfjsCoreWorker);
}
}(this, function (exports, sharedUtil, coreWorker) {
if (typeof PDFJSDev !== 'undefined' && PDFJSDev.test('FIREFOX || MOZCENTRAL')) {
throw new Error('Module "pdfjs/core/network" shall not ' +
'be used with FIREFOX or MOZCENTRAL build.');
}
var OK_RESPONSE = 200;
var PARTIAL_CONTENT_RESPONSE = 206;
function NetworkManager(url, args) {
this.url = url;
args = args || {};
this.isHttp = /^https?:/i.test(url);
this.httpHeaders = (this.isHttp && args.httpHeaders) || {};
this.withCredentials = args.withCredentials || false;
this.getXhr = args.getXhr ||
function NetworkManager_getXhr() {
return new XMLHttpRequest();
};
this.currXhrId = 0;
this.pendingRequests = Object.create(null);
this.loadedRequests = Object.create(null);
}
function getArrayBuffer(xhr) {
var data = xhr.response;
if (typeof data !== 'string') {
return data;
}
var length = data.length;
var array = new Uint8Array(length);
for (var i = 0; i < length; i++) {
array[i] = data.charCodeAt(i) & 0xFF;
}
return array.buffer;
}
var supportsMozChunked =
typeof PDFJSDev !== 'undefined' && PDFJSDev.test('CHROME') ? false :
(function supportsMozChunkedClosure() {
try {
var x = new XMLHttpRequest();
// Firefox 37- required .open() to be called before setting responseType.
// https://bugzilla.mozilla.org/show_bug.cgi?id=707484
// Even though the URL is not visited, .open() could fail if the URL is
// blocked, e.g. via the connect-src CSP directive or the NoScript addon.
// When this error occurs, this feature detection method will mistakenly
// report that moz-chunked-arraybuffer is not supported in Firefox 37-.
x.open('GET', 'https://example.com');
x.responseType = 'moz-chunked-arraybuffer';
return x.responseType === 'moz-chunked-arraybuffer';
} catch (e) {
return false;
}
})();
NetworkManager.prototype = {
requestRange: function NetworkManager_requestRange(begin, end, listeners) {
var args = {
begin: begin,
end: end
};
for (var prop in listeners) {
args[prop] = listeners[prop];
}
return this.request(args);
},
requestFull: function NetworkManager_requestFull(listeners) {
return this.request(listeners);
},
request: function NetworkManager_request(args) {
var xhr = this.getXhr();
var xhrId = this.currXhrId++;
var pendingRequest = this.pendingRequests[xhrId] = {
xhr: xhr
};
xhr.open('GET', this.url);
xhr.withCredentials = this.withCredentials;
for (var property in this.httpHeaders) {
var value = this.httpHeaders[property];
if (typeof value === 'undefined') {
continue;
}
xhr.setRequestHeader(property, value);
}
if (this.isHttp && 'begin' in args && 'end' in args) {
var rangeStr = args.begin + '-' + (args.end - 1);
xhr.setRequestHeader('Range', 'bytes=' + rangeStr);
pendingRequest.expectedStatus = 206;
} else {
pendingRequest.expectedStatus = 200;
}
var useMozChunkedLoading = supportsMozChunked && !!args.onProgressiveData;
if (useMozChunkedLoading) {
xhr.responseType = 'moz-chunked-arraybuffer';
pendingRequest.onProgressiveData = args.onProgressiveData;
pendingRequest.mozChunked = true;
} else {
xhr.responseType = 'arraybuffer';
}
if (args.onError) {
xhr.onerror = function(evt) {
args.onError(xhr.status);
};
}
xhr.onreadystatechange = this.onStateChange.bind(this, xhrId);
xhr.onprogress = this.onProgress.bind(this, xhrId);
pendingRequest.onHeadersReceived = args.onHeadersReceived;
pendingRequest.onDone = args.onDone;
pendingRequest.onError = args.onError;
pendingRequest.onProgress = args.onProgress;
xhr.send(null);
return xhrId;
},
onProgress: function NetworkManager_onProgress(xhrId, evt) {
var pendingRequest = this.pendingRequests[xhrId];
if (!pendingRequest) {
// Maybe abortRequest was called...
return;
}
if (pendingRequest.mozChunked) {
var chunk = getArrayBuffer(pendingRequest.xhr);
pendingRequest.onProgressiveData(chunk);
}
var onProgress = pendingRequest.onProgress;
if (onProgress) {
onProgress(evt);
}
},
onStateChange: function NetworkManager_onStateChange(xhrId, evt) {
var pendingRequest = this.pendingRequests[xhrId];
if (!pendingRequest) {
// Maybe abortRequest was called...
return;
}
var xhr = pendingRequest.xhr;
if (xhr.readyState >= 2 && pendingRequest.onHeadersReceived) {
pendingRequest.onHeadersReceived();
delete pendingRequest.onHeadersReceived;
}
if (xhr.readyState !== 4) {
return;
}
if (!(xhrId in this.pendingRequests)) {
// The XHR request might have been aborted in onHeadersReceived()
// callback, in which case we should abort request
return;
}
delete this.pendingRequests[xhrId];
// success status == 0 can be on ftp, file and other protocols
if (xhr.status === 0 && this.isHttp) {
if (pendingRequest.onError) {
pendingRequest.onError(xhr.status);
}
return;
}
var xhrStatus = xhr.status || OK_RESPONSE;
// From http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.35.2:
// "A server MAY ignore the Range header". This means it's possible to
// get a 200 rather than a 206 response from a range request.
var ok_response_on_range_request =
xhrStatus === OK_RESPONSE &&
pendingRequest.expectedStatus === PARTIAL_CONTENT_RESPONSE;
if (!ok_response_on_range_request &&
xhrStatus !== pendingRequest.expectedStatus) {
if (pendingRequest.onError) {
pendingRequest.onError(xhr.status);
}
return;
}
this.loadedRequests[xhrId] = true;
var chunk = getArrayBuffer(xhr);
if (xhrStatus === PARTIAL_CONTENT_RESPONSE) {
var rangeHeader = xhr.getResponseHeader('Content-Range');
var matches = /bytes (\d+)-(\d+)\/(\d+)/.exec(rangeHeader);
var begin = parseInt(matches[1], 10);
pendingRequest.onDone({
begin: begin,
chunk: chunk
});
} else if (pendingRequest.onProgressiveData) {
pendingRequest.onDone(null);
} else if (chunk) {
pendingRequest.onDone({
begin: 0,
chunk: chunk
});
} else if (pendingRequest.onError) {
pendingRequest.onError(xhr.status);
}
},
hasPendingRequests: function NetworkManager_hasPendingRequests() {
for (var xhrId in this.pendingRequests) {
return true;
}
return false;
},
getRequestXhr: function NetworkManager_getXhr(xhrId) {
return this.pendingRequests[xhrId].xhr;
},
isStreamingRequest: function NetworkManager_isStreamingRequest(xhrId) {
return !!(this.pendingRequests[xhrId].onProgressiveData);
},
isPendingRequest: function NetworkManager_isPendingRequest(xhrId) {
return xhrId in this.pendingRequests;
},
isLoadedRequest: function NetworkManager_isLoadedRequest(xhrId) {
return xhrId in this.loadedRequests;
},
abortAllRequests: function NetworkManager_abortAllRequests() {
for (var xhrId in this.pendingRequests) {
this.abortRequest(xhrId | 0);
}
},
abortRequest: function NetworkManager_abortRequest(xhrId) {
var xhr = this.pendingRequests[xhrId].xhr;
delete this.pendingRequests[xhrId];
xhr.abort();
}
};
var assert = sharedUtil.assert;
var createPromiseCapability = sharedUtil.createPromiseCapability;
var isInt = sharedUtil.isInt;
var MissingPDFException = sharedUtil.MissingPDFException;
var UnexpectedResponseException = sharedUtil.UnexpectedResponseException;
/** @implements {IPDFStream} */
function PDFNetworkStream(options) {
this._options = options;
var source = options.source;
this._manager = new NetworkManager(source.url, {
httpHeaders: source.httpHeaders,
withCredentials: source.withCredentials
});
this._rangeChunkSize = source.rangeChunkSize;
this._fullRequestReader = null;
this._rangeRequestReaders = [];
}
PDFNetworkStream.prototype = {
_onRangeRequestReaderClosed:
function PDFNetworkStream_onRangeRequestReaderClosed(reader) {
var i = this._rangeRequestReaders.indexOf(reader);
if (i >= 0) {
this._rangeRequestReaders.splice(i, 1);
}
},
getFullReader: function PDFNetworkStream_getFullReader() {
assert(!this._fullRequestReader);
this._fullRequestReader =
new PDFNetworkStreamFullRequestReader(this._manager, this._options);
return this._fullRequestReader;
},
getRangeReader: function PDFNetworkStream_getRangeReader(begin, end) {
var reader = new PDFNetworkStreamRangeRequestReader(this._manager,
begin, end);
reader.onClosed = this._onRangeRequestReaderClosed.bind(this);
this._rangeRequestReaders.push(reader);
return reader;
},
cancelAllRequests: function PDFNetworkStream_cancelAllRequests(reason) {
if (this._fullRequestReader) {
this._fullRequestReader.cancel(reason);
}
var readers = this._rangeRequestReaders.slice(0);
readers.forEach(function (reader) {
reader.cancel(reason);
});
}
};
/** @implements {IPDFStreamReader} */
function PDFNetworkStreamFullRequestReader(manager, options) {
this._manager = manager;
var source = options.source;
var args = {
onHeadersReceived: this._onHeadersReceived.bind(this),
onProgressiveData: source.disableStream ? null :
this._onProgressiveData.bind(this),
onDone: this._onDone.bind(this),
onError: this._onError.bind(this),
onProgress: this._onProgress.bind(this)
};
this._url = source.url;
this._fullRequestId = manager.requestFull(args);
this._headersReceivedCapability = createPromiseCapability();
this._disableRange = options.disableRange || false;
this._contentLength = source.length; // optional
this._rangeChunkSize = source.rangeChunkSize;
if (!this._rangeChunkSize && !this._disableRange) {
this._disableRange = true;
}
this._isStreamingSupported = false;
this._isRangeSupported = false;
this._cachedChunks = [];
this._requests = [];
this._done = false;
this._storedError = undefined;
this.onProgress = null;
}
PDFNetworkStreamFullRequestReader.prototype = {
_validateRangeRequestCapabilities: function
PDFNetworkStreamFullRequestReader_validateRangeRequestCapabilities() {
if (this._disableRange) {
return false;
}
var networkManager = this._manager;
if (!networkManager.isHttp) {
return false;
}
var fullRequestXhrId = this._fullRequestId;
var fullRequestXhr = networkManager.getRequestXhr(fullRequestXhrId);
if (fullRequestXhr.getResponseHeader('Accept-Ranges') !== 'bytes') {
return false;
}
var contentEncoding =
fullRequestXhr.getResponseHeader('Content-Encoding') || 'identity';
if (contentEncoding !== 'identity') {
return false;
}
var length = fullRequestXhr.getResponseHeader('Content-Length');
length = parseInt(length, 10);
if (!isInt(length)) {
return false;
}
this._contentLength = length; // setting right content length
if (length <= 2 * this._rangeChunkSize) {
// The file size is smaller than the size of two chunks, so it does
// not make any sense to abort the request and retry with a range
// request.
return false;
}
return true;
},
_onHeadersReceived:
function PDFNetworkStreamFullRequestReader_onHeadersReceived() {
if (this._validateRangeRequestCapabilities()) {
this._isRangeSupported = true;
}
var networkManager = this._manager;
var fullRequestXhrId = this._fullRequestId;
if (networkManager.isStreamingRequest(fullRequestXhrId)) {
// We can continue fetching when progressive loading is enabled,
// and we don't need the autoFetch feature.
this._isStreamingSupported = true;
} else if (this._isRangeSupported) {
// NOTE: by cancelling the full request, and then issuing range
// requests, there will be an issue for sites where you can only
// request the pdf once. However, if this is the case, then the
// server should not be returning that it can support range
// requests.
networkManager.abortRequest(fullRequestXhrId);
}
this._headersReceivedCapability.resolve();
},
_onProgressiveData:
function PDFNetworkStreamFullRequestReader_onProgressiveData(chunk) {
if (this._requests.length > 0) {
var requestCapability = this._requests.shift();
requestCapability.resolve({value: chunk, done: false});
} else {
this._cachedChunks.push(chunk);
}
},
_onDone: function PDFNetworkStreamFullRequestReader_onDone(args) {
if (args) {
this._onProgressiveData(args.chunk);
}
this._done = true;
if (this._cachedChunks.length > 0) {
return;
}
this._requests.forEach(function (requestCapability) {
requestCapability.resolve({value: undefined, done: true});
});
this._requests = [];
},
_onError: function PDFNetworkStreamFullRequestReader_onError(status) {
var url = this._url;
var exception;
if (status === 404 || status === 0 && /^file:/.test(url)) {
exception = new MissingPDFException('Missing PDF "' + url + '".');
} else {
exception = new UnexpectedResponseException(
'Unexpected server response (' + status +
') while retrieving PDF "' + url + '".', status);
}
this._storedError = exception;
this._headersReceivedCapability.reject(exception);
this._requests.forEach(function (requestCapability) {
requestCapability.reject(exception);
});
this._requests = [];
this._cachedChunks = [];
},
_onProgress: function PDFNetworkStreamFullRequestReader_onProgress(data) {
if (this.onProgress) {
this.onProgress({
loaded: data.loaded,
total: data.lengthComputable ? data.total : this._contentLength
});
}
},
get isRangeSupported() {
return this._isRangeSupported;
},
get isStreamingSupported() {
return this._isStreamingSupported;
},
get contentLength() {
return this._contentLength;
},
get headersReady() {
return this._headersReceivedCapability.promise;
},
read: function PDFNetworkStreamFullRequestReader_read() {
if (this._storedError) {
return Promise.reject(this._storedError);
}
if (this._cachedChunks.length > 0) {
var chunk = this._cachedChunks.shift();
return Promise.resolve(chunk);
}
if (this._done) {
return Promise.resolve({value: undefined, done: true});
}
var requestCapability = createPromiseCapability();
this._requests.push(requestCapability);
return requestCapability.promise;
},
cancel: function PDFNetworkStreamFullRequestReader_cancel(reason) {
this._done = true;
this._headersReceivedCapability.reject(reason);
this._requests.forEach(function (requestCapability) {
requestCapability.resolve({value: undefined, done: true});
});
this._requests = [];
if (this._manager.isPendingRequest(this._fullRequestId)) {
this._manager.abortRequest(this._fullRequestId);
}
this._fullRequestReader = null;
}
};
/** @implements {IPDFStreamRangeReader} */
function PDFNetworkStreamRangeRequestReader(manager, begin, end) {
this._manager = manager;
var args = {
onDone: this._onDone.bind(this),
onProgress: this._onProgress.bind(this)
};
this._requestId = manager.requestRange(begin, end, args);
this._requests = [];
this._queuedChunk = null;
this._done = false;
this.onProgress = null;
this.onClosed = null;
}
PDFNetworkStreamRangeRequestReader.prototype = {
_close: function PDFNetworkStreamRangeRequestReader_close() {
if (this.onClosed) {
this.onClosed(this);
}
},
_onDone: function PDFNetworkStreamRangeRequestReader_onDone(data) {
var chunk = data.chunk;
if (this._requests.length > 0) {
var requestCapability = this._requests.shift();
requestCapability.resolve({value: chunk, done: false});
} else {
this._queuedChunk = chunk;
}
this._done = true;
this._requests.forEach(function (requestCapability) {
requestCapability.resolve({value: undefined, done: true});
});
this._requests = [];
this._close();
},
_onProgress: function PDFNetworkStreamRangeRequestReader_onProgress(evt) {
if (!this.isStreamingSupported && this.onProgress) {
this.onProgress({
loaded: evt.loaded
});
}
},
get isStreamingSupported() {
return false; // TODO allow progressive range bytes loading
},
read: function PDFNetworkStreamRangeRequestReader_read() {
if (this._queuedChunk !== null) {
var chunk = this._queuedChunk;
this._queuedChunk = null;
return Promise.resolve({value: chunk, done: false});
}
if (this._done) {
return Promise.resolve({value: undefined, done: true});
}
var requestCapability = createPromiseCapability();
this._requests.push(requestCapability);
return requestCapability.promise;
},
cancel: function PDFNetworkStreamRangeRequestReader_cancel(reason) {
this._done = true;
this._requests.forEach(function (requestCapability) {
requestCapability.resolve({value: undefined, done: true});
});
this._requests = [];
if (this._manager.isPendingRequest(this._requestId)) {
this._manager.abortRequest(this._requestId);
}
this._close();
}
};
coreWorker.setPDFNetworkStreamClass(PDFNetworkStream);
exports.PDFNetworkStream = PDFNetworkStream;
exports.NetworkManager = NetworkManager;
}));

View File

@ -121,12 +121,12 @@
get: translateString,
// get the document language
getLanguage: function() {
getLanguage() {
return gLanguage;
},
// get the direction (ltr|rtl) of the current language
getDirection: function() {
getDirection() {
// http://www.w3.org/International/questions/qa-scripts
// Arabic, Hebrew, Farsi, Pashto, Urdu
var rtlList = ['ar', 'he', 'fa', 'ps', 'ur'];
@ -137,9 +137,11 @@
return (rtlList.indexOf(shortCode) >= 0) ? 'rtl' : 'ltr';
},
getReadyState: function() { return gReadyState; },
getReadyState() {
return gReadyState;
},
setExternalLocalizerServices: function (externalLocalizerServices) {
setExternalLocalizerServices(externalLocalizerServices) {
gExternalLocalizerServices = externalLocalizerServices;
// ... in case if we missed DOMContentLoaded above.

View File

@ -2478,8 +2478,8 @@ var pdfjsWebLibs;
};
this.anchor = anchor;
var div = document.createElement('div');
div.id = 'thumbnailContainer' + id;
div.className = 'thumbnail';
div.setAttribute('data-page-number', this.id);
this.div = div;
if (id === 1) {
div.classList.add('selected');
@ -3873,7 +3873,7 @@ var pdfjsWebLibs;
this.annotationLayerFactory = annotationLayerFactory;
this.renderer = options.renderer || RendererType.CANVAS;
this.paintTask = null;
this.paintedViewport = null;
this.paintedViewportMap = new WeakMap();
this.renderingState = RenderingStates.INITIAL;
this.resume = null;
this.error = null;
@ -3883,7 +3883,6 @@ var pdfjsWebLibs;
this.zoomLayer = null;
this.annotationLayer = null;
var div = document.createElement('div');
div.id = 'pageContainer' + this.id;
div.className = 'page';
div.style.width = Math.floor(this.viewport.width) + 'px';
div.style.height = Math.floor(this.viewport.height) + 'px';
@ -3929,16 +3928,15 @@ var pdfjsWebLibs;
this.annotationLayer = null;
}
if (this.canvas && !currentZoomLayerNode) {
this.paintedViewportMap.delete(this.canvas);
this.canvas.width = 0;
this.canvas.height = 0;
delete this.canvas;
}
if (this.svg) {
this.paintedViewportMap.delete(this.svg);
delete this.svg;
}
if (!currentZoomLayerNode) {
this.paintedViewport = null;
}
this.loadingIconDiv = document.createElement('div');
this.loadingIconDiv.className = 'loadingIcon';
div.appendChild(this.loadingIconDiv);
@ -4013,7 +4011,7 @@ var pdfjsWebLibs;
var div = this.div;
target.style.width = target.parentNode.style.width = div.style.width = Math.floor(width) + 'px';
target.style.height = target.parentNode.style.height = div.style.height = Math.floor(height) + 'px';
var relativeRotation = this.viewport.rotation - this.paintedViewport.rotation;
var relativeRotation = this.viewport.rotation - this.paintedViewportMap.get(target).rotation;
var absRotation = Math.abs(relativeRotation);
var scaleX = 1, scaleY = 1;
if (absRotation === 90 || absRotation === 270) {
@ -4131,6 +4129,7 @@ var pdfjsWebLibs;
}
if (self.zoomLayer) {
var zoomLayerCanvas = self.zoomLayer.firstChild;
self.paintedViewportMap.delete(zoomLayerCanvas);
zoomLayerCanvas.width = 0;
zoomLayerCanvas.height = 0;
if (div.contains(self.zoomLayer)) {
@ -4238,7 +4237,7 @@ var pdfjsWebLibs;
canvas.height = roundToDivide(viewport.height * outputScale.sy, sfy[0]);
canvas.style.width = roundToDivide(viewport.width, sfx[1]) + 'px';
canvas.style.height = roundToDivide(viewport.height, sfy[1]) + 'px';
this.paintedViewport = viewport;
this.paintedViewportMap.set(canvas, viewport);
var transform = !outputScale.scaled ? null : [
outputScale.sx,
0,
@ -4324,7 +4323,7 @@ var pdfjsWebLibs;
if (selected) {
selected.classList.remove('selected');
}
var thumbnail = document.getElementById('thumbnailContainer' + page);
var thumbnail = document.querySelector('div.thumbnail[data-page-number="' + page + '"]');
if (thumbnail) {
thumbnail.classList.add('selected');
}

View File

@ -36,7 +36,7 @@
<!ENTITY healthReportLearnMore.label "Learn More">
<!ENTITY telemetryDesc.label "Shares performance, usage, hardware and customization data about your browser with &vendorShortName; to help us make &brandShortName; better">
<!ENTITY enableTelemetryData.label "Share additional data (i.e., Telemetry)">
<!ENTITY enableTelemetryData.label "Share Additional Data (i.e., Telemetry)">
<!ENTITY enableTelemetryData.accesskey "T">
<!ENTITY telemetryLearnMore.label "Learn More">
@ -83,7 +83,7 @@
<!ENTITY updateTab.label "Update">
<!ENTITY updateApplication.label "&brandShortName; updates">
<!ENTITY updateApplication.label "&brandShortName; Updates">
<!ENTITY updateAuto1.label "Automatically install updates (recommended: improved security)">
<!ENTITY updateAuto1.accesskey "A">
<!ENTITY updateCheckChoose.label "Check for updates, but let you choose whether to install them">
@ -97,7 +97,7 @@
<!ENTITY useService.label "Use a background service to install updates">
<!ENTITY useService.accesskey "b">
<!ENTITY autoUpdateOthers.label "Automatically update">
<!ENTITY autoUpdateOthers.label "Automatically Update">
<!ENTITY enableSearchUpdate.label "Search Engines">
<!ENTITY enableSearchUpdate.accesskey "E">

View File

@ -53,7 +53,7 @@
<!ENTITY translation.options.attribution.beforeLogo "Translations by">
<!ENTITY translation.options.attribution.afterLogo "">
<!ENTITY drmContent.label "DRM content">
<!ENTITY drmContent.label "DRM Content">
<!ENTITY playDRMContent.label "Play DRM content">
<!ENTITY playDRMContent.accesskey "P">

View File

@ -13,7 +13,7 @@
<!ENTITY showURLBarSuggestions.accesskey "l">
<!ENTITY urlBarSuggestionsPermanentPB.label "Search suggestions will not be shown in location bar results because you have configured &brandShortName; to never remember history.">
<!ENTITY oneClickSearchEngines.label "One-click search engines">
<!ENTITY oneClickSearchEngines.label "One-click Search Engines">
<!ENTITY chooseWhichOneToDisplay.label "The search bar lets you search alternate engines directly. Choose which ones to display.">

View File

@ -90,7 +90,7 @@ both, to better adapt this sentence to their language.
<!ENTITY welcome.useOldSync.label "Using an older version of Sync?">
<!ENTITY signedOut.caption "Take your Web with you">
<!ENTITY signedOut.caption "Take Your Web With You">
<!ENTITY signedOut.description "Synchronize your bookmarks, history, tabs, passwords, add-ons, and preferences across all your devices.">
<!ENTITY signedOut.accountBox.title "Connect with a &syncBrand.fxAccount.label;">
<!ENTITY signedOut.accountBox.create "Create Account">
@ -98,7 +98,7 @@ both, to better adapt this sentence to their language.
<!ENTITY signedOut.accountBox.signin "Sign In">
<!ENTITY signedOut.accountBox.signin.accesskey "I">
<!ENTITY signedIn.engines.label "Sync across all devices">
<!ENTITY signedIn.engines.label "Sync Across All Devices">
<!-- LOCALIZATION NOTE (mobilePromo3.*): the following strings will be used to
create a single sentence with active links.

View File

@ -273,9 +273,9 @@ this.ExtensionsUI = {
let doc = this.browser.ownerDocument;
doc.getElementById("addon-webext-perm-header").innerHTML = header;
if (text) {
doc.getElementById("addon-webext-perm-text").innerHTML = text;
}
let textEl = doc.getElementById("addon-webext-perm-text");
textEl.innerHTML = text;
textEl.hidden = !text;
let listIntroEl = doc.getElementById("addon-webext-perm-intro");
listIntroEl.value = listIntro;

View File

@ -417,6 +417,23 @@ def split_triplet(triplet):
)
# This defines a fake target/host namespace for when running with --help
@depends('--help')
def help_host_target(help):
if help:
return namespace(
alias='unknown-unknown-unknown',
cpu='unknown',
bitness='unknown',
kernel='unknown',
os='unknown',
endianness='unknown',
raw_cpu='unknown',
raw_os='unknown',
toolchain='unknown-unknown',
)
@imports('subprocess')
def config_sub(shell, triplet):
config_sub = os.path.join(os.path.dirname(__file__), '..',
@ -437,6 +454,8 @@ def host(value, shell):
return split_triplet(config_sub(shell, host))
host = help_host_target | host
@depends('--target', host, shell)
@checking('for target system type', lambda t: t.alias)
@ -445,6 +464,8 @@ def target(value, host, shell):
return host
return split_triplet(config_sub(shell, value[0]))
target = help_host_target | target
@depends(host, target)
@checking('whether cross compiling')

View File

@ -27,9 +27,11 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=995943
SimpleTest.waitForExplicitFinish();
SimpleTest.requestCompleteLog();
if (navigator.userAgent.indexOf("Mac OS X 10.10") != -1)
SimpleTest.expectAssertions(5, 9); // See bug 1067022
SimpleTest.expectAssertions(5, 11); // See bug 1067022, 1307988
else if (Services.appinfo.OS == "WINNT")
SimpleTest.expectAssertions(0, 1); // See bug 1067022
else
SimpleTest.expectAssertions(0, 2); // See bug 1305241
var rootdir = Services.appinfo.OS == "WINNT" ? "file:///C:" : "file:///";

View File

@ -922,7 +922,9 @@ cargo_build_flags += --features "quantum_render"
endif
cargo_build_flags += --manifest-path $(CARGO_FILE)
ifdef BUILD_VERBOSE_LOG
cargo_build_flags += --verbose
endif
# Enable color output if original stdout was a TTY and color settings
# aren't already present. This essentially restores the default behavior

View File

@ -58581,7 +58581,7 @@ var Debugger =
onFocus: e => this.setState({ focused: true }),
onBlur: e => this.setState({ focused: false }),
onKeyDown: this.onKeyDown,
placeholder: L10N.getStr("sourceSearch.search1")
placeholder: L10N.getStr("sourceSearch.search")
});
},
@ -58600,7 +58600,7 @@ var Debugger =
var resultCountSummary = "";
if (this.state.inputValue) {
resultCountSummary = L10N.getFormatStr("sourceSearch1.resultsSummary", searchResults.length, this.state.inputValue);
resultCountSummary = L10N.getFormatStr("sourceSearch.resultsSummary", searchResults.length, this.state.inputValue);
}
return dom.div({ className: "results-summary" }, resultCountSummary);
},
@ -82185,7 +82185,7 @@ var Debugger =
renderStepButtons() {
var className = this.props.pause ? "active" : "disabled";
return [debugBtn(this.props.stepOver, "stepOver", className, L10N.getFormatStr("stepOverTooltip1", formatKey("stepOver"))), debugBtn(this.props.stepIn, "stepIn", className, L10N.getFormatStr("stepInTooltip1", formatKey("stepIn"))), debugBtn(this.props.stepOut, "stepOut", className, L10N.getFormatStr("stepOutTooltip1", formatKey("stepOut")))];
return [debugBtn(this.props.stepOver, "stepOver", className, L10N.getFormatStr("stepOverTooltip", formatKey("stepOver"))), debugBtn(this.props.stepIn, "stepIn", className, L10N.getFormatStr("stepInTooltip", formatKey("stepIn"))), debugBtn(this.props.stepOut, "stepOut", className, L10N.getFormatStr("stepOutTooltip", formatKey("stepOut")))];
},
renderPauseButton() {
@ -82196,14 +82196,14 @@ var Debugger =
if (pause) {
return debugBtn(this.props.resume, "resume", "active", L10N.getFormatStr("resumeButtonTooltip1", formatKey("resume")));
return debugBtn(this.props.resume, "resume", "active", L10N.getFormatStr("resumeButtonTooltip", formatKey("resume")));
}
if (isWaitingOnBreak) {
return debugBtn(null, "pause", "disabled", L10N.getStr("pausePendingButtonTooltip"));
}
return debugBtn(breakOnNext, "pause", "active", L10N.getFormatStr("pauseButtonTooltip1", formatKey("pause")));
return debugBtn(breakOnNext, "pause", "active", L10N.getFormatStr("pauseButtonTooltip", formatKey("pause")));
},
/*
@ -82308,7 +82308,7 @@ var Debugger =
},
render() {
var searchLabel = L10N.getFormatStr("welcome.search1", formatKeyShortcut(`CmdOrCtrl+${ L10N.getStr("sources.search.key") }`));
var searchLabel = L10N.getFormatStr("welcome.search", formatKeyShortcut(`CmdOrCtrl+${ L10N.getStr("sources.search.key") }`));
return dom.div({ className: "welcomebox" }, searchLabel, this.renderToggleButton());
}
});
@ -82786,22 +82786,22 @@ var Debugger =
"sources.search.key": "P",
"watchExpressions.header": "Watch Expressions",
"watchExpressions.refreshButton": "Refresh",
"welcome.search1": "%S to search for sources",
"sourceSearch.search1": "Search Sources...",
"welcome.search": "%S to search for sources",
"sourceSearch.search": "Search Sources...",
"sourceSearch.search.key": "F",
"sourceSearch.search.again.key": "G",
"sourceSearch1.resultsSummary": "%d instances of \"%S\"",
"sourceSearch.resultsSummary": "%d instances of \"%S\"",
"sourceSearch.noResults": "No files matching %S found",
"sourceFooter.debugBtnTooltip": "Prettify Source",
"ignoreExceptions": "Ignore exceptions. Click to pause on uncaught exceptions",
"pauseOnUncaughtExceptions": "Pause on uncaught exceptions. Click to pause on all exceptions",
"pauseOnExceptions": "Pause on all exceptions. Click to ignore exceptions",
"stepOutTooltip1": "Step Out %S",
"stepInTooltip1": "Step In %S",
"stepOverTooltip1": "Step Over %S",
"resumeButtonTooltip1": "Resume %S",
"stepOutTooltip": "Step Out %S",
"stepInTooltip": "Step In %S",
"stepOverTooltip": "Step Over %S",
"resumeButtonTooltip": "Resume %S",
"pausePendingButtonTooltip": "Waiting for next execution",
"pauseButtonTooltip1": "Pause %S",
"pauseButtonTooltip": "Pause %S",
"sourceTabs.closeTab": "Close tab",
"sourceTabs.closeOtherTabs": "Close others",
"sourceTabs.closeTabsToRight": "Close tabs to the right",
@ -82826,4 +82826,4 @@ var Debugger =
/***/ }
/******/ ]);
//# sourceMappingURL=debugger.js.map
//# sourceMappingURL=debugger.js.map

View File

@ -273,7 +273,7 @@ skip-if = e10s && debug
[browser_dbg_searchbox-help-popup-02.js]
skip-if = e10s && debug
[browser_dbg_searchbox-parse.js]
skip-if = (e10s && debug) || (os == 'linux' && asan) # asan, bug 1313861
skip-if = (debug) || (os == 'linux' && asan) # asan, bug 1313861, debug: bug 1313861
[browser_dbg_source-maps-01.js]
skip-if = e10s && debug
[browser_dbg_source-maps-02.js]

View File

@ -18,59 +18,29 @@ collapsePanes=Collapse panes
# that expands the left and right panes in the debugger UI.
expandPanes=Expand panes
# LOCALIZATION NOTE (pauseButtonTooltip1): The tooltip that is displayed for the pause
# button when the debugger is in a running state.
pauseButtonTooltip1=Pause %S
# LOCALIZATION NOTE (pausePendingButtonTooltip): The tooltip that is displayed for
# the pause button after it's been clicked but before the next JavaScript to run.
pausePendingButtonTooltip=Waiting for next execution
# LOCALIZATION NOTE (resumeButtonTooltip1): The label that is displayed on the pause
# button when the debugger is in a paused state.
resumeButtonTooltip1=Resume %S
# LOCALIZATION NOTE (stepOverTooltip1): The label that is displayed on the
# button that steps over a function call.
stepOverTooltip1=Step Over %S
# LOCALIZATION NOTE (stepInTooltip1): The label that is displayed on the
# button that steps into a function call.
stepInTooltip1=Step In %S
# LOCALIZATION NOTE (stepOutTooltip1): The label that is displayed on the
# button that steps out of a function call.
stepOutTooltip1=Step Out %S
# LOCALIZATION NOTE (pauseButtonTooltip): The tooltip that is displayed for the pause
# button when the debugger is in a running state.
# Used in the old debugger frontend.
pauseButtonTooltip=Click to pause (%S)
pauseButtonTooltip=Pause %S
# LOCALIZATION NOTE (pausePendingButtonTooltip): The tooltip that is displayed for
# the pause button after it's been clicked but before the next JavaScript to run.
# Used in the old debugger frontend.
pausePendingButtonTooltip=Waiting for next execution
# LOCALIZATION NOTE (resumeButtonTooltip): The label that is displayed on the pause
# button when the debugger is in a paused state.
# Used in the old debugger frontend.
resumeButtonTooltip=Click to resume (%S)
resumeButtonTooltip=Resume %S
# LOCALIZATION NOTE (stepOverTooltip): The label that is displayed on the
# button that steps over a function call.
# Used in the old debugger frontend.
stepOverTooltip=Step Over (%S)
stepOverTooltip=Step Over %S
# LOCALIZATION NOTE (stepInTooltip): The label that is displayed on the
# button that steps into a function call.
# Used in the old debugger frontend.
stepInTooltip=Step In (%S)
stepInTooltip=Step In %S
# LOCALIZATION NOTE (stepOutTooltip): The label that is displayed on the
# button that steps out of a function call.
# Used in the old debugger frontend.
stepOutTooltip=Step Out (%S)
stepOutTooltip=Step Out %S
# LOCALIZATION NOTE (noWorkersText): The text to display in the workers list
# when there are no workers.
@ -154,9 +124,9 @@ sourceSearch.search.key=F
# the search for re-searching the same search triggered from a sourceSearch
sourceSearch.search.again.key=G
# LOCALIZATION NOTE (sourceSearch1.resultsSummary): Shows a summary of
# LOCALIZATION NOTE (sourceSearch.resultsSummary): Shows a summary of
# the number of matches for autocomplete
sourceSearch1.resultsSummary=%d instances of “%S”
sourceSearch.resultsSummary=%d instances of “%S”
# LOCALIZATION NOTE (noMatchingStringsText): The text to display in the
# global search results when there are no matching strings after filtering.
@ -281,7 +251,7 @@ editor.addConditionalBreakpoint=Add Conditional Breakpoint
# input element inside ConditionalPanel component
editor.conditionalPanel.placeholder=This breakpoint will pause when the expression is true
# LOCALIZATION NOTE(editor.jumpToMappedLocation1): Context menu item
# LOCALIZATION NOTE (editor.jumpToMappedLocation1): Context menu item
# for navigating to a source mapped location
editor.jumpToMappedLocation1=Jump to %S location
@ -350,14 +320,14 @@ watchExpressions.header=Watch Expressions
# button for refreshing the expressions.
watchExpressions.refreshButton=Refresh
# LOCALIZATION NOTE (welcome.search1): The center pane welcome panel's
# LOCALIZATION NOTE (welcome.search): The center pane welcome panel's
# search prompt. e.g. cmd+p to search for files. On windows, it's ctrl, on
# a mac we use the unicode character.
welcome.search1=%S to search for sources
welcome.search=%S to search for sources
# LOCALIZATION NOTE (sourceSearch.search1): The center pane Source Search
# LOCALIZATION NOTE (sourceSearch.search): The center pane Source Search
# prompt for searching for files.
sourceSearch.search1=Search Sources…
sourceSearch.search=Search Sources…
# LOCALIZATION NOTE (sourceSearch.search): The center pane Source Search
# prompt for searching for files.

View File

@ -48,12 +48,12 @@ function resizeWaterfall(width) {
/**
* Change the selected tab for details panel.
*
* @param {number} index - tab index to be selected
* @param {string} id - tab id to be selected
*/
function selectDetailsPanelTab(index) {
function selectDetailsPanelTab(id) {
return {
type: SELECT_DETAILS_PANEL_TAB,
index,
id,
};
}

View File

@ -264,7 +264,7 @@ module.exports = connect(
const { securityState } = item;
// Choose the security tab.
if (securityState && securityState !== "insecure") {
dispatch(Actions.selectDetailsPanelTab(5));
dispatch(Actions.selectDetailsPanelTab("security"));
}
},
})

View File

@ -59,15 +59,9 @@ const EVENTS = {
RESPONSE_IMAGE_THUMBNAIL_DISPLAYED:
"NetMonitor:ResponseImageThumbnailAvailable",
// When a tab is selected in the NetworkDetailsView and subsequently rendered.
TAB_UPDATED: "NetMonitor:TabUpdated",
// Fired when Sidebar has finished being populated.
SIDEBAR_POPULATED: "NetMonitor:SidebarPopulated",
// Fired when NetworkDetailsView has finished being populated.
NETWORKDETAILSVIEW_POPULATED: "NetMonitor:NetworkDetailsViewPopulated",
// Fired when CustomRequestView has finished being populated.
CUSTOMREQUESTVIEW_POPULATED: "NetMonitor:CustomRequestViewPopulated",

View File

@ -13,7 +13,7 @@ const {
} = require("../constants");
const UI = I.Record({
detailsPanelSelectedTab: 0,
detailsPanelSelectedTab: "headers",
sidebarOpen: false,
statisticsOpen: false,
waterfallWidth: null,
@ -35,7 +35,7 @@ function openStatistics(state, action) {
}
function setDetailsPanelTab(state, action) {
return state.set("detailsPanelSelectedTab", action.index);
return state.set("detailsPanelSelectedTab", action.id);
}
function ui(state = new UI(), action) {

View File

@ -38,10 +38,10 @@ const PREVIEW_TITLE = L10N.getStr("netmonitor.tab.preview");
* Display the network request details
*/
function DetailsPanel({
activeTabId,
cloneSelectedRequest,
request,
setTabIndex,
tabIndex,
selectTab,
toolbox,
}) {
if (!request) {
@ -50,9 +50,10 @@ function DetailsPanel({
return (
Tabbar({
onSelect: setTabIndex,
activeTabId,
onSelect: selectTab,
renderOnlySelected: true,
showAllTabsMenu: true,
tabActive: tabIndex,
toolbox,
},
TabPanel({
@ -109,17 +110,17 @@ DetailsPanel.propTypes = {
cloneSelectedRequest: PropTypes.func.isRequired,
request: PropTypes.object,
setTabIndex: PropTypes.func.isRequired,
tabIndex: PropTypes.number.isRequired,
selectedTab: PropTypes.number.isRequired,
toolbox: PropTypes.object.isRequired,
};
module.exports = connect(
(state) => ({
activeTabId: state.ui.detailsPanelSelectedTab,
request: getSelectedRequest(state),
tabIndex: state.ui.detailsPanelSelectedTab,
}),
(dispatch) => ({
cloneSelectedRequest: () => dispatch(Actions.cloneSelectedRequest()),
setTabIndex: (index) => dispatch(Actions.selectDetailsPanelTab(index)),
selectTab: (tabId) => dispatch(Actions.selectDetailsPanelTab(tabId)),
}),
)(DetailsPanel);

View File

@ -10,6 +10,7 @@ const { createClass, DOM, PropTypes } = require("devtools/client/shared/vendor/r
const SourceEditor = require("devtools/client/sourceeditor/editor");
const { div } = DOM;
const SYNTAX_HIGHLIGHT_MAX_SIZE = 102400;
/**
* CodeMirror editor as a React component
@ -39,7 +40,7 @@ const Editor = createClass({
this.editor = new SourceEditor({
lineNumbers: true,
mode,
mode: text.length < SYNTAX_HIGHLIGHT_MAX_SIZE ? mode : null,
readOnly: true,
value: text,
});
@ -54,7 +55,7 @@ const Editor = createClass({
return;
}
if (prevProps.mode !== mode) {
if (prevProps.mode !== mode && text.length < SYNTAX_HIGHLIGHT_MAX_SIZE) {
this.deferEditor.then(() => {
this.editor.setMode(mode);
});

View File

@ -64,7 +64,11 @@ const ResponsePanel = createClass({
try {
json = JSON.parse(response);
} catch (err) {
error = err;
try {
json = JSON.parse(atob(response));
} catch (err64) {
error = err;
}
}
if (/\bjson/.test(mimeType) || json) {

View File

@ -16,6 +16,7 @@ support-files =
html_frame-subdocument.html
html_filter-test-page.html
html_infinite-get-page.html
html_json-b64.html
html_json-custom-mime-test-page.html
html_json-long-test-page.html
html_json-malformed-test-page.html
@ -94,8 +95,6 @@ skip-if = (os == 'linux' && bits == 32 && debug) # bug 1328915, disable linux32
[browser_net_cors_requests.js]
[browser_net_cyrillic-01.js]
[browser_net_cyrillic-02.js]
[browser_net_details-no-duplicated-content.js]
skip-if = true # Test broken in React version, is too low-level
[browser_net_frame.js]
skip-if = (os == 'linux' && debug && bits == 32) # Bug 1321434
[browser_net_filter-01.js]
@ -107,6 +106,7 @@ skip-if = (os == 'linux' && debug && bits == 32) # Bug 1303439
[browser_net_html-preview.js]
[browser_net_icon-preview.js]
[browser_net_image-tooltip.js]
[browser_net_json-b64.js]
[browser_net_json-long.js]
[browser_net_json-malformed.js]
[browser_net_json_custom_mime.js]

View File

@ -38,10 +38,10 @@ add_task(function* () {
time: true
});
wait = waitForDOM(document, "#panel-3 .editor-mount iframe");
wait = waitForDOM(document, "#response-panel .editor-mount iframe");
EventUtils.sendMouseEvent({ type: "mousedown" },
document.getElementById("details-pane-toggle"));
document.querySelector("#tab-3 a").click();
document.querySelector("#response-tab").click();
let [editorFrame] = yield wait;
yield once(editorFrame, "DOMContentLoaded");

View File

@ -25,43 +25,43 @@ add_task(function* () {
});
yield wait;
wait = waitForDOM(document, "#panel-2 .tree-section", 2);
wait = waitForDOM(document, "#params-panel .tree-section", 2);
EventUtils.sendMouseEvent({ type: "mousedown" },
document.getElementById("details-pane-toggle"));
document.querySelector("#tab-2 a").click();
document.querySelector("#params-tab").click();
yield wait;
testParamsTab1("a", '""', '{ "foo": "bar" }', '""');
wait = waitForDOM(document, "#panel-2 .tree-section", 2);
wait = waitForDOM(document, "#params-panel .tree-section", 2);
RequestsMenu.selectedIndex = 1;
yield wait;
testParamsTab1("a", '"b"', '{ "foo": "bar" }', '""');
wait = waitForDOM(document, "#panel-2 .tree-section", 2);
wait = waitForDOM(document, "#params-panel .tree-section", 2);
RequestsMenu.selectedIndex = 2;
yield wait;
testParamsTab1("a", '"b"', "foo", '"bar"');
wait = waitForDOM(document, "#panel-2 tr:not(.tree-section).treeRow", 2);
wait = waitForDOM(document, "#params-panel tr:not(.tree-section).treeRow", 2);
RequestsMenu.selectedIndex = 3;
yield wait;
testParamsTab2("a", '""', '{ "foo": "bar" }', "js");
wait = waitForDOM(document, "#panel-2 tr:not(.tree-section).treeRow", 2);
wait = waitForDOM(document, "#params-panel tr:not(.tree-section).treeRow", 2);
RequestsMenu.selectedIndex = 4;
yield wait;
testParamsTab2("a", '"b"', '{ "foo": "bar" }', "js");
// Wait for all tree sections and editor updated by react
let waitSections = waitForDOM(document, "#panel-2 .tree-section", 2);
let waitEditor = waitForDOM(document, "#panel-2 .editor-mount iframe");
let waitSections = waitForDOM(document, "#params-panel .tree-section", 2);
let waitEditor = waitForDOM(document, "#params-panel .editor-mount iframe");
RequestsMenu.selectedIndex = 5;
let [, editorFrames] = yield Promise.all([waitSections, waitEditor]);
yield once(editorFrames[0], "DOMContentLoaded");
yield waitForDOM(editorFrames[0].contentDocument, ".CodeMirror-code");
testParamsTab2("a", '"b"', "?foo=bar", "text");
wait = waitForDOM(document, "#panel-2 .empty-notice");
wait = waitForDOM(document, "#params-panel .empty-notice");
RequestsMenu.selectedIndex = 6;
yield wait;
testParamsTab3();
@ -70,7 +70,7 @@ add_task(function* () {
function testParamsTab1(queryStringParamName, queryStringParamValue,
formDataParamName, formDataParamValue) {
let tabpanel = document.querySelector("#panel-2");
let tabpanel = document.querySelector("#params-panel");
is(tabpanel.querySelectorAll(".tree-section").length, 2,
"The number of param tree sections displayed in this tabpanel is incorrect.");
@ -111,7 +111,7 @@ add_task(function* () {
function testParamsTab2(queryStringParamName, queryStringParamValue,
requestPayload, editorMode) {
let isJSON = editorMode === "js";
let tabpanel = document.querySelector("#panel-2");
let tabpanel = document.querySelector("#params-panel");
is(tabpanel.querySelectorAll(".tree-section").length, 2,
"The number of param tree sections displayed in this tabpanel is incorrect.");
@ -164,7 +164,7 @@ add_task(function* () {
}
function testParamsTab3() {
let tabpanel = document.querySelector("#panel-2");
let tabpanel = document.querySelector("#params-panel");
is(tabpanel.querySelectorAll(".tree-section").length, 0,
"The number of param tree sections displayed in this tabpanel is incorrect.");

View File

@ -90,14 +90,6 @@ add_task(function* () {
time: true
});
wait = waitForDOM(document, "#panel-3");
EventUtils.sendMouseEvent({ type: "mousedown" },
document.getElementById("details-pane-toggle"));
document.querySelector("#tab-3 a").click();
yield wait;
RequestsMenu.selectedIndex = -1;
yield selectIndexAndWaitForEditor(0);
yield testResponseTab("xml");
@ -122,7 +114,7 @@ add_task(function* () {
yield teardown(monitor);
function* testResponseTab(type) {
let tabpanel = document.querySelector("#panel-3");
let tabpanel = document.querySelector("#response-panel");
function checkVisibility(box) {
is(tabpanel.querySelector(".response-error-header") === null,
@ -232,10 +224,11 @@ add_task(function* () {
}
function* selectIndexAndWaitForEditor(index) {
let editor = document.querySelector("#panel-3 .editor-mount iframe");
let editor = document.querySelector("#response-panel .editor-mount iframe");
if (!editor) {
let waitDOM = waitForDOM(document, ".editor-mount iframe");
let waitDOM = waitForDOM(document, "#response-panel .editor-mount iframe");
RequestsMenu.selectedIndex = index;
document.querySelector("#response-tab").click();
[editor] = yield waitDOM;
yield once(editor, "DOMContentLoaded");
} else {
@ -246,14 +239,14 @@ add_task(function* () {
}
function* selectIndexAndWaitForJSONView(index) {
let tabpanel = document.querySelector("#panel-3");
let tabpanel = document.querySelector("#response-panel");
let waitDOM = waitForDOM(tabpanel, ".treeTable");
RequestsMenu.selectedIndex = index;
yield waitDOM;
}
function* selectIndexAndWaitForImageView(index) {
let tabpanel = document.querySelector("#panel-3");
let tabpanel = document.querySelector("#response-panel");
let waitDOM = waitForDOM(tabpanel, ".response-image");
RequestsMenu.selectedIndex = index;
let [imageNode] = yield waitDOM;

View File

@ -28,10 +28,10 @@ add_task(function* () {
statusText: "DA DA DA"
});
wait = waitForDOM(document, "#panel-3 .editor-mount iframe");
wait = waitForDOM(document, "#response-panel .editor-mount iframe");
EventUtils.sendMouseEvent({ type: "mousedown" },
document.getElementById("details-pane-toggle"));
document.querySelector("#tab-3 a").click();
document.querySelector("#response-tab").click();
let [editor] = yield wait;
yield once(editor, "DOMContentLoaded");
yield waitForDOM(editor.contentDocument, ".CodeMirror-code");

View File

@ -27,10 +27,10 @@ add_task(function* () {
statusText: "OK"
});
wait = waitForDOM(document, "#panel-3 .editor-mount iframe");
wait = waitForDOM(document, "#response-panel .editor-mount iframe");
EventUtils.sendMouseEvent({ type: "mousedown" },
document.getElementById("details-pane-toggle"));
document.querySelector("#tab-3 a").click();
document.querySelector("#response-tab").click();
let [editor] = yield wait;
yield once(editor, "DOMContentLoaded");
yield waitForDOM(editor.contentDocument, ".CodeMirror-code");

View File

@ -1,171 +0,0 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
"use strict";
// A test to ensure that the content in details pane is not duplicated.
add_task(function* () {
let { tab, monitor } = yield initNetMonitor(CUSTOM_GET_URL);
let panel = monitor.panelWin;
let { NetMonitorView, EVENTS } = panel;
let { RequestsMenu, NetworkDetails } = NetMonitorView;
const COOKIE_UNIQUE_PATH = "/do-not-use-in-other-tests-using-cookies";
let TEST_CASES = [
{
desc: "Test headers tab",
pageURI: CUSTOM_GET_URL,
requestURI: null,
isPost: false,
tabIndex: 0,
variablesView: NetworkDetails._headers,
expectedScopeLength: 2,
},
{
desc: "Test cookies tab",
pageURI: CUSTOM_GET_URL,
requestURI: COOKIE_UNIQUE_PATH,
isPost: false,
tabIndex: 1,
variablesView: NetworkDetails._cookies,
expectedScopeLength: 1,
},
{
desc: "Test params tab",
pageURI: POST_RAW_URL,
requestURI: null,
isPost: true,
tabIndex: 2,
variablesView: NetworkDetails._params,
expectedScopeLength: 1,
},
];
info("Adding a cookie for the \"Cookie\" tab test");
yield setDocCookie("a=b; path=" + COOKIE_UNIQUE_PATH);
info("Running tests");
for (let spec of TEST_CASES) {
yield runTestCase(spec);
}
// Remove the cookie. If an error occurs the path of the cookie ensures it
// doesn't mess with the other tests.
info("Removing the added cookie.");
yield setDocCookie(
"a=; expires=Thu, 01 Jan 1970 00:00:00 GMT; path=" + COOKIE_UNIQUE_PATH);
yield teardown(monitor);
/**
* Set a content document cookie
*/
function setDocCookie(cookie) {
return ContentTask.spawn(tab.linkedBrowser, cookie, function* (cookieArg) {
content.document.cookie = cookieArg;
});
}
/**
* A helper that handles the execution of each case.
*/
function* runTestCase(spec) {
info("Running case: " + spec.desc);
let wait = waitForNetworkEvents(monitor, 1);
tab.linkedBrowser.loadURI(spec.pageURI);
yield wait;
RequestsMenu.clear();
yield waitForFinalDetailTabUpdate(spec.tabIndex, spec.isPost, spec.requestURI);
is(spec.variablesView._store.length, spec.expectedScopeLength,
"View contains " + spec.expectedScopeLength + " scope headers");
}
/**
* A helper that prepares the variables view for the actual testing. It
* - selects the correct tab
* - performs the specified request to specified URI
* - opens the details view
* - waits for the final update to happen
*/
function* waitForFinalDetailTabUpdate(tabIndex, isPost, uri) {
let onNetworkEvent = panel.once(EVENTS.NETWORK_EVENT);
let onDetailsPopulated = panel.once(EVENTS.NETWORKDETAILSVIEW_POPULATED);
let onRequestFinished = isPost ?
waitForNetworkEvents(monitor, 0, 1) :
waitForNetworkEvents(monitor, 1);
info("Performing a request");
yield ContentTask.spawn(tab.linkedBrowser, uri, function* (url) {
content.wrappedJSObject.performRequests(1, url);
});
info("Waiting for NETWORK_EVENT");
yield onNetworkEvent;
if (!RequestsMenu.getItemAtIndex(0)) {
info("Waiting for the request to be added to the view");
yield monitor.panelWin.once(EVENTS.REQUEST_ADDED);
}
ok(true, "Received NETWORK_EVENT. Selecting the item.");
let item = RequestsMenu.getItemAtIndex(0);
RequestsMenu.selectedItem = item;
info("Item selected. Waiting for NETWORKDETAILSVIEW_POPULATED");
yield onDetailsPopulated;
info("Received populated event. Selecting tab at index " + tabIndex);
NetworkDetails.widget.selectedIndex = tabIndex;
info("Waiting for request to finish.");
yield onRequestFinished;
ok(true, "Request finished.");
/**
* Because this test uses lazy updates there's four scenarios to consider:
* #1: Everything is updated and test is ready to continue.
* #2: There's updates that are waiting to be flushed.
* #3: Updates are flushed but the tab update is still running.
* #4: There's pending updates and a tab update is still running.
*
* For case #1 there's not going to be a TAB_UPDATED event so don't wait for
* it (bug 1106181).
*
* For cases #2 and #3 it's enough to wait for one TAB_UPDATED event as for
* - case #2 the next flush will perform the final update and single
* TAB_UPDATED event is emitted.
* - case #3 the running update is the final update that'll emit one
* TAB_UPDATED event.
*
* For case #4 we must wait for the updates to be flushed before we can
* start waiting for TAB_UPDATED event or we'll continue the test right
* after the pending update finishes.
*/
let hasQueuedUpdates = RequestsMenu._updateQueue.length !== 0;
let hasRunningTabUpdate = NetworkDetails._viewState.updating[tabIndex];
if (hasQueuedUpdates || hasRunningTabUpdate) {
info("There's pending updates - waiting for them to finish.");
info(" hasQueuedUpdates: " + hasQueuedUpdates);
info(" hasRunningTabUpdate: " + hasRunningTabUpdate);
if (hasQueuedUpdates && hasRunningTabUpdate) {
info("Waiting for updates to be flushed.");
// _flushRequests calls .populate which emits the following event
yield panel.once(EVENTS.NETWORKDETAILSVIEW_POPULATED);
info("Requests flushed.");
}
info("Waiting for final tab update.");
yield waitFor(panel, EVENTS.TAB_UPDATED);
}
info("All updates completed.");
}
});

View File

@ -25,26 +25,26 @@ add_task(function* () {
EventUtils.sendMouseEvent({ type: "mousedown" },
document.getElementById("details-pane-toggle"));
ok(document.querySelector("#tab-0.is-active"),
ok(document.querySelector("#headers-tab[aria-selected=true]"),
"The headers tab in the details panel should be selected.");
ok(!document.querySelector("#tab-5"),
ok(!document.querySelector("#preview-tab"),
"The preview tab should be hidden for non html responses.");
ok(!document.querySelector("#panel-5"),
ok(!document.querySelector("#preview-panel"),
"The preview panel is hidden for non html responses.");
wait = waitForDOM(document, "#tab-5");
wait = waitForDOM(document, ".tabs");
EventUtils.sendMouseEvent({ type: "mousedown" },
document.querySelectorAll(".request-list-item")[4]);
yield wait;
document.querySelector("#tab-5 a").click();
document.querySelector("#preview-tab").click();
ok(document.querySelector("#tab-5.is-active"),
ok(document.querySelector("#preview-tab[aria-selected=true]"),
"The preview tab in the details panel should be selected.");
ok(document.querySelector("#panel-5"),
ok(document.querySelector("#preview-panel"),
"The preview panel should be visible now.");
let iframe = document.querySelector("#panel-5 iframe");
let iframe = document.querySelector("#preview-panel iframe");
yield once(iframe, "DOMContentLoaded");
ok(iframe,
@ -57,11 +57,11 @@ add_task(function* () {
EventUtils.sendMouseEvent({ type: "mousedown" },
document.querySelectorAll(".request-list-item")[5]);
ok(document.querySelector("#tab-0.is-active"),
ok(document.querySelector("#headers-tab[aria-selected=true]"),
"The headers tab in the details panel should be selected again.");
ok(!document.querySelector("#tab-5"),
ok(!document.querySelector("#preview-tab"),
"The preview tab should be hidden again for non html responses.");
ok(!document.querySelector("#panel-5"),
ok(!document.querySelector("#preview-panel"),
"The preview panel is hidden again for non html responses.");
yield teardown(monitor);

View File

@ -0,0 +1,62 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
"use strict";
/**
* Tests if JSON responses encoded in base64 are handled correctly.
*/
add_task(function* () {
let { L10N } = require("devtools/client/netmonitor/l10n");
let { tab, monitor } = yield initNetMonitor(JSON_B64_URL);
info("Starting test... ");
let { document, NetMonitorView } = monitor.panelWin;
let { RequestsMenu } = NetMonitorView;
RequestsMenu.lazyUpdate = false;
let wait = waitForNetworkEvents(monitor, 1);
yield ContentTask.spawn(tab.linkedBrowser, {}, function* () {
content.wrappedJSObject.performRequests();
});
yield wait;
wait = waitForDOM(document, "#response-panel");
EventUtils.sendMouseEvent({ type: "mousedown" },
document.getElementById("details-pane-toggle"));
document.querySelector("#response-tab").click();
yield wait;
let tabpanel = document.querySelector("#response-panel");
is(tabpanel.querySelector(".response-error-header") === null, true,
"The response error header doesn't have the intended visibility.");
let jsonView = tabpanel.querySelector(".tree-section .treeLabel") || {};
is(jsonView.textContent === L10N.getStr("jsonScopeName"), true,
"The response json view has the intended visibility.");
is(tabpanel.querySelector(".editor-mount iframe") === null, true,
"The response editor doesn't have the intended visibility.");
is(tabpanel.querySelector(".response-image-box") === null, true,
"The response image box doesn't have the intended visibility.");
is(tabpanel.querySelectorAll(".tree-section").length, 1,
"There should be 1 tree sections displayed in this tabpanel.");
is(tabpanel.querySelectorAll(".treeRow:not(.tree-section)").length, 1,
"There should be 1 json properties displayed in this tabpanel.");
is(tabpanel.querySelectorAll(".empty-notice").length, 0,
"The empty notice should not be displayed in this tabpanel.");
let labels = tabpanel
.querySelectorAll("tr:not(.tree-section) .treeLabelCell .treeLabel");
let values = tabpanel
.querySelectorAll("tr:not(.tree-section) .treeValueCell .objectBox");
is(labels[0].textContent, "greeting",
"The first json property name was incorrect.");
is(values[0].textContent, "\"This is a base 64 string.\"",
"The first json property value was incorrect.");
yield teardown(monitor);
});

View File

@ -39,10 +39,10 @@ add_task(function* () {
time: true
});
wait = waitForDOM(document, "#panel-3");
wait = waitForDOM(document, "#response-panel");
EventUtils.sendMouseEvent({ type: "mousedown" },
document.getElementById("details-pane-toggle"));
document.querySelector("#tab-3 a").click();
document.querySelector("#response-tab").click();
yield wait;
testResponseTab();
@ -50,7 +50,7 @@ add_task(function* () {
yield teardown(monitor);
function testResponseTab() {
let tabpanel = document.querySelector("#panel-3");
let tabpanel = document.querySelector("#response-panel");
is(tabpanel.querySelector(".response-error-header") === null, true,
"The response error header doesn't have the intended visibility.");

View File

@ -31,15 +31,15 @@ add_task(function* () {
fullMimeType: "text/json; charset=utf-8"
});
wait = waitForDOM(document, "#panel-3 .editor-mount iframe");
wait = waitForDOM(document, "#response-panel .editor-mount iframe");
EventUtils.sendMouseEvent({ type: "mousedown" },
document.getElementById("details-pane-toggle"));
document.querySelector("#tab-3 a").click();
document.querySelector("#response-tab").click();
let [editor] = yield wait;
yield once(editor, "DOMContentLoaded");
yield waitForDOM(editor.contentDocument, ".CodeMirror-code");
let tabpanel = document.querySelector("#panel-3");
let tabpanel = document.querySelector("#response-panel");
is(tabpanel.querySelector(".response-error-header") === null, false,
"The response error header doesn't have the intended visibility.");
is(tabpanel.querySelector(".response-error-header").textContent,

View File

@ -34,10 +34,10 @@ add_task(function* () {
time: true
});
wait = waitForDOM(document, "#panel-3");
wait = waitForDOM(document, "#response-panel");
EventUtils.sendMouseEvent({ type: "mousedown" },
document.getElementById("details-pane-toggle"));
document.querySelector("#tab-3 a").click();
document.querySelector("#response-tab").click();
yield wait;
testResponseTab();
@ -45,7 +45,7 @@ add_task(function* () {
yield teardown(monitor);
function testResponseTab() {
let tabpanel = document.querySelector("#panel-3");
let tabpanel = document.querySelector("#response-panel");
is(tabpanel.querySelector(".response-error-header") === null, true,
"The response error header doesn't have the intended visibility.");

View File

@ -34,10 +34,10 @@ add_task(function* () {
time: true
});
wait = waitForDOM(document, "#panel-3");
wait = waitForDOM(document, "#response-panel");
EventUtils.sendMouseEvent({ type: "mousedown" },
document.getElementById("details-pane-toggle"));
document.querySelector("#tab-3 a").click();
document.querySelector("#response-tab").click();
yield wait;
testResponseTab();
@ -45,7 +45,7 @@ add_task(function* () {
yield teardown(monitor);
function testResponseTab() {
let tabpanel = document.querySelector("#panel-3");
let tabpanel = document.querySelector("#response-panel");
is(tabpanel.querySelector(".response-error-header") === null, true,
"The response error header doesn't have the intended visibility.");

View File

@ -43,15 +43,15 @@ add_task(function* () {
time: true
});
wait = waitForDOM(document, "#panel-3");
wait = waitForDOM(document, "#response-panel");
EventUtils.sendMouseEvent({ type: "mousedown" },
document.getElementById("details-pane-toggle"));
document.querySelector("#tab-3 a").click();
document.querySelector("#response-tab").click();
yield wait;
testResponseTab("$_0123Fun", "\"Hello JSONP!\"");
wait = waitForDOM(document, "#panel-3 .tree-section");
wait = waitForDOM(document, "#response-panel .tree-section");
RequestsMenu.selectedIndex = 1;
yield wait;
@ -60,7 +60,7 @@ add_task(function* () {
yield teardown(monitor);
function testResponseTab(func, greeting) {
let tabpanel = document.querySelector("#panel-3");
let tabpanel = document.querySelector("#response-panel");
is(tabpanel.querySelector(".response-error-header") === null, true,
"The response error header doesn't have the intended visibility.");

View File

@ -34,10 +34,10 @@ add_task(function* () {
statusText: "OK"
});
let waitDOM = waitForDOM(document, "#panel-3 .editor-mount iframe");
let waitDOM = waitForDOM(document, "#response-panel .editor-mount iframe");
EventUtils.sendMouseEvent({ type: "mousedown" },
document.getElementById("details-pane-toggle"));
document.querySelector("#tab-3 a").click();
document.querySelector("#response-tab").click();
let [editor] = yield waitDOM;
yield once(editor, "DOMContentLoaded");
yield waitForDOM(editor.contentDocument, ".CodeMirror-code");

View File

@ -47,16 +47,16 @@ add_task(function* () {
});
// Wait for all tree sections updated by react
wait = waitForDOM(document, "#panel-2 .tree-section", 2);
wait = waitForDOM(document, "#params-panel .tree-section", 2);
EventUtils.sendMouseEvent({ type: "mousedown" },
document.getElementById("details-pane-toggle"));
document.querySelector("#tab-2 a").click();
document.querySelector("#params-tab").click();
yield wait;
yield testParamsTab("urlencoded");
// Wait for all tree sections and editor updated by react
let waitForSections = waitForDOM(document, "#panel-2 .tree-section", 2);
let waitForEditor = waitForDOM(document, "#panel-2 .editor-mount iframe");
let waitForSections = waitForDOM(document, "#params-panel .tree-section", 2);
let waitForEditor = waitForDOM(document, "#params-panel .editor-mount iframe");
RequestsMenu.selectedIndex = 1;
let [, editorFrames] = yield Promise.all([waitForSections, waitForEditor]);
yield once(editorFrames[0], "DOMContentLoaded");
@ -66,7 +66,7 @@ add_task(function* () {
return teardown(monitor);
function* testParamsTab(type) {
let tabpanel = document.querySelector("#panel-2");
let tabpanel = document.querySelector("#params-panel");
function checkVisibility(box) {
is(!tabpanel.querySelector(".treeTable"), !box.includes("params"),

View File

@ -26,13 +26,13 @@ add_task(function* () {
yield wait;
// Wait for all tree view updated by react
wait = waitForDOM(document, "#panel-2 .tree-section");
wait = waitForDOM(document, "#params-panel .tree-section");
EventUtils.sendMouseEvent({ type: "mousedown" },
document.getElementById("details-pane-toggle"));
document.querySelector("#tab-2 a").click();
document.querySelector("#params-tab").click();
yield wait;
let tabpanel = document.querySelector("#panel-2");
let tabpanel = document.querySelector("#params-panel");
ok(tabpanel.querySelector(".treeTable"),
"The request params doesn't have the indended visibility.");

View File

@ -26,13 +26,13 @@ add_task(function* () {
yield wait;
// Wait for all tree view updated by react
wait = waitForDOM(document, "#panel-0");
wait = waitForDOM(document, "#headers-panel");
EventUtils.sendMouseEvent({ type: "mousedown" },
document.getElementById("details-pane-toggle"));
document.querySelector("#tab-0 a").click();
document.querySelector("#headers-tab").click();
yield wait;
let tabpanel = document.querySelector("#panel-0");
let tabpanel = document.querySelector("#headers-panel");
is(tabpanel.querySelectorAll(".tree-section .treeLabel").length, 3,
"There should be 3 header sections displayed in this tabpanel.");
@ -57,11 +57,11 @@ add_task(function* () {
"The second request header value was incorrect.");
// Wait for all tree sections updated by react
wait = waitForDOM(document, "#panel-2 .tree-section");
document.querySelector("#tab-2 a").click();
wait = waitForDOM(document, "#params-panel .tree-section");
document.querySelector("#params-tab").click();
yield wait;
tabpanel = document.querySelector("#panel-2");
tabpanel = document.querySelector("#params-panel");
ok(tabpanel.querySelector(".treeTable"),
"The params tree view should be displayed.");

View File

@ -26,13 +26,13 @@ add_task(function* () {
yield wait;
// Wait for all tree view updated by react
wait = waitForDOM(document, "#panel-2 .tree-section");
wait = waitForDOM(document, "#params-panel .tree-section");
EventUtils.sendMouseEvent({ type: "mousedown" },
document.getElementById("details-pane-toggle"));
document.querySelector("#tab-2 a").click();
document.querySelector("#params-tab").click();
yield wait;
let tabpanel = document.querySelector("#panel-2");
let tabpanel = document.querySelector("#params-panel");
ok(tabpanel.querySelector(".treeTable"),
"The request params doesn't have the indended visibility.");

View File

@ -22,13 +22,13 @@ add_task(function* () {
});
yield wait;
wait = waitForDOM(document, "#panel-5");
wait = waitForDOM(document, "#security-panel");
EventUtils.sendMouseEvent({ type: "mousedown" },
document.querySelector("#details-pane-toggle"));
document.querySelector("#tab-5 a").click();
document.querySelector("#security-tab").click();
yield wait;
let tabpanel = document.querySelector("#panel-5");
let tabpanel = document.querySelector("#security-panel");
let textboxes = tabpanel.querySelectorAll(".textbox-input");
// Connection

View File

@ -21,10 +21,10 @@ add_task(function* () {
});
yield wait;
wait = waitForDOM(document, "#panel-5");
wait = waitForDOM(document, "#security-panel");
EventUtils.sendMouseEvent({ type: "mousedown" },
document.querySelector("#details-pane-toggle"));
document.querySelector("#tab-5 a").click();
document.querySelector("#security-tab").click();
yield wait;
let errormsg = document.querySelector(".security-info-value");

View File

@ -24,7 +24,7 @@ add_task(function* () {
info("Selecting headers panel again.");
EventUtils.sendMouseEvent({ type: "mousedown" },
document.querySelector("#tab-0 a"));
document.querySelector("#headers-tab"));
info("Sorting the items by filename.");
EventUtils.sendMouseEvent({ type: "click" },
@ -47,10 +47,11 @@ add_task(function* () {
let item = RequestsMenu.getItemAtIndex(0);
let icon = document.querySelector(".requests-security-state-icon");
let wait = waitForDOM(document, "#panel-5");
let wait = waitForDOM(document, "#security-panel");
info("Clicking security icon of the first request and waiting for panel update.");
EventUtils.synthesizeMouseAtCenter(icon, {}, monitor.panelWin);
yield wait;
ok(document.querySelector("#tab-5.is-active"), "Security tab is selected.");
ok(document.querySelector("#security-tab[aria-selected=true]"), "Security tab is selected.");
}
});

View File

@ -36,13 +36,13 @@ add_task(function* () {
info("Selecting security tab.");
EventUtils.sendMouseEvent({ type: "mousedown" },
document.querySelector("#tab-5 a"));
document.querySelector("#security-tab"));
info("Selecting insecure request.");
EventUtils.sendMouseEvent({ type: "mousedown" },
document.querySelectorAll(".request-list-item")[1]);
ok(document.querySelector("#tab-0.is-active"),
ok(document.querySelector("#headers-tab[aria-selected=true]"),
"Selected tab was reset when selected security tab was hidden.");
return teardown(monitor);

View File

@ -58,34 +58,25 @@ add_task(function* () {
is(RequestsMenu.selectedItem.securityState, undefined,
"Security state has not yet arrived.");
is(!!document.querySelector("#tab-5"), testcase.visibleOnNewEvent,
is(!!document.querySelector("#security-tab"), testcase.visibleOnNewEvent,
"Security tab is " + (testcase.visibleOnNewEvent ? "visible" : "hidden") +
" after new request was added to the menu.");
is(!!document.querySelector("#panel-5"), testcase.visibleOnNewEvent,
"Security panel is " + (testcase.visibleOnNewEvent ? "visible" : "hidden") +
" after new request was added to the menu.");
info("Waiting for security information to arrive.");
yield onSecurityInfo;
ok(RequestsMenu.selectedItem.securityState,
"Security state arrived.");
is(!!document.querySelector("#tab-5"), testcase.visibleOnSecurityInfo,
is(!!document.querySelector("#security-tab"), testcase.visibleOnSecurityInfo,
"Security tab is " + (testcase.visibleOnSecurityInfo ? "visible" : "hidden") +
" after security information arrived.");
is(!!document.querySelector("#panel-5"), testcase.visibleOnSecurityInfo,
"Security panel is " + (testcase.visibleOnSecurityInfo? "visible" : "hidden") +
" after security information arrived.");
info("Waiting for request to complete.");
yield onComplete;
is(!!document.querySelector("#tab-5"), testcase.visibleOnceComplete,
is(!!document.querySelector("#security-tab"), testcase.visibleOnceComplete,
"Security tab is " + (testcase.visibleOnceComplete ? "visible" : "hidden") +
" after request has been completed.");
is(!!document.querySelector("#panel-5"), testcase.visibleOnceComplete,
"Security panel is " + (testcase.visibleOnceComplete? "visible" : "hidden") +
" after request has been completed.");
info("Clearing requests.");
RequestsMenu.clear();

View File

@ -38,10 +38,10 @@ add_task(function* () {
document.querySelectorAll(".request-list-item")[0]);
yield wait;
if (!document.querySelector("#tab-5.is-active")) {
if (!document.querySelector("#security-tab[aria-selected=true]")) {
info("Selecting security tab.");
wait = waitForDOM(document, "#panel-5 .properties-view");
document.querySelector("#tab-5 a").click();
wait = waitForDOM(document, "#security-panel .properties-view");
document.querySelector("#security-tab").click();
yield wait;
}

View File

@ -145,12 +145,12 @@ add_task(function* () {
* A function that tests "Headers" panel contains correct information.
*/
function* testHeaders(data, index) {
let wait = waitForDOM(document, "#panel-0");
let wait = waitForDOM(document, "#headers-panel");
EventUtils.sendMouseEvent({ type: "mousedown" },
document.querySelectorAll(".request-list-item")[index]);
yield wait;
let panel = document.querySelector("#panel-0");
let panel = document.querySelector("#headers-panel");
let summaryValues = panel.querySelectorAll(".tabpanel-summary-value.textbox-input");
let { method, uri, details: { status, statusText } } = data;
@ -166,13 +166,13 @@ add_task(function* () {
* A function that tests "Params" panel contains correct information.
*/
function* testParams(data, index) {
let wait = waitForDOM(document, "#panel-2 .properties-view");
let wait = waitForDOM(document, "#params-panel .properties-view");
EventUtils.sendMouseEvent({ type: "mousedown" },
document.querySelectorAll(".request-list-item")[index]);
document.querySelector("#tab-2 a").click();
document.querySelector("#params-tab").click();
yield wait;
let panel = document.querySelector("#panel-2");
let panel = document.querySelector("#params-panel");
let statusParamValue = data.uri.split("=").pop();
let statusParamShownValue = "\"" + statusParamValue + "\"";
let treeSections = panel.querySelectorAll(".tree-section");

View File

@ -40,10 +40,10 @@ add_task(function* () {
});
});
wait = waitForDOM(document, "#panel-3");
wait = waitForDOM(document, "#response-panel");
EventUtils.sendMouseEvent({ type: "mousedown" },
document.getElementById("details-pane-toggle"));
document.querySelector("#tab-3 a").click();
document.querySelector("#response-tab").click();
yield wait;
RequestsMenu.selectedIndex = -1;
@ -59,10 +59,11 @@ add_task(function* () {
return teardown(monitor);
function* selectIndexAndWaitForEditor(index) {
let editor = document.querySelector("#panel-3 .editor-mount iframe");
let editor = document.querySelector("#response-panel .editor-mount iframe");
if (!editor) {
let waitDOM = waitForDOM(document, "#panel-3 .editor-mount iframe");
let waitDOM = waitForDOM(document, "#response-panel .editor-mount iframe");
RequestsMenu.selectedIndex = index;
document.querySelector("#response-tab").click();
[editor] = yield waitDOM;
yield once(editor, "DOMContentLoaded");
} else {
@ -73,7 +74,7 @@ add_task(function* () {
}
function testEditorContent([ fmt, textRe ]) {
let editor = document.querySelector("#panel-3 .editor-mount iframe");
let editor = document.querySelector("#response-panel .editor-mount iframe");
let text = editor.contentDocument
.querySelector(".CodeMirror-line").textContent;

View File

@ -39,6 +39,7 @@ const JSON_LONG_URL = EXAMPLE_URL + "html_json-long-test-page.html";
const JSON_MALFORMED_URL = EXAMPLE_URL + "html_json-malformed-test-page.html";
const JSON_CUSTOM_MIME_URL = EXAMPLE_URL + "html_json-custom-mime-test-page.html";
const JSON_TEXT_MIME_URL = EXAMPLE_URL + "html_json-text-mime-test-page.html";
const JSON_B64_URL = EXAMPLE_URL + "html_json-b64.html";
const SORTING_URL = EXAMPLE_URL + "html_sorting-test-page.html";
const FILTERING_URL = EXAMPLE_URL + "html_filter-test-page.html";
const INFINITE_GET_URL = EXAMPLE_URL + "html_infinite-get-page.html";

View File

@ -0,0 +1,38 @@
<!-- Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ -->
<!doctype html>
<html>
<head>
<meta charset="utf-8"/>
<meta http-equiv="Cache-Control" content="no-cache, no-store, must-revalidate" />
<meta http-equiv="Pragma" content="no-cache" />
<meta http-equiv="Expires" content="0" />
<title>Network Monitor test page</title>
</head>
<body>
<p>JSON b64 test</p>
<script type="text/javascript">
function get(aAddress, aCallback) {
var xhr = new XMLHttpRequest();
xhr.open("GET", aAddress, true);
xhr.onreadystatechange = function() {
if (this.readyState == this.DONE) {
aCallback();
}
};
xhr.send(null);
}
function performRequests() {
get("sjs_content-type-test-server.sjs?fmt=json-b64", function() {
// Done.
});
}
</script>
</body>
</html>

View File

@ -137,6 +137,14 @@ function handleRequest(request, response) {
response.finish();
break;
}
case "json-b64": {
response.setStatusLine(request.httpVersion, status, "OK");
response.setHeader("Content-Type", "text/json; charset=utf-8", false);
setCacheHeaders();
response.write(btoa("{ \"greeting\": \"This is a base 64 string.\" }"));
response.finish();
break;
}
case "json-long": {
let str = "{ \"greeting\": \"Hello long string JSON!\" },";
response.setStatusLine(request.httpVersion, status, "OK");

View File

@ -25,30 +25,39 @@ let Tabbar = createClass({
children: PropTypes.object,
onSelect: PropTypes.func,
showAllTabsMenu: PropTypes.bool,
tabActive: PropTypes.number,
activeTabId: PropTypes.string,
toolbox: PropTypes.object,
renderOnlySelected: PropTypes.bool,
},
getDefaultProps: function () {
return {
showAllTabsMenu: false,
tabActive: 0,
};
},
getInitialState: function () {
let { children } = this.props;
let { activeTabId, children = [] } = this.props;
let tabs = this.createTabs(children);
let activeTab = tabs.findIndex((tab, index) => tab.id === activeTabId);
return {
tabs: children ? this.createTabs(children) : [],
activeTab: 0
activeTab: activeTab === -1 ? 0 : activeTab,
tabs,
};
},
componentWillReceiveProps: function (nextProps) {
let { children } = nextProps;
let { activeTabId, children = [] } = nextProps;
let tabs = this.createTabs(children);
let activeTab = tabs.findIndex((tab, index) => tab.id === activeTabId);
if (children && children !== this.props.children) {
this.setState({ tabs: this.createTabs(children) });
if (activeTab !== this.state.activeTab ||
(children !== this.props.children)) {
this.setState({
activeTab: activeTab === -1 ? 0 : activeTab,
tabs,
});
}
},
@ -57,7 +66,7 @@ let Tabbar = createClass({
.filter((panel) => panel)
.map((panel, index) =>
Object.assign({}, children[index], {
id: index,
id: panel.props.id || index,
panel,
title: panel.props.title,
})
@ -137,7 +146,7 @@ let Tabbar = createClass({
getTabIndex: function (tabId) {
let tabIndex = -1;
this.state.tabs.forEach((tab, index) => {
if (tab.id == tabId) {
if (tab.id === tabId) {
tabIndex = index;
}
});
@ -213,8 +222,9 @@ let Tabbar = createClass({
div({className: "devtools-sidebar-tabs"},
Tabs({
onAllTabsMenuClick: this.onAllTabsMenuClick,
renderOnlySelected: this.props.renderOnlySelected,
showAllTabsMenu: this.props.showAllTabsMenu,
tabActive: this.props.tabActive || this.state.activeTab,
tabActive: this.state.activeTab,
onAfterChange: this.onTabChanged,
},
tabs

View File

@ -50,12 +50,18 @@ define(function (require, exports, module) {
]).isRequired,
showAllTabsMenu: React.PropTypes.bool,
onAllTabsMenuClick: React.PropTypes.func,
// Set true will only render selected panel on DOM. It's complete
// opposite of the created array, and it's useful if panels content
// is unpredictable and update frequently.
renderOnlySelected: React.PropTypes.bool,
},
getDefaultProps: function () {
return {
tabActive: 0,
showAllTabsMenu: false,
renderOnlySelected: false,
};
},
@ -105,8 +111,9 @@ define(function (require, exports, module) {
if (typeof tabActive === "number") {
let panels = children.filter((panel) => panel);
// Reset to index 0 if index larger than number of panels
tabActive = tabActive < panels.length ? tabActive : 0;
// Reset to index 0 if index overflows the range of panel array
tabActive = (tabActive < panels.length && tabActive >= 0) ?
tabActive : 0;
let created = [...this.state.created];
created[tabActive] = true;
@ -224,17 +231,16 @@ define(function (require, exports, module) {
}
let tabs = this.props.children
.map(tab => {
return typeof tab === "function" ? tab() : tab;
}).filter(tab => {
return tab;
}).map((tab, index) => {
let ref = ("tab-menu-" + index);
.map((tab) => typeof tab === "function" ? tab() : tab)
.filter((tab) => tab)
.map((tab, index) => {
let id = tab.props.id;
let ref = "tab-menu-" + index;
let title = tab.props.title;
let tabClassName = tab.props.className;
let isTabSelected = this.state.tabActive === index;
let classes = [
let className = [
"tabs-menu-item",
tabClassName,
isTabSelected ? "is-active" : ""
@ -247,15 +253,15 @@ define(function (require, exports, module) {
// See also `onKeyDown()` event handler.
return (
DOM.li({
ref: ref,
className,
key: index,
id: "tab-" + index,
className: classes,
ref,
role: "presentation",
},
DOM.a({
tabIndex: this.state.tabActive === index ? 0 : -1,
"aria-controls": "panel-" + index,
id: id ? id + "-tab" : "tab-" + index,
tabIndex: isTabSelected ? 0 : -1,
"aria-controls": id ? id + "-panel" : "panel-" + index,
"aria-selected": isTabSelected,
role: "tab",
onClick: this.onClickTab.bind(this, index),
@ -286,23 +292,28 @@ define(function (require, exports, module) {
},
renderPanels: function () {
if (!this.props.children) {
let { children, renderOnlySelected } = this.props;
if (!children) {
throw new Error("There must be at least one Tab");
}
if (!Array.isArray(this.props.children)) {
this.props.children = [this.props.children];
if (!Array.isArray(children)) {
children = [children];
}
let selectedIndex = this.state.tabActive;
let panels = this.props.children
.map(tab => {
return typeof tab === "function" ? tab() : tab;
}).filter(tab => {
return tab;
}).map((tab, index) => {
let selected = selectedIndex == index;
let panels = children
.map((tab) => typeof tab === "function" ? tab() : tab)
.filter((tab) => tab)
.map((tab, index) => {
let selected = selectedIndex === index;
if (renderOnlySelected && !selected) {
return null;
}
let id = tab.props.id;
// Use 'visibility:hidden' + 'width/height:0' for hiding
// content of non-selected tab. It's faster (not sure why)
@ -315,12 +326,12 @@ define(function (require, exports, module) {
return (
DOM.div({
id: id ? id + "-panel" : "panel-" + index,
key: index,
id: "panel-" + index,
style: style,
className: "tab-panel-box",
role: "tabpanel",
"aria-labelledby": "tab-" + index,
"aria-labelledby": id ? id + "-tab" : "tab-" + index,
},
(selected || this.state.created[index]) ? tab : null
)
@ -335,12 +346,10 @@ define(function (require, exports, module) {
},
render: function () {
let classNames = ["tabs", this.props.className].join(" ");
return (
DOM.div({className: classNames},
DOM.div({ className: ["tabs", this.props.className].join(" ") },
this.renderMenuItems(),
this.renderPanels()
this.renderPanels(),
)
);
},

View File

@ -40,11 +40,11 @@ window.onload = Task.async(function* () {
is(tabAnchors[0].parentElement.getAttribute("role"), "presentation", "li role is set correctly");
is(tabAnchors[0].getAttribute("role"), "tab", "Anchor role is set correctly");
is(tabAnchors[0].getAttribute("aria-selected"), "true", "Anchor aria-selected is set correctly by default");
is(tabAnchors[0].getAttribute("aria-controls"), "panel-0", "Anchor aria-controls is set correctly");
is(tabAnchors[0].getAttribute("aria-controls"), "sidebar-0-panel", "Anchor aria-controls is set correctly");
is(tabAnchors[1].parentElement.getAttribute("role"), "presentation", "li role is set correctly");
is(tabAnchors[1].getAttribute("role"), "tab", "Anchor role is set correctly");
is(tabAnchors[1].getAttribute("aria-selected"), "false", "Anchor aria-selected is set correctly by default");
is(tabAnchors[1].getAttribute("aria-controls"), "panel-1", "Anchor aria-controls is set correctly");
is(tabAnchors[1].getAttribute("aria-controls"), "sidebar-1-panel", "Anchor aria-controls is set correctly");
yield setState(tabbarReact, Object.assign({}, tabbarReact.state, {
activeTab: 1
@ -56,12 +56,12 @@ window.onload = Task.async(function* () {
function addTabWithPanel(tabId) {
// Setup for InspectorTabPanel
let panel = document.createElement("div");
panel.id = `sidebar-panel-${tabId}`;
panel.id = `sidebar-${tabId}`;
document.body.appendChild(panel);
return setState(tabbarReact, Object.assign({}, tabbarReact.state, {
tabs: tabbarReact.state.tabs.concat({
id: `sidebar-panel-${tabId}`,
id: `sidebar-${tabId}`,
title: `tab-${tabId}`,
panel: InspectorTabPanel
}),

View File

@ -8,42 +8,25 @@
#define mozilla_dom_Dispatcher_h
#include "mozilla/AlreadyAddRefed.h"
#include "mozilla/TaskCategory.h"
#include "nsISupports.h"
class nsIEventTarget;
class nsIRunnable;
// This file defines basic functionality for dispatching runnables to various
// groups: either the SystemGroup or a DocGroup or TabGroup. Ideally all
// runnables destined for the main thread should be dispatched to a group
// instead so that we know what kind of web content they'll be
// touching. Runnables sent to the SystemGroup never touch web
// content. Runnables sent to a DocGroup can only touch documents belonging to
// that DocGroup. Runnables sent to a TabGroup can touch any document in any of
// the tabs belonging to the TabGroup.
namespace mozilla {
class AbstractThread;
namespace dom {
class TabGroup;
class DocGroup;
enum class TaskCategory {
// User input (clicks, keypresses, etc.)
UI,
// Data from the network
Network,
// setTimeout, setInterval
Timer,
// Runnables posted from a worker to the main thread
Worker,
// requestIdleCallback
IdleCallback,
// Vsync notifications
RefreshDriver,
// Most DOM events (postMessage, media, plugins)
Other,
Count
};
// This trait should be attached to classes like nsIGlobalObject and nsIDocument
// that have a DocGroup or TabGroup attached to them. The methods here should
@ -83,7 +66,7 @@ public:
// off the main thread.
virtual AbstractThread* AbstractMainThreadFor(TaskCategory aCategory) = 0;
// These methods perform a safe cast. They return null if |this| is not of the
// This method performs a safe cast. It returns null if |this| is not of the
// requested type.
virtual TabGroup* AsTabGroup() { return nullptr; }

View File

@ -689,11 +689,11 @@ EventSourceImpl::StreamReaderFunc(nsIInputStream* aInputStream,
uint32_t* aWriteCount)
{
EventSourceImpl* thisObject = static_cast<EventSourceImpl*>(aClosure);
thisObject->AssertIsOnTargetThread();
if (!thisObject || !aWriteCount) {
NS_WARNING("EventSource cannot read from stream: no aClosure or aWriteCount");
return NS_ERROR_FAILURE;
}
thisObject->AssertIsOnTargetThread();
thisObject->ParseSegment((const char*)aFromRawSegment, aCount);
*aWriteCount = aCount;
return NS_OK;

View File

@ -12,7 +12,11 @@
#include "nsCOMPtr.h"
#include "nsCycleCollectionParticipant.h"
#include "nsDOMNavigationTiming.h"
#include "nsICancelableRunnable.h"
#include "nsIIncrementalRunnable.h"
#include "nsIRunnable.h"
#include "nsITimeoutHandler.h"
#include "nsString.h"
class nsPIDOMWindowInner;

View File

@ -3013,7 +3013,7 @@ nsIDocument::EventTargetFor(TaskCategory aCategory) const
}
AbstractThread*
nsIDocument::AbstractMainThreadFor(mozilla::dom::TaskCategory aCategory)
nsIDocument::AbstractMainThreadFor(mozilla::TaskCategory aCategory)
{
MOZ_ASSERT(NS_IsMainThread());
if (mDocGroup) {

View File

@ -1777,14 +1777,14 @@ private:
public:
// Dispatch a runnable related to the global.
virtual nsresult Dispatch(const char* aName,
mozilla::dom::TaskCategory aCategory,
mozilla::TaskCategory aCategory,
already_AddRefed<nsIRunnable>&& aRunnable) override;
virtual nsIEventTarget*
EventTargetFor(mozilla::dom::TaskCategory aCategory) const override;
EventTargetFor(mozilla::TaskCategory aCategory) const override;
virtual mozilla::AbstractThread*
AbstractMainThreadFor(mozilla::dom::TaskCategory aCategory) override;
AbstractMainThreadFor(mozilla::TaskCategory aCategory) override;
protected:
// These members are only used on outer window objects. Make sure

View File

@ -2876,14 +2876,14 @@ public:
// Dispatch a runnable related to the document.
virtual nsresult Dispatch(const char* aName,
mozilla::dom::TaskCategory aCategory,
mozilla::TaskCategory aCategory,
already_AddRefed<nsIRunnable>&& aRunnable) override;
virtual nsIEventTarget*
EventTargetFor(mozilla::dom::TaskCategory aCategory) const override;
EventTargetFor(mozilla::TaskCategory aCategory) const override;
virtual mozilla::AbstractThread*
AbstractMainThreadFor(mozilla::dom::TaskCategory aCategory) override;
AbstractMainThreadFor(mozilla::TaskCategory aCategory) override;
// The URLs passed to these functions should match what
// JS::DescribeScriptedCaller() returns, since these APIs are used to

View File

@ -604,7 +604,7 @@ public:
mozilla::dom::DocGroup* GetDocGroup() const;
virtual nsIEventTarget*
EventTargetFor(mozilla::dom::TaskCategory aCategory) const = 0;
EventTargetFor(mozilla::TaskCategory aCategory) const = 0;
protected:
// The nsPIDOMWindow constructor. The aOuterWindow argument should

View File

@ -1338,6 +1338,7 @@ XrayResolveAttribute(JSContext* cx, JS::Handle<JSObject*> wrapper,
desc.setSetter(nullptr);
}
desc.object().set(wrapper);
desc.value().setUndefined();
return true;
}
}

6
dom/cache/Action.h vendored
View File

@ -28,11 +28,7 @@ public:
// Action::RunOnTarget().
virtual void Resolve(nsresult aRv) = 0;
NS_IMETHOD_(MozExternalRefCountType)
AddRef(void) = 0;
NS_IMETHOD_(MozExternalRefCountType)
Release(void) = 0;
NS_INLINE_DECL_PURE_VIRTUAL_REFCOUNTING
};
// Class containing data that can be opportunistically shared between

View File

@ -67,11 +67,7 @@ public:
virtual bool
HasEverBeenRead() const = 0;
NS_IMETHOD_(MozExternalRefCountType)
AddRef(void) = 0;
NS_IMETHOD_(MozExternalRefCountType)
Release(void) = 0;
NS_INLINE_DECL_PURE_VIRTUAL_REFCOUNTING
};
static already_AddRefed<ReadStream>

View File

@ -26,6 +26,7 @@
#include "mozilla/dom/CloseEvent.h"
#include "mozilla/dom/CustomEvent.h"
#include "mozilla/dom/DeviceOrientationEvent.h"
#include "mozilla/dom/ErrorEvent.h"
#include "mozilla/dom/EventTarget.h"
#include "mozilla/dom/FocusEvent.h"
#include "mozilla/dom/HashChangeEvent.h"
@ -37,8 +38,10 @@
#include "mozilla/dom/PageTransitionEvent.h"
#include "mozilla/dom/PointerEvent.h"
#include "mozilla/dom/PopStateEvent.h"
#include "mozilla/dom/RootedDictionary.h"
#include "mozilla/dom/ScrollAreaEvent.h"
#include "mozilla/dom/SimpleGestureEvent.h"
#include "mozilla/dom/ScriptSettings.h"
#include "mozilla/dom/StorageEvent.h"
#include "mozilla/dom/SVGZoomEvent.h"
#include "mozilla/dom/TimeEvent.h"
@ -1164,6 +1167,14 @@ EventDispatcher::CreateEvent(EventTarget* aOwner,
event->MarkUninitialized();
return event.forget();
}
if (aEventType.LowerCaseEqualsLiteral("errorevent")) {
LOG_EVENT_CREATION(ERROREVENT);
RootedDictionary<ErrorEventInit> init(RootingCx());
RefPtr<Event> event =
ErrorEvent::Constructor(aOwner, EmptyString(), init);
event->MarkUninitialized();
return event.forget();
}
#undef LOG_EVENT_CREATION

Some files were not shown because too many files have changed in this diff Show More