зеркало из https://github.com/mozilla/gecko-dev.git
merge mozilla-central to mozilla-inbound. r=merge a=merge
This commit is contained in:
Коммит
444f7c3600
2
.flake8
2
.flake8
|
@ -2,3 +2,5 @@
|
||||||
# See http://pep8.readthedocs.io/en/latest/intro.html#configuration
|
# See http://pep8.readthedocs.io/en/latest/intro.html#configuration
|
||||||
ignore = E121, E123, E126, E129, E133, E226, E241, E242, E704, W503, E402
|
ignore = E121, E123, E126, E129, E133, E226, E241, E242, E704, W503, E402
|
||||||
max-line-length = 99
|
max-line-length = 99
|
||||||
|
exclude =
|
||||||
|
testing/mochitest/pywebsocket,
|
||||||
|
|
2
CLOBBER
2
CLOBBER
|
@ -22,4 +22,4 @@
|
||||||
# changes to stick? As of bug 928195, this shouldn't be necessary! Please
|
# changes to stick? As of bug 928195, this shouldn't be necessary! Please
|
||||||
# don't change CLOBBER for WebIDL changes any more.
|
# don't change CLOBBER for WebIDL changes any more.
|
||||||
|
|
||||||
Bug 1340910 - clobber required for Brotli 0.6.0 update due to changes in exported headers.
|
Bug 1395286 - Fix packaging error for Android builds, presumably due to bug 1255404 and/or bug 863246.
|
||||||
|
|
|
@ -339,6 +339,7 @@ var BrowserPageActions = {
|
||||||
_makeUrlbarButtonNode(action) {
|
_makeUrlbarButtonNode(action) {
|
||||||
let buttonNode = document.createElement("image");
|
let buttonNode = document.createElement("image");
|
||||||
buttonNode.classList.add("urlbar-icon", "urlbar-page-action");
|
buttonNode.classList.add("urlbar-icon", "urlbar-page-action");
|
||||||
|
buttonNode.setAttribute("role", "button");
|
||||||
if (action.tooltip) {
|
if (action.tooltip) {
|
||||||
buttonNode.setAttribute("tooltiptext", action.tooltip);
|
buttonNode.setAttribute("tooltiptext", action.tooltip);
|
||||||
}
|
}
|
||||||
|
@ -721,7 +722,7 @@ var BrowserPageActionFeedback = {
|
||||||
// The timeout value used here allows the panel to stay open for
|
// The timeout value used here allows the panel to stay open for
|
||||||
// 1 second after the text transition (duration=120ms) has finished.
|
// 1 second after the text transition (duration=120ms) has finished.
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
this.panelNode.hidePopup();
|
this.panelNode.hidePopup(true);
|
||||||
}, Services.prefs.getIntPref("browser.pageActions.feedbackTimeoutMS", 1120));
|
}, Services.prefs.getIntPref("browser.pageActions.feedbackTimeoutMS", 1120));
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
|
@ -881,11 +881,13 @@
|
||||||
</hbox>
|
</hbox>
|
||||||
<image id="page-report-button"
|
<image id="page-report-button"
|
||||||
class="urlbar-icon urlbar-page-action"
|
class="urlbar-icon urlbar-page-action"
|
||||||
|
role="button"
|
||||||
hidden="true"
|
hidden="true"
|
||||||
tooltiptext="&pageReportIcon.tooltip;"
|
tooltiptext="&pageReportIcon.tooltip;"
|
||||||
onmousedown="gPopupBlockerObserver.onReportButtonMousedown(event);"/>
|
onmousedown="gPopupBlockerObserver.onReportButtonMousedown(event);"/>
|
||||||
<image id="reader-mode-button"
|
<image id="reader-mode-button"
|
||||||
class="urlbar-icon urlbar-page-action"
|
class="urlbar-icon urlbar-page-action"
|
||||||
|
role="button"
|
||||||
hidden="true"
|
hidden="true"
|
||||||
onclick="ReaderParent.buttonClick(event);"/>
|
onclick="ReaderParent.buttonClick(event);"/>
|
||||||
<toolbarbutton id="urlbar-zoom-button"
|
<toolbarbutton id="urlbar-zoom-button"
|
||||||
|
@ -895,19 +897,23 @@
|
||||||
<box id="pageActionSeparator" class="urlbar-page-action"/>
|
<box id="pageActionSeparator" class="urlbar-page-action"/>
|
||||||
<image id="pageActionButton"
|
<image id="pageActionButton"
|
||||||
class="urlbar-icon urlbar-page-action"
|
class="urlbar-icon urlbar-page-action"
|
||||||
|
role="button"
|
||||||
tooltiptext="&pageActionButton.tooltip;"
|
tooltiptext="&pageActionButton.tooltip;"
|
||||||
onclick="BrowserPageActions.mainButtonClicked(event);"/>
|
onclick="BrowserPageActions.mainButtonClicked(event);"/>
|
||||||
<hbox id="star-button-box"
|
<hbox id="star-button-box"
|
||||||
hidden="true"
|
hidden="true"
|
||||||
class="urlbar-icon-wrapper urlbar-page-action"
|
class="urlbar-icon-wrapper urlbar-page-action"
|
||||||
|
role="button"
|
||||||
context="pageActionPanelContextMenu"
|
context="pageActionPanelContextMenu"
|
||||||
oncontextmenu="BrowserPageActions.onContextMenu(event);"
|
oncontextmenu="BrowserPageActions.onContextMenu(event);"
|
||||||
onclick="BrowserPageActions.bookmark.onUrlbarNodeClicked(event);">
|
onclick="BrowserPageActions.bookmark.onUrlbarNodeClicked(event);">
|
||||||
<image id="star-button"
|
<image id="star-button"
|
||||||
class="urlbar-icon"
|
class="urlbar-icon"
|
||||||
|
role="button"
|
||||||
observes="bookmarkThisPageBroadcaster"/>
|
observes="bookmarkThisPageBroadcaster"/>
|
||||||
<hbox id="star-button-animatable-box">
|
<hbox id="star-button-animatable-box">
|
||||||
<image id="star-button-animatable-image"
|
<image id="star-button-animatable-image"
|
||||||
|
role="button"
|
||||||
observes="bookmarkThisPageBroadcaster"/>
|
observes="bookmarkThisPageBroadcaster"/>
|
||||||
</hbox>
|
</hbox>
|
||||||
</hbox>
|
</hbox>
|
||||||
|
|
|
@ -1,4 +1,9 @@
|
||||||
add_task(async function() {
|
add_task(async function() {
|
||||||
|
// When about:home is set to Activity Stream, there are no 'narrow' attributes
|
||||||
|
// therefore for this test, we want to ensure we're using the original about:home
|
||||||
|
await SpecialPowers.pushPrefEnv({set: [
|
||||||
|
["browser.newtabpage.activity-stream.aboutHome.enabled", false]
|
||||||
|
]});
|
||||||
let newWindow = await BrowserTestUtils.openNewBrowserWindow();
|
let newWindow = await BrowserTestUtils.openNewBrowserWindow();
|
||||||
|
|
||||||
let resizedPromise = BrowserTestUtils.waitForEvent(newWindow, "resize");
|
let resizedPromise = BrowserTestUtils.waitForEvent(newWindow, "resize");
|
||||||
|
|
|
@ -445,7 +445,7 @@ this.tabs = class extends ExtensionAPI {
|
||||||
}
|
}
|
||||||
if (updateProperties.muted !== null) {
|
if (updateProperties.muted !== null) {
|
||||||
if (nativeTab.muted != updateProperties.muted) {
|
if (nativeTab.muted != updateProperties.muted) {
|
||||||
nativeTab.toggleMuteAudio(extension.uuid);
|
nativeTab.toggleMuteAudio(extension.id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (updateProperties.pinned !== null) {
|
if (updateProperties.pinned !== null) {
|
||||||
|
|
|
@ -115,8 +115,7 @@ add_task(async function() {
|
||||||
for (let obj of [nonMuted.changeInfo, nonMuted.tab, muted.changeInfo, muted.tab]) {
|
for (let obj of [nonMuted.changeInfo, nonMuted.tab, muted.changeInfo, muted.tab]) {
|
||||||
browser.test.assertEq("extension", obj.mutedInfo.reason, "Mute state changed by extension");
|
browser.test.assertEq("extension", obj.mutedInfo.reason, "Mute state changed by extension");
|
||||||
|
|
||||||
// FIXME: browser.runtime.id is currently broken.
|
browser.test.assertEq(browser.runtime.id,
|
||||||
browser.test.assertEq(browser.i18n.getMessage("@@extension_id"),
|
|
||||||
obj.mutedInfo.extensionId,
|
obj.mutedInfo.extensionId,
|
||||||
"Mute state changed by extension");
|
"Mute state changed by extension");
|
||||||
}
|
}
|
||||||
|
@ -128,8 +127,7 @@ add_task(async function() {
|
||||||
|
|
||||||
browser.test.assertEq("extension", tab.mutedInfo.reason, "Mute state changed by extension");
|
browser.test.assertEq("extension", tab.mutedInfo.reason, "Mute state changed by extension");
|
||||||
|
|
||||||
// FIXME: browser.runtime.id is currently broken.
|
browser.test.assertEq(browser.runtime.id,
|
||||||
browser.test.assertEq(browser.i18n.getMessage("@@extension_id"),
|
|
||||||
tab.mutedInfo.extensionId,
|
tab.mutedInfo.extensionId,
|
||||||
"Mute state changed by extension");
|
"Mute state changed by extension");
|
||||||
|
|
||||||
|
|
|
@ -1602,10 +1602,27 @@ var PlacesControllerDragHelper = {
|
||||||
// Adjust insertion index to prevent reversal of dragged items. When you
|
// Adjust insertion index to prevent reversal of dragged items. When you
|
||||||
// drag multiple elts upward: need to increment index or each successive
|
// drag multiple elts upward: need to increment index or each successive
|
||||||
// elt will be inserted at the same index, each above the previous.
|
// elt will be inserted at the same index, each above the previous.
|
||||||
let dragginUp = insertionPoint.itemId == unwrapped.parent &&
|
if (index != -1 && unwrapped.itemGuid) {
|
||||||
index < (await PlacesUtils.bookmarks.fetch(unwrapped.itemGuid)).index;
|
// Note: we use the parent from the existing bookmark as the sidebar
|
||||||
if (index != -1 && dragginUp)
|
// gives us an unwrapped.parent that is actually a query and not the real
|
||||||
|
// parent.
|
||||||
|
let existingBookmark = await PlacesUtils.bookmarks.fetch(unwrapped.itemGuid);
|
||||||
|
let dragginUp = parentGuid == existingBookmark.parentGuid &&
|
||||||
|
index < existingBookmark.index;
|
||||||
|
|
||||||
|
if (dragginUp) {
|
||||||
index += movedCount++;
|
index += movedCount++;
|
||||||
|
} else if (PlacesUIUtils.useAsyncTransactions) {
|
||||||
|
if (index == existingBookmark.index) {
|
||||||
|
// We're moving to the same index, so there's nothing for us to do.
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
// If we're dragging down, we need to go one lower to insert at
|
||||||
|
// the real point as moving the element changes the index of
|
||||||
|
// everything below by 1.
|
||||||
|
index--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// If dragging over a tag container we should tag the item.
|
// If dragging over a tag container we should tag the item.
|
||||||
if (insertionPoint.isTag) {
|
if (insertionPoint.isTag) {
|
||||||
|
@ -1638,7 +1655,11 @@ var PlacesControllerDragHelper = {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// Check if we actually have something to add, if we don't it probably wasn't
|
||||||
|
// valid, or it was moving to the same location, so just ignore it.
|
||||||
|
if (!transactions.length) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
if (PlacesUIUtils.useAsyncTransactions) {
|
if (PlacesUIUtils.useAsyncTransactions) {
|
||||||
await PlacesTransactions.batch(transactions);
|
await PlacesTransactions.batch(transactions);
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -28,6 +28,7 @@ support-files =
|
||||||
[browser_click_bookmarks_on_toolbar.js]
|
[browser_click_bookmarks_on_toolbar.js]
|
||||||
[browser_cutting_bookmarks.js]
|
[browser_cutting_bookmarks.js]
|
||||||
subsuite = clipboard
|
subsuite = clipboard
|
||||||
|
[browser_controller_onDrop.js]
|
||||||
[browser_copy_folder_tree.js]
|
[browser_copy_folder_tree.js]
|
||||||
[browser_copy_query_without_tree.js]
|
[browser_copy_query_without_tree.js]
|
||||||
subsuite = clipboard
|
subsuite = clipboard
|
||||||
|
|
|
@ -0,0 +1,132 @@
|
||||||
|
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
/* global sinon */
|
||||||
|
Services.scriptloader.loadSubScript("resource://testing-common/sinon-2.3.2.js");
|
||||||
|
|
||||||
|
const sandbox = sinon.sandbox.create();
|
||||||
|
|
||||||
|
var bookmarks;
|
||||||
|
var bookmarkIds;
|
||||||
|
|
||||||
|
add_task(async function setup() {
|
||||||
|
registerCleanupFunction(async function() {
|
||||||
|
sandbox.restore();
|
||||||
|
delete window.sinon;
|
||||||
|
await PlacesUtils.bookmarks.eraseEverything();
|
||||||
|
await PlacesTestUtils.clearHistory();
|
||||||
|
});
|
||||||
|
|
||||||
|
sandbox.stub(PlacesUIUtils, "getTransactionForData");
|
||||||
|
sandbox.stub(PlacesTransactions, "batch");
|
||||||
|
|
||||||
|
bookmarks = await PlacesUtils.bookmarks.insertTree({
|
||||||
|
guid: PlacesUtils.bookmarks.unfiledGuid,
|
||||||
|
children: [{
|
||||||
|
title: "bm1",
|
||||||
|
url: "http://example1.com"
|
||||||
|
}, {
|
||||||
|
title: "bm2",
|
||||||
|
url: "http://example2.com"
|
||||||
|
}, {
|
||||||
|
title: "bm3",
|
||||||
|
url: "http://example3.com"
|
||||||
|
}]
|
||||||
|
});
|
||||||
|
|
||||||
|
bookmarkIds = await PlacesUtils.promiseManyItemIds([
|
||||||
|
bookmarks[0].guid,
|
||||||
|
bookmarks[1].guid,
|
||||||
|
bookmarks[2].guid,
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
|
||||||
|
async function run_drag_test(startBookmarkIndex, insertionIndex,
|
||||||
|
realInsertionIndex, expectTransactionCreated = true) {
|
||||||
|
// Reset the stubs so that previous test runs don't count against us.
|
||||||
|
PlacesUIUtils.getTransactionForData.reset();
|
||||||
|
PlacesTransactions.batch.reset();
|
||||||
|
|
||||||
|
let dragBookmark = bookmarks[startBookmarkIndex];
|
||||||
|
|
||||||
|
await withSidebarTree("bookmarks", async (tree) => {
|
||||||
|
tree.selectItems([PlacesUtils.unfiledBookmarksFolderId]);
|
||||||
|
PlacesUtils.asContainer(tree.selectedNode).containerOpen = true;
|
||||||
|
|
||||||
|
// Simulating a drag-drop with a tree view turns out to be really difficult
|
||||||
|
// as you can't get a node for the source/target. Hence, we fake the
|
||||||
|
// insertion point and drag data and call the function direct.
|
||||||
|
let ip = new InsertionPoint({
|
||||||
|
parentId: await PlacesUtils.promiseItemId(PlacesUtils.bookmarks.unfiledGuid),
|
||||||
|
parentGuid: PlacesUtils.bookmarks.unfiledGuid,
|
||||||
|
index: insertionIndex,
|
||||||
|
orientation: Ci.nsITreeView.DROP_ON
|
||||||
|
});
|
||||||
|
|
||||||
|
let bookmarkWithId = JSON.stringify(Object.assign({
|
||||||
|
id: bookmarkIds.get(dragBookmark.guid),
|
||||||
|
itemGuid: dragBookmark.guid,
|
||||||
|
parent: PlacesUtils.unfiledBookmarksFolderId,
|
||||||
|
}, dragBookmark));
|
||||||
|
|
||||||
|
let dt = {
|
||||||
|
dropEffect: "move",
|
||||||
|
mozCursor: "auto",
|
||||||
|
mozItemCount: 1,
|
||||||
|
types: [ PlacesUtils.TYPE_X_MOZ_PLACE ],
|
||||||
|
mozTypesAt(i) {
|
||||||
|
return this.types;
|
||||||
|
},
|
||||||
|
mozGetDataAt(i) {
|
||||||
|
return bookmarkWithId;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
await PlacesControllerDragHelper.onDrop(ip, dt);
|
||||||
|
|
||||||
|
if (!expectTransactionCreated) {
|
||||||
|
Assert.ok(PlacesUIUtils.getTransactionForData.notCalled,
|
||||||
|
"Should not have created transaction data");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Assert.ok(PlacesUIUtils.getTransactionForData.calledOnce,
|
||||||
|
"Should have called getTransactionForData at least once.");
|
||||||
|
|
||||||
|
let args = PlacesUIUtils.getTransactionForData.args[0];
|
||||||
|
|
||||||
|
Assert.deepEqual(args[0], JSON.parse(bookmarkWithId),
|
||||||
|
"Should have called getTransactionForData with the correct unwrapped bookmark");
|
||||||
|
Assert.equal(args[1], PlacesUtils.TYPE_X_MOZ_PLACE,
|
||||||
|
"Should have called getTransactionForData with the correct flavor");
|
||||||
|
Assert.equal(args[2], PlacesUtils.bookmarks.unfiledGuid,
|
||||||
|
"Should have called getTransactionForData with the correct parent guid");
|
||||||
|
Assert.equal(args[3], realInsertionIndex,
|
||||||
|
"Should have called getTransactionForData with the correct index");
|
||||||
|
Assert.equal(args[4], false,
|
||||||
|
"Should have called getTransactionForData with a move");
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
add_task(async function test_simple_move_down() {
|
||||||
|
// When we move items down the list, we'll get a drag index that is one higher
|
||||||
|
// than where we actually want to insert to - as the item is being moved up,
|
||||||
|
// everything shifts down one. Hence the index to pass to the transaction should
|
||||||
|
// be one less than the supplied index.
|
||||||
|
await run_drag_test(0, 2, 1);
|
||||||
|
});
|
||||||
|
|
||||||
|
add_task(async function test_simple_move_up() {
|
||||||
|
// When we move items up the list, we want the matching index to be passed to
|
||||||
|
// the transaction as there's no changes below the item in the list.
|
||||||
|
await run_drag_test(2, 0, 0);
|
||||||
|
});
|
||||||
|
|
||||||
|
add_task(async function test_simple_move_to_same() {
|
||||||
|
// If we move to the same index, then we don't expect any transactions to be
|
||||||
|
// created.
|
||||||
|
await run_drag_test(1, 1, 1, false);
|
||||||
|
});
|
|
@ -230,6 +230,7 @@ function search(aQuery, aAttribute, aSubquery, aSubAttribute) {
|
||||||
let attributeValue = element.getAttribute(aAttribute);
|
let attributeValue = element.getAttribute(aAttribute);
|
||||||
if (attributeValue == aQuery) {
|
if (attributeValue == aQuery) {
|
||||||
if (!element.classList.contains("header") &&
|
if (!element.classList.contains("header") &&
|
||||||
|
element.localName !== "preferences" &&
|
||||||
aSubquery && aSubAttribute) {
|
aSubquery && aSubAttribute) {
|
||||||
let subAttributeValue = element.getAttribute(aSubAttribute);
|
let subAttributeValue = element.getAttribute(aSubAttribute);
|
||||||
element.hidden = subAttributeValue != aSubquery;
|
element.hidden = subAttributeValue != aSubquery;
|
||||||
|
|
|
@ -45,6 +45,49 @@ add_task(async function() {
|
||||||
await BrowserTestUtils.removeTab(gBrowser.selectedTab);
|
await BrowserTestUtils.removeTab(gBrowser.selectedTab);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Test opening to a subcategory displays the correct values for preferences
|
||||||
|
add_task(async function() {
|
||||||
|
// Skip if crash reporting isn't enabled since the checkbox will be missing.
|
||||||
|
if (!AppConstants.MOZ_CRASHREPORTER) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
await SpecialPowers.pushPrefEnv({
|
||||||
|
set: [["browser.crashReports.unsubmittedCheck.autoSubmit", true]],
|
||||||
|
});
|
||||||
|
await openPreferencesViaOpenPreferencesAPI("privacy-reports", {leaveOpen: true});
|
||||||
|
|
||||||
|
let doc = gBrowser.contentDocument;
|
||||||
|
ok(
|
||||||
|
doc.querySelector("#automaticallySubmitCrashesBox").checked,
|
||||||
|
"Checkbox for automatically submitting crashes should be checked when the pref is true and only Reports are requested"
|
||||||
|
);
|
||||||
|
|
||||||
|
await BrowserTestUtils.removeTab(gBrowser.selectedTab);
|
||||||
|
await SpecialPowers.popPrefEnv();
|
||||||
|
});
|
||||||
|
|
||||||
|
add_task(async function() {
|
||||||
|
// Skip if crash reporting isn't enabled since the checkbox will be missing.
|
||||||
|
if (!AppConstants.MOZ_CRASHREPORTER) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
await SpecialPowers.pushPrefEnv({
|
||||||
|
set: [["browser.crashReports.unsubmittedCheck.autoSubmit", false]],
|
||||||
|
});
|
||||||
|
await openPreferencesViaOpenPreferencesAPI("privacy-reports", {leaveOpen: true});
|
||||||
|
|
||||||
|
let doc = gBrowser.contentDocument;
|
||||||
|
ok(
|
||||||
|
!doc.querySelector("#automaticallySubmitCrashesBox").checked,
|
||||||
|
"Checkbox for automatically submitting crashes should not be checked when the pref is false only Reports are requested"
|
||||||
|
);
|
||||||
|
|
||||||
|
await BrowserTestUtils.removeTab(gBrowser.selectedTab);
|
||||||
|
await SpecialPowers.popPrefEnv();
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
function openPreferencesViaHash(aPane) {
|
function openPreferencesViaHash(aPane) {
|
||||||
return new Promise(resolve => {
|
return new Promise(resolve => {
|
||||||
|
|
|
@ -5,6 +5,11 @@
|
||||||
// This test checks that the Session Restore "Restore Previous Session"
|
// This test checks that the Session Restore "Restore Previous Session"
|
||||||
// button on about:home is disabled in private mode
|
// button on about:home is disabled in private mode
|
||||||
add_task(async function test_no_sessionrestore_button() {
|
add_task(async function test_no_sessionrestore_button() {
|
||||||
|
// Activity Stream page does not have a restore session button.
|
||||||
|
// We want to run this test only when Activity Stream is disabled from about:home.
|
||||||
|
await SpecialPowers.pushPrefEnv({set: [
|
||||||
|
["browser.newtabpage.activity-stream.aboutHome.enabled", false]
|
||||||
|
]});
|
||||||
// Opening, then closing, a private window shouldn't create session data.
|
// Opening, then closing, a private window shouldn't create session data.
|
||||||
(await BrowserTestUtils.openNewBrowserWindow({private: true})).close();
|
(await BrowserTestUtils.openNewBrowserWindow({private: true})).close();
|
||||||
|
|
||||||
|
|
|
@ -971,6 +971,8 @@ var SessionStoreInternal = {
|
||||||
SessionStoreInternal.restoreNextTab();
|
SessionStoreInternal.restoreNextTab();
|
||||||
|
|
||||||
this._sendTabRestoredNotification(tab, data.isRemotenessUpdate);
|
this._sendTabRestoredNotification(tab, data.isRemotenessUpdate);
|
||||||
|
|
||||||
|
Services.obs.notifyObservers(null, "sessionstore-one-or-no-tab-restored");
|
||||||
break;
|
break;
|
||||||
case "SessionStore:crashedTabRevived":
|
case "SessionStore:crashedTabRevived":
|
||||||
// The browser was revived by navigating to a different page
|
// The browser was revived by navigating to a different page
|
||||||
|
@ -1149,6 +1151,7 @@ var SessionStoreInternal = {
|
||||||
|
|
||||||
// Nothing to restore now, notify observers things are complete.
|
// Nothing to restore now, notify observers things are complete.
|
||||||
Services.obs.notifyObservers(null, NOTIFY_WINDOWS_RESTORED);
|
Services.obs.notifyObservers(null, NOTIFY_WINDOWS_RESTORED);
|
||||||
|
Services.obs.notifyObservers(null, "sessionstore-one-or-no-tab-restored");
|
||||||
this._deferredAllWindowsRestored.resolve();
|
this._deferredAllWindowsRestored.resolve();
|
||||||
} else {
|
} else {
|
||||||
TelemetryTimestamps.add("sessionRestoreRestoring");
|
TelemetryTimestamps.add("sessionRestoreRestoring");
|
||||||
|
@ -1168,6 +1171,7 @@ var SessionStoreInternal = {
|
||||||
} else {
|
} else {
|
||||||
// Nothing to restore, notify observers things are complete.
|
// Nothing to restore, notify observers things are complete.
|
||||||
Services.obs.notifyObservers(null, NOTIFY_WINDOWS_RESTORED);
|
Services.obs.notifyObservers(null, NOTIFY_WINDOWS_RESTORED);
|
||||||
|
Services.obs.notifyObservers(null, "sessionstore-one-or-no-tab-restored");
|
||||||
this._deferredAllWindowsRestored.resolve();
|
this._deferredAllWindowsRestored.resolve();
|
||||||
}
|
}
|
||||||
// this window was opened by _openWindowWithState
|
// this window was opened by _openWindowWithState
|
||||||
|
|
|
@ -0,0 +1,26 @@
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"version": "Visual Studio 2015 Update 3 14.0.25425.01 / SDK 10.0.14393.0",
|
||||||
|
"size": 326656969,
|
||||||
|
"digest": "babc414ffc0457d27f5a1ed24a8e4873afbe2f1c1a4075469a27c005e1babc3b2a788f643f825efedff95b79686664c67ec4340ed535487168a3482e68559bc7",
|
||||||
|
"algorithm": "sha512",
|
||||||
|
"filename": "vs2015u3.zip",
|
||||||
|
"unpack": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"version": "Ninja 1.7.1",
|
||||||
|
"size": 184821,
|
||||||
|
"digest": "e4f9a1ae624a2630e75264ba37d396d9c7407d6e6aea3763056210ba6e1387908bd31cf4037a6a3661a418e86c4d2761e0c333e6a3bd0d66549d2b0d72d3f43b",
|
||||||
|
"algorithm": "sha512",
|
||||||
|
"filename": "ninja171.zip",
|
||||||
|
"unpack": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"version": "MinGit-2.13.3-64-bit",
|
||||||
|
"size": 21482885,
|
||||||
|
"digest": "929bb3c07be8487ee519422a312bdbfeec8f4db4b62c49d02f9aad9fd2a66c0ee5fad63d2b06c8744c336dc9d50446fa4457897333ad17ffd783ecabd1e2ddbb",
|
||||||
|
"algorithm": "sha512",
|
||||||
|
"filename": "git.zip",
|
||||||
|
"unpack": true
|
||||||
|
}
|
||||||
|
]
|
|
@ -372,10 +372,12 @@ var FormAutofillContent = {
|
||||||
*
|
*
|
||||||
* @param {Object} profile Submitted form's address/creditcard guid and record.
|
* @param {Object} profile Submitted form's address/creditcard guid and record.
|
||||||
* @param {Object} domWin Current content window.
|
* @param {Object} domWin Current content window.
|
||||||
|
* @param {int} timeStartedFillingMS Time of form filling started.
|
||||||
*/
|
*/
|
||||||
_onFormSubmit(profile, domWin) {
|
_onFormSubmit(profile, domWin, timeStartedFillingMS) {
|
||||||
let mm = this._messageManagerFromWindow(domWin);
|
let mm = this._messageManagerFromWindow(domWin);
|
||||||
mm.sendAsyncMessage("FormAutofill:OnFormSubmit", profile);
|
mm.sendAsyncMessage("FormAutofill:OnFormSubmit",
|
||||||
|
{profile, timeStartedFillingMS});
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -407,7 +409,7 @@ var FormAutofillContent = {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
this._onFormSubmit(records, domWin);
|
this._onFormSubmit(records, domWin, handler.timeStartedFillingMS);
|
||||||
return true;
|
return true;
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
|
@ -114,6 +114,11 @@ FormAutofillHandler.prototype = {
|
||||||
return this._formFieldCount != this.form.elements.length;
|
return this._formFieldCount != this.form.elements.length;
|
||||||
},
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Time in milliseconds since epoch when a user started filling in the form.
|
||||||
|
*/
|
||||||
|
timeStartedFillingMS: null,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set fieldDetails from the form about fields that can be autofilled.
|
* Set fieldDetails from the form about fields that can be autofilled.
|
||||||
*
|
*
|
||||||
|
@ -127,6 +132,7 @@ FormAutofillHandler.prototype = {
|
||||||
this._formFieldCount = this.form.elements.length;
|
this._formFieldCount = this.form.elements.length;
|
||||||
let fieldDetails = FormAutofillHeuristics.getFormInfo(this.form, allowDuplicates);
|
let fieldDetails = FormAutofillHeuristics.getFormInfo(this.form, allowDuplicates);
|
||||||
this.fieldDetails = fieldDetails ? fieldDetails : [];
|
this.fieldDetails = fieldDetails ? fieldDetails : [];
|
||||||
|
this.form.rootElement.addEventListener("input", this);
|
||||||
log.debug("Collected details on", this.fieldDetails.length, "fields");
|
log.debug("Collected details on", this.fieldDetails.length, "fields");
|
||||||
|
|
||||||
this.address.fieldDetails = this.fieldDetails.filter(
|
this.address.fieldDetails = this.fieldDetails.filter(
|
||||||
|
@ -582,4 +588,43 @@ FormAutofillHandler.prototype = {
|
||||||
Services.cpmm.sendAsyncMessage("FormAutofill:GetDecryptedString", {cipherText, reauth});
|
Services.cpmm.sendAsyncMessage("FormAutofill:GetDecryptedString", {cipherText, reauth});
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Find the fieldDetail by HTML element (assume all details were collected in collectFormFields).
|
||||||
|
*
|
||||||
|
* @param {HTMLElement} element
|
||||||
|
*
|
||||||
|
* @returns {Object|null}
|
||||||
|
* Return fieldDetail if fieldDetail's element ref could match the target.
|
||||||
|
* (or return null if the element could not match any fieldDetail).
|
||||||
|
*/
|
||||||
|
getFieldDetailsForElement(element) {
|
||||||
|
for (let detail of this.fieldDetails) {
|
||||||
|
if (detail.elementWeakRef.get() == element) {
|
||||||
|
return detail;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
},
|
||||||
|
|
||||||
|
handleEvent(event) {
|
||||||
|
switch (event.type) {
|
||||||
|
case "input":
|
||||||
|
if (!event.isTrusted) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!FormAutofillUtils.isFieldEligibleForAutofill(event.target)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!this.getFieldDetailsForElement(event.target)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.form.rootElement.removeEventListener("input", this);
|
||||||
|
this.timeStartedFillingMS = Date.now();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
|
@ -355,7 +355,7 @@ FormAutofillParent.prototype = {
|
||||||
this._updateStatus();
|
this._updateStatus();
|
||||||
},
|
},
|
||||||
|
|
||||||
_onAddressSubmit(address, target) {
|
_onAddressSubmit(address, target, timeStartedFillingMS) {
|
||||||
if (address.guid) {
|
if (address.guid) {
|
||||||
// Avoid updating the fields that users don't modify.
|
// Avoid updating the fields that users don't modify.
|
||||||
let originalAddress = this.profileStorage.addresses.get(address.guid);
|
let originalAddress = this.profileStorage.addresses.get(address.guid);
|
||||||
|
@ -366,6 +366,8 @@ FormAutofillParent.prototype = {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!this.profileStorage.addresses.mergeIfPossible(address.guid, address.record)) {
|
if (!this.profileStorage.addresses.mergeIfPossible(address.guid, address.record)) {
|
||||||
|
this._recordFormFillingTime("address", "autofill-update", timeStartedFillingMS);
|
||||||
|
|
||||||
FormAutofillDoorhanger.show(target, "update").then((state) => {
|
FormAutofillDoorhanger.show(target, "update").then((state) => {
|
||||||
let changedGUIDs = this.profileStorage.addresses.mergeToStorage(address.record);
|
let changedGUIDs = this.profileStorage.addresses.mergeToStorage(address.record);
|
||||||
switch (state) {
|
switch (state) {
|
||||||
|
@ -389,6 +391,7 @@ FormAutofillParent.prototype = {
|
||||||
Services.telemetry.scalarAdd("formautofill.addresses.fill_type_autofill_update", 1);
|
Services.telemetry.scalarAdd("formautofill.addresses.fill_type_autofill_update", 1);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
this._recordFormFillingTime("address", "autofill", timeStartedFillingMS);
|
||||||
this.profileStorage.addresses.notifyUsed(address.guid);
|
this.profileStorage.addresses.notifyUsed(address.guid);
|
||||||
// Address is merged successfully
|
// Address is merged successfully
|
||||||
Services.telemetry.scalarAdd("formautofill.addresses.fill_type_autofill", 1);
|
Services.telemetry.scalarAdd("formautofill.addresses.fill_type_autofill", 1);
|
||||||
|
@ -398,6 +401,7 @@ FormAutofillParent.prototype = {
|
||||||
changedGUIDs.push(this.profileStorage.addresses.add(address.record));
|
changedGUIDs.push(this.profileStorage.addresses.add(address.record));
|
||||||
}
|
}
|
||||||
changedGUIDs.forEach(guid => this.profileStorage.addresses.notifyUsed(guid));
|
changedGUIDs.forEach(guid => this.profileStorage.addresses.notifyUsed(guid));
|
||||||
|
this._recordFormFillingTime("address", "manual", timeStartedFillingMS);
|
||||||
|
|
||||||
// Show first time use doorhanger
|
// Show first time use doorhanger
|
||||||
if (Services.prefs.getBoolPref("extensions.formautofill.firstTimeUse")) {
|
if (Services.prefs.getBoolPref("extensions.formautofill.firstTimeUse")) {
|
||||||
|
@ -441,13 +445,28 @@ FormAutofillParent.prototype = {
|
||||||
},
|
},
|
||||||
|
|
||||||
_onFormSubmit(data, target) {
|
_onFormSubmit(data, target) {
|
||||||
let {address, creditCard} = data;
|
let {profile: {address, creditCard}, timeStartedFillingMS} = data;
|
||||||
|
|
||||||
if (address) {
|
if (address) {
|
||||||
this._onAddressSubmit(address, target);
|
this._onAddressSubmit(address, target, timeStartedFillingMS);
|
||||||
}
|
}
|
||||||
if (creditCard) {
|
if (creditCard) {
|
||||||
this._onCreditCardSubmit(creditCard, target);
|
this._onCreditCardSubmit(creditCard, target);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
/**
|
||||||
|
* Set the probes for the filling time with specific filling type and form type.
|
||||||
|
*
|
||||||
|
* @private
|
||||||
|
* @param {string} formType
|
||||||
|
* 3 type of form (address/creditcard/address-creditcard).
|
||||||
|
* @param {string} fillingType
|
||||||
|
* 3 filling type (manual/autofill/autofill-update).
|
||||||
|
* @param {int} startedFillingMS
|
||||||
|
* Time that form started to filling in ms.
|
||||||
|
*/
|
||||||
|
_recordFormFillingTime(formType, fillingType, startedFillingMS) {
|
||||||
|
let histogram = Services.telemetry.getKeyedHistogramById("FORM_FILLING_REQUIRED_TIME_MS");
|
||||||
|
histogram.add(`${formType}-${fillingType}`, Date.now() - startedFillingMS);
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
|
@ -118,9 +118,15 @@ var PocketPageAction = {
|
||||||
animatableBox.id = "pocket-animatable-box";
|
animatableBox.id = "pocket-animatable-box";
|
||||||
let animatableImage = doc.createElement("image");
|
let animatableImage = doc.createElement("image");
|
||||||
animatableImage.id = "pocket-animatable-image";
|
animatableImage.id = "pocket-animatable-image";
|
||||||
|
animatableImage.setAttribute("role", "button");
|
||||||
|
let tooltip =
|
||||||
|
gPocketBundle.GetStringFromName("pocket-button.tooltiptext");
|
||||||
|
animatableImage.setAttribute("tooltiptext", tooltip);
|
||||||
let pocketButton = doc.createElement("image");
|
let pocketButton = doc.createElement("image");
|
||||||
pocketButton.id = "pocket-button";
|
pocketButton.id = "pocket-button";
|
||||||
pocketButton.classList.add("urlbar-icon");
|
pocketButton.classList.add("urlbar-icon");
|
||||||
|
pocketButton.setAttribute("role", "button");
|
||||||
|
pocketButton.setAttribute("tooltiptext", tooltip);
|
||||||
|
|
||||||
wrapper.appendChild(pocketButton);
|
wrapper.appendChild(pocketButton);
|
||||||
wrapper.appendChild(animatableBox);
|
wrapper.appendChild(animatableBox);
|
||||||
|
|
|
@ -43,8 +43,9 @@ const prefs = Services.prefs.getBranch("extensions.shield-recipe-client.");
|
||||||
const TIMER_NAME = "recipe-client-addon-run";
|
const TIMER_NAME = "recipe-client-addon-run";
|
||||||
const RUN_INTERVAL_PREF = "run_interval_seconds";
|
const RUN_INTERVAL_PREF = "run_interval_seconds";
|
||||||
const FIRST_RUN_PREF = "first_run";
|
const FIRST_RUN_PREF = "first_run";
|
||||||
const UI_AVAILABLE_NOTIFICATION = "sessionstore-windows-restored";
|
const UI_AVAILABLE_TOPIC = "sessionstore-windows-restored";
|
||||||
const SHIELD_INIT_NOTIFICATION = "shield-init-complete";
|
const SHIELD_INIT_TOPIC = "shield-init-complete";
|
||||||
|
const PREF_CHANGED_TOPIC = "nsPref:changed";
|
||||||
|
|
||||||
this.RecipeRunner = {
|
this.RecipeRunner = {
|
||||||
init() {
|
init() {
|
||||||
|
@ -60,19 +61,8 @@ this.RecipeRunner = {
|
||||||
if (prefs.getBoolPref(FIRST_RUN_PREF)) {
|
if (prefs.getBoolPref(FIRST_RUN_PREF)) {
|
||||||
// Run once immediately after the UI is available. Do this before adding the
|
// Run once immediately after the UI is available. Do this before adding the
|
||||||
// timer so we can't end up racing it.
|
// timer so we can't end up racing it.
|
||||||
const observer = {
|
Services.obs.addObserver(this, UI_AVAILABLE_TOPIC);
|
||||||
observe: async (subject, topic, data) => {
|
CleanupManager.addCleanupHandler(() => Services.obs.removeObserver(this, UI_AVAILABLE_TOPIC));
|
||||||
Services.obs.removeObserver(observer, UI_AVAILABLE_NOTIFICATION);
|
|
||||||
|
|
||||||
await this.run();
|
|
||||||
this.registerTimer();
|
|
||||||
prefs.setBoolPref(FIRST_RUN_PREF, false);
|
|
||||||
|
|
||||||
Services.obs.notifyObservers(null, SHIELD_INIT_NOTIFICATION);
|
|
||||||
},
|
|
||||||
};
|
|
||||||
Services.obs.addObserver(observer, UI_AVAILABLE_NOTIFICATION);
|
|
||||||
CleanupManager.addCleanupHandler(() => Services.obs.removeObserver(observer, UI_AVAILABLE_NOTIFICATION));
|
|
||||||
} else {
|
} else {
|
||||||
this.registerTimer();
|
this.registerTimer();
|
||||||
}
|
}
|
||||||
|
@ -108,17 +98,38 @@ this.RecipeRunner = {
|
||||||
return true;
|
return true;
|
||||||
},
|
},
|
||||||
|
|
||||||
|
observe(subject, topic, data) {
|
||||||
|
switch (topic) {
|
||||||
|
case PREF_CHANGED_TOPIC:
|
||||||
|
this.observePrefChange(data);
|
||||||
|
break;
|
||||||
|
case UI_AVAILABLE_TOPIC:
|
||||||
|
this.observeUIAvailable().catch(err => Cu.reportError(err));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Watch for preference changes from Services.pref.addObserver.
|
* Watch for preference changes from Services.pref.addObserver.
|
||||||
*/
|
*/
|
||||||
observe(changedPrefBranch, action, changedPref) {
|
observePrefChange(prefName) {
|
||||||
if (action === "nsPref:changed" && changedPref === RUN_INTERVAL_PREF) {
|
if (prefName === RUN_INTERVAL_PREF) {
|
||||||
this.updateRunInterval();
|
this.updateRunInterval();
|
||||||
} else {
|
} else {
|
||||||
log.debug(`Observer fired with unexpected pref change: ${action} ${changedPref}`);
|
log.debug(`Observer fired with unexpected pref change: ${prefName}`);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
async observeUIAvailable() {
|
||||||
|
Services.obs.removeObserver(this, UI_AVAILABLE_TOPIC);
|
||||||
|
|
||||||
|
await this.run();
|
||||||
|
this.registerTimer();
|
||||||
|
prefs.setBoolPref(FIRST_RUN_PREF, false);
|
||||||
|
|
||||||
|
Services.obs.notifyObservers(null, SHIELD_INIT_TOPIC);
|
||||||
|
},
|
||||||
|
|
||||||
updateRunInterval() {
|
updateRunInterval() {
|
||||||
// Run once every `runInterval` wall-clock seconds. This is managed by setting a "last ran"
|
// Run once every `runInterval` wall-clock seconds. This is managed by setting a "last ran"
|
||||||
// timestamp, and running if it is more than `runInterval` seconds ago. Even with very short
|
// timestamp, and running if it is more than `runInterval` seconds ago. Even with very short
|
||||||
|
|
|
@ -376,7 +376,7 @@ decorate_task(
|
||||||
ok(!runStub.called, "RecipeRunner.run is not called immediately");
|
ok(!runStub.called, "RecipeRunner.run is not called immediately");
|
||||||
ok(!registerTimerStub.called, "RecipeRunner.registerTimer is not called immediately");
|
ok(!registerTimerStub.called, "RecipeRunner.registerTimer is not called immediately");
|
||||||
|
|
||||||
Services.obs.notifyObservers(null, "sessionstore-windows-restored");
|
RecipeRunner.observe(null, "sessionstore-windows-restored");
|
||||||
await TestUtils.topicObserved("shield-init-complete");
|
await TestUtils.topicObserved("shield-init-complete");
|
||||||
ok(runStub.called, "RecipeRunner.run is called after the UI is available");
|
ok(runStub.called, "RecipeRunner.run is called after the UI is available");
|
||||||
ok(registerTimerStub.called, "RecipeRunner.registerTimer is called after the UI is available");
|
ok(registerTimerStub.called, "RecipeRunner.registerTimer is called after the UI is available");
|
||||||
|
|
|
@ -3,6 +3,11 @@
|
||||||
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
# 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/.
|
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||||
|
|
||||||
|
ifndef ENABLE_TESTS
|
||||||
|
# We can't package tests if they aren't enabled.
|
||||||
|
MOZ_AUTOMATION_PACKAGE_TESTS = 0
|
||||||
|
endif
|
||||||
|
|
||||||
ifneq (,$(filter automation/%,$(MAKECMDGOALS)))
|
ifneq (,$(filter automation/%,$(MAKECMDGOALS)))
|
||||||
ifeq (4.0,$(firstword $(sort 4.0 $(MAKE_VERSION))))
|
ifeq (4.0,$(firstword $(sort 4.0 $(MAKE_VERSION))))
|
||||||
MAKEFLAGS += --output-sync=target
|
MAKEFLAGS += --output-sync=target
|
||||||
|
|
|
@ -31,6 +31,10 @@ def jemalloc(value, target, build_project, c_compiler):
|
||||||
if target.kernel == 'Linux':
|
if target.kernel == 'Linux':
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
if value and target.kernel not in ('WINNT', 'Linux', 'Darwin', 'kFreeBSD',
|
||||||
|
'FreeBSD', 'NetBSD'):
|
||||||
|
die('--enable-jemalloc is not supported on %s', target.kernel)
|
||||||
|
|
||||||
|
|
||||||
set_config('MOZ_MEMORY', jemalloc)
|
set_config('MOZ_MEMORY', jemalloc)
|
||||||
set_define('MOZ_MEMORY', jemalloc)
|
set_define('MOZ_MEMORY', jemalloc)
|
||||||
|
@ -47,29 +51,6 @@ def jemalloc_for_old_configure(jemalloc):
|
||||||
add_old_configure_arg(jemalloc_for_old_configure)
|
add_old_configure_arg(jemalloc_for_old_configure)
|
||||||
|
|
||||||
|
|
||||||
@depends(jemalloc, target)
|
|
||||||
def jemalloc_os_define(jemalloc, target):
|
|
||||||
if jemalloc:
|
|
||||||
if target.kernel == 'WINNT':
|
|
||||||
return 'MOZ_MEMORY_WINDOWS'
|
|
||||||
if target.kernel == 'Linux':
|
|
||||||
return 'MOZ_MEMORY_LINUX'
|
|
||||||
if target.kernel == 'Darwin':
|
|
||||||
return 'MOZ_MEMORY_DARWIN'
|
|
||||||
if target.kernel in ('kFreeBSD', 'FreeBSD', 'NetBSD'):
|
|
||||||
return 'MOZ_MEMORY_BSD'
|
|
||||||
die('--enable-jemalloc is not supported on %s', target.kernel)
|
|
||||||
|
|
||||||
set_define(jemalloc_os_define, '1')
|
|
||||||
|
|
||||||
@depends(jemalloc, target)
|
|
||||||
def jemalloc_os_define_android(jemalloc, target):
|
|
||||||
if jemalloc and target.os == 'Android':
|
|
||||||
return 'MOZ_MEMORY_ANDROID'
|
|
||||||
|
|
||||||
set_define(jemalloc_os_define_android, '1')
|
|
||||||
|
|
||||||
|
|
||||||
option('--enable-replace-malloc',
|
option('--enable-replace-malloc',
|
||||||
help='Enable ability to dynamically replace the malloc implementation')
|
help='Enable ability to dynamically replace the malloc implementation')
|
||||||
|
|
||||||
|
|
|
@ -7,5 +7,6 @@ support-files =
|
||||||
!/caps/tests/mochitest/file_disableScript.html
|
!/caps/tests/mochitest/file_disableScript.html
|
||||||
|
|
||||||
[test_bug995943.xul]
|
[test_bug995943.xul]
|
||||||
|
skip-if = stylo && debug && os == 'linux' # bug 1384701
|
||||||
[test_addonMayLoad.html]
|
[test_addonMayLoad.html]
|
||||||
[test_disableScript.xul]
|
[test_disableScript.xul]
|
||||||
|
|
|
@ -11,7 +11,7 @@
|
||||||
|
|
||||||
const TAB_URL = EXAMPLE_URL + "doc_promise-get-allocation-stack.html";
|
const TAB_URL = EXAMPLE_URL + "doc_promise-get-allocation-stack.html";
|
||||||
const { PromisesFront } = require("devtools/shared/fronts/promises");
|
const { PromisesFront } = require("devtools/shared/fronts/promises");
|
||||||
var events = require("devtools/shared/event-emitter");
|
var EventEmitter = require("devtools/shared/event-emitter");
|
||||||
|
|
||||||
function test() {
|
function test() {
|
||||||
Task.spawn(function* () {
|
Task.spawn(function* () {
|
||||||
|
@ -48,7 +48,7 @@ function* testGetAllocationStack(client, form, tab) {
|
||||||
|
|
||||||
// Get the grip for promise p
|
// Get the grip for promise p
|
||||||
let onNewPromise = new Promise(resolve => {
|
let onNewPromise = new Promise(resolve => {
|
||||||
events.on(front, "new-promises", promises => {
|
EventEmitter.on(front, "new-promises", promises => {
|
||||||
for (let p of promises) {
|
for (let p of promises) {
|
||||||
if (p.preview.ownProperties.name &&
|
if (p.preview.ownProperties.name &&
|
||||||
p.preview.ownProperties.name.value === "p") {
|
p.preview.ownProperties.name.value === "p") {
|
||||||
|
|
|
@ -12,7 +12,7 @@
|
||||||
|
|
||||||
const SOURCE_URL = "browser_dbg_promises-chrome-allocation-stack.js";
|
const SOURCE_URL = "browser_dbg_promises-chrome-allocation-stack.js";
|
||||||
const PromisesFront = require("devtools/shared/fronts/promises");
|
const PromisesFront = require("devtools/shared/fronts/promises");
|
||||||
var events = require("devtools/shared/event-emitter");
|
var EventEmitter = require("devtools/shared/event-emitter");
|
||||||
|
|
||||||
const STACK_DATA = [
|
const STACK_DATA = [
|
||||||
{ functionDisplayName: "test/</<" },
|
{ functionDisplayName: "test/</<" },
|
||||||
|
@ -57,7 +57,7 @@ function* testGetAllocationStack(client, form, makePromises) {
|
||||||
|
|
||||||
// Get the grip for promise p
|
// Get the grip for promise p
|
||||||
let onNewPromise = new Promise(resolve => {
|
let onNewPromise = new Promise(resolve => {
|
||||||
events.on(front, "new-promises", promises => {
|
EventEmitter.on(front, "new-promises", promises => {
|
||||||
for (let p of promises) {
|
for (let p of promises) {
|
||||||
if (p.preview.ownProperties.name &&
|
if (p.preview.ownProperties.name &&
|
||||||
p.preview.ownProperties.name.value === "p") {
|
p.preview.ownProperties.name.value === "p") {
|
||||||
|
|
|
@ -11,7 +11,7 @@
|
||||||
|
|
||||||
const TAB_URL = EXAMPLE_URL + "doc_promise-get-fulfillment-stack.html";
|
const TAB_URL = EXAMPLE_URL + "doc_promise-get-fulfillment-stack.html";
|
||||||
const { PromisesFront } = require("devtools/shared/fronts/promises");
|
const { PromisesFront } = require("devtools/shared/fronts/promises");
|
||||||
var events = require("devtools/shared/event-emitter");
|
var EventEmitter = require("devtools/shared/event-emitter");
|
||||||
|
|
||||||
const TEST_DATA = [
|
const TEST_DATA = [
|
||||||
{
|
{
|
||||||
|
@ -66,7 +66,7 @@ function* testGetFulfillmentStack(client, form, tab) {
|
||||||
|
|
||||||
// Get the grip for promise p
|
// Get the grip for promise p
|
||||||
let onNewPromise = new Promise(resolve => {
|
let onNewPromise = new Promise(resolve => {
|
||||||
events.on(front, "new-promises", promises => {
|
EventEmitter.on(front, "new-promises", promises => {
|
||||||
for (let p of promises) {
|
for (let p of promises) {
|
||||||
if (p.preview.ownProperties.name &&
|
if (p.preview.ownProperties.name &&
|
||||||
p.preview.ownProperties.name.value === "p") {
|
p.preview.ownProperties.name.value === "p") {
|
||||||
|
|
|
@ -11,7 +11,7 @@
|
||||||
|
|
||||||
const TAB_URL = EXAMPLE_URL + "doc_promise-get-rejection-stack.html";
|
const TAB_URL = EXAMPLE_URL + "doc_promise-get-rejection-stack.html";
|
||||||
const { PromisesFront } = require("devtools/shared/fronts/promises");
|
const { PromisesFront } = require("devtools/shared/fronts/promises");
|
||||||
var events = require("devtools/shared/event-emitter");
|
var EventEmitter = require("devtools/shared/event-emitter");
|
||||||
|
|
||||||
// The code in the document above leaves an uncaught rejection. This is only
|
// The code in the document above leaves an uncaught rejection. This is only
|
||||||
// reported to the testing framework if the code is loaded in the main process.
|
// reported to the testing framework if the code is loaded in the main process.
|
||||||
|
@ -73,7 +73,7 @@ function* testGetRejectionStack(client, form, tab) {
|
||||||
|
|
||||||
// Get the grip for promise p
|
// Get the grip for promise p
|
||||||
let onNewPromise = new Promise(resolve => {
|
let onNewPromise = new Promise(resolve => {
|
||||||
events.on(front, "new-promises", promises => {
|
EventEmitter.on(front, "new-promises", promises => {
|
||||||
for (let p of promises) {
|
for (let p of promises) {
|
||||||
if (p.preview.ownProperties.name &&
|
if (p.preview.ownProperties.name &&
|
||||||
p.preview.ownProperties.name.value === "p") {
|
p.preview.ownProperties.name.value === "p") {
|
||||||
|
|
|
@ -36,11 +36,14 @@ function SourceMapURLService(target, threadClient, sourceMapService) {
|
||||||
Services.prefs.addObserver(SOURCE_MAP_PREF, this._onPrefChanged);
|
Services.prefs.addObserver(SOURCE_MAP_PREF, this._onPrefChanged);
|
||||||
|
|
||||||
// Start fetching the sources now.
|
// Start fetching the sources now.
|
||||||
this._loadingPromise = new Promise(resolve => {
|
this._loadingPromise = threadClient.getSources().then(({sources}) => {
|
||||||
threadClient.getSources(({sources}) => {
|
// Ignore errors. Register the sources we got; we can't rely on
|
||||||
// Just ignore errors.
|
// an event to arrive if the source actor already existed.
|
||||||
resolve(sources);
|
for (let source of sources) {
|
||||||
});
|
this._onSourceUpdated(null, {source});
|
||||||
|
}
|
||||||
|
}, e => {
|
||||||
|
// Also ignore any protocol-based errors.
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -63,6 +63,7 @@ skip-if = debug # Bug 1282269
|
||||||
[browser_source_map-01.js]
|
[browser_source_map-01.js]
|
||||||
[browser_source_map-absolute.js]
|
[browser_source_map-absolute.js]
|
||||||
[browser_source_map-cross-domain.js]
|
[browser_source_map-cross-domain.js]
|
||||||
|
[browser_source_map-init.js]
|
||||||
[browser_source_map-inline.js]
|
[browser_source_map-inline.js]
|
||||||
[browser_source_map-no-race.js]
|
[browser_source_map-no-race.js]
|
||||||
[browser_source_map-reload.js]
|
[browser_source_map-reload.js]
|
||||||
|
|
|
@ -0,0 +1,43 @@
|
||||||
|
/* Any copyright is dedicated to the Public Domain.
|
||||||
|
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||||
|
|
||||||
|
// Test that the source map service initializes properly when source
|
||||||
|
// actors have already been created. Regression test for bug 1391768.
|
||||||
|
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
const JS_URL = URL_ROOT + "code_bundle_no_race.js";
|
||||||
|
|
||||||
|
const PAGE_URL = `data:text/html,
|
||||||
|
<!doctype html>
|
||||||
|
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8"/>
|
||||||
|
<title>Empty test page to test race case</title>
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
<script src="${JS_URL}"></script>
|
||||||
|
</body>
|
||||||
|
|
||||||
|
</html>`;
|
||||||
|
|
||||||
|
const ORIGINAL_URL = "webpack:///code_no_race.js";
|
||||||
|
|
||||||
|
const GENERATED_LINE = 84;
|
||||||
|
const ORIGINAL_LINE = 11;
|
||||||
|
|
||||||
|
add_task(function* () {
|
||||||
|
// Opening the debugger causes the source actors to be created.
|
||||||
|
const toolbox = yield openNewTabAndToolbox(PAGE_URL, "jsdebugger");
|
||||||
|
// In bug 1391768, when the sourceMapURLService was created, it was
|
||||||
|
// ignoring any source actors that already existed, leading to
|
||||||
|
// source-mapping failures for those.
|
||||||
|
const service = toolbox.sourceMapURLService;
|
||||||
|
|
||||||
|
info(`checking original location for ${JS_URL}:${GENERATED_LINE}`);
|
||||||
|
let newLoc = yield service.originalPositionFor(JS_URL, GENERATED_LINE);
|
||||||
|
is(newLoc.sourceUrl, ORIGINAL_URL, "check mapped URL");
|
||||||
|
is(newLoc.line, ORIGINAL_LINE, "check mapped line number");
|
||||||
|
});
|
|
@ -7,7 +7,7 @@
|
||||||
// on NodeActor. Custom form property is set when 'form' event is sent
|
// on NodeActor. Custom form property is set when 'form' event is sent
|
||||||
// by NodeActor actor (see 'onNodeActorForm' method).
|
// by NodeActor actor (see 'onNodeActorForm' method).
|
||||||
|
|
||||||
const Events = require("devtools/shared/event-emitter");
|
const EventEmitter = require("devtools/shared/event-emitter");
|
||||||
const {ActorClassWithSpec, Actor, FrontClassWithSpec, Front, generateActorSpec} =
|
const {ActorClassWithSpec, Actor, FrontClassWithSpec, Front, generateActorSpec} =
|
||||||
require("devtools/shared/protocol");
|
require("devtools/shared/protocol");
|
||||||
|
|
||||||
|
@ -34,11 +34,11 @@ var EventsFormActor = ActorClassWithSpec(eventsSpec, {
|
||||||
},
|
},
|
||||||
|
|
||||||
attach: function () {
|
attach: function () {
|
||||||
Events.on(NodeActor, "form", this.onNodeActorForm);
|
EventEmitter.on(NodeActor, "form", this.onNodeActorForm);
|
||||||
},
|
},
|
||||||
|
|
||||||
detach: function () {
|
detach: function () {
|
||||||
Events.off(NodeActor, "form", this.onNodeActorForm);
|
EventEmitter.off(NodeActor, "form", this.onNodeActorForm);
|
||||||
},
|
},
|
||||||
|
|
||||||
onNodeActorForm: function (event) {
|
onNodeActorForm: function (event) {
|
||||||
|
|
|
@ -47,7 +47,6 @@ support-files =
|
||||||
!/devtools/client/shared/test/test-actor-registry.js
|
!/devtools/client/shared/test/test-actor-registry.js
|
||||||
|
|
||||||
[browser_rules_add-property-and-reselect.js]
|
[browser_rules_add-property-and-reselect.js]
|
||||||
skip-if = stylo # Bug 1387445
|
|
||||||
[browser_rules_add-property-cancel_01.js]
|
[browser_rules_add-property-cancel_01.js]
|
||||||
[browser_rules_add-property-cancel_02.js]
|
[browser_rules_add-property-cancel_02.js]
|
||||||
[browser_rules_add-property-cancel_03.js]
|
[browser_rules_add-property-cancel_03.js]
|
||||||
|
@ -112,7 +111,7 @@ skip-if = (os == 'linux' && bits == 32 && debug) # bug 1328915, disable linux32
|
||||||
[browser_rules_cubicbezier-commit-on-ENTER.js]
|
[browser_rules_cubicbezier-commit-on-ENTER.js]
|
||||||
[browser_rules_cubicbezier-revert-on-ESC.js]
|
[browser_rules_cubicbezier-revert-on-ESC.js]
|
||||||
[browser_rules_custom.js]
|
[browser_rules_custom.js]
|
||||||
skip-if = stylo # Bug 1387445
|
skip-if = stylo # Bug 1391198
|
||||||
[browser_rules_cycle-angle.js]
|
[browser_rules_cycle-angle.js]
|
||||||
[browser_rules_cycle-color.js]
|
[browser_rules_cycle-color.js]
|
||||||
[browser_rules_edit-display-grid-property.js]
|
[browser_rules_edit-display-grid-property.js]
|
||||||
|
@ -132,7 +131,7 @@ skip-if = (os == "linux") # Bug 1356214
|
||||||
[browser_rules_edit-property_04.js]
|
[browser_rules_edit-property_04.js]
|
||||||
[browser_rules_edit-property_05.js]
|
[browser_rules_edit-property_05.js]
|
||||||
[browser_rules_edit-property_06.js]
|
[browser_rules_edit-property_06.js]
|
||||||
skip-if = stylo # Bug 1387445
|
skip-if = stylo # Bug 1391198
|
||||||
[browser_rules_edit-property_07.js]
|
[browser_rules_edit-property_07.js]
|
||||||
[browser_rules_edit-property_08.js]
|
[browser_rules_edit-property_08.js]
|
||||||
[browser_rules_edit-property_09.js]
|
[browser_rules_edit-property_09.js]
|
||||||
|
@ -183,17 +182,17 @@ skip-if = (os == "win" && debug) # bug 963492: win.
|
||||||
[browser_rules_invalid-source-map.js]
|
[browser_rules_invalid-source-map.js]
|
||||||
[browser_rules_keybindings.js]
|
[browser_rules_keybindings.js]
|
||||||
[browser_rules_keyframes-rule_01.js]
|
[browser_rules_keyframes-rule_01.js]
|
||||||
skip-if = stylo # Bug 1387445
|
skip-if = stylo # Bug 1394994
|
||||||
[browser_rules_keyframes-rule_02.js]
|
[browser_rules_keyframes-rule_02.js]
|
||||||
skip-if = stylo # Bug 1387445
|
skip-if = stylo # Bug 1394994
|
||||||
[browser_rules_keyframeLineNumbers.js]
|
[browser_rules_keyframeLineNumbers.js]
|
||||||
skip-if = stylo # Bug 1387445
|
skip-if = stylo # Bug 1394994
|
||||||
[browser_rules_lineNumbers.js]
|
[browser_rules_lineNumbers.js]
|
||||||
[browser_rules_livepreview.js]
|
[browser_rules_livepreview.js]
|
||||||
[browser_rules_mark_overridden_01.js]
|
[browser_rules_mark_overridden_01.js]
|
||||||
[browser_rules_mark_overridden_02.js]
|
[browser_rules_mark_overridden_02.js]
|
||||||
[browser_rules_mark_overridden_03.js]
|
[browser_rules_mark_overridden_03.js]
|
||||||
skip-if = stylo # Bug 1387445
|
skip-if = stylo # Bug 1391198
|
||||||
[browser_rules_mark_overridden_04.js]
|
[browser_rules_mark_overridden_04.js]
|
||||||
[browser_rules_mark_overridden_05.js]
|
[browser_rules_mark_overridden_05.js]
|
||||||
[browser_rules_mark_overridden_06.js]
|
[browser_rules_mark_overridden_06.js]
|
||||||
|
@ -223,7 +222,7 @@ skip-if = stylo # Bug 1387445
|
||||||
[browser_rules_search-filter-overridden-property.js]
|
[browser_rules_search-filter-overridden-property.js]
|
||||||
[browser_rules_search-filter_01.js]
|
[browser_rules_search-filter_01.js]
|
||||||
[browser_rules_search-filter_02.js]
|
[browser_rules_search-filter_02.js]
|
||||||
skip-if = stylo # Bug 1387445
|
skip-if = stylo # Bug 1394994
|
||||||
[browser_rules_search-filter_03.js]
|
[browser_rules_search-filter_03.js]
|
||||||
[browser_rules_search-filter_04.js]
|
[browser_rules_search-filter_04.js]
|
||||||
[browser_rules_search-filter_05.js]
|
[browser_rules_search-filter_05.js]
|
||||||
|
|
|
@ -215,6 +215,12 @@ webconsole.menu.copyURL.accesskey=a
|
||||||
webconsole.menu.openURL.label=Open URL in New Tab
|
webconsole.menu.openURL.label=Open URL in New Tab
|
||||||
webconsole.menu.openURL.accesskey=T
|
webconsole.menu.openURL.accesskey=T
|
||||||
|
|
||||||
|
# LOCALIZATION NOTE (webconsole.menu.openInNetworkPanel.label)
|
||||||
|
# Label used for a context-menu item displayed for network message logs. Clicking on it
|
||||||
|
# opens the network message in the Network panel
|
||||||
|
webconsole.menu.openInNetworkPanel.label=Open in Network Panel
|
||||||
|
webconsole.menu.openInNetworkPanel.accesskey=N
|
||||||
|
|
||||||
# LOCALIZATION NOTE (webconsole.menu.openInVarView.label)
|
# LOCALIZATION NOTE (webconsole.menu.openInVarView.label)
|
||||||
# Label used for a context-menu item displayed for object/variable logs. Clicking on it
|
# Label used for a context-menu item displayed for object/variable logs. Clicking on it
|
||||||
# opens the webconsole variable view for the logged variable.
|
# opens the webconsole variable view for the logged variable.
|
||||||
|
|
|
@ -203,11 +203,11 @@ const HeadersPanel = createClass({
|
||||||
className: "headers-summary learn-more-link",
|
className: "headers-summary learn-more-link",
|
||||||
}),
|
}),
|
||||||
button({
|
button({
|
||||||
className: "devtools-button",
|
className: "devtools-button edit-and-resend-button",
|
||||||
onClick: cloneSelectedRequest,
|
onClick: cloneSelectedRequest,
|
||||||
}, EDIT_AND_RESEND),
|
}, EDIT_AND_RESEND),
|
||||||
button({
|
button({
|
||||||
className: "devtools-button",
|
className: "devtools-button raw-headers-button",
|
||||||
onClick: this.toggleRawHeaders,
|
onClick: this.toggleRawHeaders,
|
||||||
}, RAW_HEADERS),
|
}, RAW_HEADERS),
|
||||||
)
|
)
|
||||||
|
|
|
@ -41,9 +41,9 @@ function NetworkDetailsPanel({
|
||||||
request,
|
request,
|
||||||
selectTab,
|
selectTab,
|
||||||
sourceMapService,
|
sourceMapService,
|
||||||
|
cloneSelectedRequest,
|
||||||
}) :
|
}) :
|
||||||
CustomRequestPanel({
|
CustomRequestPanel({
|
||||||
cloneSelectedRequest,
|
|
||||||
request,
|
request,
|
||||||
})
|
})
|
||||||
)
|
)
|
||||||
|
|
|
@ -9,9 +9,8 @@ const {
|
||||||
PropTypes,
|
PropTypes,
|
||||||
} = require("devtools/client/shared/vendor/react");
|
} = require("devtools/client/shared/vendor/react");
|
||||||
const { connect } = require("devtools/client/shared/vendor/react-redux");
|
const { connect } = require("devtools/client/shared/vendor/react-redux");
|
||||||
const Actions = require("../actions/index");
|
|
||||||
const { L10N } = require("../utils/l10n");
|
const { L10N } = require("../utils/l10n");
|
||||||
const { getSelectedRequest } = require("../selectors/index");
|
const { PANELS } = require("../constants");
|
||||||
|
|
||||||
// Components
|
// Components
|
||||||
const Tabbar = createFactory(require("devtools/client/shared/components/tabs/tabbar"));
|
const Tabbar = createFactory(require("devtools/client/shared/components/tabs/tabbar"));
|
||||||
|
@ -38,7 +37,7 @@ const TIMINGS_TITLE = L10N.getStr("netmonitor.tab.timings");
|
||||||
*/
|
*/
|
||||||
function TabboxPanel({
|
function TabboxPanel({
|
||||||
activeTabId,
|
activeTabId,
|
||||||
cloneSelectedRequest,
|
cloneSelectedRequest = ()=>{},
|
||||||
request,
|
request,
|
||||||
selectTab,
|
selectTab,
|
||||||
sourceMapService,
|
sourceMapService,
|
||||||
|
@ -56,45 +55,45 @@ function TabboxPanel({
|
||||||
showAllTabsMenu: true,
|
showAllTabsMenu: true,
|
||||||
},
|
},
|
||||||
TabPanel({
|
TabPanel({
|
||||||
id: "headers",
|
id: PANELS.HEADERS,
|
||||||
title: HEADERS_TITLE,
|
title: HEADERS_TITLE,
|
||||||
},
|
},
|
||||||
HeadersPanel({ request, cloneSelectedRequest }),
|
HeadersPanel({ request, cloneSelectedRequest }),
|
||||||
),
|
),
|
||||||
TabPanel({
|
TabPanel({
|
||||||
id: "cookies",
|
id: PANELS.COOKIES,
|
||||||
title: COOKIES_TITLE,
|
title: COOKIES_TITLE,
|
||||||
},
|
},
|
||||||
CookiesPanel({ request }),
|
CookiesPanel({ request }),
|
||||||
),
|
),
|
||||||
TabPanel({
|
TabPanel({
|
||||||
id: "params",
|
id: PANELS.PARAMS,
|
||||||
title: PARAMS_TITLE,
|
title: PARAMS_TITLE,
|
||||||
},
|
},
|
||||||
ParamsPanel({ request }),
|
ParamsPanel({ request }),
|
||||||
),
|
),
|
||||||
TabPanel({
|
TabPanel({
|
||||||
id: "response",
|
id: PANELS.RESPONSE,
|
||||||
title: RESPONSE_TITLE,
|
title: RESPONSE_TITLE,
|
||||||
},
|
},
|
||||||
ResponsePanel({ request }),
|
ResponsePanel({ request }),
|
||||||
),
|
),
|
||||||
TabPanel({
|
TabPanel({
|
||||||
id: "timings",
|
id: PANELS.TIMINGS,
|
||||||
title: TIMINGS_TITLE,
|
title: TIMINGS_TITLE,
|
||||||
},
|
},
|
||||||
TimingsPanel({ request }),
|
TimingsPanel({ request }),
|
||||||
),
|
),
|
||||||
request.cause && request.cause.stacktrace && request.cause.stacktrace.length > 0 &&
|
request.cause && request.cause.stacktrace && request.cause.stacktrace.length > 0 &&
|
||||||
TabPanel({
|
TabPanel({
|
||||||
id: "stack-trace",
|
id: PANELS.STACK_TRACE,
|
||||||
title: STACK_TRACE_TITLE,
|
title: STACK_TRACE_TITLE,
|
||||||
},
|
},
|
||||||
StackTracePanel({ request, sourceMapService }),
|
StackTracePanel({ request, sourceMapService }),
|
||||||
),
|
),
|
||||||
request.securityState && request.securityState !== "insecure" &&
|
request.securityState && request.securityState !== "insecure" &&
|
||||||
TabPanel({
|
TabPanel({
|
||||||
id: "security",
|
id: PANELS.SECURITY,
|
||||||
title: SECURITY_TITLE,
|
title: SECURITY_TITLE,
|
||||||
},
|
},
|
||||||
SecurityPanel({ request }),
|
SecurityPanel({ request }),
|
||||||
|
@ -107,20 +106,11 @@ TabboxPanel.displayName = "TabboxPanel";
|
||||||
|
|
||||||
TabboxPanel.propTypes = {
|
TabboxPanel.propTypes = {
|
||||||
activeTabId: PropTypes.string,
|
activeTabId: PropTypes.string,
|
||||||
cloneSelectedRequest: PropTypes.func.isRequired,
|
cloneSelectedRequest: PropTypes.func,
|
||||||
request: PropTypes.object,
|
request: PropTypes.object,
|
||||||
selectTab: PropTypes.func.isRequired,
|
selectTab: PropTypes.func.isRequired,
|
||||||
// Service to enable the source map feature.
|
// Service to enable the source map feature.
|
||||||
sourceMapService: PropTypes.object,
|
sourceMapService: PropTypes.object,
|
||||||
};
|
};
|
||||||
|
|
||||||
module.exports = connect(
|
module.exports = connect()(TabboxPanel);
|
||||||
(state) => ({
|
|
||||||
activeTabId: state.ui.detailsPanelSelectedTab,
|
|
||||||
request: getSelectedRequest(state),
|
|
||||||
}),
|
|
||||||
(dispatch) => ({
|
|
||||||
cloneSelectedRequest: () => dispatch(Actions.cloneSelectedRequest()),
|
|
||||||
selectTab: (tabId) => dispatch(Actions.selectDetailsPanelTab(tabId)),
|
|
||||||
}),
|
|
||||||
)(TabboxPanel);
|
|
||||||
|
|
|
@ -5,54 +5,29 @@
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
const Services = require("Services");
|
const Services = require("Services");
|
||||||
const { CurlUtils } = require("devtools/client/shared/curl");
|
|
||||||
const { TimelineFront } = require("devtools/shared/fronts/timeline");
|
const { TimelineFront } = require("devtools/shared/fronts/timeline");
|
||||||
const { ACTIVITY_TYPE, EVENTS } = require("../constants");
|
const { ACTIVITY_TYPE, EVENTS } = require("../constants");
|
||||||
const { getDisplayedRequestById } = require("../selectors/index");
|
const { getDisplayedRequestById } = require("../selectors/index");
|
||||||
const { fetchHeaders, formDataURI } = require("../utils/request-utils");
|
const FirefoxDataProvider = require("./firefox-data-provider");
|
||||||
|
|
||||||
class FirefoxConnector {
|
class FirefoxConnector {
|
||||||
constructor() {
|
constructor() {
|
||||||
// Internal properties
|
|
||||||
this.payloadQueue = [];
|
|
||||||
|
|
||||||
// Public methods
|
// Public methods
|
||||||
this.connect = this.connect.bind(this);
|
this.connect = this.connect.bind(this);
|
||||||
this.disconnect = this.disconnect.bind(this);
|
this.disconnect = this.disconnect.bind(this);
|
||||||
this.willNavigate = this.willNavigate.bind(this);
|
this.willNavigate = this.willNavigate.bind(this);
|
||||||
this.displayCachedEvents = this.displayCachedEvents.bind(this);
|
this.displayCachedEvents = this.displayCachedEvents.bind(this);
|
||||||
this.onDocLoadingMarker = this.onDocLoadingMarker.bind(this);
|
this.onDocLoadingMarker = this.onDocLoadingMarker.bind(this);
|
||||||
this.addRequest = this.addRequest.bind(this);
|
|
||||||
this.updateRequest = this.updateRequest.bind(this);
|
|
||||||
this.fetchImage = this.fetchImage.bind(this);
|
|
||||||
this.fetchRequestHeaders = this.fetchRequestHeaders.bind(this);
|
|
||||||
this.fetchResponseHeaders = this.fetchResponseHeaders.bind(this);
|
|
||||||
this.fetchPostData = this.fetchPostData.bind(this);
|
|
||||||
this.fetchResponseCookies = this.fetchResponseCookies.bind(this);
|
|
||||||
this.fetchRequestCookies = this.fetchRequestCookies.bind(this);
|
|
||||||
this.getPayloadFromQueue = this.getPayloadFromQueue.bind(this);
|
|
||||||
this.isQueuePayloadReady = this.isQueuePayloadReady.bind(this);
|
|
||||||
this.pushPayloadToQueue = this.pushPayloadToQueue.bind(this);
|
|
||||||
this.sendHTTPRequest = this.sendHTTPRequest.bind(this);
|
this.sendHTTPRequest = this.sendHTTPRequest.bind(this);
|
||||||
this.setPreferences = this.setPreferences.bind(this);
|
this.setPreferences = this.setPreferences.bind(this);
|
||||||
this.triggerActivity = this.triggerActivity.bind(this);
|
this.triggerActivity = this.triggerActivity.bind(this);
|
||||||
this.inspectRequest = this.inspectRequest.bind(this);
|
this.inspectRequest = this.inspectRequest.bind(this);
|
||||||
this.getLongString = this.getLongString.bind(this);
|
|
||||||
this.getNetworkRequest = this.getNetworkRequest.bind(this);
|
|
||||||
this.getTabTarget = this.getTabTarget.bind(this);
|
this.getTabTarget = this.getTabTarget.bind(this);
|
||||||
this.viewSourceInDebugger = this.viewSourceInDebugger.bind(this);
|
this.viewSourceInDebugger = this.viewSourceInDebugger.bind(this);
|
||||||
|
|
||||||
// Event handlers
|
// Internals
|
||||||
this.onNetworkEvent = this.onNetworkEvent.bind(this);
|
this.getLongString = this.getLongString.bind(this);
|
||||||
this.onNetworkEventUpdate = this.onNetworkEventUpdate.bind(this);
|
this.getNetworkRequest = this.getNetworkRequest.bind(this);
|
||||||
this.onRequestHeaders = this.onRequestHeaders.bind(this);
|
|
||||||
this.onRequestCookies = this.onRequestCookies.bind(this);
|
|
||||||
this.onRequestPostData = this.onRequestPostData.bind(this);
|
|
||||||
this.onSecurityInfo = this.onSecurityInfo.bind(this);
|
|
||||||
this.onResponseHeaders = this.onResponseHeaders.bind(this);
|
|
||||||
this.onResponseCookies = this.onResponseCookies.bind(this);
|
|
||||||
this.onResponseContent = this.onResponseContent.bind(this);
|
|
||||||
this.onEventTimings = this.onEventTimings.bind(this);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async connect(connection, actions, getState) {
|
async connect(connection, actions, getState) {
|
||||||
|
@ -63,10 +38,17 @@ class FirefoxConnector {
|
||||||
|
|
||||||
this.webConsoleClient = this.tabTarget.activeConsole;
|
this.webConsoleClient = this.tabTarget.activeConsole;
|
||||||
|
|
||||||
|
this.dataProvider = new FirefoxDataProvider({
|
||||||
|
webConsoleClient: this.webConsoleClient,
|
||||||
|
actions: this.actions,
|
||||||
|
});
|
||||||
|
|
||||||
this.tabTarget.on("will-navigate", this.willNavigate);
|
this.tabTarget.on("will-navigate", this.willNavigate);
|
||||||
this.tabTarget.on("close", this.disconnect);
|
this.tabTarget.on("close", this.disconnect);
|
||||||
this.webConsoleClient.on("networkEvent", this.onNetworkEvent);
|
this.webConsoleClient.on("networkEvent",
|
||||||
this.webConsoleClient.on("networkEventUpdate", this.onNetworkEventUpdate);
|
this.dataProvider.onNetworkEvent);
|
||||||
|
this.webConsoleClient.on("networkEventUpdate",
|
||||||
|
this.dataProvider.onNetworkEventUpdate);
|
||||||
|
|
||||||
// Don't start up waiting for timeline markers if the server isn't
|
// Don't start up waiting for timeline markers if the server isn't
|
||||||
// recent enough to emit the markers we're interested in.
|
// recent enough to emit the markers we're interested in.
|
||||||
|
@ -96,6 +78,7 @@ class FirefoxConnector {
|
||||||
this.webConsoleClient.off("networkEventUpdate");
|
this.webConsoleClient.off("networkEventUpdate");
|
||||||
this.webConsoleClient = null;
|
this.webConsoleClient = null;
|
||||||
this.timelineFront = null;
|
this.timelineFront = null;
|
||||||
|
this.dataProvider = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
willNavigate() {
|
willNavigate() {
|
||||||
|
@ -114,10 +97,10 @@ class FirefoxConnector {
|
||||||
displayCachedEvents() {
|
displayCachedEvents() {
|
||||||
for (let networkInfo of this.webConsoleClient.getNetworkEvents()) {
|
for (let networkInfo of this.webConsoleClient.getNetworkEvents()) {
|
||||||
// First add the request to the timeline.
|
// First add the request to the timeline.
|
||||||
this.onNetworkEvent("networkEvent", networkInfo);
|
this.dataProvider.onNetworkEvent("networkEvent", networkInfo);
|
||||||
// Then replay any updates already received.
|
// Then replay any updates already received.
|
||||||
for (let updateType of networkInfo.updates) {
|
for (let updateType of networkInfo.updates) {
|
||||||
this.onNetworkEventUpdate("networkEventUpdate", {
|
this.dataProvider.onNetworkEventUpdate("networkEventUpdate", {
|
||||||
packet: { updateType },
|
packet: { updateType },
|
||||||
networkInfo,
|
networkInfo,
|
||||||
});
|
});
|
||||||
|
@ -135,222 +118,6 @@ class FirefoxConnector {
|
||||||
this.actions.addTimingMarker(marker);
|
this.actions.addTimingMarker(marker);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Add a new network request to application state.
|
|
||||||
*
|
|
||||||
* @param {string} id request id
|
|
||||||
* @param {object} data data payload will be added to application state
|
|
||||||
*/
|
|
||||||
addRequest(id, data) {
|
|
||||||
let {
|
|
||||||
method,
|
|
||||||
url,
|
|
||||||
isXHR,
|
|
||||||
cause,
|
|
||||||
startedDateTime,
|
|
||||||
fromCache,
|
|
||||||
fromServiceWorker,
|
|
||||||
} = data;
|
|
||||||
|
|
||||||
this.actions.addRequest(
|
|
||||||
id,
|
|
||||||
{
|
|
||||||
// Convert the received date/time string to a unix timestamp.
|
|
||||||
startedMillis: Date.parse(startedDateTime),
|
|
||||||
method,
|
|
||||||
url,
|
|
||||||
isXHR,
|
|
||||||
cause,
|
|
||||||
fromCache,
|
|
||||||
fromServiceWorker,
|
|
||||||
},
|
|
||||||
true,
|
|
||||||
)
|
|
||||||
.then(() => window.emit(EVENTS.REQUEST_ADDED, id));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Update a network request if it already exists in application state.
|
|
||||||
*
|
|
||||||
* @param {string} id request id
|
|
||||||
* @param {object} data data payload will be updated to application state
|
|
||||||
*/
|
|
||||||
async updateRequest(id, data) {
|
|
||||||
let {
|
|
||||||
mimeType,
|
|
||||||
responseContent,
|
|
||||||
responseCookies,
|
|
||||||
responseHeaders,
|
|
||||||
requestCookies,
|
|
||||||
requestHeaders,
|
|
||||||
requestPostData,
|
|
||||||
} = data;
|
|
||||||
|
|
||||||
// fetch request detail contents in parallel
|
|
||||||
let [
|
|
||||||
imageObj,
|
|
||||||
requestHeadersObj,
|
|
||||||
responseHeadersObj,
|
|
||||||
postDataObj,
|
|
||||||
requestCookiesObj,
|
|
||||||
responseCookiesObj,
|
|
||||||
] = await Promise.all([
|
|
||||||
this.fetchImage(mimeType, responseContent),
|
|
||||||
this.fetchRequestHeaders(requestHeaders),
|
|
||||||
this.fetchResponseHeaders(responseHeaders),
|
|
||||||
this.fetchPostData(requestPostData),
|
|
||||||
this.fetchRequestCookies(requestCookies),
|
|
||||||
this.fetchResponseCookies(responseCookies),
|
|
||||||
]);
|
|
||||||
|
|
||||||
let payload = Object.assign({}, data,
|
|
||||||
imageObj, requestHeadersObj, responseHeadersObj,
|
|
||||||
postDataObj, requestCookiesObj, responseCookiesObj);
|
|
||||||
|
|
||||||
this.pushPayloadToQueue(id, payload);
|
|
||||||
|
|
||||||
if (this.isQueuePayloadReady(id)) {
|
|
||||||
await this.actions.updateRequest(id, this.getPayloadFromQueue(id).payload, true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async fetchImage(mimeType, responseContent) {
|
|
||||||
let payload = {};
|
|
||||||
if (mimeType && responseContent && responseContent.content) {
|
|
||||||
let { encoding, text } = responseContent.content;
|
|
||||||
let response = await this.getLongString(text);
|
|
||||||
|
|
||||||
if (mimeType.includes("image/")) {
|
|
||||||
payload.responseContentDataUri = formDataURI(mimeType, encoding, response);
|
|
||||||
}
|
|
||||||
|
|
||||||
responseContent.content.text = response;
|
|
||||||
payload.responseContent = responseContent;
|
|
||||||
}
|
|
||||||
return payload;
|
|
||||||
}
|
|
||||||
|
|
||||||
async fetchRequestHeaders(requestHeaders) {
|
|
||||||
let payload = {};
|
|
||||||
if (requestHeaders && requestHeaders.headers && requestHeaders.headers.length) {
|
|
||||||
let headers = await fetchHeaders(requestHeaders, this.getLongString);
|
|
||||||
if (headers) {
|
|
||||||
payload.requestHeaders = headers;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return payload;
|
|
||||||
}
|
|
||||||
|
|
||||||
async fetchResponseHeaders(responseHeaders) {
|
|
||||||
let payload = {};
|
|
||||||
if (responseHeaders && responseHeaders.headers && responseHeaders.headers.length) {
|
|
||||||
let headers = await fetchHeaders(responseHeaders, this.getLongString);
|
|
||||||
if (headers) {
|
|
||||||
payload.responseHeaders = headers;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return payload;
|
|
||||||
}
|
|
||||||
|
|
||||||
async fetchPostData(requestPostData) {
|
|
||||||
let payload = {};
|
|
||||||
if (requestPostData && requestPostData.postData) {
|
|
||||||
let { text } = requestPostData.postData;
|
|
||||||
let postData = await this.getLongString(text);
|
|
||||||
const headers = CurlUtils.getHeadersFromMultipartText(postData);
|
|
||||||
const headersSize = headers.reduce((acc, { name, value }) => {
|
|
||||||
return acc + name.length + value.length + 2;
|
|
||||||
}, 0);
|
|
||||||
requestPostData.postData.text = postData;
|
|
||||||
payload.requestPostData = Object.assign({}, requestPostData);
|
|
||||||
payload.requestHeadersFromUploadStream = { headers, headersSize };
|
|
||||||
}
|
|
||||||
return payload;
|
|
||||||
}
|
|
||||||
|
|
||||||
async fetchResponseCookies(responseCookies) {
|
|
||||||
let payload = {};
|
|
||||||
if (responseCookies) {
|
|
||||||
let resCookies = [];
|
|
||||||
// response store cookies in responseCookies or responseCookies.cookies
|
|
||||||
let cookies = responseCookies.cookies ?
|
|
||||||
responseCookies.cookies : responseCookies;
|
|
||||||
// make sure cookies is iterable
|
|
||||||
if (typeof cookies[Symbol.iterator] === "function") {
|
|
||||||
for (let cookie of cookies) {
|
|
||||||
resCookies.push(Object.assign({}, cookie, {
|
|
||||||
value: await this.getLongString(cookie.value),
|
|
||||||
}));
|
|
||||||
}
|
|
||||||
if (resCookies.length) {
|
|
||||||
payload.responseCookies = resCookies;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return payload;
|
|
||||||
}
|
|
||||||
|
|
||||||
async fetchRequestCookies(requestCookies) {
|
|
||||||
let payload = {};
|
|
||||||
if (requestCookies) {
|
|
||||||
let reqCookies = [];
|
|
||||||
// request store cookies in requestCookies or requestCookies.cookies
|
|
||||||
let cookies = requestCookies.cookies ?
|
|
||||||
requestCookies.cookies : requestCookies;
|
|
||||||
// make sure cookies is iterable
|
|
||||||
if (typeof cookies[Symbol.iterator] === "function") {
|
|
||||||
for (let cookie of cookies) {
|
|
||||||
reqCookies.push(Object.assign({}, cookie, {
|
|
||||||
value: await this.getLongString(cookie.value),
|
|
||||||
}));
|
|
||||||
}
|
|
||||||
if (reqCookies.length) {
|
|
||||||
payload.requestCookies = reqCookies;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return payload;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Access a payload item from payload queue.
|
|
||||||
*
|
|
||||||
* @param {string} id request id
|
|
||||||
* @return {boolean} return a queued payload item from queue.
|
|
||||||
*/
|
|
||||||
getPayloadFromQueue(id) {
|
|
||||||
return this.payloadQueue.find((item) => item.id === id);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Packet order of "networkUpdateEvent" is predictable, as a result we can wait for
|
|
||||||
* the last one "eventTimings" packet arrives to check payload is ready.
|
|
||||||
*
|
|
||||||
* @param {string} id request id
|
|
||||||
* @return {boolean} return whether a specific networkEvent has been updated completely.
|
|
||||||
*/
|
|
||||||
isQueuePayloadReady(id) {
|
|
||||||
let queuedPayload = this.getPayloadFromQueue(id);
|
|
||||||
return queuedPayload && queuedPayload.payload.eventTimings;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Push a request payload into a queue if request doesn't exist. Otherwise update the
|
|
||||||
* request itself.
|
|
||||||
*
|
|
||||||
* @param {string} id request id
|
|
||||||
* @param {object} payload request data payload
|
|
||||||
*/
|
|
||||||
pushPayloadToQueue(id, payload) {
|
|
||||||
let queuedPayload = this.getPayloadFromQueue(id);
|
|
||||||
if (!queuedPayload) {
|
|
||||||
this.payloadQueue.push({ id, payload });
|
|
||||||
} else {
|
|
||||||
// Merge upcoming networkEventUpdate payload into existing one
|
|
||||||
queuedPayload.payload = Object.assign({}, queuedPayload.payload, payload);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Send a HTTP request data payload
|
* Send a HTTP request data payload
|
||||||
*
|
*
|
||||||
|
@ -490,7 +257,7 @@ class FirefoxConnector {
|
||||||
* @return {object} networkInfo data packet
|
* @return {object} networkInfo data packet
|
||||||
*/
|
*/
|
||||||
getNetworkRequest(id) {
|
getNetworkRequest(id) {
|
||||||
return this.webConsoleClient.getNetworkRequest(id);
|
return this.dataProvider.getNetworkRequest(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -505,7 +272,7 @@ class FirefoxConnector {
|
||||||
* are available, or rejected if something goes wrong.
|
* are available, or rejected if something goes wrong.
|
||||||
*/
|
*/
|
||||||
getLongString(stringGrip) {
|
getLongString(stringGrip) {
|
||||||
return this.webConsoleClient.getString(stringGrip);
|
return this.dataProvider.getLongString(stringGrip);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -526,213 +293,6 @@ class FirefoxConnector {
|
||||||
this.toolbox.viewSourceInDebugger(sourceURL, sourceLine);
|
this.toolbox.viewSourceInDebugger(sourceURL, sourceLine);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* The "networkEvent" message type handler.
|
|
||||||
*
|
|
||||||
* @param {string} type message type
|
|
||||||
* @param {object} networkInfo network request information
|
|
||||||
*/
|
|
||||||
onNetworkEvent(type, networkInfo) {
|
|
||||||
let {
|
|
||||||
actor,
|
|
||||||
cause,
|
|
||||||
fromCache,
|
|
||||||
fromServiceWorker,
|
|
||||||
isXHR,
|
|
||||||
request: {
|
|
||||||
method,
|
|
||||||
url,
|
|
||||||
},
|
|
||||||
startedDateTime,
|
|
||||||
} = networkInfo;
|
|
||||||
|
|
||||||
this.addRequest(actor, {
|
|
||||||
cause,
|
|
||||||
fromCache,
|
|
||||||
fromServiceWorker,
|
|
||||||
isXHR,
|
|
||||||
method,
|
|
||||||
startedDateTime,
|
|
||||||
url,
|
|
||||||
});
|
|
||||||
|
|
||||||
window.emit(EVENTS.NETWORK_EVENT, actor);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The "networkEventUpdate" message type handler.
|
|
||||||
*
|
|
||||||
* @param {string} type message type
|
|
||||||
* @param {object} packet the message received from the server.
|
|
||||||
* @param {object} networkInfo the network request information.
|
|
||||||
*/
|
|
||||||
onNetworkEventUpdate(type, { packet, networkInfo }) {
|
|
||||||
let { actor } = networkInfo;
|
|
||||||
|
|
||||||
switch (packet.updateType) {
|
|
||||||
case "requestHeaders":
|
|
||||||
this.webConsoleClient.getRequestHeaders(actor, this.onRequestHeaders);
|
|
||||||
window.emit(EVENTS.UPDATING_REQUEST_HEADERS, actor);
|
|
||||||
break;
|
|
||||||
case "requestCookies":
|
|
||||||
this.webConsoleClient.getRequestCookies(actor, this.onRequestCookies);
|
|
||||||
window.emit(EVENTS.UPDATING_REQUEST_COOKIES, actor);
|
|
||||||
break;
|
|
||||||
case "requestPostData":
|
|
||||||
this.webConsoleClient.getRequestPostData(actor, this.onRequestPostData);
|
|
||||||
window.emit(EVENTS.UPDATING_REQUEST_POST_DATA, actor);
|
|
||||||
break;
|
|
||||||
case "securityInfo":
|
|
||||||
this.updateRequest(actor, {
|
|
||||||
securityState: networkInfo.securityInfo,
|
|
||||||
}).then(() => {
|
|
||||||
this.webConsoleClient.getSecurityInfo(actor, this.onSecurityInfo);
|
|
||||||
window.emit(EVENTS.UPDATING_SECURITY_INFO, actor);
|
|
||||||
});
|
|
||||||
break;
|
|
||||||
case "responseHeaders":
|
|
||||||
this.webConsoleClient.getResponseHeaders(actor, this.onResponseHeaders);
|
|
||||||
window.emit(EVENTS.UPDATING_RESPONSE_HEADERS, actor);
|
|
||||||
break;
|
|
||||||
case "responseCookies":
|
|
||||||
this.webConsoleClient.getResponseCookies(actor, this.onResponseCookies);
|
|
||||||
window.emit(EVENTS.UPDATING_RESPONSE_COOKIES, actor);
|
|
||||||
break;
|
|
||||||
case "responseStart":
|
|
||||||
this.updateRequest(actor, {
|
|
||||||
httpVersion: networkInfo.response.httpVersion,
|
|
||||||
remoteAddress: networkInfo.response.remoteAddress,
|
|
||||||
remotePort: networkInfo.response.remotePort,
|
|
||||||
status: networkInfo.response.status,
|
|
||||||
statusText: networkInfo.response.statusText,
|
|
||||||
headersSize: networkInfo.response.headersSize
|
|
||||||
}).then(() => {
|
|
||||||
window.emit(EVENTS.STARTED_RECEIVING_RESPONSE, actor);
|
|
||||||
});
|
|
||||||
break;
|
|
||||||
case "responseContent":
|
|
||||||
this.webConsoleClient.getResponseContent(actor,
|
|
||||||
this.onResponseContent.bind(this, {
|
|
||||||
contentSize: networkInfo.response.bodySize,
|
|
||||||
transferredSize: networkInfo.response.transferredSize,
|
|
||||||
mimeType: networkInfo.response.content.mimeType
|
|
||||||
}));
|
|
||||||
window.emit(EVENTS.UPDATING_RESPONSE_CONTENT, actor);
|
|
||||||
break;
|
|
||||||
case "eventTimings":
|
|
||||||
this.updateRequest(actor, { totalTime: networkInfo.totalTime })
|
|
||||||
.then(() => {
|
|
||||||
this.webConsoleClient.getEventTimings(actor, this.onEventTimings);
|
|
||||||
window.emit(EVENTS.UPDATING_EVENT_TIMINGS, actor);
|
|
||||||
});
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Handles additional information received for a "requestHeaders" packet.
|
|
||||||
*
|
|
||||||
* @param {object} response the message received from the server.
|
|
||||||
*/
|
|
||||||
onRequestHeaders(response) {
|
|
||||||
this.updateRequest(response.from, {
|
|
||||||
requestHeaders: response
|
|
||||||
}).then(() => {
|
|
||||||
window.emit(EVENTS.RECEIVED_REQUEST_HEADERS, response.from);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Handles additional information received for a "requestCookies" packet.
|
|
||||||
*
|
|
||||||
* @param {object} response the message received from the server.
|
|
||||||
*/
|
|
||||||
onRequestCookies(response) {
|
|
||||||
this.updateRequest(response.from, {
|
|
||||||
requestCookies: response
|
|
||||||
}).then(() => {
|
|
||||||
window.emit(EVENTS.RECEIVED_REQUEST_COOKIES, response.from);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Handles additional information received for a "requestPostData" packet.
|
|
||||||
*
|
|
||||||
* @param {object} response the message received from the server.
|
|
||||||
*/
|
|
||||||
onRequestPostData(response) {
|
|
||||||
this.updateRequest(response.from, {
|
|
||||||
requestPostData: response
|
|
||||||
}).then(() => {
|
|
||||||
window.emit(EVENTS.RECEIVED_REQUEST_POST_DATA, response.from);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Handles additional information received for a "securityInfo" packet.
|
|
||||||
*
|
|
||||||
* @param {object} response the message received from the server.
|
|
||||||
*/
|
|
||||||
onSecurityInfo(response) {
|
|
||||||
this.updateRequest(response.from, {
|
|
||||||
securityInfo: response.securityInfo
|
|
||||||
}).then(() => {
|
|
||||||
window.emit(EVENTS.RECEIVED_SECURITY_INFO, response.from);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Handles additional information received for a "responseHeaders" packet.
|
|
||||||
*
|
|
||||||
* @param {object} response the message received from the server.
|
|
||||||
*/
|
|
||||||
onResponseHeaders(response) {
|
|
||||||
this.updateRequest(response.from, {
|
|
||||||
responseHeaders: response
|
|
||||||
}).then(() => {
|
|
||||||
window.emit(EVENTS.RECEIVED_RESPONSE_HEADERS, response.from);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Handles additional information received for a "responseCookies" packet.
|
|
||||||
*
|
|
||||||
* @param {object} response the message received from the server.
|
|
||||||
*/
|
|
||||||
onResponseCookies(response) {
|
|
||||||
this.updateRequest(response.from, {
|
|
||||||
responseCookies: response
|
|
||||||
}).then(() => {
|
|
||||||
window.emit(EVENTS.RECEIVED_RESPONSE_COOKIES, response.from);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Handles additional information received for a "responseContent" packet.
|
|
||||||
*
|
|
||||||
* @param {object} data the message received from the server event.
|
|
||||||
* @param {object} response the message received from the server.
|
|
||||||
*/
|
|
||||||
onResponseContent(data, response) {
|
|
||||||
let payload = Object.assign({ responseContent: response }, data);
|
|
||||||
this.updateRequest(response.from, payload).then(() => {
|
|
||||||
window.emit(EVENTS.RECEIVED_RESPONSE_CONTENT, response.from);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Handles additional information received for a "eventTimings" packet.
|
|
||||||
*
|
|
||||||
* @param {object} response the message received from the server.
|
|
||||||
*/
|
|
||||||
onEventTimings(response) {
|
|
||||||
this.updateRequest(response.from, {
|
|
||||||
eventTimings: response
|
|
||||||
}).then(() => {
|
|
||||||
window.emit(EVENTS.RECEIVED_EVENT_TIMINGS, response.from);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = new FirefoxConnector();
|
module.exports = new FirefoxConnector();
|
||||||
|
|
|
@ -0,0 +1,525 @@
|
||||||
|
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
/* eslint-disable block-scoped-var */
|
||||||
|
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
const { EVENTS } = require("../constants");
|
||||||
|
const { CurlUtils } = require("devtools/client/shared/curl");
|
||||||
|
const { fetchHeaders, formDataURI } = require("../utils/request-utils");
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This object is responsible for fetching additional HTTP
|
||||||
|
* data from the backend.
|
||||||
|
*/
|
||||||
|
class FirefoxDataProvider {
|
||||||
|
constructor({webConsoleClient, actions}) {
|
||||||
|
// Options
|
||||||
|
this.webConsoleClient = webConsoleClient;
|
||||||
|
this.actions = actions;
|
||||||
|
|
||||||
|
// Internal properties
|
||||||
|
this.payloadQueue = [];
|
||||||
|
|
||||||
|
// Public methods
|
||||||
|
this.addRequest = this.addRequest.bind(this);
|
||||||
|
this.updateRequest = this.updateRequest.bind(this);
|
||||||
|
|
||||||
|
// Internals
|
||||||
|
this.fetchImage = this.fetchImage.bind(this);
|
||||||
|
this.fetchRequestHeaders = this.fetchRequestHeaders.bind(this);
|
||||||
|
this.fetchResponseHeaders = this.fetchResponseHeaders.bind(this);
|
||||||
|
this.fetchPostData = this.fetchPostData.bind(this);
|
||||||
|
this.fetchResponseCookies = this.fetchResponseCookies.bind(this);
|
||||||
|
this.fetchRequestCookies = this.fetchRequestCookies.bind(this);
|
||||||
|
this.getPayloadFromQueue = this.getPayloadFromQueue.bind(this);
|
||||||
|
this.isQueuePayloadReady = this.isQueuePayloadReady.bind(this);
|
||||||
|
this.pushPayloadToQueue = this.pushPayloadToQueue.bind(this);
|
||||||
|
this.getLongString = this.getLongString.bind(this);
|
||||||
|
this.getNetworkRequest = this.getNetworkRequest.bind(this);
|
||||||
|
|
||||||
|
// Event handlers
|
||||||
|
this.onNetworkEvent = this.onNetworkEvent.bind(this);
|
||||||
|
this.onNetworkEventUpdate = this.onNetworkEventUpdate.bind(this);
|
||||||
|
this.onRequestHeaders = this.onRequestHeaders.bind(this);
|
||||||
|
this.onRequestCookies = this.onRequestCookies.bind(this);
|
||||||
|
this.onRequestPostData = this.onRequestPostData.bind(this);
|
||||||
|
this.onSecurityInfo = this.onSecurityInfo.bind(this);
|
||||||
|
this.onResponseHeaders = this.onResponseHeaders.bind(this);
|
||||||
|
this.onResponseCookies = this.onResponseCookies.bind(this);
|
||||||
|
this.onResponseContent = this.onResponseContent.bind(this);
|
||||||
|
this.onEventTimings = this.onEventTimings.bind(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add a new network request to application state.
|
||||||
|
*
|
||||||
|
* @param {string} id request id
|
||||||
|
* @param {object} data data payload will be added to application state
|
||||||
|
*/
|
||||||
|
async addRequest(id, data) {
|
||||||
|
let {
|
||||||
|
method,
|
||||||
|
url,
|
||||||
|
isXHR,
|
||||||
|
cause,
|
||||||
|
startedDateTime,
|
||||||
|
fromCache,
|
||||||
|
fromServiceWorker,
|
||||||
|
} = data;
|
||||||
|
|
||||||
|
if (this.actions.addRequest) {
|
||||||
|
await this.actions.addRequest(id, {
|
||||||
|
// Convert the received date/time string to a unix timestamp.
|
||||||
|
startedMillis: Date.parse(startedDateTime),
|
||||||
|
method,
|
||||||
|
url,
|
||||||
|
isXHR,
|
||||||
|
cause,
|
||||||
|
fromCache,
|
||||||
|
fromServiceWorker},
|
||||||
|
true,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
emit(EVENTS.REQUEST_ADDED, id);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Update a network request if it already exists in application state.
|
||||||
|
*
|
||||||
|
* @param {string} id request id
|
||||||
|
* @param {object} data data payload will be updated to application state
|
||||||
|
*/
|
||||||
|
async updateRequest(id, data) {
|
||||||
|
let {
|
||||||
|
mimeType,
|
||||||
|
responseContent,
|
||||||
|
responseCookies,
|
||||||
|
responseHeaders,
|
||||||
|
requestCookies,
|
||||||
|
requestHeaders,
|
||||||
|
requestPostData,
|
||||||
|
} = data;
|
||||||
|
|
||||||
|
// fetch request detail contents in parallel
|
||||||
|
let [
|
||||||
|
imageObj,
|
||||||
|
requestHeadersObj,
|
||||||
|
responseHeadersObj,
|
||||||
|
postDataObj,
|
||||||
|
requestCookiesObj,
|
||||||
|
responseCookiesObj,
|
||||||
|
] = await Promise.all([
|
||||||
|
this.fetchImage(mimeType, responseContent),
|
||||||
|
this.fetchRequestHeaders(requestHeaders),
|
||||||
|
this.fetchResponseHeaders(responseHeaders),
|
||||||
|
this.fetchPostData(requestPostData),
|
||||||
|
this.fetchRequestCookies(requestCookies),
|
||||||
|
this.fetchResponseCookies(responseCookies),
|
||||||
|
]);
|
||||||
|
|
||||||
|
let payload = Object.assign({},
|
||||||
|
data,
|
||||||
|
imageObj,
|
||||||
|
requestHeadersObj,
|
||||||
|
responseHeadersObj,
|
||||||
|
postDataObj,
|
||||||
|
requestCookiesObj,
|
||||||
|
responseCookiesObj
|
||||||
|
);
|
||||||
|
|
||||||
|
this.pushPayloadToQueue(id, payload);
|
||||||
|
|
||||||
|
if (this.actions.updateRequest && this.isQueuePayloadReady(id)) {
|
||||||
|
await this.actions.updateRequest(id, this.getPayloadFromQueue(id).payload, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async fetchImage(mimeType, responseContent) {
|
||||||
|
let payload = {};
|
||||||
|
if (mimeType && responseContent && responseContent.content) {
|
||||||
|
let { encoding, text } = responseContent.content;
|
||||||
|
let response = await this.getLongString(text);
|
||||||
|
|
||||||
|
if (mimeType.includes("image/")) {
|
||||||
|
payload.responseContentDataUri = formDataURI(mimeType, encoding, response);
|
||||||
|
}
|
||||||
|
|
||||||
|
responseContent.content.text = response;
|
||||||
|
payload.responseContent = responseContent;
|
||||||
|
}
|
||||||
|
return payload;
|
||||||
|
}
|
||||||
|
|
||||||
|
async fetchRequestHeaders(requestHeaders) {
|
||||||
|
let payload = {};
|
||||||
|
if (requestHeaders && requestHeaders.headers && requestHeaders.headers.length) {
|
||||||
|
let headers = await fetchHeaders(requestHeaders, this.getLongString);
|
||||||
|
if (headers) {
|
||||||
|
payload.requestHeaders = headers;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return payload;
|
||||||
|
}
|
||||||
|
|
||||||
|
async fetchResponseHeaders(responseHeaders) {
|
||||||
|
let payload = {};
|
||||||
|
if (responseHeaders && responseHeaders.headers && responseHeaders.headers.length) {
|
||||||
|
let headers = await fetchHeaders(responseHeaders, this.getLongString);
|
||||||
|
if (headers) {
|
||||||
|
payload.responseHeaders = headers;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return payload;
|
||||||
|
}
|
||||||
|
|
||||||
|
async fetchPostData(requestPostData) {
|
||||||
|
let payload = {};
|
||||||
|
if (requestPostData && requestPostData.postData) {
|
||||||
|
let { text } = requestPostData.postData;
|
||||||
|
let postData = await this.getLongString(text);
|
||||||
|
const headers = CurlUtils.getHeadersFromMultipartText(postData);
|
||||||
|
|
||||||
|
// Calculate total header size and don't forget to include
|
||||||
|
// two new-line characters at the end.
|
||||||
|
const headersSize = headers.reduce((acc, { name, value }) => {
|
||||||
|
return acc + name.length + value.length + 2;
|
||||||
|
}, 0);
|
||||||
|
|
||||||
|
requestPostData.postData.text = postData;
|
||||||
|
payload.requestPostData = Object.assign({}, requestPostData);
|
||||||
|
payload.requestHeadersFromUploadStream = { headers, headersSize };
|
||||||
|
}
|
||||||
|
return payload;
|
||||||
|
}
|
||||||
|
|
||||||
|
async fetchResponseCookies(responseCookies) {
|
||||||
|
let payload = {};
|
||||||
|
if (responseCookies) {
|
||||||
|
let resCookies = [];
|
||||||
|
// response store cookies in responseCookies or responseCookies.cookies
|
||||||
|
let cookies = responseCookies.cookies ?
|
||||||
|
responseCookies.cookies : responseCookies;
|
||||||
|
// make sure cookies is iterable
|
||||||
|
if (typeof cookies[Symbol.iterator] === "function") {
|
||||||
|
for (let cookie of cookies) {
|
||||||
|
resCookies.push(Object.assign({}, cookie, {
|
||||||
|
value: await this.getLongString(cookie.value),
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
if (resCookies.length) {
|
||||||
|
payload.responseCookies = resCookies;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return payload;
|
||||||
|
}
|
||||||
|
|
||||||
|
async fetchRequestCookies(requestCookies) {
|
||||||
|
let payload = {};
|
||||||
|
if (requestCookies) {
|
||||||
|
let reqCookies = [];
|
||||||
|
// request store cookies in requestCookies or requestCookies.cookies
|
||||||
|
let cookies = requestCookies.cookies ?
|
||||||
|
requestCookies.cookies : requestCookies;
|
||||||
|
// make sure cookies is iterable
|
||||||
|
if (typeof cookies[Symbol.iterator] === "function") {
|
||||||
|
for (let cookie of cookies) {
|
||||||
|
reqCookies.push(Object.assign({}, cookie, {
|
||||||
|
value: await this.getLongString(cookie.value),
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
if (reqCookies.length) {
|
||||||
|
payload.requestCookies = reqCookies;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return payload;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Access a payload item from payload queue.
|
||||||
|
*
|
||||||
|
* @param {string} id request id
|
||||||
|
* @return {boolean} return a queued payload item from queue.
|
||||||
|
*/
|
||||||
|
getPayloadFromQueue(id) {
|
||||||
|
return this.payloadQueue.find((item) => item.id === id);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return true if payload is ready (all data fetched from the backend)
|
||||||
|
*
|
||||||
|
* @param {string} id request id
|
||||||
|
* @return {boolean} return whether a specific networkEvent has been updated completely.
|
||||||
|
*/
|
||||||
|
isQueuePayloadReady(id) {
|
||||||
|
let queuedPayload = this.getPayloadFromQueue(id);
|
||||||
|
|
||||||
|
// TODO we should find a better solution since it might happen
|
||||||
|
// that eventTimings is not the last update.
|
||||||
|
return queuedPayload && queuedPayload.payload.eventTimings;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Push a request payload into a queue if request doesn't exist. Otherwise update the
|
||||||
|
* request itself.
|
||||||
|
*
|
||||||
|
* @param {string} id request id
|
||||||
|
* @param {object} payload request data payload
|
||||||
|
*/
|
||||||
|
pushPayloadToQueue(id, payload) {
|
||||||
|
let queuedPayload = this.getPayloadFromQueue(id);
|
||||||
|
if (!queuedPayload) {
|
||||||
|
this.payloadQueue.push({ id, payload });
|
||||||
|
} else {
|
||||||
|
// Merge upcoming networkEventUpdate payload into existing one
|
||||||
|
queuedPayload.payload = Object.assign({}, queuedPayload.payload, payload);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fetches the network information packet from actor server
|
||||||
|
*
|
||||||
|
* @param {string} id request id
|
||||||
|
* @return {object} networkInfo data packet
|
||||||
|
*/
|
||||||
|
getNetworkRequest(id) {
|
||||||
|
return this.webConsoleClient.getNetworkRequest(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fetches the full text of a LongString.
|
||||||
|
*
|
||||||
|
* @param {object|string} stringGrip
|
||||||
|
* The long string grip containing the corresponding actor.
|
||||||
|
* If you pass in a plain string (by accident or because you're lazy),
|
||||||
|
* then a promise of the same string is simply returned.
|
||||||
|
* @return {object}
|
||||||
|
* A promise that is resolved when the full string contents
|
||||||
|
* are available, or rejected if something goes wrong.
|
||||||
|
*/
|
||||||
|
getLongString(stringGrip) {
|
||||||
|
return this.webConsoleClient.getString(stringGrip);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The "networkEvent" message type handler.
|
||||||
|
*
|
||||||
|
* @param {string} type message type
|
||||||
|
* @param {object} networkInfo network request information
|
||||||
|
*/
|
||||||
|
onNetworkEvent(type, networkInfo) {
|
||||||
|
let {
|
||||||
|
actor,
|
||||||
|
cause,
|
||||||
|
fromCache,
|
||||||
|
fromServiceWorker,
|
||||||
|
isXHR,
|
||||||
|
request: {
|
||||||
|
method,
|
||||||
|
url,
|
||||||
|
},
|
||||||
|
startedDateTime,
|
||||||
|
} = networkInfo;
|
||||||
|
|
||||||
|
this.addRequest(actor, {
|
||||||
|
cause,
|
||||||
|
fromCache,
|
||||||
|
fromServiceWorker,
|
||||||
|
isXHR,
|
||||||
|
method,
|
||||||
|
startedDateTime,
|
||||||
|
url,
|
||||||
|
});
|
||||||
|
|
||||||
|
emit(EVENTS.NETWORK_EVENT, actor);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The "networkEventUpdate" message type handler.
|
||||||
|
*
|
||||||
|
* @param {string} type message type
|
||||||
|
* @param {object} packet the message received from the server.
|
||||||
|
* @param {object} networkInfo the network request information.
|
||||||
|
*/
|
||||||
|
onNetworkEventUpdate(type, { packet, networkInfo }) {
|
||||||
|
let { actor } = networkInfo;
|
||||||
|
|
||||||
|
switch (packet.updateType) {
|
||||||
|
case "requestHeaders":
|
||||||
|
this.webConsoleClient.getRequestHeaders(actor, this.onRequestHeaders);
|
||||||
|
emit(EVENTS.UPDATING_REQUEST_HEADERS, actor);
|
||||||
|
break;
|
||||||
|
case "requestCookies":
|
||||||
|
this.webConsoleClient.getRequestCookies(actor, this.onRequestCookies);
|
||||||
|
emit(EVENTS.UPDATING_REQUEST_COOKIES, actor);
|
||||||
|
break;
|
||||||
|
case "requestPostData":
|
||||||
|
this.webConsoleClient.getRequestPostData(actor, this.onRequestPostData);
|
||||||
|
emit(EVENTS.UPDATING_REQUEST_POST_DATA, actor);
|
||||||
|
break;
|
||||||
|
case "securityInfo":
|
||||||
|
this.updateRequest(actor, {
|
||||||
|
securityState: networkInfo.securityInfo,
|
||||||
|
}).then(() => {
|
||||||
|
this.webConsoleClient.getSecurityInfo(actor, this.onSecurityInfo);
|
||||||
|
emit(EVENTS.UPDATING_SECURITY_INFO, actor);
|
||||||
|
});
|
||||||
|
break;
|
||||||
|
case "responseHeaders":
|
||||||
|
this.webConsoleClient.getResponseHeaders(actor, this.onResponseHeaders);
|
||||||
|
emit(EVENTS.UPDATING_RESPONSE_HEADERS, actor);
|
||||||
|
break;
|
||||||
|
case "responseCookies":
|
||||||
|
this.webConsoleClient.getResponseCookies(actor, this.onResponseCookies);
|
||||||
|
emit(EVENTS.UPDATING_RESPONSE_COOKIES, actor);
|
||||||
|
break;
|
||||||
|
case "responseStart":
|
||||||
|
this.updateRequest(actor, {
|
||||||
|
httpVersion: networkInfo.response.httpVersion,
|
||||||
|
remoteAddress: networkInfo.response.remoteAddress,
|
||||||
|
remotePort: networkInfo.response.remotePort,
|
||||||
|
status: networkInfo.response.status,
|
||||||
|
statusText: networkInfo.response.statusText,
|
||||||
|
headersSize: networkInfo.response.headersSize
|
||||||
|
}).then(() => {
|
||||||
|
emit(EVENTS.STARTED_RECEIVING_RESPONSE, actor);
|
||||||
|
});
|
||||||
|
break;
|
||||||
|
case "responseContent":
|
||||||
|
this.webConsoleClient.getResponseContent(actor,
|
||||||
|
this.onResponseContent.bind(this, {
|
||||||
|
contentSize: networkInfo.response.bodySize,
|
||||||
|
transferredSize: networkInfo.response.transferredSize,
|
||||||
|
mimeType: networkInfo.response.content.mimeType
|
||||||
|
}));
|
||||||
|
emit(EVENTS.UPDATING_RESPONSE_CONTENT, actor);
|
||||||
|
break;
|
||||||
|
case "eventTimings":
|
||||||
|
this.updateRequest(actor, { totalTime: networkInfo.totalTime })
|
||||||
|
.then(() => {
|
||||||
|
this.webConsoleClient.getEventTimings(actor, this.onEventTimings);
|
||||||
|
emit(EVENTS.UPDATING_EVENT_TIMINGS, actor);
|
||||||
|
});
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handles additional information received for a "requestHeaders" packet.
|
||||||
|
*
|
||||||
|
* @param {object} response the message received from the server.
|
||||||
|
*/
|
||||||
|
onRequestHeaders(response) {
|
||||||
|
this.updateRequest(response.from, {
|
||||||
|
requestHeaders: response
|
||||||
|
}).then(() => {
|
||||||
|
emit(EVENTS.RECEIVED_REQUEST_HEADERS, response.from);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handles additional information received for a "requestCookies" packet.
|
||||||
|
*
|
||||||
|
* @param {object} response the message received from the server.
|
||||||
|
*/
|
||||||
|
onRequestCookies(response) {
|
||||||
|
this.updateRequest(response.from, {
|
||||||
|
requestCookies: response
|
||||||
|
}).then(() => {
|
||||||
|
emit(EVENTS.RECEIVED_REQUEST_COOKIES, response.from);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handles additional information received for a "requestPostData" packet.
|
||||||
|
*
|
||||||
|
* @param {object} response the message received from the server.
|
||||||
|
*/
|
||||||
|
onRequestPostData(response) {
|
||||||
|
this.updateRequest(response.from, {
|
||||||
|
requestPostData: response
|
||||||
|
}).then(() => {
|
||||||
|
emit(EVENTS.RECEIVED_REQUEST_POST_DATA, response.from);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handles additional information received for a "securityInfo" packet.
|
||||||
|
*
|
||||||
|
* @param {object} response the message received from the server.
|
||||||
|
*/
|
||||||
|
onSecurityInfo(response) {
|
||||||
|
this.updateRequest(response.from, {
|
||||||
|
securityInfo: response.securityInfo
|
||||||
|
}).then(() => {
|
||||||
|
emit(EVENTS.RECEIVED_SECURITY_INFO, response.from);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handles additional information received for a "responseHeaders" packet.
|
||||||
|
*
|
||||||
|
* @param {object} response the message received from the server.
|
||||||
|
*/
|
||||||
|
onResponseHeaders(response) {
|
||||||
|
this.updateRequest(response.from, {
|
||||||
|
responseHeaders: response
|
||||||
|
}).then(() => {
|
||||||
|
emit(EVENTS.RECEIVED_RESPONSE_HEADERS, response.from);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handles additional information received for a "responseCookies" packet.
|
||||||
|
*
|
||||||
|
* @param {object} response the message received from the server.
|
||||||
|
*/
|
||||||
|
onResponseCookies(response) {
|
||||||
|
this.updateRequest(response.from, {
|
||||||
|
responseCookies: response
|
||||||
|
}).then(() => {
|
||||||
|
emit(EVENTS.RECEIVED_RESPONSE_COOKIES, response.from);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handles additional information received for a "responseContent" packet.
|
||||||
|
*
|
||||||
|
* @param {object} data the message received from the server event.
|
||||||
|
* @param {object} response the message received from the server.
|
||||||
|
*/
|
||||||
|
onResponseContent(data, response) {
|
||||||
|
let payload = Object.assign({ responseContent: response }, data);
|
||||||
|
this.updateRequest(response.from, payload).then(() => {
|
||||||
|
emit(EVENTS.RECEIVED_RESPONSE_CONTENT, response.from);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handles additional information received for a "eventTimings" packet.
|
||||||
|
*
|
||||||
|
* @param {object} response the message received from the server.
|
||||||
|
*/
|
||||||
|
onEventTimings(response) {
|
||||||
|
this.updateRequest(response.from, {
|
||||||
|
eventTimings: response
|
||||||
|
}).then(() => {
|
||||||
|
emit(EVENTS.RECEIVED_EVENT_TIMINGS, response.from);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Guard 'emit' to avoid exception in non-window environment.
|
||||||
|
*/
|
||||||
|
function emit(type, data) {
|
||||||
|
if (typeof window != "undefined") {
|
||||||
|
window.emit(type, data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = FirefoxDataProvider;
|
|
@ -4,5 +4,6 @@
|
||||||
|
|
||||||
DevToolsModules(
|
DevToolsModules(
|
||||||
'firefox-connector.js',
|
'firefox-connector.js',
|
||||||
|
'firefox-data-provider.js',
|
||||||
'index.js',
|
'index.js',
|
||||||
)
|
)
|
||||||
|
|
|
@ -94,6 +94,44 @@ const EVENTS = {
|
||||||
CONNECTED: "connected",
|
CONNECTED: "connected",
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const UPDATE_PROPS = [
|
||||||
|
"method",
|
||||||
|
"url",
|
||||||
|
"remotePort",
|
||||||
|
"remoteAddress",
|
||||||
|
"status",
|
||||||
|
"statusText",
|
||||||
|
"httpVersion",
|
||||||
|
"securityState",
|
||||||
|
"securityInfo",
|
||||||
|
"mimeType",
|
||||||
|
"contentSize",
|
||||||
|
"transferredSize",
|
||||||
|
"totalTime",
|
||||||
|
"eventTimings",
|
||||||
|
"headersSize",
|
||||||
|
"customQueryValue",
|
||||||
|
"requestHeaders",
|
||||||
|
"requestHeadersFromUploadStream",
|
||||||
|
"requestCookies",
|
||||||
|
"requestPostData",
|
||||||
|
"responseHeaders",
|
||||||
|
"responseCookies",
|
||||||
|
"responseContent",
|
||||||
|
"responseContentDataUri",
|
||||||
|
"formDataSections",
|
||||||
|
];
|
||||||
|
|
||||||
|
const PANELS = {
|
||||||
|
COOKIES: "cookies",
|
||||||
|
HEADERS: "headers",
|
||||||
|
PARAMS: "params",
|
||||||
|
RESPONSE: "response",
|
||||||
|
SECURITY: "security",
|
||||||
|
STACK_TRACE: "stack-trace",
|
||||||
|
TIMINGS: "timings",
|
||||||
|
};
|
||||||
|
|
||||||
const RESPONSE_HEADERS = [
|
const RESPONSE_HEADERS = [
|
||||||
"Cache-Control",
|
"Cache-Control",
|
||||||
"Connection",
|
"Connection",
|
||||||
|
@ -246,11 +284,13 @@ const general = {
|
||||||
ACTIVITY_TYPE,
|
ACTIVITY_TYPE,
|
||||||
EVENTS,
|
EVENTS,
|
||||||
FILTER_SEARCH_DELAY: 200,
|
FILTER_SEARCH_DELAY: 200,
|
||||||
|
UPDATE_PROPS,
|
||||||
HEADERS,
|
HEADERS,
|
||||||
RESPONSE_HEADERS,
|
RESPONSE_HEADERS,
|
||||||
FILTER_FLAGS,
|
FILTER_FLAGS,
|
||||||
SOURCE_EDITOR_SYNTAX_HIGHLIGHT_MAX_SIZE: 51200, // 50 KB in bytes
|
SOURCE_EDITOR_SYNTAX_HIGHLIGHT_MAX_SIZE: 51200, // 50 KB in bytes
|
||||||
REQUESTS_WATERFALL,
|
REQUESTS_WATERFALL,
|
||||||
|
PANELS,
|
||||||
};
|
};
|
||||||
|
|
||||||
// flatten constants
|
// flatten constants
|
||||||
|
|
|
@ -15,6 +15,7 @@ const {
|
||||||
SELECT_REQUEST,
|
SELECT_REQUEST,
|
||||||
SEND_CUSTOM_REQUEST,
|
SEND_CUSTOM_REQUEST,
|
||||||
UPDATE_REQUEST,
|
UPDATE_REQUEST,
|
||||||
|
UPDATE_PROPS,
|
||||||
} = require("../constants");
|
} = require("../constants");
|
||||||
|
|
||||||
const Request = I.Record({
|
const Request = I.Record({
|
||||||
|
@ -68,34 +69,6 @@ const Requests = I.Record({
|
||||||
lastEndedMillis: -Infinity,
|
lastEndedMillis: -Infinity,
|
||||||
});
|
});
|
||||||
|
|
||||||
const UPDATE_PROPS = [
|
|
||||||
"method",
|
|
||||||
"url",
|
|
||||||
"remotePort",
|
|
||||||
"remoteAddress",
|
|
||||||
"status",
|
|
||||||
"statusText",
|
|
||||||
"httpVersion",
|
|
||||||
"securityState",
|
|
||||||
"securityInfo",
|
|
||||||
"mimeType",
|
|
||||||
"contentSize",
|
|
||||||
"transferredSize",
|
|
||||||
"totalTime",
|
|
||||||
"eventTimings",
|
|
||||||
"headersSize",
|
|
||||||
"customQueryValue",
|
|
||||||
"requestHeaders",
|
|
||||||
"requestHeadersFromUploadStream",
|
|
||||||
"requestCookies",
|
|
||||||
"requestPostData",
|
|
||||||
"responseHeaders",
|
|
||||||
"responseCookies",
|
|
||||||
"responseContent",
|
|
||||||
"responseContentDataUri",
|
|
||||||
"formDataSections",
|
|
||||||
];
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Remove the currently selected custom request.
|
* Remove the currently selected custom request.
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -19,6 +19,7 @@ const {
|
||||||
SELECT_REQUEST,
|
SELECT_REQUEST,
|
||||||
TOGGLE_COLUMN,
|
TOGGLE_COLUMN,
|
||||||
WATERFALL_RESIZE,
|
WATERFALL_RESIZE,
|
||||||
|
PANELS,
|
||||||
} = require("../constants");
|
} = require("../constants");
|
||||||
|
|
||||||
const cols = {
|
const cols = {
|
||||||
|
@ -51,7 +52,7 @@ const Columns = I.Record(
|
||||||
|
|
||||||
const UI = I.Record({
|
const UI = I.Record({
|
||||||
columns: new Columns(),
|
columns: new Columns(),
|
||||||
detailsPanelSelectedTab: "headers",
|
detailsPanelSelectedTab: PANELS.HEADERS,
|
||||||
networkDetailsOpen: false,
|
networkDetailsOpen: false,
|
||||||
browserCacheDisabled: Services.prefs.getBoolPref("devtools.cache.disabled"),
|
browserCacheDisabled: Services.prefs.getBoolPref("devtools.cache.disabled"),
|
||||||
statisticsOpen: false,
|
statisticsOpen: false,
|
||||||
|
|
|
@ -13,9 +13,6 @@ pref("devtools.devedition.promo.url", "https://www.mozilla.org/firefox/developer
|
||||||
pref("devtools.devedition.promo.enabled", false);
|
pref("devtools.devedition.promo.enabled", false);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// DevTools development workflow
|
|
||||||
pref("devtools.loader.hotreload", false);
|
|
||||||
|
|
||||||
// Developer toolbar preferences
|
// Developer toolbar preferences
|
||||||
pref("devtools.toolbar.enabled", true);
|
pref("devtools.toolbar.enabled", true);
|
||||||
|
|
||||||
|
|
|
@ -3,8 +3,7 @@ tags = devtools
|
||||||
subsuite = devtools
|
subsuite = devtools
|
||||||
# !e10s: RDM only works for remote tabs
|
# !e10s: RDM only works for remote tabs
|
||||||
# Win: Bug 1319248
|
# Win: Bug 1319248
|
||||||
# Stylo: Bug 1384701
|
skip-if = !e10s || os == "win"
|
||||||
skip-if = !e10s || os == "win" || (stylo && os == "linux" && debug)
|
|
||||||
support-files =
|
support-files =
|
||||||
devices.json
|
devices.json
|
||||||
doc_page_state.html
|
doc_page_state.html
|
||||||
|
|
|
@ -8,7 +8,6 @@ const loaders = Cu.import("resource://gre/modules/commonjs/toolkit/loader.js", {
|
||||||
const { devtools } = Cu.import("resource://devtools/shared/Loader.jsm", {});
|
const { devtools } = Cu.import("resource://devtools/shared/Loader.jsm", {});
|
||||||
const { joinURI } = devtools.require("devtools/shared/path");
|
const { joinURI } = devtools.require("devtools/shared/path");
|
||||||
const { assert } = devtools.require("devtools/shared/DevToolsUtils");
|
const { assert } = devtools.require("devtools/shared/DevToolsUtils");
|
||||||
const Services = devtools.require("Services");
|
|
||||||
const { AppConstants } = devtools.require("resource://gre/modules/AppConstants.jsm");
|
const { AppConstants } = devtools.require("resource://gre/modules/AppConstants.jsm");
|
||||||
|
|
||||||
const BROWSER_BASED_DIRS = [
|
const BROWSER_BASED_DIRS = [
|
||||||
|
@ -37,10 +36,6 @@ const COMMON_LIBRARY_DIRS = [
|
||||||
const browserBasedDirsRegExp =
|
const browserBasedDirsRegExp =
|
||||||
/^resource\:\/\/devtools\/client\/\S*\/components\//;
|
/^resource\:\/\/devtools\/client\/\S*\/components\//;
|
||||||
|
|
||||||
function clearCache() {
|
|
||||||
Services.obs.notifyObservers(null, "startupcache-invalidate");
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Create a loader to be used in a browser environment. This evaluates
|
* Create a loader to be used in a browser environment. This evaluates
|
||||||
* modules in their own environment, but sets window (the normal
|
* modules in their own environment, but sets window (the normal
|
||||||
|
@ -101,7 +96,6 @@ function BrowserLoaderBuilder({ baseURI, window, useOnlyShared, commonLibRequire
|
||||||
|
|
||||||
const loaderOptions = devtools.require("@loader/options");
|
const loaderOptions = devtools.require("@loader/options");
|
||||||
const dynamicPaths = {};
|
const dynamicPaths = {};
|
||||||
const componentProxies = new Map();
|
|
||||||
|
|
||||||
if (AppConstants.DEBUG || AppConstants.DEBUG_JS_MODULES) {
|
if (AppConstants.DEBUG || AppConstants.DEBUG_JS_MODULES) {
|
||||||
dynamicPaths["devtools/client/shared/vendor/react"] =
|
dynamicPaths["devtools/client/shared/vendor/react"] =
|
||||||
|
@ -169,39 +163,6 @@ function BrowserLoaderBuilder({ baseURI, window, useOnlyShared, commonLibRequire
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
if (Services.prefs.getBoolPref("devtools.loader.hotreload")) {
|
|
||||||
opts.loadModuleHook = (module, require) => {
|
|
||||||
const { uri, exports } = module;
|
|
||||||
|
|
||||||
if (exports.prototype &&
|
|
||||||
exports.prototype.isReactComponent) {
|
|
||||||
const { createProxy, getForceUpdate } =
|
|
||||||
require("devtools/client/shared/vendor/react-proxy");
|
|
||||||
const React = require("devtools/client/shared/vendor/react");
|
|
||||||
|
|
||||||
if (!componentProxies.get(uri)) {
|
|
||||||
const proxy = createProxy(exports);
|
|
||||||
componentProxies.set(uri, proxy);
|
|
||||||
module.exports = proxy.get();
|
|
||||||
} else {
|
|
||||||
const proxy = componentProxies.get(uri);
|
|
||||||
const instances = proxy.update(exports);
|
|
||||||
instances.forEach(getForceUpdate(React));
|
|
||||||
module.exports = proxy.get();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return exports;
|
|
||||||
};
|
|
||||||
const watcher = devtools.require("devtools/client/shared/devtools-file-watcher");
|
|
||||||
let onFileChanged = (_, relativePath, path) => {
|
|
||||||
this.hotReloadFile(componentProxies, "resource://devtools/" + relativePath);
|
|
||||||
};
|
|
||||||
watcher.on("file-changed", onFileChanged);
|
|
||||||
window.addEventListener("unload", () => {
|
|
||||||
watcher.off("file-changed", onFileChanged);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
const mainModule = loaders.Module(baseURI, joinURI(baseURI, "main.js"));
|
const mainModule = loaders.Module(baseURI, joinURI(baseURI, "main.js"));
|
||||||
this.loader = loaders.Loader(opts);
|
this.loader = loaders.Loader(opts);
|
||||||
this.require = loaders.Require(this.loader, mainModule);
|
this.require = loaders.Require(this.loader, mainModule);
|
||||||
|
@ -228,20 +189,6 @@ BrowserLoaderBuilder.prototype = {
|
||||||
? this.require(module)[property]
|
? this.require(module)[property]
|
||||||
: this.require(module || property);
|
: this.require(module || property);
|
||||||
});
|
});
|
||||||
},
|
|
||||||
|
|
||||||
hotReloadFile: function (componentProxies, fileURI) {
|
|
||||||
if (fileURI.match(/\.js$/)) {
|
|
||||||
// Test for React proxy components
|
|
||||||
const proxy = componentProxies.get(fileURI);
|
|
||||||
if (proxy) {
|
|
||||||
// Remove the old module and re-require the new one; the require
|
|
||||||
// hook in the loader will take care of the rest
|
|
||||||
delete this.loader.modules[fileURI];
|
|
||||||
clearCache();
|
|
||||||
this.require(fileURI);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -1,142 +0,0 @@
|
||||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
|
||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
||||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
|
||||||
"use strict";
|
|
||||||
|
|
||||||
const { Services } = require("resource://gre/modules/Services.jsm");
|
|
||||||
const { getTheme } = require("devtools/client/shared/theme");
|
|
||||||
|
|
||||||
function iterStyleNodes(window, func) {
|
|
||||||
for (let node of window.document.childNodes) {
|
|
||||||
// Look for ProcessingInstruction nodes.
|
|
||||||
if (node.nodeType === 7) {
|
|
||||||
func(node);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const links = window.document.getElementsByTagNameNS(
|
|
||||||
"http://www.w3.org/1999/xhtml", "link"
|
|
||||||
);
|
|
||||||
for (let node of links) {
|
|
||||||
func(node);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function replaceCSS(window, fileURI) {
|
|
||||||
const document = window.document;
|
|
||||||
const randomKey = Math.random();
|
|
||||||
Services.obs.notifyObservers(null, "startupcache-invalidate");
|
|
||||||
|
|
||||||
// Scan every CSS tag and reload ones that match the file we are
|
|
||||||
// looking for.
|
|
||||||
iterStyleNodes(window, node => {
|
|
||||||
if (node.nodeType === 7) {
|
|
||||||
// xml-stylesheet declaration
|
|
||||||
if (node.data.includes(fileURI)) {
|
|
||||||
const newNode = window.document.createProcessingInstruction(
|
|
||||||
"xml-stylesheet",
|
|
||||||
`href="${fileURI}?s=${randomKey}" type="text/css"`
|
|
||||||
);
|
|
||||||
document.insertBefore(newNode, node);
|
|
||||||
document.removeChild(node);
|
|
||||||
}
|
|
||||||
} else if (node.href.includes(fileURI)) {
|
|
||||||
const parentNode = node.parentNode;
|
|
||||||
const newNode = window.document.createElementNS(
|
|
||||||
"http://www.w3.org/1999/xhtml",
|
|
||||||
"link"
|
|
||||||
);
|
|
||||||
newNode.rel = "stylesheet";
|
|
||||||
newNode.type = "text/css";
|
|
||||||
newNode.href = fileURI + "?s=" + randomKey;
|
|
||||||
|
|
||||||
parentNode.insertBefore(newNode, node);
|
|
||||||
parentNode.removeChild(node);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function _replaceResourceInSheet(sheet, filename, randomKey) {
|
|
||||||
for (let i = 0; i < sheet.cssRules.length; i++) {
|
|
||||||
const rule = sheet.cssRules[i];
|
|
||||||
if (rule.type === rule.IMPORT_RULE) {
|
|
||||||
_replaceResourceInSheet(rule.styleSheet, filename);
|
|
||||||
} else if (rule.cssText.includes(filename)) {
|
|
||||||
// Strip off any existing query strings. This might lose
|
|
||||||
// updates for files if there are multiple resources
|
|
||||||
// referenced in the same rule, but the chances of someone hot
|
|
||||||
// reloading multiple resources in the same rule is very low.
|
|
||||||
const text = rule.cssText.replace(/\?s=0.\d+/g, "");
|
|
||||||
const newRule = (
|
|
||||||
text.replace(filename, filename + "?s=" + randomKey)
|
|
||||||
);
|
|
||||||
|
|
||||||
sheet.deleteRule(i);
|
|
||||||
sheet.insertRule(newRule, i);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function replaceCSSResource(window, fileURI) {
|
|
||||||
const document = window.document;
|
|
||||||
const randomKey = Math.random();
|
|
||||||
|
|
||||||
// Only match the filename. False positives are much better than
|
|
||||||
// missing updates, as all that would happen is we reload more
|
|
||||||
// resources than we need. We do this because many resources only
|
|
||||||
// use relative paths.
|
|
||||||
const parts = fileURI.split("/");
|
|
||||||
const file = parts[parts.length - 1];
|
|
||||||
|
|
||||||
// Scan every single rule in the entire page for any reference to
|
|
||||||
// this resource, and re-insert the rule to force it to update.
|
|
||||||
for (let sheet of document.styleSheets) {
|
|
||||||
_replaceResourceInSheet(sheet, file, randomKey);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (let node of document.querySelectorAll("img,image")) {
|
|
||||||
if (node.src.startsWith(fileURI)) {
|
|
||||||
node.src = fileURI + "?s=" + randomKey;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function watchCSS(window) {
|
|
||||||
if (Services.prefs.getBoolPref("devtools.loader.hotreload")) {
|
|
||||||
const watcher = require("devtools/client/shared/devtools-file-watcher");
|
|
||||||
|
|
||||||
function onFileChanged(_, relativePath) {
|
|
||||||
if (relativePath.match(/\.css$/)) {
|
|
||||||
if (relativePath.startsWith("client/themes")) {
|
|
||||||
let path = relativePath.replace(/^client\/themes\//, "");
|
|
||||||
|
|
||||||
// Special-case a few files that get imported from other CSS
|
|
||||||
// files. We just manually hot reload the parent CSS file.
|
|
||||||
if (path === "variables.css" || path === "toolbars.css" ||
|
|
||||||
path === "common.css" || path === "splitters.css") {
|
|
||||||
replaceCSS(window, "chrome://devtools/skin/" + getTheme() + "-theme.css");
|
|
||||||
} else {
|
|
||||||
replaceCSS(window, "chrome://devtools/skin/" + path);
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
replaceCSS(
|
|
||||||
window,
|
|
||||||
"chrome://devtools/content/" + relativePath.replace(/^client\//, "")
|
|
||||||
);
|
|
||||||
replaceCSS(window, "resource://devtools/" + relativePath);
|
|
||||||
} else if (relativePath.match(/\.(svg|png)$/)) {
|
|
||||||
relativePath = relativePath.replace(/^client\/themes\//, "");
|
|
||||||
replaceCSSResource(window, "chrome://devtools/skin/" + relativePath);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
watcher.on("file-changed", onFileChanged);
|
|
||||||
|
|
||||||
window.addEventListener("unload", () => {
|
|
||||||
watcher.off("file-changed", onFileChanged);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
module.exports = { watchCSS };
|
|
|
@ -1,78 +0,0 @@
|
||||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
|
||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
||||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
|
||||||
"use strict";
|
|
||||||
|
|
||||||
const { Ci } = require("chrome");
|
|
||||||
const Services = require("Services");
|
|
||||||
const EventEmitter = require("devtools/shared/old-event-emitter");
|
|
||||||
|
|
||||||
loader.lazyImporter(this, "OS", "resource://gre/modules/osfile.jsm");
|
|
||||||
|
|
||||||
const HOTRELOAD_PREF = "devtools.loader.hotreload";
|
|
||||||
|
|
||||||
function resolveResourcePath(uri) {
|
|
||||||
const handler = Services.io.getProtocolHandler("resource")
|
|
||||||
.QueryInterface(Ci.nsIResProtocolHandler);
|
|
||||||
const resolved = handler.resolveURI(Services.io.newURI(uri));
|
|
||||||
return resolved.replace(/file:\/\//, "");
|
|
||||||
}
|
|
||||||
|
|
||||||
function findSourceDir(path) {
|
|
||||||
if (path === "" || path === "/") {
|
|
||||||
return Promise.resolve(null);
|
|
||||||
}
|
|
||||||
|
|
||||||
return OS.File.exists(
|
|
||||||
OS.Path.join(path, "devtools/client/shared/file-watcher.js")
|
|
||||||
).then(exists => {
|
|
||||||
if (exists) {
|
|
||||||
return path;
|
|
||||||
}
|
|
||||||
return findSourceDir(OS.Path.dirname(path));
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
let worker = null;
|
|
||||||
const onPrefChange = function () {
|
|
||||||
// We need to figure out a src dir to watch. These are the actual
|
|
||||||
// files the user is working with, not the files in the obj dir. We
|
|
||||||
// do this by walking up the filesystem and looking for the devtools
|
|
||||||
// directories, and falling back to the raw path. This means none of
|
|
||||||
// this will work for users who store their obj dirs outside of the
|
|
||||||
// src dir.
|
|
||||||
//
|
|
||||||
// We take care not to mess with the `devtoolsPath` if that's what
|
|
||||||
// we end up using, because it might be intentionally mapped to a
|
|
||||||
// specific place on the filesystem for loading devtools externally.
|
|
||||||
//
|
|
||||||
// `devtoolsPath` is currently the devtools directory inside of the
|
|
||||||
// obj dir, and we search for `devtools/client`, so go up 2 levels
|
|
||||||
// to skip that devtools dir and start searching for the src dir.
|
|
||||||
if (Services.prefs.getBoolPref(HOTRELOAD_PREF) && !worker) {
|
|
||||||
const devtoolsPath = resolveResourcePath("resource://devtools")
|
|
||||||
.replace(/\/$/, "");
|
|
||||||
const searchPoint = OS.Path.dirname(OS.Path.dirname(devtoolsPath));
|
|
||||||
findSourceDir(searchPoint)
|
|
||||||
.then(srcPath => {
|
|
||||||
const rootPath = srcPath ? OS.Path.join(srcPath, "devtools")
|
|
||||||
: devtoolsPath;
|
|
||||||
const watchPath = OS.Path.join(rootPath, "client");
|
|
||||||
const { watchFiles } = require("devtools/client/shared/file-watcher");
|
|
||||||
worker = watchFiles(watchPath, path => {
|
|
||||||
let relativePath = path.replace(rootPath + "/", "");
|
|
||||||
module.exports.emit("file-changed", relativePath, path);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
} else if (worker) {
|
|
||||||
worker.terminate();
|
|
||||||
worker = null;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
Services.prefs.addObserver(HOTRELOAD_PREF, {
|
|
||||||
observe: onPrefChange
|
|
||||||
});
|
|
||||||
onPrefChange();
|
|
||||||
|
|
||||||
EventEmitter.decorate(module.exports);
|
|
|
@ -1,81 +0,0 @@
|
||||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
|
||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
||||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
|
||||||
"use strict";
|
|
||||||
|
|
||||||
/* eslint-env worker */
|
|
||||||
/* global OS */
|
|
||||||
importScripts("resource://gre/modules/osfile.jsm");
|
|
||||||
|
|
||||||
const modifiedTimes = new Map();
|
|
||||||
|
|
||||||
function gatherFiles(path, fileRegex) {
|
|
||||||
let files = [];
|
|
||||||
const iterator = new OS.File.DirectoryIterator(path);
|
|
||||||
|
|
||||||
try {
|
|
||||||
for (let child of iterator) {
|
|
||||||
// Don't descend into test directories. Saves us some time and
|
|
||||||
// there's no reason to.
|
|
||||||
if (child.isDir && !child.path.endsWith("/test")) {
|
|
||||||
files = files.concat(gatherFiles(child.path, fileRegex));
|
|
||||||
} else if (child.path.match(fileRegex)) {
|
|
||||||
let info;
|
|
||||||
try {
|
|
||||||
info = OS.File.stat(child.path);
|
|
||||||
} catch (e) {
|
|
||||||
// Just ignore it.
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
files.push(child.path);
|
|
||||||
modifiedTimes.set(child.path, info.lastModificationDate.getTime());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} finally {
|
|
||||||
iterator.close();
|
|
||||||
}
|
|
||||||
|
|
||||||
return files;
|
|
||||||
}
|
|
||||||
|
|
||||||
function scanFiles(files, onChangedFile) {
|
|
||||||
files.forEach(file => {
|
|
||||||
let info;
|
|
||||||
try {
|
|
||||||
info = OS.File.stat(file);
|
|
||||||
} catch (e) {
|
|
||||||
// Just ignore it. It was probably deleted.
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const lastTime = modifiedTimes.get(file);
|
|
||||||
|
|
||||||
if (info.lastModificationDate.getTime() > lastTime) {
|
|
||||||
modifiedTimes.set(file, info.lastModificationDate.getTime());
|
|
||||||
onChangedFile(file);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
onmessage = function (event) {
|
|
||||||
const { path, fileRegex } = event.data;
|
|
||||||
|
|
||||||
const info = OS.File.stat(path);
|
|
||||||
if (!info.isDir) {
|
|
||||||
throw new Error("Watcher expects a directory as root path");
|
|
||||||
}
|
|
||||||
|
|
||||||
// We get a list of all the files upfront, which means we don't
|
|
||||||
// support adding new files. But you need to rebuild Firefox when
|
|
||||||
// adding a new file anyway.
|
|
||||||
const files = gatherFiles(path, fileRegex || /.*/);
|
|
||||||
|
|
||||||
// Every second, scan for file changes by stat-ing each of them and
|
|
||||||
// comparing modification time.
|
|
||||||
setInterval(() => {
|
|
||||||
scanFiles(files, changedFile => {
|
|
||||||
postMessage({ path: changedFile });
|
|
||||||
});
|
|
||||||
}, 1000);
|
|
||||||
};
|
|
|
@ -1,28 +0,0 @@
|
||||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
|
||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
||||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
|
||||||
"use strict";
|
|
||||||
|
|
||||||
const { ChromeWorker } = require("chrome");
|
|
||||||
|
|
||||||
function watchFiles(path, onFileChanged) {
|
|
||||||
const watchWorker = new ChromeWorker(
|
|
||||||
"resource://devtools/client/shared/file-watcher-worker.js"
|
|
||||||
);
|
|
||||||
|
|
||||||
watchWorker.onmessage = event => {
|
|
||||||
// We need to turn a local path back into a resource URI (or
|
|
||||||
// chrome). This means that this system will only work when built
|
|
||||||
// files are symlinked, so that these URIs actually read from
|
|
||||||
// local sources. There might be a better way to do this.
|
|
||||||
const { path: newPath } = event.data;
|
|
||||||
onFileChanged(newPath);
|
|
||||||
};
|
|
||||||
|
|
||||||
watchWorker.postMessage({
|
|
||||||
path,
|
|
||||||
fileRegex: /\.(js|css|svg|png)$/
|
|
||||||
});
|
|
||||||
return watchWorker;
|
|
||||||
}
|
|
||||||
exports.watchFiles = watchFiles;
|
|
|
@ -20,18 +20,14 @@ DevToolsModules(
|
||||||
'autocomplete-popup.js',
|
'autocomplete-popup.js',
|
||||||
'browser-loader.js',
|
'browser-loader.js',
|
||||||
'css-angle.js',
|
'css-angle.js',
|
||||||
'css-reload.js',
|
|
||||||
'curl.js',
|
'curl.js',
|
||||||
'demangle.js',
|
'demangle.js',
|
||||||
'developer-toolbar.js',
|
'developer-toolbar.js',
|
||||||
'devices.js',
|
'devices.js',
|
||||||
'devtools-file-watcher.js',
|
|
||||||
'DOMHelpers.jsm',
|
'DOMHelpers.jsm',
|
||||||
'doorhanger.js',
|
'doorhanger.js',
|
||||||
'enum.js',
|
'enum.js',
|
||||||
'file-saver.js',
|
'file-saver.js',
|
||||||
'file-watcher-worker.js',
|
|
||||||
'file-watcher.js',
|
|
||||||
'getjson.js',
|
'getjson.js',
|
||||||
'inplace-editor.js',
|
'inplace-editor.js',
|
||||||
'Jsbeautify.jsm',
|
'Jsbeautify.jsm',
|
||||||
|
|
|
@ -9,7 +9,6 @@
|
||||||
const { require } = Cu.import("resource://devtools/shared/Loader.jsm", {});
|
const { require } = Cu.import("resource://devtools/shared/Loader.jsm", {});
|
||||||
const Services = require("Services");
|
const Services = require("Services");
|
||||||
const { gDevTools } = require("devtools/client/framework/devtools");
|
const { gDevTools } = require("devtools/client/framework/devtools");
|
||||||
const { watchCSS } = require("devtools/client/shared/css-reload");
|
|
||||||
const { appendStyleSheet } = require("devtools/client/shared/stylesheet-utils");
|
const { appendStyleSheet } = require("devtools/client/shared/stylesheet-utils");
|
||||||
|
|
||||||
let documentElement = document.documentElement;
|
let documentElement = document.documentElement;
|
||||||
|
@ -154,6 +153,4 @@
|
||||||
Services.prefs.removeObserver("devtools.theme", handlePrefChange);
|
Services.prefs.removeObserver("devtools.theme", handlePrefChange);
|
||||||
}, { once: true });
|
}, { once: true });
|
||||||
}
|
}
|
||||||
|
|
||||||
watchCSS(window);
|
|
||||||
})();
|
})();
|
||||||
|
|
|
@ -25,7 +25,6 @@ if CONFIG['DEBUG_JS_MODULES'] or CONFIG['MOZ_DEBUG']:
|
||||||
modules += [
|
modules += [
|
||||||
'react-dom-server.js',
|
'react-dom-server.js',
|
||||||
'react-dom.js',
|
'react-dom.js',
|
||||||
'react-proxy.js',
|
|
||||||
'react-redux.js',
|
'react-redux.js',
|
||||||
'react-virtualized.js',
|
'react-virtualized.js',
|
||||||
'react.js',
|
'react.js',
|
||||||
|
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -49,6 +49,8 @@
|
||||||
<hbox id="storage-toolbar" class="devtools-toolbar">
|
<hbox id="storage-toolbar" class="devtools-toolbar">
|
||||||
<button id="add-button"
|
<button id="add-button"
|
||||||
class="devtools-button add-button"></button>
|
class="devtools-button add-button"></button>
|
||||||
|
<button id="refresh-button"
|
||||||
|
class="devtools-button refresh-button"></button>
|
||||||
<spacer flex="1"/>
|
<spacer flex="1"/>
|
||||||
<textbox id="storage-searchbox"
|
<textbox id="storage-searchbox"
|
||||||
class="devtools-filterinput"
|
class="devtools-filterinput"
|
||||||
|
|
|
@ -169,6 +169,7 @@ function StorageUI(front, target, panelWin, toolbox) {
|
||||||
this._tablePopup = this._panelDoc.getElementById("storage-table-popup");
|
this._tablePopup = this._panelDoc.getElementById("storage-table-popup");
|
||||||
this._tablePopup.addEventListener("popupshowing", this.onTablePopupShowing);
|
this._tablePopup.addEventListener("popupshowing", this.onTablePopupShowing);
|
||||||
|
|
||||||
|
this.onRefreshTable = this.onRefreshTable.bind(this);
|
||||||
this.onAddItem = this.onAddItem.bind(this);
|
this.onAddItem = this.onAddItem.bind(this);
|
||||||
this.onRemoveItem = this.onRemoveItem.bind(this);
|
this.onRemoveItem = this.onRemoveItem.bind(this);
|
||||||
this.onRemoveAllFrom = this.onRemoveAllFrom.bind(this);
|
this.onRemoveAllFrom = this.onRemoveAllFrom.bind(this);
|
||||||
|
@ -176,6 +177,9 @@ function StorageUI(front, target, panelWin, toolbox) {
|
||||||
this.onRemoveAllSessionCookies = this.onRemoveAllSessionCookies.bind(this);
|
this.onRemoveAllSessionCookies = this.onRemoveAllSessionCookies.bind(this);
|
||||||
this.onRemoveTreeItem = this.onRemoveTreeItem.bind(this);
|
this.onRemoveTreeItem = this.onRemoveTreeItem.bind(this);
|
||||||
|
|
||||||
|
this._refreshButton = this._panelDoc.getElementById("refresh-button");
|
||||||
|
this._refreshButton.addEventListener("command", this.onRefreshTable);
|
||||||
|
|
||||||
this._addButton = this._panelDoc.getElementById("add-button");
|
this._addButton = this._panelDoc.getElementById("add-button");
|
||||||
this._addButton.addEventListener("command", this.onAddItem);
|
this._addButton.addEventListener("command", this.onAddItem);
|
||||||
|
|
||||||
|
@ -242,6 +246,7 @@ StorageUI.prototype = {
|
||||||
this.sidebarToggleBtn = null;
|
this.sidebarToggleBtn = null;
|
||||||
|
|
||||||
this._treePopup.removeEventListener("popupshowing", this.onTreePopupShowing);
|
this._treePopup.removeEventListener("popupshowing", this.onTreePopupShowing);
|
||||||
|
this._refreshButton.removeEventListener("command", this.onRefreshTable);
|
||||||
this._addButton.removeEventListener("command", this.onAddItem);
|
this._addButton.removeEventListener("command", this.onAddItem);
|
||||||
this._tablePopupAddItem.removeEventListener("command", this.onAddItem);
|
this._tablePopupAddItem.removeEventListener("command", this.onAddItem);
|
||||||
this._treePopupDeleteAll.removeEventListener("command", this.onRemoveAll);
|
this._treePopupDeleteAll.removeEventListener("command", this.onRemoveAll);
|
||||||
|
@ -1162,6 +1167,13 @@ StorageUI.prototype = {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handles refreshing the selected storage
|
||||||
|
*/
|
||||||
|
onRefreshTable: function (event) {
|
||||||
|
this.onHostSelect(event, this.tree.selectedItem);
|
||||||
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handles adding an item from the storage
|
* Handles adding an item from the storage
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
<!-- This Source Code Form is subject to the terms of the Mozilla Public
|
<!-- This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
- License, v. 2.0. If a copy of the MPL was not distributed with this
|
- 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/. -->
|
- file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 14 14" width="14" height="14">
|
<svg width="16" height="16" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
|
||||||
<path d="M12,7H6l2.4-2.4C7.6,4,6.6,3.8,5.5,4.1C4.3,4.5,3.3,5.5,3,6.8 C2.6,9,4.3,11,6.5,11c1,0,2-0.5,2.6-1.2l1.7,1c-1.3,1.6-3.3,2.5-5.6,2c-2-0.5-3.6-2.1-4-4.1C0.4,5.1,3.1,2,6.5,2 c1.3,0,2.4,0.4,3.3,1.2L12,1V7z"/>
|
<path d="M13.917 7C13.44 4.162 10.973 2 8 2 4.686 2 2 4.686 2 8s2.686 6 6 6c2.22 0 4.16-1.207 5.197-3H12c-.912 1.214-2.364 2-4 2-2.76 0-5-2.24-5-5s2.24-5 5-5c2.42 0 4.437 1.718 4.9 4h1.017z"/>
|
||||||
|
<path d="M14 1L8 7h6V1zm-1 1L9 6h4V2z" fill-rule="evenodd"/>
|
||||||
</svg>
|
</svg>
|
||||||
|
|
До Ширина: | Высота: | Размер: 517 B После Ширина: | Высота: | Размер: 565 B |
|
@ -37,6 +37,11 @@
|
||||||
-moz-user-focus: normal;
|
-moz-user-focus: normal;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#storage-toolbar .refresh-button::before {
|
||||||
|
background-image: url("chrome://devtools/skin/images/reload.svg");
|
||||||
|
-moz-user-focus: normal;
|
||||||
|
}
|
||||||
|
|
||||||
#storage-toolbar .devtools-button {
|
#storage-toolbar .devtools-button {
|
||||||
min-width: 0;
|
min-width: 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -854,14 +854,43 @@ a.learn-more-link.webconsole-learn-more-link {
|
||||||
background-position: -36px -36px;
|
background-position: -36px -36px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Network Messages */
|
||||||
|
|
||||||
.message.network .method {
|
.message.network .method {
|
||||||
margin-inline-end: 5px;
|
margin-inline-end: 5px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.network.message .network-info {
|
||||||
|
display: none;
|
||||||
|
margin-top: 8px;
|
||||||
|
border: solid 1px var(--theme-splitter-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
.network.message.open .network-info {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
.network.message .network-info .panels {
|
||||||
|
max-height: 250px;
|
||||||
|
min-height: 100px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Hide 'Edit And Resend' button since the feature isn't
|
||||||
|
supported in the Console panel. */
|
||||||
|
.network.message #headers-panel .edit-and-resend-button {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.network.message #response-panel .treeTable {
|
||||||
|
overflow-y: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
.network .message-flex-body > .message-body {
|
.network .message-flex-body > .message-body {
|
||||||
display: flex;
|
display: flex;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Output Wrapper */
|
||||||
|
|
||||||
.webconsole-output-wrapper .message .indent {
|
.webconsole-output-wrapper .message .indent {
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
border-inline-end: solid 1px var(--theme-splitter-color);
|
border-inline-end: solid 1px var(--theme-splitter-color);
|
||||||
|
|
|
@ -15,6 +15,7 @@ const { batchActions } = require("devtools/client/shared/redux/middleware/deboun
|
||||||
const {
|
const {
|
||||||
MESSAGE_ADD,
|
MESSAGE_ADD,
|
||||||
NETWORK_MESSAGE_UPDATE,
|
NETWORK_MESSAGE_UPDATE,
|
||||||
|
NETWORK_UPDATE_REQUEST,
|
||||||
MESSAGES_CLEAR,
|
MESSAGES_CLEAR,
|
||||||
MESSAGE_OPEN,
|
MESSAGE_OPEN,
|
||||||
MESSAGE_CLOSE,
|
MESSAGE_CLOSE,
|
||||||
|
@ -94,7 +95,7 @@ function messageTableDataReceive(id, data) {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
function networkMessageUpdate(packet, idGenerator = null) {
|
function networkMessageUpdate(packet, idGenerator = null, response) {
|
||||||
if (idGenerator == null) {
|
if (idGenerator == null) {
|
||||||
idGenerator = defaultIdGenerator;
|
idGenerator = defaultIdGenerator;
|
||||||
}
|
}
|
||||||
|
@ -104,6 +105,15 @@ function networkMessageUpdate(packet, idGenerator = null) {
|
||||||
return {
|
return {
|
||||||
type: NETWORK_MESSAGE_UPDATE,
|
type: NETWORK_MESSAGE_UPDATE,
|
||||||
message,
|
message,
|
||||||
|
response,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function networkUpdateRequest(id, data) {
|
||||||
|
return {
|
||||||
|
type: NETWORK_UPDATE_REQUEST,
|
||||||
|
id,
|
||||||
|
data,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -179,6 +189,7 @@ module.exports = {
|
||||||
messageClose,
|
messageClose,
|
||||||
messageTableDataGet,
|
messageTableDataGet,
|
||||||
networkMessageUpdate,
|
networkMessageUpdate,
|
||||||
|
networkUpdateRequest,
|
||||||
messageObjectPropertiesLoad,
|
messageObjectPropertiesLoad,
|
||||||
messageObjectEntriesLoad,
|
messageObjectEntriesLoad,
|
||||||
// for test purpose only.
|
// for test purpose only.
|
||||||
|
|
|
@ -13,6 +13,7 @@ const {
|
||||||
FILTER_BAR_TOGGLE,
|
FILTER_BAR_TOGGLE,
|
||||||
PREFS,
|
PREFS,
|
||||||
TIMESTAMPS_TOGGLE,
|
TIMESTAMPS_TOGGLE,
|
||||||
|
SELECT_NETWORK_MESSAGE_TAB,
|
||||||
} = require("devtools/client/webconsole/new-console-output/constants");
|
} = require("devtools/client/webconsole/new-console-output/constants");
|
||||||
|
|
||||||
function filterBarToggle(show) {
|
function filterBarToggle(show) {
|
||||||
|
@ -32,7 +33,15 @@ function timestampsToggle(visible) {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function selectNetworkMessageTab(id) {
|
||||||
|
return {
|
||||||
|
type: SELECT_NETWORK_MESSAGE_TAB,
|
||||||
|
id,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
filterBarToggle,
|
filterBarToggle,
|
||||||
timestampsToggle,
|
timestampsToggle,
|
||||||
|
selectNetworkMessageTab,
|
||||||
};
|
};
|
||||||
|
|
|
@ -46,6 +46,7 @@ const ConsoleOutput = createClass({
|
||||||
messagesRepeat: PropTypes.object.isRequired,
|
messagesRepeat: PropTypes.object.isRequired,
|
||||||
networkMessagesUpdate: PropTypes.object.isRequired,
|
networkMessagesUpdate: PropTypes.object.isRequired,
|
||||||
visibleMessages: PropTypes.array.isRequired,
|
visibleMessages: PropTypes.array.isRequired,
|
||||||
|
networkMessageActiveTabId: PropTypes.string.isRequired,
|
||||||
},
|
},
|
||||||
|
|
||||||
componentDidMount() {
|
componentDidMount() {
|
||||||
|
@ -67,7 +68,7 @@ const ConsoleOutput = createClass({
|
||||||
const visibleMessagesDelta =
|
const visibleMessagesDelta =
|
||||||
nextProps.visibleMessages.length - this.props.visibleMessages.length;
|
nextProps.visibleMessages.length - this.props.visibleMessages.length;
|
||||||
const messagesDelta =
|
const messagesDelta =
|
||||||
nextProps.messages.length - this.props.messages.length;
|
nextProps.messages.size - this.props.messages.size;
|
||||||
|
|
||||||
// We need to scroll to the bottom if:
|
// We need to scroll to the bottom if:
|
||||||
// - the number of messages displayed changed
|
// - the number of messages displayed changed
|
||||||
|
@ -102,6 +103,7 @@ const ConsoleOutput = createClass({
|
||||||
messagesObjectEntries,
|
messagesObjectEntries,
|
||||||
messagesRepeat,
|
messagesRepeat,
|
||||||
networkMessagesUpdate,
|
networkMessagesUpdate,
|
||||||
|
networkMessageActiveTabId,
|
||||||
serviceContainer,
|
serviceContainer,
|
||||||
timestampsVisible,
|
timestampsVisible,
|
||||||
} = this.props;
|
} = this.props;
|
||||||
|
@ -116,6 +118,7 @@ const ConsoleOutput = createClass({
|
||||||
timestampsVisible,
|
timestampsVisible,
|
||||||
repeat: messagesRepeat[messageId],
|
repeat: messagesRepeat[messageId],
|
||||||
networkMessageUpdate: networkMessagesUpdate[messageId],
|
networkMessageUpdate: networkMessagesUpdate[messageId],
|
||||||
|
networkMessageActiveTabId,
|
||||||
getMessage: () => messages.get(messageId),
|
getMessage: () => messages.get(messageId),
|
||||||
loadedObjectProperties: messagesObjectProperties.get(messageId),
|
loadedObjectProperties: messagesObjectProperties.get(messageId),
|
||||||
loadedObjectEntries: messagesObjectEntries.get(messageId),
|
loadedObjectEntries: messagesObjectEntries.get(messageId),
|
||||||
|
@ -156,6 +159,7 @@ function mapStateToProps(state, props) {
|
||||||
messagesRepeat: getAllRepeatById(state),
|
messagesRepeat: getAllRepeatById(state),
|
||||||
networkMessagesUpdate: getAllNetworkMessagesUpdateById(state),
|
networkMessagesUpdate: getAllNetworkMessagesUpdateById(state),
|
||||||
timestampsVisible: state.ui.timestampsVisible,
|
timestampsVisible: state.ui.timestampsVisible,
|
||||||
|
networkMessageActiveTabId: state.ui.networkMessageActiveTabId,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -13,7 +13,9 @@ const {
|
||||||
PropTypes
|
PropTypes
|
||||||
} = require("devtools/client/shared/vendor/react");
|
} = require("devtools/client/shared/vendor/react");
|
||||||
const Message = createFactory(require("devtools/client/webconsole/new-console-output/components/message"));
|
const Message = createFactory(require("devtools/client/webconsole/new-console-output/components/message"));
|
||||||
|
const actions = require("devtools/client/webconsole/new-console-output/actions/index");
|
||||||
const { l10n } = require("devtools/client/webconsole/new-console-output/utils/messages");
|
const { l10n } = require("devtools/client/webconsole/new-console-output/utils/messages");
|
||||||
|
const TabboxPanel = createFactory(require("devtools/client/netmonitor/src/components/tabbox-panel"));
|
||||||
|
|
||||||
NetworkEventMessage.displayName = "NetworkEventMessage";
|
NetworkEventMessage.displayName = "NetworkEventMessage";
|
||||||
|
|
||||||
|
@ -26,14 +28,30 @@ NetworkEventMessage.propTypes = {
|
||||||
networkMessageUpdate: PropTypes.object.isRequired,
|
networkMessageUpdate: PropTypes.object.isRequired,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This component is responsible for rendering network messages
|
||||||
|
* in the Console panel.
|
||||||
|
*
|
||||||
|
* Network logs are expandable and the user can inspect it inline
|
||||||
|
* within the Console panel (no need to switch to the Network panel).
|
||||||
|
*
|
||||||
|
* HTTP details are rendered using `TabboxPanel` component used to
|
||||||
|
* render contents of the side bar in the Network panel.
|
||||||
|
*
|
||||||
|
* All HTTP details data are fetched from the backend on-demand
|
||||||
|
* when the user is expanding network log for the first time.
|
||||||
|
*/
|
||||||
function NetworkEventMessage({
|
function NetworkEventMessage({
|
||||||
message = {},
|
message = {},
|
||||||
serviceContainer,
|
serviceContainer,
|
||||||
timestampsVisible,
|
timestampsVisible,
|
||||||
networkMessageUpdate = {},
|
networkMessageUpdate = {},
|
||||||
|
networkMessageActiveTabId,
|
||||||
|
dispatch,
|
||||||
|
open,
|
||||||
}) {
|
}) {
|
||||||
const {
|
const {
|
||||||
actor,
|
id,
|
||||||
indent,
|
indent,
|
||||||
source,
|
source,
|
||||||
type,
|
type,
|
||||||
|
@ -61,27 +79,50 @@ function NetworkEventMessage({
|
||||||
statusInfo = `[${httpVersion} ${status} ${statusText} ${totalTime}ms]`;
|
statusInfo = `[${httpVersion} ${status} ${statusText} ${totalTime}ms]`;
|
||||||
}
|
}
|
||||||
|
|
||||||
const openNetworkMonitor = serviceContainer.openNetworkPanel
|
const toggle = () => {
|
||||||
? () => serviceContainer.openNetworkPanel(actor)
|
if (open) {
|
||||||
: null;
|
dispatch(actions.messageClose(id));
|
||||||
|
} else {
|
||||||
|
dispatch(actions.messageOpen(id));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Message body components.
|
||||||
const method = dom.span({className: "method" }, request.method);
|
const method = dom.span({className: "method" }, request.method);
|
||||||
const xhr = isXHR
|
const xhr = isXHR
|
||||||
? dom.span({ className: "xhr" }, l10n.getStr("webConsoleXhrIndicator"))
|
? dom.span({ className: "xhr" }, l10n.getStr("webConsoleXhrIndicator"))
|
||||||
: null;
|
: null;
|
||||||
const url = dom.a({ className: "url", title: request.url, onClick: openNetworkMonitor },
|
const url = dom.a({ className: "url", title: request.url, onClick: toggle },
|
||||||
request.url.replace(/\?.+/, ""));
|
request.url.replace(/\?.+/, ""));
|
||||||
const statusBody = statusInfo
|
const statusBody = statusInfo
|
||||||
? dom.a({ className: "status", onClick: openNetworkMonitor }, statusInfo)
|
? dom.a({ className: "status", onClick: toggle }, statusInfo)
|
||||||
: null;
|
: null;
|
||||||
|
|
||||||
const messageBody = [method, xhr, url, statusBody];
|
const messageBody = [method, xhr, url, statusBody];
|
||||||
|
|
||||||
|
// Only render the attachment if the network-event is
|
||||||
|
// actually opened (performance optimization).
|
||||||
|
const attachment = open && dom.div({className: "network-info devtools-monospace"},
|
||||||
|
TabboxPanel({
|
||||||
|
activeTabId: networkMessageActiveTabId,
|
||||||
|
request: networkMessageUpdate,
|
||||||
|
sourceMapService: serviceContainer.sourceMapService,
|
||||||
|
selectTab: (tabId) => {
|
||||||
|
dispatch(actions.selectNetworkMessageTab(tabId));
|
||||||
|
},
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
return Message({
|
return Message({
|
||||||
|
dispatch,
|
||||||
|
messageId: id,
|
||||||
source,
|
source,
|
||||||
type,
|
type,
|
||||||
level,
|
level,
|
||||||
indent,
|
indent,
|
||||||
|
collapsible: true,
|
||||||
|
open,
|
||||||
|
attachment,
|
||||||
topLevelClasses,
|
topLevelClasses,
|
||||||
timeStamp,
|
timeStamp,
|
||||||
messageBody,
|
messageBody,
|
||||||
|
|
|
@ -89,10 +89,11 @@ const Message = createClass({
|
||||||
},
|
},
|
||||||
|
|
||||||
onContextMenu(e) {
|
onContextMenu(e) {
|
||||||
let { serviceContainer, source, request } = this.props;
|
let { serviceContainer, source, request, messageId } = this.props;
|
||||||
let messageInfo = {
|
let messageInfo = {
|
||||||
source,
|
source,
|
||||||
request,
|
request,
|
||||||
|
messageId,
|
||||||
};
|
};
|
||||||
serviceContainer.openContextMenu(e, messageInfo);
|
serviceContainer.openContextMenu(e, messageInfo);
|
||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
|
|
|
@ -12,6 +12,7 @@ const actionTypes = {
|
||||||
MESSAGE_OPEN: "MESSAGE_OPEN",
|
MESSAGE_OPEN: "MESSAGE_OPEN",
|
||||||
MESSAGE_CLOSE: "MESSAGE_CLOSE",
|
MESSAGE_CLOSE: "MESSAGE_CLOSE",
|
||||||
NETWORK_MESSAGE_UPDATE: "NETWORK_MESSAGE_UPDATE",
|
NETWORK_MESSAGE_UPDATE: "NETWORK_MESSAGE_UPDATE",
|
||||||
|
NETWORK_UPDATE_REQUEST: "NETWORK_UPDATE_REQUEST",
|
||||||
MESSAGE_TABLE_RECEIVE: "MESSAGE_TABLE_RECEIVE",
|
MESSAGE_TABLE_RECEIVE: "MESSAGE_TABLE_RECEIVE",
|
||||||
MESSAGE_OBJECT_PROPERTIES_RECEIVE: "MESSAGE_OBJECT_PROPERTIES_RECEIVE",
|
MESSAGE_OBJECT_PROPERTIES_RECEIVE: "MESSAGE_OBJECT_PROPERTIES_RECEIVE",
|
||||||
MESSAGE_OBJECT_ENTRIES_RECEIVE: "MESSAGE_OBJECT_ENTRIES_RECEIVE",
|
MESSAGE_OBJECT_ENTRIES_RECEIVE: "MESSAGE_OBJECT_ENTRIES_RECEIVE",
|
||||||
|
@ -22,6 +23,7 @@ const actionTypes = {
|
||||||
FILTERS_CLEAR: "FILTERS_CLEAR",
|
FILTERS_CLEAR: "FILTERS_CLEAR",
|
||||||
DEFAULT_FILTERS_RESET: "DEFAULT_FILTERS_RESET",
|
DEFAULT_FILTERS_RESET: "DEFAULT_FILTERS_RESET",
|
||||||
FILTER_BAR_TOGGLE: "FILTER_BAR_TOGGLE",
|
FILTER_BAR_TOGGLE: "FILTER_BAR_TOGGLE",
|
||||||
|
SELECT_NETWORK_MESSAGE_TAB: "SELECT_NETWORK_MESSAGE_TAB",
|
||||||
};
|
};
|
||||||
|
|
||||||
const prefs = {
|
const prefs = {
|
||||||
|
|
|
@ -52,6 +52,11 @@ NewConsoleOutputWrapper.prototype = {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Do not focus if an input field was clicked
|
||||||
|
if (target.closest("input")) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// Do not focus if something other than the output region was clicked
|
// Do not focus if something other than the output region was clicked
|
||||||
if (!target.closest(".webconsole-output")) {
|
if (!target.closest(".webconsole-output")) {
|
||||||
return;
|
return;
|
||||||
|
@ -75,7 +80,16 @@ NewConsoleOutputWrapper.prototype = {
|
||||||
}]));
|
}]));
|
||||||
},
|
},
|
||||||
hudProxyClient: this.jsterm.hud.proxy.client,
|
hudProxyClient: this.jsterm.hud.proxy.client,
|
||||||
openContextMenu: (e, message) => {
|
openLink: url => this.jsterm.hud.owner.openLink(url),
|
||||||
|
createElement: nodename => {
|
||||||
|
return this.document.createElementNS("http://www.w3.org/1999/xhtml", nodename);
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
// Set `openContextMenu` this way so, `serviceContainer` variable
|
||||||
|
// is available in the current scope and we can pass it into
|
||||||
|
// `createContextMenu` method.
|
||||||
|
serviceContainer.openContextMenu = (e, message) => {
|
||||||
let { screenX, screenY, target } = e;
|
let { screenX, screenY, target } = e;
|
||||||
|
|
||||||
let messageEl = target.closest(".message");
|
let messageEl = target.closest(".message");
|
||||||
|
@ -86,18 +100,13 @@ NewConsoleOutputWrapper.prototype = {
|
||||||
let actor = actorEl ? actorEl.dataset.linkActorId : null;
|
let actor = actorEl ? actorEl.dataset.linkActorId : null;
|
||||||
|
|
||||||
let menu = createContextMenu(this.jsterm, this.parentNode,
|
let menu = createContextMenu(this.jsterm, this.parentNode,
|
||||||
{ actor, clipboardText, message });
|
{ actor, clipboardText, message, serviceContainer });
|
||||||
|
|
||||||
// Emit the "menu-open" event for testing.
|
// Emit the "menu-open" event for testing.
|
||||||
menu.once("open", () => this.emit("menu-open"));
|
menu.once("open", () => this.emit("menu-open"));
|
||||||
menu.popup(screenX, screenY, this.toolbox);
|
menu.popup(screenX, screenY, this.toolbox);
|
||||||
|
|
||||||
return menu;
|
return menu;
|
||||||
},
|
|
||||||
openLink: url => this.jsterm.hud.owner.openLink(url),
|
|
||||||
createElement: nodename => {
|
|
||||||
return this.document.createElementNS("http://www.w3.org/1999/xhtml", nodename);
|
|
||||||
},
|
|
||||||
};
|
};
|
||||||
|
|
||||||
if (this.toolbox) {
|
if (this.toolbox) {
|
||||||
|
@ -219,6 +228,19 @@ NewConsoleOutputWrapper.prototype = {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
dispatchRequestUpdate: function (id, data) {
|
||||||
|
batchedMessageAdd(actions.networkUpdateRequest(id, data));
|
||||||
|
|
||||||
|
// Fire an event indicating that all data fetched from
|
||||||
|
// the backend has been received. This is based on
|
||||||
|
// 'FirefoxDataProvider.isQueuePayloadReady', see more
|
||||||
|
// comments in that method.
|
||||||
|
// (netmonitor/src/connector/firefox-data-provider).
|
||||||
|
// This event might be utilized in tests to find the right
|
||||||
|
// time when to finish.
|
||||||
|
this.jsterm.hud.emit("network-request-payload-ready", {id, data});
|
||||||
|
},
|
||||||
|
|
||||||
// Should be used for test purpose only.
|
// Should be used for test purpose only.
|
||||||
getStore: function () {
|
getStore: function () {
|
||||||
return store;
|
return store;
|
||||||
|
|
|
@ -22,6 +22,10 @@ const {
|
||||||
const { getGripPreviewItems } = require("devtools/client/shared/components/reps/reps");
|
const { getGripPreviewItems } = require("devtools/client/shared/components/reps/reps");
|
||||||
const { getSourceNames } = require("devtools/client/shared/source-utils");
|
const { getSourceNames } = require("devtools/client/shared/source-utils");
|
||||||
|
|
||||||
|
const {
|
||||||
|
UPDATE_PROPS
|
||||||
|
} = require("devtools/client/netmonitor/src/constants");
|
||||||
|
|
||||||
const MessageState = Immutable.Record({
|
const MessageState = Immutable.Record({
|
||||||
// List of all the messages added to the console.
|
// List of all the messages added to the console.
|
||||||
messagesById: Immutable.OrderedMap(),
|
messagesById: Immutable.OrderedMap(),
|
||||||
|
@ -166,8 +170,10 @@ function messages(state = new MessageState(), action, filtersState, prefsState)
|
||||||
return state.withMutations(function (record) {
|
return state.withMutations(function (record) {
|
||||||
record.set("messagesUiById", messagesUiById.push(action.id));
|
record.set("messagesUiById", messagesUiById.push(action.id));
|
||||||
|
|
||||||
|
let currMessage = messagesById.get(action.id);
|
||||||
|
|
||||||
// If the message is a group
|
// If the message is a group
|
||||||
if (isGroupType(messagesById.get(action.id).type)) {
|
if (isGroupType(currMessage.type)) {
|
||||||
// We want to make its children visible
|
// We want to make its children visible
|
||||||
const messagesToShow = [...messagesById].reduce((res, [id, message]) => {
|
const messagesToShow = [...messagesById].reduce((res, [id, message]) => {
|
||||||
if (
|
if (
|
||||||
|
@ -195,6 +201,21 @@ function messages(state = new MessageState(), action, filtersState, prefsState)
|
||||||
...visibleMessages.slice(insertIndex),
|
...visibleMessages.slice(insertIndex),
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If the current message is a network event, mark it as opened-once,
|
||||||
|
// so HTTP details are not fetched again the next time the user
|
||||||
|
// opens the log.
|
||||||
|
if (currMessage.source == "network") {
|
||||||
|
record.set("messagesById",
|
||||||
|
messagesById.set(
|
||||||
|
action.id, Object.assign({},
|
||||||
|
currMessage, {
|
||||||
|
openedOnce: true
|
||||||
|
}
|
||||||
|
)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
case constants.MESSAGE_CLOSE:
|
case constants.MESSAGE_CLOSE:
|
||||||
|
@ -250,6 +271,44 @@ function messages(state = new MessageState(), action, filtersState, prefsState)
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
|
||||||
|
case constants.NETWORK_UPDATE_REQUEST: {
|
||||||
|
let request = networkMessagesUpdateById[action.id];
|
||||||
|
if (!request) {
|
||||||
|
return state;
|
||||||
|
}
|
||||||
|
|
||||||
|
let values = {};
|
||||||
|
for (let [key, value] of Object.entries(action.data)) {
|
||||||
|
if (UPDATE_PROPS.includes(key)) {
|
||||||
|
values[key] = value;
|
||||||
|
|
||||||
|
switch (key) {
|
||||||
|
case "securityInfo":
|
||||||
|
values.securityState = value.state;
|
||||||
|
break;
|
||||||
|
case "totalTime":
|
||||||
|
values.totalTime = request.totalTime;
|
||||||
|
break;
|
||||||
|
case "requestPostData":
|
||||||
|
values.requestHeadersFromUploadStream = {
|
||||||
|
headers: [],
|
||||||
|
headersSize: 0,
|
||||||
|
};
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let newState = state.set(
|
||||||
|
"networkMessagesUpdateById",
|
||||||
|
Object.assign({}, networkMessagesUpdateById, {
|
||||||
|
[action.id]: Object.assign({}, request, values)
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
|
return newState;
|
||||||
|
}
|
||||||
|
|
||||||
case constants.REMOVED_ACTORS_CLEAR:
|
case constants.REMOVED_ACTORS_CLEAR:
|
||||||
return state.set("removedActors", []);
|
return state.set("removedActors", []);
|
||||||
|
|
||||||
|
|
|
@ -7,14 +7,20 @@
|
||||||
|
|
||||||
const {
|
const {
|
||||||
FILTER_BAR_TOGGLE,
|
FILTER_BAR_TOGGLE,
|
||||||
TIMESTAMPS_TOGGLE
|
TIMESTAMPS_TOGGLE,
|
||||||
|
SELECT_NETWORK_MESSAGE_TAB,
|
||||||
} = require("devtools/client/webconsole/new-console-output/constants");
|
} = require("devtools/client/webconsole/new-console-output/constants");
|
||||||
const Immutable = require("devtools/client/shared/vendor/immutable");
|
const Immutable = require("devtools/client/shared/vendor/immutable");
|
||||||
|
|
||||||
|
const {
|
||||||
|
PANELS,
|
||||||
|
} = require("devtools/client/netmonitor/src/constants");
|
||||||
|
|
||||||
const UiState = Immutable.Record({
|
const UiState = Immutable.Record({
|
||||||
filterBarVisible: false,
|
filterBarVisible: false,
|
||||||
filteredMessageVisible: false,
|
filteredMessageVisible: false,
|
||||||
timestampsVisible: true,
|
timestampsVisible: true,
|
||||||
|
networkMessageActiveTabId: PANELS.HEADERS,
|
||||||
});
|
});
|
||||||
|
|
||||||
function ui(state = new UiState(), action) {
|
function ui(state = new UiState(), action) {
|
||||||
|
@ -23,6 +29,8 @@ function ui(state = new UiState(), action) {
|
||||||
return state.set("filterBarVisible", !state.filterBarVisible);
|
return state.set("filterBarVisible", !state.filterBarVisible);
|
||||||
case TIMESTAMPS_TOGGLE:
|
case TIMESTAMPS_TOGGLE:
|
||||||
return state.set("timestampsVisible", action.visible);
|
return state.set("timestampsVisible", action.visible);
|
||||||
|
case SELECT_NETWORK_MESSAGE_TAB:
|
||||||
|
return state.set("networkMessageActiveTabId", action.id);
|
||||||
}
|
}
|
||||||
|
|
||||||
return state;
|
return state;
|
||||||
|
|
|
@ -17,13 +17,24 @@ const {
|
||||||
} = require("devtools/client/shared/redux/middleware/debounce");
|
} = require("devtools/client/shared/redux/middleware/debounce");
|
||||||
const {
|
const {
|
||||||
MESSAGE_ADD,
|
MESSAGE_ADD,
|
||||||
|
MESSAGE_OPEN,
|
||||||
MESSAGES_CLEAR,
|
MESSAGES_CLEAR,
|
||||||
REMOVED_ACTORS_CLEAR,
|
REMOVED_ACTORS_CLEAR,
|
||||||
|
NETWORK_MESSAGE_UPDATE,
|
||||||
PREFS,
|
PREFS,
|
||||||
} = require("devtools/client/webconsole/new-console-output/constants");
|
} = require("devtools/client/webconsole/new-console-output/constants");
|
||||||
const { reducers } = require("./reducers/index");
|
const { reducers } = require("./reducers/index");
|
||||||
const Services = require("Services");
|
const Services = require("Services");
|
||||||
|
const {
|
||||||
|
getMessage,
|
||||||
|
getAllMessagesUiById,
|
||||||
|
} = require("devtools/client/webconsole/new-console-output/selectors/messages");
|
||||||
|
const DataProvider = require("devtools/client/netmonitor/src/connector/firefox-data-provider");
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create and configure store for the Console panel. This is the place
|
||||||
|
* where various enhancers and middleware can be registered.
|
||||||
|
*/
|
||||||
function configureStore(hud, options = {}) {
|
function configureStore(hud, options = {}) {
|
||||||
const logLimit = options.logLimit
|
const logLimit = options.logLimit
|
||||||
|| Math.max(Services.prefs.getIntPref("devtools.hud.loglimit"), 1);
|
|| Math.max(Services.prefs.getIntPref("devtools.hud.loglimit"), 1);
|
||||||
|
@ -42,13 +53,19 @@ function configureStore(hud, options = {}) {
|
||||||
}),
|
}),
|
||||||
ui: new UiState({
|
ui: new UiState({
|
||||||
filterBarVisible: Services.prefs.getBoolPref(PREFS.UI.FILTER_BAR),
|
filterBarVisible: Services.prefs.getBoolPref(PREFS.UI.FILTER_BAR),
|
||||||
|
networkMessageActiveTabId: "headers",
|
||||||
})
|
})
|
||||||
};
|
};
|
||||||
|
|
||||||
return createStore(
|
return createStore(
|
||||||
createRootReducer(),
|
createRootReducer(),
|
||||||
initialState,
|
initialState,
|
||||||
compose(applyMiddleware(thunk), enableActorReleaser(hud), enableBatching())
|
compose(
|
||||||
|
applyMiddleware(thunk),
|
||||||
|
enableActorReleaser(hud),
|
||||||
|
enableBatching(),
|
||||||
|
enableNetProvider(hud)
|
||||||
|
)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -125,6 +142,69 @@ function enableActorReleaser(hud) {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This enhancer is responsible for fetching HTTP details data
|
||||||
|
* collected by the backend. The fetch happens on-demand
|
||||||
|
* when the user expands network log in order to inspect it.
|
||||||
|
*
|
||||||
|
* This way we don't slow down the Console logging by fetching.
|
||||||
|
* unnecessary data over RDP.
|
||||||
|
*/
|
||||||
|
function enableNetProvider(hud) {
|
||||||
|
let dataProvider;
|
||||||
|
return next => (reducer, initialState, enhancer) => {
|
||||||
|
function netProviderEnhancer(state, action) {
|
||||||
|
let proxy = hud ? hud.proxy : null;
|
||||||
|
if (!proxy) {
|
||||||
|
return reducer(state, action);
|
||||||
|
}
|
||||||
|
|
||||||
|
let actions = {
|
||||||
|
updateRequest: (id, data, batch) => {
|
||||||
|
proxy.dispatchRequestUpdate(id, data);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Data provider implements async logic for fetching
|
||||||
|
// data from the backend. It's created the first
|
||||||
|
// time it's needed.
|
||||||
|
if (!dataProvider) {
|
||||||
|
dataProvider = new DataProvider({
|
||||||
|
actions,
|
||||||
|
webConsoleClient: proxy.webConsoleClient
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
let type = action.type;
|
||||||
|
|
||||||
|
// If network message has been opened, fetch all
|
||||||
|
// HTTP details from the backend.
|
||||||
|
if (type == MESSAGE_OPEN) {
|
||||||
|
let message = getMessage(state, action.id);
|
||||||
|
if (!message.openedOnce && message.source == "network") {
|
||||||
|
message.updates.forEach(updateType => {
|
||||||
|
dataProvider.onNetworkEventUpdate(null, {
|
||||||
|
packet: { updateType: updateType },
|
||||||
|
networkInfo: message,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Process all incoming HTTP details packets.
|
||||||
|
if (type == NETWORK_MESSAGE_UPDATE) {
|
||||||
|
let open = getAllMessagesUiById(state).includes(action.id);
|
||||||
|
if (open) {
|
||||||
|
dataProvider.onNetworkEventUpdate(null, action.response);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return reducer(state, action);
|
||||||
|
}
|
||||||
|
|
||||||
|
return next(netProviderEnhancer, initialState, enhancer);
|
||||||
|
};
|
||||||
|
}
|
||||||
/**
|
/**
|
||||||
* Helper function for releasing backend actors.
|
* Helper function for releasing backend actors.
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -109,4 +109,16 @@ describe("NetworkEventMessage component:", () => {
|
||||||
expect(wrapper.find(".message-body .status").text()).toMatch(EXPECTED_STATUS);
|
expect(wrapper.find(".message-body .status").text()).toMatch(EXPECTED_STATUS);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe("is expandable", () => {
|
||||||
|
it("renders as expected", () => {
|
||||||
|
const message = stubPreparedMessages.get("XHR POST request");
|
||||||
|
const wrapper = render(NetworkEventMessage({
|
||||||
|
message,
|
||||||
|
serviceContainer,
|
||||||
|
}));
|
||||||
|
|
||||||
|
expect(wrapper.find(".message .theme-twisty")).toExist();
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -27,7 +27,48 @@ stubPreparedMessages.set("GET request", new NetworkEventMessage({
|
||||||
"type": "log",
|
"type": "log",
|
||||||
"groupId": null,
|
"groupId": null,
|
||||||
"timeStamp": 1487022056850,
|
"timeStamp": 1487022056850,
|
||||||
"indent": 0
|
"indent": 0,
|
||||||
|
"updates": [],
|
||||||
|
"openedOnce": false,
|
||||||
|
"securityState": null,
|
||||||
|
"securityInfo": null,
|
||||||
|
"requestHeadersFromUploadStream": null,
|
||||||
|
"url": "http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/inexistent.html",
|
||||||
|
"urlDetails": {
|
||||||
|
"baseNameWithQuery": "inexistent.html",
|
||||||
|
"host": "example.com",
|
||||||
|
"scheme": "http",
|
||||||
|
"unicodeUrl": "http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/inexistent.html",
|
||||||
|
"isLocal": null
|
||||||
|
},
|
||||||
|
"method": "GET",
|
||||||
|
"cause": {
|
||||||
|
"type": "img",
|
||||||
|
"loadingDocumentUri": "http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-network-event.html",
|
||||||
|
"stacktrace": [
|
||||||
|
{
|
||||||
|
"filename": "http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-network-event.html",
|
||||||
|
"lineNumber": 3,
|
||||||
|
"columnNumber": 1,
|
||||||
|
"functionName": "triggerPacket",
|
||||||
|
"asyncCause": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"filename": "resource://testing-common/content-task.js line 52 > eval",
|
||||||
|
"lineNumber": 8,
|
||||||
|
"columnNumber": 9,
|
||||||
|
"functionName": null,
|
||||||
|
"asyncCause": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"filename": "resource://testing-common/content-task.js",
|
||||||
|
"lineNumber": 53,
|
||||||
|
"columnNumber": 20,
|
||||||
|
"functionName": null,
|
||||||
|
"asyncCause": null
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
}));
|
}));
|
||||||
|
|
||||||
stubPreparedMessages.set("GET request update", new NetworkEventMessage({
|
stubPreparedMessages.set("GET request update", new NetworkEventMessage({
|
||||||
|
@ -56,7 +97,20 @@ stubPreparedMessages.set("GET request update", new NetworkEventMessage({
|
||||||
"type": "log",
|
"type": "log",
|
||||||
"groupId": null,
|
"groupId": null,
|
||||||
"totalTime": 16,
|
"totalTime": 16,
|
||||||
"indent": 0
|
"indent": 0,
|
||||||
|
"openedOnce": false,
|
||||||
|
"securityState": null,
|
||||||
|
"securityInfo": null,
|
||||||
|
"requestHeadersFromUploadStream": null,
|
||||||
|
"url": "http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/inexistent.html",
|
||||||
|
"urlDetails": {
|
||||||
|
"baseNameWithQuery": "inexistent.html",
|
||||||
|
"host": "example.com",
|
||||||
|
"scheme": "http",
|
||||||
|
"unicodeUrl": "http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/inexistent.html",
|
||||||
|
"isLocal": null
|
||||||
|
},
|
||||||
|
"method": "GET"
|
||||||
}));
|
}));
|
||||||
|
|
||||||
stubPreparedMessages.set("XHR GET request", new NetworkEventMessage({
|
stubPreparedMessages.set("XHR GET request", new NetworkEventMessage({
|
||||||
|
@ -73,7 +127,48 @@ stubPreparedMessages.set("XHR GET request", new NetworkEventMessage({
|
||||||
"type": "log",
|
"type": "log",
|
||||||
"groupId": null,
|
"groupId": null,
|
||||||
"timeStamp": 1487022057746,
|
"timeStamp": 1487022057746,
|
||||||
"indent": 0
|
"indent": 0,
|
||||||
|
"updates": [],
|
||||||
|
"openedOnce": false,
|
||||||
|
"securityState": null,
|
||||||
|
"securityInfo": null,
|
||||||
|
"requestHeadersFromUploadStream": null,
|
||||||
|
"url": "http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/inexistent.html",
|
||||||
|
"urlDetails": {
|
||||||
|
"baseNameWithQuery": "inexistent.html",
|
||||||
|
"host": "example.com",
|
||||||
|
"scheme": "http",
|
||||||
|
"unicodeUrl": "http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/inexistent.html",
|
||||||
|
"isLocal": null
|
||||||
|
},
|
||||||
|
"method": "GET",
|
||||||
|
"cause": {
|
||||||
|
"type": "xhr",
|
||||||
|
"loadingDocumentUri": "http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-network-event.html",
|
||||||
|
"stacktrace": [
|
||||||
|
{
|
||||||
|
"filename": "http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-network-event.html",
|
||||||
|
"lineNumber": 4,
|
||||||
|
"columnNumber": 1,
|
||||||
|
"functionName": "triggerPacket",
|
||||||
|
"asyncCause": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"filename": "resource://testing-common/content-task.js line 52 > eval",
|
||||||
|
"lineNumber": 8,
|
||||||
|
"columnNumber": 9,
|
||||||
|
"functionName": null,
|
||||||
|
"asyncCause": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"filename": "resource://testing-common/content-task.js",
|
||||||
|
"lineNumber": 53,
|
||||||
|
"columnNumber": 20,
|
||||||
|
"functionName": null,
|
||||||
|
"asyncCause": null
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
}));
|
}));
|
||||||
|
|
||||||
stubPreparedMessages.set("XHR GET request update", new NetworkEventMessage({
|
stubPreparedMessages.set("XHR GET request update", new NetworkEventMessage({
|
||||||
|
@ -102,7 +197,20 @@ stubPreparedMessages.set("XHR GET request update", new NetworkEventMessage({
|
||||||
"type": "log",
|
"type": "log",
|
||||||
"groupId": null,
|
"groupId": null,
|
||||||
"totalTime": 16,
|
"totalTime": 16,
|
||||||
"indent": 0
|
"indent": 0,
|
||||||
|
"openedOnce": false,
|
||||||
|
"securityState": null,
|
||||||
|
"securityInfo": null,
|
||||||
|
"requestHeadersFromUploadStream": null,
|
||||||
|
"url": "http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/inexistent.html",
|
||||||
|
"urlDetails": {
|
||||||
|
"baseNameWithQuery": "inexistent.html",
|
||||||
|
"host": "example.com",
|
||||||
|
"scheme": "http",
|
||||||
|
"unicodeUrl": "http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/inexistent.html",
|
||||||
|
"isLocal": null
|
||||||
|
},
|
||||||
|
"method": "GET"
|
||||||
}));
|
}));
|
||||||
|
|
||||||
stubPreparedMessages.set("XHR POST request", new NetworkEventMessage({
|
stubPreparedMessages.set("XHR POST request", new NetworkEventMessage({
|
||||||
|
@ -119,7 +227,48 @@ stubPreparedMessages.set("XHR POST request", new NetworkEventMessage({
|
||||||
"type": "log",
|
"type": "log",
|
||||||
"groupId": null,
|
"groupId": null,
|
||||||
"timeStamp": 1487022058414,
|
"timeStamp": 1487022058414,
|
||||||
"indent": 0
|
"indent": 0,
|
||||||
|
"updates": [],
|
||||||
|
"openedOnce": false,
|
||||||
|
"securityState": null,
|
||||||
|
"securityInfo": null,
|
||||||
|
"requestHeadersFromUploadStream": null,
|
||||||
|
"url": "http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/inexistent.html",
|
||||||
|
"urlDetails": {
|
||||||
|
"baseNameWithQuery": "inexistent.html",
|
||||||
|
"host": "example.com",
|
||||||
|
"scheme": "http",
|
||||||
|
"unicodeUrl": "http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/inexistent.html",
|
||||||
|
"isLocal": null
|
||||||
|
},
|
||||||
|
"method": "POST",
|
||||||
|
"cause": {
|
||||||
|
"type": "xhr",
|
||||||
|
"loadingDocumentUri": "http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-network-event.html",
|
||||||
|
"stacktrace": [
|
||||||
|
{
|
||||||
|
"filename": "http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/test-network-event.html",
|
||||||
|
"lineNumber": 4,
|
||||||
|
"columnNumber": 1,
|
||||||
|
"functionName": "triggerPacket",
|
||||||
|
"asyncCause": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"filename": "resource://testing-common/content-task.js line 52 > eval",
|
||||||
|
"lineNumber": 8,
|
||||||
|
"columnNumber": 9,
|
||||||
|
"functionName": null,
|
||||||
|
"asyncCause": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"filename": "resource://testing-common/content-task.js",
|
||||||
|
"lineNumber": 53,
|
||||||
|
"columnNumber": 20,
|
||||||
|
"functionName": null,
|
||||||
|
"asyncCause": null
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
}));
|
}));
|
||||||
|
|
||||||
stubPreparedMessages.set("XHR POST request update", new NetworkEventMessage({
|
stubPreparedMessages.set("XHR POST request update", new NetworkEventMessage({
|
||||||
|
@ -148,7 +297,20 @@ stubPreparedMessages.set("XHR POST request update", new NetworkEventMessage({
|
||||||
"type": "log",
|
"type": "log",
|
||||||
"groupId": null,
|
"groupId": null,
|
||||||
"totalTime": 10,
|
"totalTime": 10,
|
||||||
"indent": 0
|
"indent": 0,
|
||||||
|
"openedOnce": false,
|
||||||
|
"securityState": null,
|
||||||
|
"securityInfo": null,
|
||||||
|
"requestHeadersFromUploadStream": null,
|
||||||
|
"url": "http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/inexistent.html",
|
||||||
|
"urlDetails": {
|
||||||
|
"baseNameWithQuery": "inexistent.html",
|
||||||
|
"host": "example.com",
|
||||||
|
"scheme": "http",
|
||||||
|
"unicodeUrl": "http://example.com/browser/devtools/client/webconsole/new-console-output/test/fixtures/stub-generators/inexistent.html",
|
||||||
|
"isLocal": null
|
||||||
|
},
|
||||||
|
"method": "POST"
|
||||||
}));
|
}));
|
||||||
|
|
||||||
stubPackets.set("GET request", {
|
stubPackets.set("GET request", {
|
||||||
|
|
|
@ -48,7 +48,8 @@ skip-if = (os == 'linux' && bits == 32 && debug) # bug 1328915, disable linux32
|
||||||
[browser_webconsole_location_scratchpad_link.js]
|
[browser_webconsole_location_scratchpad_link.js]
|
||||||
[browser_webconsole_location_styleeditor_link.js]
|
[browser_webconsole_location_styleeditor_link.js]
|
||||||
[browser_webconsole_logErrorInPage.js]
|
[browser_webconsole_logErrorInPage.js]
|
||||||
[browser_webconsole_network_messages_click.js]
|
[browser_webconsole_network_messages_openinnet.js]
|
||||||
|
[browser_webconsole_network_messages_expand.js]
|
||||||
[browser_webconsole_nodes_highlight.js]
|
[browser_webconsole_nodes_highlight.js]
|
||||||
[browser_webconsole_nodes_select.js]
|
[browser_webconsole_nodes_select.js]
|
||||||
[browser_webconsole_object_inspector_entries.js]
|
[browser_webconsole_object_inspector_entries.js]
|
||||||
|
|
|
@ -0,0 +1,67 @@
|
||||||
|
/* Any copyright is dedicated to the Public Domain.
|
||||||
|
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||||
|
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
const TEST_URI = "data:text/html;charset=utf8,Test that clicking on a network message " +
|
||||||
|
"in the console toggles the HTTP inspection.";
|
||||||
|
|
||||||
|
const TEST_FILE = "test-network-request.html";
|
||||||
|
const TEST_PATH = "http://example.com/browser/devtools/client/webconsole/new-console-output/test/mochitest/";
|
||||||
|
|
||||||
|
const NET_PREF = "devtools.webconsole.filter.net";
|
||||||
|
const XHR_PREF = "devtools.webconsole.filter.netxhr";
|
||||||
|
|
||||||
|
Services.prefs.setBoolPref(NET_PREF, true);
|
||||||
|
Services.prefs.setBoolPref(XHR_PREF, true);
|
||||||
|
registerCleanupFunction(() => {
|
||||||
|
Services.prefs.clearUserPref(NET_PREF);
|
||||||
|
Services.prefs.clearUserPref(XHR_PREF);
|
||||||
|
});
|
||||||
|
|
||||||
|
add_task(async function task() {
|
||||||
|
const hud = await openNewTabAndConsole(TEST_URI);
|
||||||
|
|
||||||
|
const currentTab = gBrowser.selectedTab;
|
||||||
|
let target = TargetFactory.forTab(currentTab);
|
||||||
|
let toolbox = gDevTools.getToolbox(target);
|
||||||
|
|
||||||
|
const documentUrl = TEST_PATH + TEST_FILE;
|
||||||
|
await loadDocument(documentUrl);
|
||||||
|
info("Document loaded.");
|
||||||
|
|
||||||
|
await testNetworkMessage(hud, documentUrl);
|
||||||
|
await waitForNetworkUpdates(toolbox);
|
||||||
|
});
|
||||||
|
|
||||||
|
async function testNetworkMessage(hud, url) {
|
||||||
|
let messageNode = await waitFor(() => findMessage(hud, url));
|
||||||
|
let urlNode = messageNode.querySelector(".url");
|
||||||
|
info("Network message found.");
|
||||||
|
|
||||||
|
EventUtils.sendMouseEvent({ type: "click" }, urlNode);
|
||||||
|
|
||||||
|
let headersTab = messageNode.querySelector("#headers-tab");
|
||||||
|
let cookiesTab = messageNode.querySelector("#cookies-tab");
|
||||||
|
let paramsTab = messageNode.querySelector("#params-tab");
|
||||||
|
let responseTab = messageNode.querySelector("#response-tab");
|
||||||
|
let timingsTab = messageNode.querySelector("#timings-tab");
|
||||||
|
|
||||||
|
ok(headersTab, "Headers tab is available");
|
||||||
|
ok(cookiesTab, "Cookies tab is available");
|
||||||
|
ok(paramsTab, "Params tab is available");
|
||||||
|
ok(responseTab, "Response tab is available");
|
||||||
|
ok(timingsTab, "Timings tab is available");
|
||||||
|
}
|
||||||
|
|
||||||
|
async function waitForNetworkUpdates(toolbox) {
|
||||||
|
let panel = toolbox.getCurrentPanel();
|
||||||
|
let hud = panel.hud;
|
||||||
|
let ui = hud.ui;
|
||||||
|
|
||||||
|
return new Promise(resolve => {
|
||||||
|
ui.jsterm.hud.on("network-request-payload-ready", () => {
|
||||||
|
resolve();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
|
@ -3,8 +3,8 @@
|
||||||
|
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
const TEST_URI = "data:text/html;charset=utf8,Test that clicking on a network message " +
|
const TEST_URI = "data:text/html;charset=utf8,Test that 'Open in Network Panel' " +
|
||||||
"in the console opens the netmonitor panel.";
|
"context menu item opens the selected request in netmonitor panel.";
|
||||||
|
|
||||||
const TEST_FILE = "test-network-request.html";
|
const TEST_FILE = "test-network-request.html";
|
||||||
const JSON_TEST_URL = "test-network-request.html";
|
const JSON_TEST_URL = "test-network-request.html";
|
||||||
|
@ -12,6 +12,7 @@ const TEST_PATH = "http://example.com/browser/devtools/client/webconsole/new-con
|
||||||
|
|
||||||
const NET_PREF = "devtools.webconsole.filter.net";
|
const NET_PREF = "devtools.webconsole.filter.net";
|
||||||
const XHR_PREF = "devtools.webconsole.filter.netxhr";
|
const XHR_PREF = "devtools.webconsole.filter.netxhr";
|
||||||
|
|
||||||
Services.prefs.setBoolPref(NET_PREF, true);
|
Services.prefs.setBoolPref(NET_PREF, true);
|
||||||
Services.prefs.setBoolPref(XHR_PREF, true);
|
Services.prefs.setBoolPref(XHR_PREF, true);
|
||||||
registerCleanupFunction(() => {
|
registerCleanupFunction(() => {
|
||||||
|
@ -47,17 +48,16 @@ add_task(async function task() {
|
||||||
|
|
||||||
async function testNetmonitorLink(toolbox, hud, url) {
|
async function testNetmonitorLink(toolbox, hud, url) {
|
||||||
let messageNode = await waitFor(() => findMessage(hud, url));
|
let messageNode = await waitFor(() => findMessage(hud, url));
|
||||||
let urlNode = messageNode.querySelector(".url");
|
|
||||||
info("Network message found.");
|
info("Network message found.");
|
||||||
|
|
||||||
let onNetmonitorSelected = new Promise((resolve) => {
|
let onNetmonitorSelected = toolbox.once("netmonitor-selected", (event, panel) => {
|
||||||
toolbox.once("netmonitor-selected", (event, panel) => {
|
return panel;
|
||||||
resolve(panel);
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|
||||||
info("Simulate click on the network message url.");
|
let menuPopup = await openContextMenu(hud, messageNode);
|
||||||
EventUtils.sendMouseEvent({ type: "click" }, urlNode);
|
let openInNetMenuItem = menuPopup.querySelector("#console-menu-open-in-network-panel");
|
||||||
|
ok(openInNetMenuItem, "open in network panel item is enabled");
|
||||||
|
openInNetMenuItem.click();
|
||||||
|
|
||||||
const {panelWin} = await onNetmonitorSelected;
|
const {panelWin} = await onNetmonitorSelected;
|
||||||
ok(true, "The netmonitor panel is selected when clicking on the network message");
|
ok(true, "The netmonitor panel is selected when clicking on the network message");
|
|
@ -53,7 +53,7 @@ var openNewTabAndConsole = Task.async(function* (url) {
|
||||||
});
|
});
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Wait for messages in the web console output, resolving once they are receieved.
|
* Wait for messages in the web console output, resolving once they are received.
|
||||||
*
|
*
|
||||||
* @param object options
|
* @param object options
|
||||||
* - hud: the webconsole
|
* - hud: the webconsole
|
||||||
|
@ -100,7 +100,7 @@ function waitForMessages({ hud, messages }) {
|
||||||
* idempotent function, since we have to run it a second time after it returns
|
* idempotent function, since we have to run it a second time after it returns
|
||||||
* true in order to return the value.
|
* true in order to return the value.
|
||||||
* @param string message [optional]
|
* @param string message [optional]
|
||||||
* A message to output if the condition failes.
|
* A message to output if the condition fails.
|
||||||
* @param number interval [optional]
|
* @param number interval [optional]
|
||||||
* How often the predicate is invoked, in milliseconds.
|
* How often the predicate is invoked, in milliseconds.
|
||||||
* @return object
|
* @return object
|
||||||
|
@ -144,6 +144,7 @@ function findMessages(hud, text, selector = ".message") {
|
||||||
);
|
);
|
||||||
return elements;
|
return elements;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Simulate a context menu event on the provided element, and wait for the console context
|
* Simulate a context menu event on the provided element, and wait for the console context
|
||||||
* menu to open. Returns a promise that resolves the menu popup element.
|
* menu to open. Returns a promise that resolves the menu popup element.
|
||||||
|
@ -154,10 +155,10 @@ function findMessages(hud, text, selector = ".message") {
|
||||||
* The dom element on which the context menu event should be synthesized.
|
* The dom element on which the context menu event should be synthesized.
|
||||||
* @return promise
|
* @return promise
|
||||||
*/
|
*/
|
||||||
function* openContextMenu(hud, element) {
|
async function openContextMenu(hud, element) {
|
||||||
let onConsoleMenuOpened = hud.ui.newConsoleOutput.once("menu-open");
|
let onConsoleMenuOpened = hud.ui.newConsoleOutput.once("menu-open");
|
||||||
synthesizeContextMenuEvent(element);
|
synthesizeContextMenuEvent(element);
|
||||||
yield onConsoleMenuOpened;
|
await onConsoleMenuOpened;
|
||||||
return hud.ui.newConsoleOutput.toolbox.doc.getElementById("webconsole-menu");
|
return hud.ui.newConsoleOutput.toolbox.doc.getElementById("webconsole-menu");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -36,6 +36,8 @@ requireHacker.global_hook("default", path => {
|
||||||
return `module.exports = require("devtools/client/webconsole/new-console-output/test/fixtures/Services")`;
|
return `module.exports = require("devtools/client/webconsole/new-console-output/test/fixtures/Services")`;
|
||||||
case "devtools/shared/client/main":
|
case "devtools/shared/client/main":
|
||||||
return `module.exports = require("devtools/client/webconsole/new-console-output/test/fixtures/ObjectClient")`;
|
return `module.exports = require("devtools/client/webconsole/new-console-output/test/fixtures/ObjectClient")`;
|
||||||
|
case "devtools/client/netmonitor/src/components/tabbox-panel":
|
||||||
|
return "{}";
|
||||||
}
|
}
|
||||||
return undefined;
|
return undefined;
|
||||||
});
|
});
|
||||||
|
|
|
@ -0,0 +1,85 @@
|
||||||
|
/* Any copyright is dedicated to the Public Domain.
|
||||||
|
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
const {
|
||||||
|
getAllNetworkMessagesUpdateById,
|
||||||
|
} = require("devtools/client/webconsole/new-console-output/selectors/messages");
|
||||||
|
const {
|
||||||
|
setupActions,
|
||||||
|
setupStore,
|
||||||
|
clonePacket
|
||||||
|
} = require("devtools/client/webconsole/new-console-output/test/helpers");
|
||||||
|
const { stubPackets } = require("devtools/client/webconsole/new-console-output/test/fixtures/stubs/index");
|
||||||
|
|
||||||
|
const expect = require("expect");
|
||||||
|
|
||||||
|
describe("Network message reducer:", () => {
|
||||||
|
let actions;
|
||||||
|
let getState;
|
||||||
|
let dispatch;
|
||||||
|
|
||||||
|
before(() => {
|
||||||
|
actions = setupActions();
|
||||||
|
});
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
const store = setupStore([]);
|
||||||
|
|
||||||
|
getState = store.getState;
|
||||||
|
dispatch = store.dispatch;
|
||||||
|
|
||||||
|
let packet = clonePacket(stubPackets.get("GET request"));
|
||||||
|
let updatePacket = clonePacket(stubPackets.get("GET request update"));
|
||||||
|
|
||||||
|
packet.actor = "message1";
|
||||||
|
updatePacket.networkInfo.actor = "message1";
|
||||||
|
dispatch(actions.messageAdd(packet));
|
||||||
|
dispatch(actions.networkMessageUpdate(updatePacket.networkInfo));
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("networkMessagesUpdateById", () => {
|
||||||
|
it("adds fetched HTTP request headers", () => {
|
||||||
|
let headers = {
|
||||||
|
headers: []
|
||||||
|
};
|
||||||
|
|
||||||
|
dispatch(actions.networkUpdateRequest("message1", {
|
||||||
|
requestHeaders: headers
|
||||||
|
}));
|
||||||
|
|
||||||
|
let networkUpdates = getAllNetworkMessagesUpdateById(getState());
|
||||||
|
expect(networkUpdates.message1.requestHeaders).toBe(headers);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("adds fetched HTTP security info", () => {
|
||||||
|
let securityInfo = {
|
||||||
|
state: "insecure"
|
||||||
|
};
|
||||||
|
|
||||||
|
dispatch(actions.networkUpdateRequest("message1", {
|
||||||
|
securityInfo: securityInfo
|
||||||
|
}));
|
||||||
|
|
||||||
|
let networkUpdates = getAllNetworkMessagesUpdateById(getState());
|
||||||
|
expect(networkUpdates.message1.securityInfo).toBe(securityInfo);
|
||||||
|
expect(networkUpdates.message1.securityState).toBe("insecure");
|
||||||
|
});
|
||||||
|
|
||||||
|
it("adds fetched HTTP post data", () => {
|
||||||
|
let requestPostData = {
|
||||||
|
postData: {
|
||||||
|
text: ""
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
dispatch(actions.networkUpdateRequest("message1", {
|
||||||
|
requestPostData: requestPostData
|
||||||
|
}));
|
||||||
|
|
||||||
|
let networkUpdates = getAllNetworkMessagesUpdateById(getState());
|
||||||
|
expect(networkUpdates.message1.requestPostData).toBe(requestPostData);
|
||||||
|
expect(networkUpdates.message1.requestHeadersFromUploadStream).toExist();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
|
@ -60,5 +60,10 @@ exports.NetworkEventMessage = function (props) {
|
||||||
timeStamp: null,
|
timeStamp: null,
|
||||||
totalTime: null,
|
totalTime: null,
|
||||||
indent: 0,
|
indent: 0,
|
||||||
|
updates: null,
|
||||||
|
openedOnce: false,
|
||||||
|
securityState: null,
|
||||||
|
securityInfo: null,
|
||||||
|
requestHeadersFromUploadStream: null,
|
||||||
}, props);
|
}, props);
|
||||||
};
|
};
|
||||||
|
|
|
@ -31,7 +31,12 @@ const { l10n } = require("devtools/client/webconsole/new-console-output/utils/me
|
||||||
* - {String} source
|
* - {String} source
|
||||||
* - {String} request
|
* - {String} request
|
||||||
*/
|
*/
|
||||||
function createContextMenu(jsterm, parentNode, { actor, clipboardText, message }) {
|
function createContextMenu(jsterm, parentNode, {
|
||||||
|
actor,
|
||||||
|
clipboardText,
|
||||||
|
message,
|
||||||
|
serviceContainer
|
||||||
|
}) {
|
||||||
let win = parentNode.ownerDocument.defaultView;
|
let win = parentNode.ownerDocument.defaultView;
|
||||||
let selection = win.getSelection();
|
let selection = win.getSelection();
|
||||||
|
|
||||||
|
@ -55,6 +60,19 @@ function createContextMenu(jsterm, parentNode, { actor, clipboardText, message }
|
||||||
},
|
},
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
// Open Network message in the Network panel.
|
||||||
|
menu.append(new MenuItem({
|
||||||
|
id: "console-menu-open-in-network-panel",
|
||||||
|
label: l10n.getStr("webconsole.menu.openInNetworkPanel.label"),
|
||||||
|
accesskey: l10n.getStr("webconsole.menu.openInNetworkPanel.accesskey"),
|
||||||
|
visible: source === MESSAGE_SOURCE.NETWORK,
|
||||||
|
click: () => {
|
||||||
|
if (request && serviceContainer.openNetworkPanel) {
|
||||||
|
serviceContainer.openNetworkPanel(message.messageId);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}));
|
||||||
|
|
||||||
// Open URL in a new tab for a network request.
|
// Open URL in a new tab for a network request.
|
||||||
menu.append(new MenuItem({
|
menu.append(new MenuItem({
|
||||||
id: "console-menu-open-url",
|
id: "console-menu-open-url",
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
const l10n = require("devtools/client/webconsole/webconsole-l10n");
|
const l10n = require("devtools/client/webconsole/webconsole-l10n");
|
||||||
|
const { getUrlDetails } = require("devtools/client/netmonitor/src/utils/request-utils");
|
||||||
|
|
||||||
const {
|
const {
|
||||||
MESSAGE_SOURCE,
|
MESSAGE_SOURCE,
|
||||||
|
@ -232,6 +233,11 @@ function transformNetworkEventPacket(packet) {
|
||||||
response: networkEvent.response,
|
response: networkEvent.response,
|
||||||
timeStamp: networkEvent.timeStamp,
|
timeStamp: networkEvent.timeStamp,
|
||||||
totalTime: networkEvent.totalTime,
|
totalTime: networkEvent.totalTime,
|
||||||
|
url: networkEvent.request.url,
|
||||||
|
urlDetails: getUrlDetails(networkEvent.request.url),
|
||||||
|
method: networkEvent.request.method,
|
||||||
|
updates: networkEvent.updates,
|
||||||
|
cause: networkEvent.cause,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -88,7 +88,7 @@ WebConsolePanel.prototype = {
|
||||||
let msg = "WebConsolePanel open failed. " +
|
let msg = "WebConsolePanel open failed. " +
|
||||||
reason.error + ": " + reason.message;
|
reason.error + ": " + reason.message;
|
||||||
dump(msg + "\n");
|
dump(msg + "\n");
|
||||||
console.error(msg);
|
console.error(msg, reason);
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
|
@ -243,6 +243,10 @@ WebConsoleConnectionProxy.prototype = {
|
||||||
this.webConsoleFrame.newConsoleOutput.dispatchMessageUpdate(networkInfo, response);
|
this.webConsoleFrame.newConsoleOutput.dispatchMessageUpdate(networkInfo, response);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
dispatchRequestUpdate: function (id, data) {
|
||||||
|
this.webConsoleFrame.newConsoleOutput.dispatchRequestUpdate(id, data);
|
||||||
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The "cachedMessages" response handler.
|
* The "cachedMessages" response handler.
|
||||||
*
|
*
|
||||||
|
|
|
@ -11,6 +11,10 @@
|
||||||
<link rel="stylesheet" href="chrome://devtools/skin/webconsole.css"/>
|
<link rel="stylesheet" href="chrome://devtools/skin/webconsole.css"/>
|
||||||
<link rel="stylesheet" href="chrome://devtools/skin/components-frame.css"/>
|
<link rel="stylesheet" href="chrome://devtools/skin/components-frame.css"/>
|
||||||
<link rel="stylesheet" href="resource://devtools/client/shared/components/reps/reps.css"/>
|
<link rel="stylesheet" href="resource://devtools/client/shared/components/reps/reps.css"/>
|
||||||
|
<link rel="stylesheet" href="resource://devtools/client/shared/components/tabs/tabs.css"/>
|
||||||
|
<link rel="stylesheet" href="resource://devtools/client/shared/components/tabs/tabbar.css"/>
|
||||||
|
<link rel="stylesheet" href="chrome://devtools/content/netmonitor/src/assets/styles/netmonitor.css"/>
|
||||||
|
|
||||||
<script src="chrome://devtools/content/shared/theme-switching.js"></script>
|
<script src="chrome://devtools/content/shared/theme-switching.js"></script>
|
||||||
<script type="application/javascript"
|
<script type="application/javascript"
|
||||||
src="resource://devtools/client/webconsole/new-console-output/main.js"></script>
|
src="resource://devtools/client/webconsole/new-console-output/main.js"></script>
|
||||||
|
|
|
@ -82,6 +82,7 @@ webpackConfig.resolve = {
|
||||||
"devtools/shared/old-event-emitter": "devtools-modules/src/utils/event-emitter",
|
"devtools/shared/old-event-emitter": "devtools-modules/src/utils/event-emitter",
|
||||||
"devtools/shared/client/main": path.join(__dirname, "new-console-output/test/fixtures/ObjectClient"),
|
"devtools/shared/client/main": path.join(__dirname, "new-console-output/test/fixtures/ObjectClient"),
|
||||||
"devtools/shared/platform/clipboard": path.join(__dirname, "../../shared/platform/content/clipboard"),
|
"devtools/shared/platform/clipboard": path.join(__dirname, "../../shared/platform/content/clipboard"),
|
||||||
|
"devtools/shared/platform/stack": path.join(__dirname, "../../shared/platform/content/stack"),
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -30,10 +30,8 @@
|
||||||
* [Panel SVGs](frontend/svgs.md)
|
* [Panel SVGs](frontend/svgs.md)
|
||||||
* [React](frontend/react.md)
|
* [React](frontend/react.md)
|
||||||
* [Guidelines](frontend/react-guidelines.md)
|
* [Guidelines](frontend/react-guidelines.md)
|
||||||
* [Tips](frontend/react-tips.md)
|
|
||||||
* [Redux](frontend/redux.md)
|
* [Redux](frontend/redux.md)
|
||||||
* [Guidelines](frontend/redux-guidelines.md)
|
* [Guidelines](frontend/redux-guidelines.md)
|
||||||
* [Tips](frontend/redux-tips.md)
|
|
||||||
* [Telemetry](frontend/telemetry.md)
|
* [Telemetry](frontend/telemetry.md)
|
||||||
* [Backend](backend/backend.md)
|
* [Backend](backend/backend.md)
|
||||||
* [Remote Debugging Protocol](backend/protocol.md)
|
* [Remote Debugging Protocol](backend/protocol.md)
|
||||||
|
|
|
@ -19,8 +19,8 @@ Ensure that the actor's destroy is really destroying everything that it should.
|
||||||
```js
|
```js
|
||||||
destroy: function() {
|
destroy: function() {
|
||||||
Actor.prototype.destroy.call(this);
|
Actor.prototype.destroy.call(this);
|
||||||
events.off(this.tabActor, "will-navigate", this.onWillNavigate);
|
this.tabActor.off("will-navigate", this.onWillNavigate);
|
||||||
events.off(this.tabActor, "navigate", this.onNavigate);
|
this.tabActor.off("navigate", this.onNavigate);
|
||||||
|
|
||||||
this.stopAnimationPlayerUpdates();
|
this.stopAnimationPlayerUpdates();
|
||||||
this.tabActor = this.observer = this.actors = null;
|
this.tabActor = this.observer = this.actors = null;
|
||||||
|
|
|
@ -487,11 +487,11 @@ Here's how you'd set it up in a spec:
|
||||||
|
|
||||||
Here's how the implementation would look:
|
Here's how the implementation would look:
|
||||||
|
|
||||||
const event = require("devtools/shared/event-emitter");
|
const EventEmitter = require("devtools/shared/event-emitter");
|
||||||
|
|
||||||
// In your protocol.ActorClassWithSpec definition:
|
// In your protocol.ActorClassWithSpec definition:
|
||||||
giveGoodNews: function (news) {
|
giveGoodNews: function (news) {
|
||||||
event.emit(this, "good-news", news);
|
EventEmitter.emit(this, "good-news", news);
|
||||||
}
|
}
|
||||||
|
|
||||||
Now you can listen to events on a front:
|
Now you can listen to events on a front:
|
||||||
|
|
|
@ -1,19 +0,0 @@
|
||||||
# React Tips
|
|
||||||
|
|
||||||
Learn various tips and tricks for working with our React code.
|
|
||||||
|
|
||||||
## Hot Reloading
|
|
||||||
|
|
||||||
If you followed [this
|
|
||||||
rule](react-guidelines.md#export-the-component-directly-and-create-factory-on-import)
|
|
||||||
about exporting components, and are using the BrowserLoader, you can
|
|
||||||
hot reload any React component. Just turn on the pref
|
|
||||||
`devtools.loader.hotreload`, re-open the devtools, and you should be
|
|
||||||
able to save any React component and instantly see changes.
|
|
||||||
|
|
||||||
This does not reset the state of your app, so you can quickly se
|
|
||||||
changes in the same context.
|
|
||||||
|
|
||||||
## Profiling
|
|
||||||
|
|
||||||
We need information here about how to use React.addons.Perf to profile the app.
|
|
|
@ -1,5 +0,0 @@
|
||||||
|
|
||||||
Need to document:
|
|
||||||
|
|
||||||
* How to attach various redux loggers
|
|
||||||
* How to hot reload redux code
|
|
|
@ -30,7 +30,6 @@ const promise = require("promise");
|
||||||
const protocol = require("devtools/shared/protocol");
|
const protocol = require("devtools/shared/protocol");
|
||||||
const {Actor} = protocol;
|
const {Actor} = protocol;
|
||||||
const {animationPlayerSpec, animationsSpec} = require("devtools/shared/specs/animation");
|
const {animationPlayerSpec, animationsSpec} = require("devtools/shared/specs/animation");
|
||||||
const events = require("devtools/shared/event-emitter");
|
|
||||||
|
|
||||||
// Types of animations.
|
// Types of animations.
|
||||||
const ANIMATION_TYPES = {
|
const ANIMATION_TYPES = {
|
||||||
|
@ -385,7 +384,7 @@ var AnimationPlayerActor = protocol.ActorClassWithSpec(animationPlayerSpec, {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (hasChanged) {
|
if (hasChanged) {
|
||||||
events.emit(this, "changed", this.getCurrentState());
|
this.emit("changed", this.getCurrentState());
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -595,14 +594,14 @@ exports.AnimationsActor = protocol.ActorClassWithSpec(animationsSpec, {
|
||||||
this.onAnimationMutation = this.onAnimationMutation.bind(this);
|
this.onAnimationMutation = this.onAnimationMutation.bind(this);
|
||||||
|
|
||||||
this.allAnimationsPaused = false;
|
this.allAnimationsPaused = false;
|
||||||
events.on(this.tabActor, "will-navigate", this.onWillNavigate);
|
this.tabActor.on("will-navigate", this.onWillNavigate);
|
||||||
events.on(this.tabActor, "navigate", this.onNavigate);
|
this.tabActor.on("navigate", this.onNavigate);
|
||||||
},
|
},
|
||||||
|
|
||||||
destroy: function () {
|
destroy: function () {
|
||||||
Actor.prototype.destroy.call(this);
|
Actor.prototype.destroy.call(this);
|
||||||
events.off(this.tabActor, "will-navigate", this.onWillNavigate);
|
this.tabActor.off("will-navigate", this.onWillNavigate);
|
||||||
events.off(this.tabActor, "navigate", this.onNavigate);
|
this.tabActor.off("navigate", this.onNavigate);
|
||||||
|
|
||||||
this.stopAnimationPlayerUpdates();
|
this.stopAnimationPlayerUpdates();
|
||||||
this.tabActor = this.observer = this.actors = this.walker = null;
|
this.tabActor = this.observer = this.actors = this.walker = null;
|
||||||
|
@ -729,7 +728,7 @@ exports.AnimationsActor = protocol.ActorClassWithSpec(animationsSpec, {
|
||||||
// Let's wait for all added animations to be ready before telling the
|
// Let's wait for all added animations to be ready before telling the
|
||||||
// front-end.
|
// front-end.
|
||||||
Promise.all(readyPromises).then(() => {
|
Promise.all(readyPromises).then(() => {
|
||||||
events.emit(this, "mutations", eventData);
|
this.emit("mutations", eventData);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
|
@ -6,12 +6,9 @@
|
||||||
/* global XPCNativeWrapper */
|
/* global XPCNativeWrapper */
|
||||||
|
|
||||||
const {Ci, Cu} = require("chrome");
|
const {Ci, Cu} = require("chrome");
|
||||||
const events = require("devtools/shared/event-emitter");
|
|
||||||
const protocol = require("devtools/shared/protocol");
|
const protocol = require("devtools/shared/protocol");
|
||||||
const {serializeStack, parseStack} = require("toolkit/loader");
|
const {serializeStack, parseStack} = require("toolkit/loader");
|
||||||
|
|
||||||
const {on, off, emit} = events;
|
|
||||||
|
|
||||||
const { functionCallSpec, callWatcherSpec } = require("devtools/shared/specs/call-watcher");
|
const { functionCallSpec, callWatcherSpec } = require("devtools/shared/specs/call-watcher");
|
||||||
const { CallWatcherFront } = require("devtools/shared/fronts/call-watcher");
|
const { CallWatcherFront } = require("devtools/shared/fronts/call-watcher");
|
||||||
|
|
||||||
|
@ -237,13 +234,13 @@ exports.CallWatcherActor = protocol.ActorClassWithSpec(callWatcherSpec, {
|
||||||
this._onGlobalCreated = this._onGlobalCreated.bind(this);
|
this._onGlobalCreated = this._onGlobalCreated.bind(this);
|
||||||
this._onGlobalDestroyed = this._onGlobalDestroyed.bind(this);
|
this._onGlobalDestroyed = this._onGlobalDestroyed.bind(this);
|
||||||
this._onContentFunctionCall = this._onContentFunctionCall.bind(this);
|
this._onContentFunctionCall = this._onContentFunctionCall.bind(this);
|
||||||
on(this.tabActor, "window-ready", this._onGlobalCreated);
|
this.tabActor.on("window-ready", this._onGlobalCreated);
|
||||||
on(this.tabActor, "window-destroyed", this._onGlobalDestroyed);
|
this.tabActor.on("window-destroyed", this._onGlobalDestroyed);
|
||||||
},
|
},
|
||||||
destroy: function (conn) {
|
destroy: function (conn) {
|
||||||
protocol.Actor.prototype.destroy.call(this, conn);
|
protocol.Actor.prototype.destroy.call(this, conn);
|
||||||
off(this.tabActor, "window-ready", this._onGlobalCreated);
|
this.tabActor.off("window-ready", this._onGlobalCreated);
|
||||||
off(this.tabActor, "window-destroyed", this._onGlobalDestroyed);
|
this.tabActor.off("window-destroyed", this._onGlobalDestroyed);
|
||||||
this.finalize();
|
this.finalize();
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -543,7 +540,7 @@ exports.CallWatcherActor = protocol.ActorClassWithSpec(callWatcherSpec, {
|
||||||
if (this.onCall) {
|
if (this.onCall) {
|
||||||
this.onCall(functionCall);
|
this.onCall(functionCall);
|
||||||
} else {
|
} else {
|
||||||
emit(this, "call", functionCall);
|
this.emit("call", functionCall);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
|
@ -9,7 +9,6 @@ const { Cc, Ci } = require("chrome");
|
||||||
const Services = require("Services");
|
const Services = require("Services");
|
||||||
const { XPCOMUtils } = require("resource://gre/modules/XPCOMUtils.jsm");
|
const { XPCOMUtils } = require("resource://gre/modules/XPCOMUtils.jsm");
|
||||||
|
|
||||||
const events = require("devtools/shared/event-emitter");
|
|
||||||
const protocol = require("devtools/shared/protocol");
|
const protocol = require("devtools/shared/protocol");
|
||||||
const { cssUsageSpec } = require("devtools/shared/specs/csscoverage");
|
const { cssUsageSpec } = require("devtools/shared/specs/csscoverage");
|
||||||
|
|
||||||
|
@ -135,7 +134,7 @@ var CSSUsageActor = protocol.ActorClassWithSpec(cssUsageSpec, {
|
||||||
this._tabActor.window.location.reload();
|
this._tabActor.window.location.reload();
|
||||||
}
|
}
|
||||||
|
|
||||||
events.emit(this, "state-change", { isRunning: true });
|
this.emit("state-change", { isRunning: true });
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -150,7 +149,7 @@ var CSSUsageActor = protocol.ActorClassWithSpec(cssUsageSpec, {
|
||||||
this._progress = undefined;
|
this._progress = undefined;
|
||||||
|
|
||||||
this._running = false;
|
this._running = false;
|
||||||
events.emit(this, "state-change", { isRunning: false });
|
this.emit("state-change", { isRunning: false });
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -14,7 +14,6 @@ const {Ci} = require("chrome");
|
||||||
const Services = require("Services");
|
const Services = require("Services");
|
||||||
const {XPCOMUtils} = require("resource://gre/modules/XPCOMUtils.jsm");
|
const {XPCOMUtils} = require("resource://gre/modules/XPCOMUtils.jsm");
|
||||||
const {Actor, ActorClassWithSpec} = require("devtools/shared/protocol");
|
const {Actor, ActorClassWithSpec} = require("devtools/shared/protocol");
|
||||||
const events = require("devtools/shared/event-emitter");
|
|
||||||
const {eventLoopLagSpec} = require("devtools/shared/specs/eventlooplag");
|
const {eventLoopLagSpec} = require("devtools/shared/specs/eventlooplag");
|
||||||
|
|
||||||
exports.EventLoopLagActor = ActorClassWithSpec(eventLoopLagSpec, {
|
exports.EventLoopLagActor = ActorClassWithSpec(eventLoopLagSpec, {
|
||||||
|
@ -52,7 +51,7 @@ exports.EventLoopLagActor = ActorClassWithSpec(eventLoopLagSpec, {
|
||||||
observe: function (subject, topic, data) {
|
observe: function (subject, topic, data) {
|
||||||
if (topic == "event-loop-lag") {
|
if (topic == "event-loop-lag") {
|
||||||
// Forward event loop lag event
|
// Forward event loop lag event
|
||||||
events.emit(this, "event-loop-lag", data);
|
this.emit("event-loop-lag", data);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
|
@ -6,7 +6,6 @@
|
||||||
|
|
||||||
const { Actor, ActorClassWithSpec } = require("devtools/shared/protocol");
|
const { Actor, ActorClassWithSpec } = require("devtools/shared/protocol");
|
||||||
const { gcliSpec } = require("devtools/shared/specs/gcli");
|
const { gcliSpec } = require("devtools/shared/specs/gcli");
|
||||||
const events = require("devtools/shared/event-emitter");
|
|
||||||
const { createSystem } = require("gcli/system");
|
const { createSystem } = require("gcli/system");
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -222,7 +221,7 @@ const GcliActor = ActorClassWithSpec(gcliSpec, {
|
||||||
* Pass events from requisition.system.commands.onCommandsChange upwards
|
* Pass events from requisition.system.commands.onCommandsChange upwards
|
||||||
*/
|
*/
|
||||||
_commandsChanged: function () {
|
_commandsChanged: function () {
|
||||||
events.emit(this, "commands-changed");
|
this.emit("commands-changed");
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -8,7 +8,6 @@ const { Ci, Cu } = require("chrome");
|
||||||
|
|
||||||
const { XPCOMUtils } = require("resource://gre/modules/XPCOMUtils.jsm");
|
const { XPCOMUtils } = require("resource://gre/modules/XPCOMUtils.jsm");
|
||||||
const EventEmitter = require("devtools/shared/old-event-emitter");
|
const EventEmitter = require("devtools/shared/old-event-emitter");
|
||||||
const events = require("devtools/shared/event-emitter");
|
|
||||||
const protocol = require("devtools/shared/protocol");
|
const protocol = require("devtools/shared/protocol");
|
||||||
const Services = require("Services");
|
const Services = require("Services");
|
||||||
const { isWindowIncluded } = require("devtools/shared/layout/utils");
|
const { isWindowIncluded } = require("devtools/shared/layout/utils");
|
||||||
|
@ -106,7 +105,7 @@ exports.HighlighterActor = protocol.ActorClassWithSpec(highlighterSpec, {
|
||||||
|
|
||||||
// Listen to navigation events to switch from the BoxModelHighlighter to the
|
// Listen to navigation events to switch from the BoxModelHighlighter to the
|
||||||
// SimpleOutlineHighlighter, and back, if the top level window changes.
|
// SimpleOutlineHighlighter, and back, if the top level window changes.
|
||||||
events.on(this._tabActor, "navigate", this._onNavigate);
|
this._tabActor.on("navigate", this._onNavigate);
|
||||||
},
|
},
|
||||||
|
|
||||||
get conn() {
|
get conn() {
|
||||||
|
@ -165,7 +164,7 @@ exports.HighlighterActor = protocol.ActorClassWithSpec(highlighterSpec, {
|
||||||
|
|
||||||
this.hideBoxModel();
|
this.hideBoxModel();
|
||||||
this._destroyHighlighter();
|
this._destroyHighlighter();
|
||||||
events.off(this._tabActor, "navigate", this._onNavigate);
|
this._tabActor.off("navigate", this._onNavigate);
|
||||||
|
|
||||||
this._highlighterEnv.destroy();
|
this._highlighterEnv.destroy();
|
||||||
this._highlighterEnv = null;
|
this._highlighterEnv = null;
|
||||||
|
@ -255,7 +254,7 @@ exports.HighlighterActor = protocol.ActorClassWithSpec(highlighterSpec, {
|
||||||
// If shift is pressed, this is only a preview click, send the event to
|
// If shift is pressed, this is only a preview click, send the event to
|
||||||
// the client, but don't stop picking.
|
// the client, but don't stop picking.
|
||||||
if (event.shiftKey) {
|
if (event.shiftKey) {
|
||||||
events.emit(this._walker, "picker-node-previewed",
|
this._walker.emit("picker-node-previewed",
|
||||||
this._findAndAttachElement(event));
|
this._findAndAttachElement(event));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -270,7 +269,7 @@ exports.HighlighterActor = protocol.ActorClassWithSpec(highlighterSpec, {
|
||||||
if (!this._currentNode) {
|
if (!this._currentNode) {
|
||||||
this._currentNode = this._findAndAttachElement(event);
|
this._currentNode = this._findAndAttachElement(event);
|
||||||
}
|
}
|
||||||
events.emit(this._walker, "picker-node-picked", this._currentNode);
|
this._walker.emit("picker-node-picked", this._currentNode);
|
||||||
};
|
};
|
||||||
|
|
||||||
this._onHovered = event => {
|
this._onHovered = event => {
|
||||||
|
@ -283,7 +282,7 @@ exports.HighlighterActor = protocol.ActorClassWithSpec(highlighterSpec, {
|
||||||
this._currentNode = this._findAndAttachElement(event);
|
this._currentNode = this._findAndAttachElement(event);
|
||||||
if (this._hoveredNode !== this._currentNode.node) {
|
if (this._hoveredNode !== this._currentNode.node) {
|
||||||
this._highlighter.show(this._currentNode.node.rawNode);
|
this._highlighter.show(this._currentNode.node.rawNode);
|
||||||
events.emit(this._walker, "picker-node-hovered", this._currentNode);
|
this._walker.emit("picker-node-hovered", this._currentNode);
|
||||||
this._hoveredNode = this._currentNode.node;
|
this._hoveredNode = this._currentNode.node;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -345,13 +344,13 @@ exports.HighlighterActor = protocol.ActorClassWithSpec(highlighterSpec, {
|
||||||
// Cancel pick mode.
|
// Cancel pick mode.
|
||||||
case Ci.nsIDOMKeyEvent.DOM_VK_ESCAPE:
|
case Ci.nsIDOMKeyEvent.DOM_VK_ESCAPE:
|
||||||
this.cancelPick();
|
this.cancelPick();
|
||||||
events.emit(this._walker, "picker-node-canceled");
|
this._walker.emit("picker-node-canceled");
|
||||||
return;
|
return;
|
||||||
case Ci.nsIDOMKeyEvent.DOM_VK_C:
|
case Ci.nsIDOMKeyEvent.DOM_VK_C:
|
||||||
if ((IS_OSX && event.metaKey && event.altKey) ||
|
if ((IS_OSX && event.metaKey && event.altKey) ||
|
||||||
(!IS_OSX && event.ctrlKey && event.shiftKey)) {
|
(!IS_OSX && event.ctrlKey && event.shiftKey)) {
|
||||||
this.cancelPick();
|
this.cancelPick();
|
||||||
events.emit(this._walker, "picker-node-canceled");
|
this._walker.emit("picker-node-canceled");
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
default: return;
|
default: return;
|
||||||
|
@ -360,7 +359,7 @@ exports.HighlighterActor = protocol.ActorClassWithSpec(highlighterSpec, {
|
||||||
// Store currently attached element
|
// Store currently attached element
|
||||||
this._currentNode = this._walker.attachElement(currentNode);
|
this._currentNode = this._walker.attachElement(currentNode);
|
||||||
this._highlighter.show(this._currentNode.node.rawNode);
|
this._highlighter.show(this._currentNode.node.rawNode);
|
||||||
events.emit(this._walker, "picker-node-hovered", this._currentNode);
|
this._walker.emit("picker-node-hovered", this._currentNode);
|
||||||
};
|
};
|
||||||
|
|
||||||
this._startPickerListeners();
|
this._startPickerListeners();
|
||||||
|
@ -414,11 +413,11 @@ exports.HighlighterActor = protocol.ActorClassWithSpec(highlighterSpec, {
|
||||||
},
|
},
|
||||||
|
|
||||||
_highlighterReady: function () {
|
_highlighterReady: function () {
|
||||||
events.emit(this._inspector.walker, "highlighter-ready");
|
this._inspector.walker.emit("highlighter-ready");
|
||||||
},
|
},
|
||||||
|
|
||||||
_highlighterHidden: function () {
|
_highlighterHidden: function () {
|
||||||
events.emit(this._inspector.walker, "highlighter-hide");
|
this._inspector.walker.emit("highlighter-hide");
|
||||||
},
|
},
|
||||||
|
|
||||||
cancelPick: function () {
|
cancelPick: function () {
|
||||||
|
@ -518,7 +517,7 @@ exports.CustomHighlighterActor = protocol.ActorClassWithSpec(customHighlighterSp
|
||||||
* Upon receiving an event from the highlighter, forward it to the client.
|
* Upon receiving an event from the highlighter, forward it to the client.
|
||||||
*/
|
*/
|
||||||
_onHighlighterEvent: function (type, data) {
|
_onHighlighterEvent: function (type, data) {
|
||||||
events.emit(this, "highlighter-event", data);
|
this.emit("highlighter-event", data);
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -567,9 +566,9 @@ exports.HighlighterEnvironment = HighlighterEnvironment;
|
||||||
HighlighterEnvironment.prototype = {
|
HighlighterEnvironment.prototype = {
|
||||||
initFromTabActor: function (tabActor) {
|
initFromTabActor: function (tabActor) {
|
||||||
this._tabActor = tabActor;
|
this._tabActor = tabActor;
|
||||||
events.on(this._tabActor, "window-ready", this.relayTabActorWindowReady);
|
this._tabActor.on("window-ready", this.relayTabActorWindowReady);
|
||||||
events.on(this._tabActor, "navigate", this.relayTabActorNavigate);
|
this._tabActor.on("navigate", this.relayTabActorNavigate);
|
||||||
events.on(this._tabActor, "will-navigate", this.relayTabActorWillNavigate);
|
this._tabActor.on("will-navigate", this.relayTabActorWillNavigate);
|
||||||
},
|
},
|
||||||
|
|
||||||
initFromWindow: function (win) {
|
initFromWindow: function (win) {
|
||||||
|
@ -686,9 +685,9 @@ HighlighterEnvironment.prototype = {
|
||||||
|
|
||||||
destroy: function () {
|
destroy: function () {
|
||||||
if (this._tabActor) {
|
if (this._tabActor) {
|
||||||
events.off(this._tabActor, "window-ready", this.relayTabActorWindowReady);
|
this._tabActor.off("window-ready", this.relayTabActorWindowReady);
|
||||||
events.off(this._tabActor, "navigate", this.relayTabActorNavigate);
|
this._tabActor.off("navigate", this.relayTabActorNavigate);
|
||||||
events.off(this._tabActor, "will-navigate", this.relayTabActorWillNavigate);
|
this._tabActor.off("will-navigate", this.relayTabActorWillNavigate);
|
||||||
}
|
}
|
||||||
|
|
||||||
// In case the environment was initialized from a window, we need to remove
|
// In case the environment was initialized from a window, we need to remove
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
|
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
const events = require("devtools/shared/event-emitter");
|
const EventEmitter = require("devtools/shared/event-emitter");
|
||||||
const { getCurrentZoom, getWindowDimensions,
|
const { getCurrentZoom, getWindowDimensions,
|
||||||
setIgnoreLayoutChanges } = require("devtools/shared/layout/utils");
|
setIgnoreLayoutChanges } = require("devtools/shared/layout/utils");
|
||||||
const {
|
const {
|
||||||
|
@ -212,7 +212,7 @@ MeasuringToolHighlighter.prototype = {
|
||||||
|
|
||||||
this.markup.destroy();
|
this.markup.destroy();
|
||||||
|
|
||||||
events.emit(this, "destroy");
|
EventEmitter.emit(this, "destroy");
|
||||||
},
|
},
|
||||||
|
|
||||||
show() {
|
show() {
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
|
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
const events = require("devtools/shared/event-emitter");
|
const EventEmitter = require("devtools/shared/event-emitter");
|
||||||
const { getCurrentZoom,
|
const { getCurrentZoom,
|
||||||
setIgnoreLayoutChanges } = require("devtools/shared/layout/utils");
|
setIgnoreLayoutChanges } = require("devtools/shared/layout/utils");
|
||||||
const {
|
const {
|
||||||
|
@ -277,7 +277,7 @@ RulersHighlighter.prototype = {
|
||||||
|
|
||||||
this.markup.destroy();
|
this.markup.destroy();
|
||||||
|
|
||||||
events.emit(this, "destroy");
|
EventEmitter.emit(this, "destroy");
|
||||||
},
|
},
|
||||||
|
|
||||||
show: function () {
|
show: function () {
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
const { Cc, Ci, Cu, Cr } = require("chrome");
|
const { Cc, Ci, Cu, Cr } = require("chrome");
|
||||||
const { getCurrentZoom, getWindowDimensions, getViewportDimensions,
|
const { getCurrentZoom, getWindowDimensions, getViewportDimensions,
|
||||||
getRootBindingParent, loadSheet } = require("devtools/shared/layout/utils");
|
getRootBindingParent, loadSheet } = require("devtools/shared/layout/utils");
|
||||||
const { on, emit } = require("devtools/shared/event-emitter");
|
const EventEmitter = require("devtools/shared/event-emitter");
|
||||||
|
|
||||||
const lazyContainer = {};
|
const lazyContainer = {};
|
||||||
|
|
||||||
|
@ -61,7 +61,7 @@ ClassList.prototype = {
|
||||||
if (!this.contains(token)) {
|
if (!this.contains(token)) {
|
||||||
this[_tokens].push(token);
|
this[_tokens].push(token);
|
||||||
}
|
}
|
||||||
emit(this, "update");
|
EventEmitter.emit(this, "update");
|
||||||
},
|
},
|
||||||
remove(token) {
|
remove(token) {
|
||||||
let index = this[_tokens].indexOf(token);
|
let index = this[_tokens].indexOf(token);
|
||||||
|
@ -69,7 +69,7 @@ ClassList.prototype = {
|
||||||
if (index > -1) {
|
if (index > -1) {
|
||||||
this[_tokens].splice(index, 1);
|
this[_tokens].splice(index, 1);
|
||||||
}
|
}
|
||||||
emit(this, "update");
|
EventEmitter.emit(this, "update");
|
||||||
},
|
},
|
||||||
toggle(token) {
|
toggle(token) {
|
||||||
if (this.contains(token)) {
|
if (this.contains(token)) {
|
||||||
|
@ -482,7 +482,7 @@ CanvasFrameAnonymousContentHelper.prototype = {
|
||||||
|
|
||||||
let classList = new ClassList(this.getAttributeForElement(id, "class"));
|
let classList = new ClassList(this.getAttributeForElement(id, "class"));
|
||||||
|
|
||||||
on(classList, "update", () => {
|
EventEmitter.on(classList, "update", () => {
|
||||||
this.setAttributeForElement(id, "class", classList.toString());
|
this.setAttributeForElement(id, "class", classList.toString());
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -58,7 +58,7 @@ const {LongStringActor} = require("devtools/server/actors/string");
|
||||||
const promise = require("promise");
|
const promise = require("promise");
|
||||||
const defer = require("devtools/shared/defer");
|
const defer = require("devtools/shared/defer");
|
||||||
const {Task} = require("devtools/shared/task");
|
const {Task} = require("devtools/shared/task");
|
||||||
const events = require("devtools/shared/event-emitter");
|
const EventEmitter = require("devtools/shared/event-emitter");
|
||||||
const {WalkerSearch} = require("devtools/server/actors/utils/walker-search");
|
const {WalkerSearch} = require("devtools/server/actors/utils/walker-search");
|
||||||
const {PageStyleActor, getFontPreviewData} = require("devtools/server/actors/styles");
|
const {PageStyleActor, getFontPreviewData} = require("devtools/server/actors/styles");
|
||||||
const {
|
const {
|
||||||
|
@ -298,7 +298,7 @@ var NodeActor = exports.NodeActor = protocol.ActorClassWithSpec(nodeSpec, {
|
||||||
|
|
||||||
// Fire an event so, other modules can create its own properties
|
// Fire an event so, other modules can create its own properties
|
||||||
// that should be passed to the client (within the form.props field).
|
// that should be passed to the client (within the form.props field).
|
||||||
events.emit(NodeActor, "form", {
|
EventEmitter.emit(NodeActor, "form", {
|
||||||
target: this,
|
target: this,
|
||||||
data: form
|
data: form
|
||||||
});
|
});
|
||||||
|
@ -890,8 +890,8 @@ var WalkerActor = protocol.ActorClassWithSpec(walkerSpec, {
|
||||||
this.onFrameLoad = this.onFrameLoad.bind(this);
|
this.onFrameLoad = this.onFrameLoad.bind(this);
|
||||||
this.onFrameUnload = this.onFrameUnload.bind(this);
|
this.onFrameUnload = this.onFrameUnload.bind(this);
|
||||||
|
|
||||||
events.on(tabActor, "will-navigate", this.onFrameUnload);
|
tabActor.on("will-navigate", this.onFrameUnload);
|
||||||
events.on(tabActor, "window-ready", this.onFrameLoad);
|
tabActor.on("window-ready", this.onFrameLoad);
|
||||||
|
|
||||||
// Ensure that the root document node actor is ready and
|
// Ensure that the root document node actor is ready and
|
||||||
// managed.
|
// managed.
|
||||||
|
@ -981,8 +981,8 @@ var WalkerActor = protocol.ActorClassWithSpec(walkerSpec, {
|
||||||
this._retainedOrphans = null;
|
this._retainedOrphans = null;
|
||||||
this._refMap = null;
|
this._refMap = null;
|
||||||
|
|
||||||
events.off(this.tabActor, "will-navigate", this.onFrameUnload);
|
this.tabActor.off("will-navigate", this.onFrameUnload);
|
||||||
events.off(this.tabActor, "window-ready", this.onFrameLoad);
|
this.tabActor.off("window-ready", this.onFrameLoad);
|
||||||
|
|
||||||
this.onFrameLoad = null;
|
this.onFrameLoad = null;
|
||||||
this.onFrameUnload = null;
|
this.onFrameUnload = null;
|
||||||
|
@ -1002,7 +1002,7 @@ var WalkerActor = protocol.ActorClassWithSpec(walkerSpec, {
|
||||||
this.layoutActor = null;
|
this.layoutActor = null;
|
||||||
this.tabActor = null;
|
this.tabActor = null;
|
||||||
|
|
||||||
events.emit(this, "destroyed");
|
this.emit("destroyed");
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.error(e);
|
console.error(e);
|
||||||
}
|
}
|
||||||
|
@ -1077,7 +1077,7 @@ var WalkerActor = protocol.ActorClassWithSpec(walkerSpec, {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (changes.length) {
|
if (changes.length) {
|
||||||
events.emit(this, "display-change", changes);
|
this.emit("display-change", changes);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -1085,7 +1085,7 @@ var WalkerActor = protocol.ActorClassWithSpec(walkerSpec, {
|
||||||
* When the browser window gets resized, relay the event to the front.
|
* When the browser window gets resized, relay the event to the front.
|
||||||
*/
|
*/
|
||||||
_onResize: function () {
|
_onResize: function () {
|
||||||
events.emit(this, "resize");
|
this.emit("resize");
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -2333,7 +2333,7 @@ var WalkerActor = protocol.ActorClassWithSpec(walkerSpec, {
|
||||||
this._pendingMutations.push(mutation);
|
this._pendingMutations.push(mutation);
|
||||||
|
|
||||||
if (needEvent) {
|
if (needEvent) {
|
||||||
events.emit(this, "new-mutations");
|
this.emit("new-mutations");
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -2347,7 +2347,7 @@ var WalkerActor = protocol.ActorClassWithSpec(walkerSpec, {
|
||||||
// Notify any observers that want *all* mutations (even on nodes that aren't
|
// Notify any observers that want *all* mutations (even on nodes that aren't
|
||||||
// referenced). This is not sent over the protocol so can only be used by
|
// referenced). This is not sent over the protocol so can only be used by
|
||||||
// scripts running in the server process.
|
// scripts running in the server process.
|
||||||
events.emit(this, "any-mutation");
|
this.emit("any-mutation");
|
||||||
|
|
||||||
for (let change of mutations) {
|
for (let change of mutations) {
|
||||||
let targetActor = this.getNode(change.target);
|
let targetActor = this.getNode(change.target);
|
||||||
|
@ -2760,7 +2760,7 @@ exports.InspectorActor = protocol.ActorClassWithSpec(inspectorSpec, {
|
||||||
window.removeEventListener("DOMContentLoaded", domReady, true);
|
window.removeEventListener("DOMContentLoaded", domReady, true);
|
||||||
this.walker = WalkerActor(this.conn, tabActor, options);
|
this.walker = WalkerActor(this.conn, tabActor, options);
|
||||||
this.manage(this.walker);
|
this.manage(this.walker);
|
||||||
events.once(this.walker, "destroyed", () => {
|
this.walker.once("destroyed", () => {
|
||||||
this._walkerPromise = null;
|
this._walkerPromise = null;
|
||||||
this._pageStylePromise = null;
|
this._pageStylePromise = null;
|
||||||
});
|
});
|
||||||
|
@ -2913,7 +2913,7 @@ exports.InspectorActor = protocol.ActorClassWithSpec(inspectorSpec, {
|
||||||
this._eyeDropper.show(this.window.document.documentElement, options);
|
this._eyeDropper.show(this.window.document.documentElement, options);
|
||||||
this._eyeDropper.once("selected", this._onColorPicked);
|
this._eyeDropper.once("selected", this._onColorPicked);
|
||||||
this._eyeDropper.once("canceled", this._onColorPickCanceled);
|
this._eyeDropper.once("canceled", this._onColorPickCanceled);
|
||||||
events.once(this.tabActor, "will-navigate", this.destroyEyeDropper);
|
this.tabActor.once("will-navigate", this.destroyEyeDropper);
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -2926,7 +2926,7 @@ exports.InspectorActor = protocol.ActorClassWithSpec(inspectorSpec, {
|
||||||
this._eyeDropper.hide();
|
this._eyeDropper.hide();
|
||||||
this._eyeDropper.off("selected", this._onColorPicked);
|
this._eyeDropper.off("selected", this._onColorPicked);
|
||||||
this._eyeDropper.off("canceled", this._onColorPickCanceled);
|
this._eyeDropper.off("canceled", this._onColorPickCanceled);
|
||||||
events.off(this.tabActor, "will-navigate", this.destroyEyeDropper);
|
this.tabActor.off("will-navigate", this.destroyEyeDropper);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -2954,11 +2954,11 @@ exports.InspectorActor = protocol.ActorClassWithSpec(inspectorSpec, {
|
||||||
},
|
},
|
||||||
|
|
||||||
_onColorPicked: function (e, color) {
|
_onColorPicked: function (e, color) {
|
||||||
events.emit(this, "color-picked", color);
|
this.emit("color-picked", color);
|
||||||
},
|
},
|
||||||
|
|
||||||
_onColorPickCanceled: function () {
|
_onColorPickCanceled: function () {
|
||||||
events.emit(this, "color-pick-canceled");
|
this.emit("color-pick-canceled");
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -8,7 +8,6 @@ const protocol = require("devtools/shared/protocol");
|
||||||
const { Memory } = require("devtools/server/performance/memory");
|
const { Memory } = require("devtools/server/performance/memory");
|
||||||
const { actorBridgeWithSpec } = require("devtools/server/actors/common");
|
const { actorBridgeWithSpec } = require("devtools/server/actors/common");
|
||||||
const { memorySpec } = require("devtools/shared/specs/memory");
|
const { memorySpec } = require("devtools/shared/specs/memory");
|
||||||
loader.lazyRequireGetter(this, "events", "devtools/shared/event-emitter");
|
|
||||||
loader.lazyRequireGetter(this, "StackFrameCache",
|
loader.lazyRequireGetter(this, "StackFrameCache",
|
||||||
"devtools/server/actors/utils/stack", true);
|
"devtools/server/actors/utils/stack", true);
|
||||||
|
|
||||||
|
@ -71,13 +70,13 @@ exports.MemoryActor = protocol.ActorClassWithSpec(memorySpec, {
|
||||||
|
|
||||||
_onGarbageCollection: function (data) {
|
_onGarbageCollection: function (data) {
|
||||||
if (this.conn.transport) {
|
if (this.conn.transport) {
|
||||||
events.emit(this, "garbage-collection", data);
|
this.emit("garbage-collection", data);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
_onAllocations: function (data) {
|
_onAllocations: function (data) {
|
||||||
if (this.conn.transport) {
|
if (this.conn.transport) {
|
||||||
events.emit(this, "allocations", data);
|
this.emit("allocations", data);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше
Загрузка…
Ссылка в новой задаче