From 23b06e8c67e9010828c6e765a3bb180f4499da9c Mon Sep 17 00:00:00 2001 From: Daniel Holbert Date: Thu, 16 May 2019 12:02:00 -0700 Subject: [PATCH 01/12] Bug 1508441 followup: adjust reftest failure annotation to point to an updated bug number instead of this closed bug. (no review, test-manifest-only, DONTBUILD) --- layout/reftests/w3c-css/submitted/contain/reftest.list | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/layout/reftests/w3c-css/submitted/contain/reftest.list b/layout/reftests/w3c-css/submitted/contain/reftest.list index e544aef5dacac..744554a7d3000 100644 --- a/layout/reftests/w3c-css/submitted/contain/reftest.list +++ b/layout/reftests/w3c-css/submitted/contain/reftest.list @@ -48,7 +48,7 @@ fuzzy-if(webrender&&winWidget,0-24,0-2) == contain-size-inline-flex-001.html con == contain-layout-ignored-cases-no-principal-box-002.html contain-layout-ignored-cases-no-principal-box-002-ref.html == contain-layout-ignored-cases-no-principal-box-003.html contain-layout-ignored-cases-no-principal-box-003-ref.html == contain-layout-suppress-baseline-001.html contain-layout-suppress-baseline-001-ref.html -fails == contain-layout-suppress-baseline-002.html contain-layout-suppress-baseline-002-ref.html # bug 1508441 +fails == contain-layout-suppress-baseline-002.html contain-layout-suppress-baseline-002-ref.html # bug 1552287 # The following lines are duplicates of other lines from further up in this # manifest. They're listed again here so we can re-run these tests with From aec49ddacd68cc7ccf0c50f5c8703383f00a3c2a Mon Sep 17 00:00:00 2001 From: Fabio Alessandrelli Date: Thu, 16 May 2019 23:11:46 +0200 Subject: [PATCH 02/12] Bug 1529695: Implement RTCDataChannel.negotiated. r=bwc,smaug --HG-- extra : amend_source : d16ca9ffde03d531b012c8f7263d49ef1137327b --- dom/base/nsDOMDataChannel.cpp | 2 ++ dom/base/nsDOMDataChannel.h | 1 + dom/webidl/RTCDataChannel.webidl | 1 + netwerk/sctp/datachannel/DataChannel.h | 4 ++++ .../RTCPeerConnection-createDataChannel.html.ini | 10 +--------- .../meta/webrtc/idlharness.https.window.js.ini | 6 ------ 6 files changed, 9 insertions(+), 15 deletions(-) diff --git a/dom/base/nsDOMDataChannel.cpp b/dom/base/nsDOMDataChannel.cpp index 1aa409b95fe4d..f1019258165e4 100644 --- a/dom/base/nsDOMDataChannel.cpp +++ b/dom/base/nsDOMDataChannel.cpp @@ -142,6 +142,8 @@ mozilla::dom::Nullable nsDOMDataChannel::GetMaxRetransmits() const { return mDataChannel->GetMaxRetransmits(); } +bool nsDOMDataChannel::Negotiated() const { return mDataChannel->GetNegotiated(); } + bool nsDOMDataChannel::Ordered() const { return mDataChannel->GetOrdered(); } RTCDataChannelState nsDOMDataChannel::ReadyState() const { diff --git a/dom/base/nsDOMDataChannel.h b/dom/base/nsDOMDataChannel.h index 0de40f55b0a82..d6cbbc6638780 100644 --- a/dom/base/nsDOMDataChannel.h +++ b/dom/base/nsDOMDataChannel.h @@ -74,6 +74,7 @@ class nsDOMDataChannel final : public mozilla::DOMEventTargetHelper, void Send(const mozilla::dom::ArrayBufferView& aData, mozilla::ErrorResult& aRv); + bool Negotiated() const; bool Ordered() const; mozilla::dom::Nullable GetId() const; diff --git a/dom/webidl/RTCDataChannel.webidl b/dom/webidl/RTCDataChannel.webidl index 8d83d5f1f0d2b..551e64919c748 100644 --- a/dom/webidl/RTCDataChannel.webidl +++ b/dom/webidl/RTCDataChannel.webidl @@ -17,6 +17,7 @@ enum RTCDataChannelType { interface RTCDataChannel : EventTarget { readonly attribute DOMString label; + readonly attribute boolean negotiated; readonly attribute boolean ordered; readonly attribute boolean reliable; readonly attribute unsigned short? maxPacketLifeTime; diff --git a/netwerk/sctp/datachannel/DataChannel.h b/netwerk/sctp/datachannel/DataChannel.h index fa74124bd2015..5f9d24211538c 100644 --- a/netwerk/sctp/datachannel/DataChannel.h +++ b/netwerk/sctp/datachannel/DataChannel.h @@ -384,6 +384,7 @@ class DataChannel { mStream(stream), mPrPolicy(policy), mPrValue(value), + mNegotiated(negotiated), mOrdered(ordered), mFlags(0), mId(0), @@ -439,6 +440,8 @@ class DataChannel { dom::Nullable GetMaxRetransmits() const; + bool GetNegotiated() { return mNegotiated; } + bool GetOrdered() { return mOrdered; } void IncrementBufferedAmount(uint32_t aSize, ErrorResult& aRv); @@ -493,6 +496,7 @@ class DataChannel { uint16_t mStream; uint16_t mPrPolicy; uint32_t mPrValue; + const bool mNegotiated; const bool mOrdered; uint32_t mFlags; uint32_t mId; diff --git a/testing/web-platform/meta/webrtc/RTCPeerConnection-createDataChannel.html.ini b/testing/web-platform/meta/webrtc/RTCPeerConnection-createDataChannel.html.ini index 359a92245578c..594ba1065a264 100644 --- a/testing/web-platform/meta/webrtc/RTCPeerConnection-createDataChannel.html.ini +++ b/testing/web-platform/meta/webrtc/RTCPeerConnection-createDataChannel.html.ini @@ -1,7 +1,7 @@ [RTCPeerConnection-createDataChannel.html] [createDataChannel attribute default values] expected: FAIL - bug: https://bugzilla.mozilla.org/show_bug.cgi?id=1529695 + bug: https://bugzilla.mozilla.org/show_bug.cgi?id=1531100 [createDataChannel with provided parameters should initialize attributes to provided values] expected: FAIL @@ -23,14 +23,6 @@ expected: FAIL bug: https://bugzilla.mozilla.org/show_bug.cgi?id=1526253 - [createDataChannel with negotiated false should succeed] - expected: FAIL - bug: https://bugzilla.mozilla.org/show_bug.cgi?id=1529695 - - [createDataChannel with negotiated false and id 42 should ignore the id] - expected: FAIL - bug: https://bugzilla.mozilla.org/show_bug.cgi?id=1529695 - [Reusing a data channel id that is in use (after setRemoteDescription, negotiated via DCEP) should throw OperationError] expected: FAIL bug: https://bugzilla.mozilla.org/show_bug.cgi?id=1547106 diff --git a/testing/web-platform/meta/webrtc/idlharness.https.window.js.ini b/testing/web-platform/meta/webrtc/idlharness.https.window.js.ini index 6a6606441533a..911c7193f831f 100644 --- a/testing/web-platform/meta/webrtc/idlharness.https.window.js.ini +++ b/testing/web-platform/meta/webrtc/idlharness.https.window.js.ini @@ -281,9 +281,6 @@ [RTCPeerConnectionIceErrorEvent interface: new RTCPeerConnectionIceErrorEvent('ice-error', { errorCode: 701 }); must inherit property "errorText" with the proper type] expected: FAIL - [RTCDataChannel interface: attribute negotiated] - expected: FAIL - [RTCRtpReceiver interface: attribute transport] expected: FAIL @@ -401,9 +398,6 @@ [RTCIceTransport interface: attribute onstatechange] expected: FAIL - [RTCDataChannel interface: new RTCPeerConnection().createDataChannel('') must inherit property "negotiated" with the proper type] - expected: FAIL - [RTCStatsEvent interface: existence and properties of interface prototype object's "constructor" property] expected: FAIL From 49e90dfa545ba69fe27dd3d38063ff3795d3f6ac Mon Sep 17 00:00:00 2001 From: Matthew Gregan Date: Fri, 17 May 2019 09:27:50 +1200 Subject: [PATCH 03/12] Bug 1552342 - Update libcubeb to b9e2c50. r=padenot --- media/libcubeb/disable-device-switching.patch | 79 ------------------- media/libcubeb/moz.yaml | 2 +- media/libcubeb/update.sh | 3 - 3 files changed, 1 insertion(+), 83 deletions(-) delete mode 100644 media/libcubeb/disable-device-switching.patch diff --git a/media/libcubeb/disable-device-switching.patch b/media/libcubeb/disable-device-switching.patch deleted file mode 100644 index 630a21f5c8b0f..0000000000000 --- a/media/libcubeb/disable-device-switching.patch +++ /dev/null @@ -1,79 +0,0 @@ -diff --git a/media/libcubeb/src/cubeb_wasapi.cpp b/media/libcubeb/src/cubeb_wasapi.cpp ---- a/media/libcubeb/src/cubeb_wasapi.cpp -+++ b/media/libcubeb/src/cubeb_wasapi.cpp -@@ -1829,21 +1829,26 @@ wasapi_stream_init(cubeb * context, cube - assert that the lock is held in the function. */ - auto_lock lock(stm->stream_reset_lock); - rv = setup_wasapi_stream(stm.get()); - } - if (rv != CUBEB_OK) { - return rv; - } - -- HRESULT hr = register_notification_client(stm.get()); -- if (FAILED(hr)) { -- /* this is not fatal, we can still play audio, but we won't be able -- to keep using the default audio endpoint if it changes. */ -- LOG("failed to register notification client, %lx", hr); -+ if (!((input_stream_params ? -+ (input_stream_params->prefs & CUBEB_STREAM_PREF_DISABLE_DEVICE_SWITCHING) : 0) || -+ (output_stream_params ? -+ (output_stream_params->prefs & CUBEB_STREAM_PREF_DISABLE_DEVICE_SWITCHING) : 0))) { -+ HRESULT hr = register_notification_client(stm.get()); -+ if (FAILED(hr)) { -+ /* this is not fatal, we can still play audio, but we won't be able -+ to keep using the default audio endpoint if it changes. */ -+ LOG("failed to register notification client, %lx", hr); -+ } - } - - *stream = stm.release(); - - LOG("Stream init succesfull (%p)", *stream); - return CUBEB_OK; - } - -@@ -1879,17 +1884,19 @@ void wasapi_stream_destroy(cubeb_stream - // Only free stm->emergency_bailout if we could join the thread. - // If we could not join the thread, stm->emergency_bailout is true - // and is still alive until the thread wakes up and exits cleanly. - if (stop_and_join_render_thread(stm)) { - delete stm->emergency_bailout.load(); - stm->emergency_bailout = nullptr; - } - -- unregister_notification_client(stm); -+ if (stm->notification_client) { -+ unregister_notification_client(stm); -+ } - - CloseHandle(stm->reconfigure_event); - CloseHandle(stm->refill_event); - CloseHandle(stm->input_available_event); - - // The variables intialized in wasapi_stream_init, - // must be destroyed in wasapi_stream_destroy. - stm->linear_input_buffer.reset(); -diff --git a/media/libcubeb/include/cubeb.h b/media/libcubeb/include/cubeb.h ---- a/media/libcubeb/include/cubeb.h -+++ a/media/libcubeb/include/cubeb.h -@@ -222,16 +222,19 @@ - - /** Miscellaneous stream preferences. */ - typedef enum { - CUBEB_STREAM_PREF_NONE = 0x00, /**< No stream preferences are requested. */ - CUBEB_STREAM_PREF_LOOPBACK = 0x01, /**< Request a loopback stream. Should be - specified on the input params and an - output device to loopback from should - be passed in place of an input device. */ -+ CUBEB_STREAM_PREF_DISABLE_DEVICE_SWITCHING = 0x02, /**< Disable switching -+ default device on OS -+ changes. */ - CUBEB_STREAM_PREF_VOICE = 0x04 /**< This stream is going to transport voice data. - Depending on the backend and platform, this can - change the audio input or output devices - selected, as well as the quality of the stream, - for example to accomodate bluetooth SCO modes on - bluetooth devices. */ - } cubeb_stream_prefs; - diff --git a/media/libcubeb/moz.yaml b/media/libcubeb/moz.yaml index 370a4c27052c0..3097706412557 100644 --- a/media/libcubeb/moz.yaml +++ b/media/libcubeb/moz.yaml @@ -19,5 +19,5 @@ origin: license: "ISC" # update.sh will update this value - release: "64aa80f330a3dc510b1e3ac0e92cc6bed129a9a6 (2019-04-25 17:32:33 +0200)" + release: "b9e2c50e51fc58b31b553b5364efacec24ebb76e (2019-05-17 09:21:59 +1200)" diff --git a/media/libcubeb/update.sh b/media/libcubeb/update.sh index 08f91d2ac31db..3e36ba99c1678 100755 --- a/media/libcubeb/update.sh +++ b/media/libcubeb/update.sh @@ -90,6 +90,3 @@ fi echo "Applying disable-assert.patch on top of $rev" patch -p3 < disable-assert.patch - -echo "Applying disable-device-switching.patch on top of $rev" -patch -p3 < disable-device-switching.patch From dbcde07e7062712f7710cbffc9bfb501fbaaf1eb Mon Sep 17 00:00:00 2001 From: Jonathan Watt Date: Thu, 16 May 2019 23:16:11 +0100 Subject: [PATCH 04/12] Bug 1551882. Refactor the print preview listener code to make its purpose clear. r=bobowen Differential Revision: https://phabricator.services.mozilla.com/D31252 --HG-- rename : layout/printing/nsPrintPreviewListener.cpp => layout/printing/PrintPreviewUserEventSuppressor.cpp rename : layout/printing/nsPrintPreviewListener.h => layout/printing/PrintPreviewUserEventSuppressor.h extra : rebase_source : a2bfc2635d8cb98ee7c93597c6f805122e99111f extra : amend_source : 2d3c11cbc8e07fa90b1960c4e1a4422c12f2761b --- ...pp => PrintPreviewUserEventSuppressor.cpp} | 59 ++++++------------- .../PrintPreviewUserEventSuppressor.h | 53 +++++++++++++++++ layout/printing/moz.build | 2 +- layout/printing/nsPrintData.cpp | 12 ++-- layout/printing/nsPrintData.h | 11 +++- layout/printing/nsPrintJob.cpp | 12 ++-- layout/printing/nsPrintJob.h | 8 ++- layout/printing/nsPrintPreviewListener.h | 51 ---------------- 8 files changed, 97 insertions(+), 111 deletions(-) rename layout/printing/{nsPrintPreviewListener.cpp => PrintPreviewUserEventSuppressor.cpp} (84%) create mode 100644 layout/printing/PrintPreviewUserEventSuppressor.h delete mode 100644 layout/printing/nsPrintPreviewListener.h diff --git a/layout/printing/nsPrintPreviewListener.cpp b/layout/printing/PrintPreviewUserEventSuppressor.cpp similarity index 84% rename from layout/printing/nsPrintPreviewListener.cpp rename to layout/printing/PrintPreviewUserEventSuppressor.cpp index 37d184903f771..60bae773c2b74 100644 --- a/layout/printing/nsPrintPreviewListener.cpp +++ b/layout/printing/PrintPreviewUserEventSuppressor.cpp @@ -4,7 +4,7 @@ * 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/. */ -#include "nsPrintPreviewListener.h" +#include "PrintPreviewUserEventSuppressor.h" #include "mozilla/TextEvents.h" #include "mozilla/dom/Element.h" @@ -17,28 +17,19 @@ #include "nsFocusManager.h" #include "nsLiteralString.h" -using namespace mozilla; using namespace mozilla::dom; -NS_IMPL_ISUPPORTS(nsPrintPreviewListener, nsIDOMEventListener) +namespace mozilla { -// -// nsPrintPreviewListener ctor -// -nsPrintPreviewListener::nsPrintPreviewListener(EventTarget* aTarget) +PrintPreviewUserEventSuppressor::PrintPreviewUserEventSuppressor( + EventTarget* aTarget) : mEventTarget(aTarget) { - NS_ADDREF_THIS(); -} // ctor - -nsPrintPreviewListener::~nsPrintPreviewListener() {} - -//------------------------------------------------------- -// -// AddListeners -// -// Subscribe to the events that will allow us to track various events. -// -nsresult nsPrintPreviewListener::AddListeners() { + AddListeners(); +} + +NS_IMPL_ISUPPORTS(PrintPreviewUserEventSuppressor, nsIDOMEventListener) + +void PrintPreviewUserEventSuppressor::AddListeners() { if (mEventTarget) { mEventTarget->AddEventListener(NS_LITERAL_STRING("click"), this, true); mEventTarget->AddEventListener(NS_LITERAL_STRING("contextmenu"), this, @@ -55,17 +46,9 @@ nsresult nsPrintPreviewListener::AddListeners() { mEventTarget->AddSystemEventListener(NS_LITERAL_STRING("keydown"), this, true); } - - return NS_OK; } -//------------------------------------------------------- -// -// RemoveListeners -// -// Unsubscribe from all the various events that we were listening to. -// -nsresult nsPrintPreviewListener::RemoveListeners() { +void PrintPreviewUserEventSuppressor::RemoveListeners() { if (mEventTarget) { mEventTarget->RemoveEventListener(NS_LITERAL_STRING("click"), this, true); mEventTarget->RemoveEventListener(NS_LITERAL_STRING("contextmenu"), this, @@ -87,16 +70,8 @@ nsresult nsPrintPreviewListener::RemoveListeners() { mEventTarget->RemoveSystemEventListener(NS_LITERAL_STRING("keydown"), this, true); } - - return NS_OK; } -//------------------------------------------------------- -// -// GetActionForEvent -// -// Helper function to let certain key events through -// enum eEventAction { eEventAction_Tab, eEventAction_ShiftTab, @@ -105,6 +80,7 @@ enum eEventAction { eEventAction_StopPropagation }; +// Helper function to let certain key events through static eEventAction GetActionForEvent(Event* aEvent) { WidgetKeyboardEvent* keyEvent = aEvent->WidgetEventPtr()->AsKeyboardEvent(); if (!keyEvent) { @@ -150,11 +126,11 @@ static eEventAction GetActionForEvent(Event* aEvent) { } NS_IMETHODIMP -nsPrintPreviewListener::HandleEvent(Event* aEvent) { +PrintPreviewUserEventSuppressor::HandleEvent(Event* aEvent) { nsCOMPtr content = do_QueryInterface(aEvent ? aEvent->GetOriginalTarget() : nullptr); if (content && !content->IsXULElement()) { - eEventAction action = ::GetActionForEvent(aEvent); + eEventAction action = GetActionForEvent(aEvent); switch (action) { case eEventAction_Tab: case eEventAction_ShiftTab: { @@ -173,10 +149,9 @@ nsPrintPreviewListener::HandleEvent(Event* aEvent) { nsIFocusManager* fm = nsFocusManager::GetFocusManager(); if (fm && win) { - dom::Element* fromElement = - parentDoc->FindContentForSubDocument(doc); + Element* fromElement = parentDoc->FindContentForSubDocument(doc); bool forward = (action == eEventAction_Tab); - RefPtr result; + RefPtr result; fm->MoveFocus(win, fromElement, forward ? nsIFocusManager::MOVEFOCUS_FORWARD : nsIFocusManager::MOVEFOCUS_BACKWARD, @@ -199,3 +174,5 @@ nsPrintPreviewListener::HandleEvent(Event* aEvent) { } return NS_OK; } + +} // namespace mozilla diff --git a/layout/printing/PrintPreviewUserEventSuppressor.h b/layout/printing/PrintPreviewUserEventSuppressor.h new file mode 100644 index 0000000000000..1a4f1649c5791 --- /dev/null +++ b/layout/printing/PrintPreviewUserEventSuppressor.h @@ -0,0 +1,53 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* 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/. */ + +#ifndef mozilla_PrintPreviewUserEventSuppressor_h +#define mozilla_PrintPreviewUserEventSuppressor_h + +#include "nsCOMPtr.h" +#include "nsIDOMEventListener.h" +#include "mozilla/Attributes.h" + +namespace mozilla { + +namespace dom { +class EventTarget; +} // namespace dom + +/** + * A class that filters out certain user events targeted at the given event + * target (a document). Intended for use with the Print Preview document to + * stop users from doing anything that would break printing invariants. (For + * example, blocks opening of the context menu, interaction with form controls, + * content selection, etc.) + */ +class PrintPreviewUserEventSuppressor final : public nsIDOMEventListener { + public: + NS_DECL_ISUPPORTS + NS_DECL_NSIDOMEVENTLISTENER + + explicit PrintPreviewUserEventSuppressor(dom::EventTarget* aTarget); + + /** + * Must be called before releasing this object in order to break the strong + * reference cycle between ourselves and the document we're listening to, + * or else the objects in the cylce will be leaked (since this class does + * not participate in cycle collection). + */ + void StopSuppressing() { RemoveListeners(); } + + private: + ~PrintPreviewUserEventSuppressor() { RemoveListeners(); } + + void AddListeners(); + void RemoveListeners(); + + nsCOMPtr mEventTarget; +}; + +} // namespace mozilla + +#endif // mozilla_PrintPreviewUserEventSuppressor_h diff --git a/layout/printing/moz.build b/layout/printing/moz.build index a63a8a909c6d2..37b859757087b 100644 --- a/layout/printing/moz.build +++ b/layout/printing/moz.build @@ -28,7 +28,7 @@ UNIFIED_SOURCES += [ 'nsPrintData.cpp', 'nsPrintJob.cpp', 'nsPrintObject.cpp', - 'nsPrintPreviewListener.cpp', + 'PrintPreviewUserEventSuppressor.cpp', 'PrintTranslator.cpp', ] diff --git a/layout/printing/nsPrintData.cpp b/layout/printing/nsPrintData.cpp index 012b3be0143ea..e0ac4e9421ab7 100644 --- a/layout/printing/nsPrintData.cpp +++ b/layout/printing/nsPrintData.cpp @@ -10,9 +10,9 @@ #include "nsIServiceManager.h" #include "nsIWidget.h" #include "nsPrintObject.h" -#include "nsPrintPreviewListener.h" #include "nsIWebProgressListener.h" #include "mozilla/Services.h" +#include "PrintPreviewUserEventSuppressor.h" //----------------------------------------------------- // PR LOGGING @@ -38,8 +38,7 @@ nsPrintData::nsPrintData(ePrintDataType aType) mPrintFrameType(nsIPrintSettings::kFramesAsIs), mNumPrintablePages(0), mNumPagesPrinted(0), - mShrinkRatio(1.0), - mPPEventListeners(nullptr) { + mShrinkRatio(1.0) { nsCOMPtr brandBundle; nsCOMPtr svc = mozilla::services::GetStringBundleService(); @@ -57,10 +56,9 @@ nsPrintData::nsPrintData(ePrintDataType aType) } nsPrintData::~nsPrintData() { - // remove the event listeners - if (mPPEventListeners) { - mPPEventListeners->RemoveListeners(); - NS_RELEASE(mPPEventListeners); + if (mPPEventSuppressor) { + mPPEventSuppressor->StopSuppressing(); + mPPEventSuppressor = nullptr; } // Only Send an OnEndPrinting if we have started printing diff --git a/layout/printing/nsPrintData.h b/layout/printing/nsPrintData.h index e8b2a58024402..c3c599e71905b 100644 --- a/layout/printing/nsPrintData.h +++ b/layout/printing/nsPrintData.h @@ -18,11 +18,13 @@ #include "nsTArray.h" #include "nsCOMArray.h" -// Classes class nsPrintObject; -class nsPrintPreviewListener; class nsIWebProgressListener; +namespace mozilla { +class PrintPreviewUserEventSuppressor; +} // namespace mozilla + //------------------------------------------------------------------------ // nsPrintData Class // @@ -38,6 +40,9 @@ class nsIWebProgressListener; // //------------------------------------------------------------------------ class nsPrintData { + typedef mozilla::PrintPreviewUserEventSuppressor + PrintPreviewUserEventSuppressor; + public: typedef enum { eIsPrinting, eIsPrintPreview } ePrintDataType; @@ -82,7 +87,7 @@ class nsPrintData { float mShrinkRatio; nsCOMPtr mPrintSettings; - nsPrintPreviewListener* mPPEventListeners; + RefPtr mPPEventSuppressor; nsString mBrandName; // needed as a substitute name for a document diff --git a/layout/printing/nsPrintJob.cpp b/layout/printing/nsPrintJob.cpp index c0f17f37188c5..32cdc482d58c8 100644 --- a/layout/printing/nsPrintJob.cpp +++ b/layout/printing/nsPrintJob.cpp @@ -38,8 +38,6 @@ static const char sPrintSettingsServiceContractID[] = "@mozilla.org/gfx/printsettings-service;1"; -// Printing Events -#include "nsPrintPreviewListener.h" #include "nsThreadUtils.h" // Printing @@ -116,6 +114,7 @@ static const char kPrintingPromptService[] = #include "mozilla/dom/HTMLFrameElement.h" #include "nsContentList.h" #include "nsIChannel.h" +#include "PrintPreviewUserEventSuppressor.h" #include "xpcpublic.h" #include "nsVariant.h" #include "mozilla/ServoStyleSet.h" @@ -571,8 +570,8 @@ nsresult nsPrintJob::Cancelled() { // some events from being processed while in PrintPreview // // No return code - if this fails, there isn't much we can do -void nsPrintJob::InstallPrintPreviewListener() { - if (!mPrt->mPPEventListeners) { +void nsPrintJob::SuppressPrintPreviewUserEvents() { + if (!mPrt->mPPEventSuppressor) { nsCOMPtr docShell = do_QueryReferent(mContainer); if (!docShell) { return; @@ -580,8 +579,7 @@ void nsPrintJob::InstallPrintPreviewListener() { if (nsPIDOMWindowOuter* win = docShell->GetWindow()) { nsCOMPtr target = win->GetFrameElementInternal(); - mPrt->mPPEventListeners = new nsPrintPreviewListener(target); - mPrt->mPPEventListeners->AddListeners(); + mPrt->mPPEventSuppressor = new PrintPreviewUserEventSuppressor(target); } } } @@ -1007,7 +1005,7 @@ nsresult nsPrintJob::DoCommonPrint(bool aIsPrintPreview, TurnScriptingOn(false); if (!notifyOnInit) { - InstallPrintPreviewListener(); + SuppressPrintPreviewUserEvents(); rv = InitPrintDocConstruction(false); } else { rv = NS_OK; diff --git a/layout/printing/nsPrintJob.h b/layout/printing/nsPrintJob.h index 9f5b3b635d424..c03359b2a7130 100644 --- a/layout/printing/nsPrintJob.h +++ b/layout/printing/nsPrintJob.h @@ -109,7 +109,13 @@ class nsPrintJob final : public nsIObserver, void TurnScriptingOn(bool aDoTurnOn); bool CheckDocumentForPPCaching(); - void InstallPrintPreviewListener(); + + /** + * Filters out certain user events while Print Preview is open to prevent + * the user from interacting with the Print Preview document and breaking + * printing invariants. + */ + void SuppressPrintPreviewUserEvents(); // nsIDocumentViewerPrint Printing Methods bool HasPrintCallbackCanvas(); diff --git a/layout/printing/nsPrintPreviewListener.h b/layout/printing/nsPrintPreviewListener.h deleted file mode 100644 index 1db187d244ecd..0000000000000 --- a/layout/printing/nsPrintPreviewListener.h +++ /dev/null @@ -1,51 +0,0 @@ -/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* vim: set ts=8 sts=2 et sw=2 tw=80: */ -/* 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/. */ - -#ifndef nsPrintPreviewListener_h__ -#define nsPrintPreviewListener_h__ - -// Interfaces needed to be included -#include "nsIDOMEventListener.h" -// Helper Classes -#include "nsCOMPtr.h" -#include "mozilla/Attributes.h" - -namespace mozilla { -namespace dom { -class EventTarget; -} // namespace dom -} // namespace mozilla - -// -// class nsPrintPreviewListener -// -// The class that listens to the chrome events and tells the embedding -// chrome to show context menus, as appropriate. Handles registering itself -// with the DOM with AddChromeListeners() and removing itself with -// RemoveChromeListeners(). -// -class nsPrintPreviewListener final : public nsIDOMEventListener - -{ - public: - NS_DECL_ISUPPORTS - NS_DECL_NSIDOMEVENTLISTENER - - explicit nsPrintPreviewListener(mozilla::dom::EventTarget* aTarget); - - // Add/remove the relevant listeners, based on what interfaces - // the embedding chrome implements. - nsresult AddListeners(); - nsresult RemoveListeners(); - - private: - ~nsPrintPreviewListener(); - - nsCOMPtr mEventTarget; - -}; // class nsPrintPreviewListener - -#endif /* nsPrintPreviewListener_h__ */ From c2a42226a5098f8a66525df0f8dff9a313ff6473 Mon Sep 17 00:00:00 2001 From: Brian Hackett Date: Thu, 16 May 2019 08:09:07 -1000 Subject: [PATCH 05/12] Bug 1392408 Part 5 - Listen for alternate stack traces in StackTraceCollector, r=ochameau. --HG-- extra : rebase_source : 48e4e4f1bd6d63039051e492f87451e689e6a740 --- .../network-monitor/stack-trace-collector.js | 75 +++++++++++++++---- 1 file changed, 60 insertions(+), 15 deletions(-) diff --git a/devtools/server/actors/network-monitor/stack-trace-collector.js b/devtools/server/actors/network-monitor/stack-trace-collector.js index d1e28e9821518..46f59908ce9a2 100644 --- a/devtools/server/actors/network-monitor/stack-trace-collector.js +++ b/devtools/server/actors/network-monitor/stack-trace-collector.js @@ -25,6 +25,7 @@ function StackTraceCollector(filters, netmonitors) { StackTraceCollector.prototype = { init() { Services.obs.addObserver(this, "http-on-opening-request"); + Services.obs.addObserver(this, "network-monitor-alternate-stack"); ChannelEventSinkFactory.getService().registerCollector(this); this.onGetStack = this.onGetStack.bind(this); for (const { messageManager } of this.netmonitors) { @@ -34,6 +35,7 @@ StackTraceCollector.prototype = { destroy() { Services.obs.removeObserver(this, "http-on-opening-request"); + Services.obs.removeObserver(this, "network-monitor-alternate-stack"); ChannelEventSinkFactory.getService().unregisterCollector(this); for (const { messageManager } of this.netmonitors) { messageManager.removeMessageListener("debug:request-stack:request", @@ -42,6 +44,12 @@ StackTraceCollector.prototype = { }, _saveStackTrace(channel, stacktrace) { + if (this.stacktracesById.has(channel.channelId)) { + // We can get up to two stack traces for the same channel: one each from + // the two observer topics we are listening to. Use the first stack trace + // which is specified, and ignore any later one. + return; + } for (const { messageManager } of this.netmonitors) { messageManager.sendAsyncMessage("debug:request-stack-available", { channelId: channel.channelId, @@ -51,29 +59,66 @@ StackTraceCollector.prototype = { this.stacktracesById.set(channel.channelId, stacktrace); }, - observe(subject) { + observe(subject, topic, data) { const channel = subject.QueryInterface(Ci.nsIHttpChannel); if (!matchRequest(channel, this.filters)) { return; } - // Convert the nsIStackFrame XPCOM objects to a nice JSON that can be - // passed around through message managers etc. - let frame = components.stack; const stacktrace = []; - if (frame && frame.caller) { - frame = frame.caller; - while (frame) { - stacktrace.push({ - filename: frame.filename, - lineNumber: frame.lineNumber, - columnNumber: frame.columnNumber, - functionName: frame.name, - asyncCause: frame.asyncCause, - }); - frame = frame.caller || frame.asyncCaller; + switch (topic) { + case "http-on-opening-request": { + // The channel is being opened on the main thread, associate the current + // stack with it. + // + // Convert the nsIStackFrame XPCOM objects to a nice JSON that can be + // passed around through message managers etc. + let frame = components.stack; + if (frame && frame.caller) { + frame = frame.caller; + while (frame) { + stacktrace.push({ + filename: frame.filename, + lineNumber: frame.lineNumber, + columnNumber: frame.columnNumber, + functionName: frame.name, + asyncCause: frame.asyncCause, + }); + frame = frame.caller || frame.asyncCaller; + } + } + break; + } + case "network-monitor-alternate-stack": { + // An alternate stack trace is being specified for this channel. + // The topic data is the JSON for the saved frame stack we should use, + // so convert this into the expected format. + // + // This topic is used in the following cases: + // + // - The HTTP channel is opened asynchronously or on a different thread + // from the code which triggered its creation, in which case the stack + // from components.stack will be empty. The alternate stack will be + // for the point we want to associate with the channel. + // + // - The channel is not a nsIHttpChannel, and we will receive no + // opening request notification for it. + let frame = JSON.parse(data); + while (frame) { + stacktrace.push({ + filename: frame.source, + lineNumber: frame.line, + columnNumber: frame.column, + functionName: frame.functionDisplayName, + asyncCause: frame.asyncCause, + }); + frame = frame.parent || frame.asyncParent; + } + break; } + default: + throw new Error("Unexpected observe() topic"); } this._saveStackTrace(channel, stacktrace); From 0f76b353755275c6480b21e48c28c0ef0e610ce7 Mon Sep 17 00:00:00 2001 From: Brian Hackett Date: Thu, 16 May 2019 08:09:31 -1000 Subject: [PATCH 06/12] Bug 1392408 Part 6 - Add test for capturing worker stacks in net monitor, r=ochameau. --HG-- extra : rebase_source : 1188ad754fb69e289fcb0fd29d91ad51e4a892b3 --- devtools/client/netmonitor/test/browser.ini | 4 + .../netmonitor/test/browser_net_cause.js | 40 +------ .../test/browser_net_worker_stacks.js | 100 ++++++++++++++++++ devtools/client/netmonitor/test/head.js | 47 ++++++++ .../test/html_worker-test-page.html | 13 +++ .../client/netmonitor/test/js_worker-test.js | 24 +++++ .../client/netmonitor/test/js_worker-test2.js | 3 + 7 files changed, 192 insertions(+), 39 deletions(-) create mode 100644 devtools/client/netmonitor/test/browser_net_worker_stacks.js create mode 100644 devtools/client/netmonitor/test/html_worker-test-page.html create mode 100644 devtools/client/netmonitor/test/js_worker-test.js create mode 100644 devtools/client/netmonitor/test/js_worker-test2.js diff --git a/devtools/client/netmonitor/test/browser.ini b/devtools/client/netmonitor/test/browser.ini index 369ca0317aa3c..bf0b1cbf36e11 100644 --- a/devtools/client/netmonitor/test/browser.ini +++ b/devtools/client/netmonitor/test/browser.ini @@ -44,6 +44,9 @@ support-files = html_copy-as-curl.html html_curl-utils.html html_open-request-in-tab.html + html_worker-test-page.html + js_worker-test.js + js_worker-test2.js sjs_content-type-test-server.sjs sjs_cors-test-server.sjs sjs_https-redirect-test-server.sjs @@ -221,3 +224,4 @@ skip-if = true # TODO: fix the test [browser_net_truncate.js] [browser_net_view-source-debugger.js] [browser_net_waterfall-click.js] +[browser_net_worker_stacks.js] diff --git a/devtools/client/netmonitor/test/browser_net_cause.js b/devtools/client/netmonitor/test/browser_net_cause.js index bcb66cadffe00..dee628e7b87c7 100644 --- a/devtools/client/netmonitor/test/browser_net_cause.js +++ b/devtools/client/netmonitor/test/browser_net_cause.js @@ -93,7 +93,6 @@ add_task(async function() { const { document, store, windowRequire, connector } = monitor.panelWin; const Actions = windowRequire("devtools/client/netmonitor/src/actions/index"); const { - getDisplayedRequests, getSortedRequests, } = windowRequire("devtools/client/netmonitor/src/selectors/index"); @@ -110,44 +109,7 @@ add_task(async function() { is(store.getState().requests.requests.size, EXPECTED_REQUESTS.length, "All the page events should be recorded."); - EXPECTED_REQUESTS.forEach((spec, i) => { - const { method, url, causeType, causeUri, stack } = spec; - - const requestItem = getSortedRequests(store.getState()).get(i); - verifyRequestItemTarget( - document, - getDisplayedRequests(store.getState()), - requestItem, - method, - url, - { cause: { type: causeType, loadingDocumentUri: causeUri } } - ); - - const stacktrace = requestItem.stacktrace; - const stackLen = stacktrace ? stacktrace.length : 0; - - if (stack) { - ok(stacktrace, `Request #${i} has a stacktrace`); - ok(stackLen > 0, - `Request #${i} (${causeType}) has a stacktrace with ${stackLen} items`); - - // if "stack" is array, check the details about the top stack frames - if (Array.isArray(stack)) { - stack.forEach((frame, j) => { - is(stacktrace[j].functionName, frame.fn, - `Request #${i} has the correct function on JS stack frame #${j}`); - is(stacktrace[j].filename.split("/").pop(), frame.file, - `Request #${i} has the correct file on JS stack frame #${j}`); - is(stacktrace[j].lineNumber, frame.line, - `Request #${i} has the correct line number on JS stack frame #${j}`); - is(stacktrace[j].asyncCause, frame.asyncCause, - `Request #${i} has the correct async cause on JS stack frame #${j}`); - }); - } - } else { - is(stackLen, 0, `Request #${i} (${causeType}) has an empty stacktrace`); - } - }); + validateRequests(EXPECTED_REQUESTS, monitor); // Sort the requests by cause and check the order EventUtils.sendMouseEvent({ type: "click" }, diff --git a/devtools/client/netmonitor/test/browser_net_worker_stacks.js b/devtools/client/netmonitor/test/browser_net_worker_stacks.js new file mode 100644 index 0000000000000..238d20628e22c --- /dev/null +++ b/devtools/client/netmonitor/test/browser_net_worker_stacks.js @@ -0,0 +1,100 @@ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +// Test that we get stack traces for the network requests made when starting or +// running worker threads. + +const TOP_FILE_NAME = "html_worker-test-page.html"; +const TOP_URL = EXAMPLE_URL + TOP_FILE_NAME; +const WORKER_FILE_NAME = "js_worker-test.js"; +const WORKER_URL = EXAMPLE_URL + WORKER_FILE_NAME; + +const EXPECTED_REQUESTS = [ + { + method: "GET", + url: TOP_URL, + causeType: "document", + causeUri: null, + stack: true, + }, + { + method: "GET", + url: WORKER_URL, + causeType: "script", + causeUri: TOP_URL, + stack: [ + { fn: "startWorkerInner", file: TOP_FILE_NAME, line: 11 }, + { fn: "startWorker", file: TOP_FILE_NAME, line: 8 }, + { file: TOP_FILE_NAME, line: 4 }, + ], + }, + { + method: "GET", + url: EXAMPLE_URL + "missing1.js", + causeType: "script", + causeUri: TOP_URL, + stack: [ + { fn: "importScriptsFromWorker", file: WORKER_FILE_NAME, line: 14 }, + { file: WORKER_FILE_NAME, line: 10 }, + ], + }, + { + method: "GET", + url: EXAMPLE_URL + "missing2.js", + causeType: "script", + causeUri: TOP_URL, + stack: [ + { fn: "importScriptsFromWorker", file: WORKER_FILE_NAME, line: 14 }, + { file: WORKER_FILE_NAME, line: 10 }, + ], + }, + { + method: "GET", + url: EXAMPLE_URL + "js_worker-test2.js", + causeType: "script", + causeUri: TOP_URL, + stack: [ + { fn: "startWorkerFromWorker", file: WORKER_FILE_NAME, line: 7 }, + { file: WORKER_FILE_NAME, line: 3 }, + ], + }, + { + method: "GET", + url: EXAMPLE_URL + "missing.json", + causeType: "xhr", + causeUri: TOP_URL, + stack: [ + { fn: "createJSONRequest", file: WORKER_FILE_NAME, line: 22 }, + { file: WORKER_FILE_NAME, line: 18 }, + ], + }, +]; + +add_task(async function() { + // Load a different URL first to instantiate the network monitor before we + // load the page we're really interested in. + const { tab, monitor } = await initNetMonitor(SIMPLE_URL); + + const { store, windowRequire, connector } = monitor.panelWin; + const { + getSortedRequests, + } = windowRequire("devtools/client/netmonitor/src/selectors/index"); + + BrowserTestUtils.loadURI(tab.linkedBrowser, TOP_URL); + + await waitForNetworkEvents(monitor, EXPECTED_REQUESTS.length); + + is(store.getState().requests.requests.size, EXPECTED_REQUESTS.length, + "All the page events should be recorded."); + + // Wait for stack traces from all requests. + const requests = getSortedRequests(store.getState()); + await Promise.all(requests.map(requestItem => + connector.requestData(requestItem.id, "stackTrace"))); + + validateRequests(EXPECTED_REQUESTS, monitor); + + await teardown(monitor); +}); diff --git a/devtools/client/netmonitor/test/head.js b/devtools/client/netmonitor/test/head.js index 29201c1c1130c..ca788ad425e81 100644 --- a/devtools/client/netmonitor/test/head.js +++ b/devtools/client/netmonitor/test/head.js @@ -869,6 +869,53 @@ function queryTelemetryEvents(query) { return filtersChangedEvents.map(event => event[5]); } +function validateRequests(requests, monitor) { + const { document, store, windowRequire } = monitor.panelWin; + + const { + getDisplayedRequests, + } = windowRequire("devtools/client/netmonitor/src/selectors/index"); + + requests.forEach((spec, i) => { + const { method, url, causeType, causeUri, stack } = spec; + + const requestItem = getSortedRequests(store.getState()).get(i); + verifyRequestItemTarget( + document, + getDisplayedRequests(store.getState()), + requestItem, + method, + url, + { cause: { type: causeType, loadingDocumentUri: causeUri } } + ); + + const stacktrace = requestItem.stacktrace; + const stackLen = stacktrace ? stacktrace.length : 0; + + if (stack) { + ok(stacktrace, `Request #${i} has a stacktrace`); + ok(stackLen > 0, + `Request #${i} (${causeType}) has a stacktrace with ${stackLen} items`); + + // if "stack" is array, check the details about the top stack frames + if (Array.isArray(stack)) { + stack.forEach((frame, j) => { + is(stacktrace[j].functionName, frame.fn, + `Request #${i} has the correct function on JS stack frame #${j}`); + is(stacktrace[j].filename.split("/").pop(), frame.file, + `Request #${i} has the correct file on JS stack frame #${j}`); + is(stacktrace[j].lineNumber, frame.line, + `Request #${i} has the correct line number on JS stack frame #${j}`); + is(stacktrace[j].asyncCause, frame.asyncCause, + `Request #${i} has the correct async cause on JS stack frame #${j}`); + }); + } + } else { + is(stackLen, 0, `Request #${i} (${causeType}) has an empty stacktrace`); + } + }); +} + /** * Retrieve the context menu element corresponding to the provided id, for the provided * netmonitor instance. diff --git a/devtools/client/netmonitor/test/html_worker-test-page.html b/devtools/client/netmonitor/test/html_worker-test-page.html new file mode 100644 index 0000000000000..46f64368a194f --- /dev/null +++ b/devtools/client/netmonitor/test/html_worker-test-page.html @@ -0,0 +1,13 @@ + diff --git a/devtools/client/netmonitor/test/js_worker-test.js b/devtools/client/netmonitor/test/js_worker-test.js new file mode 100644 index 0000000000000..cf48ac6f9437e --- /dev/null +++ b/devtools/client/netmonitor/test/js_worker-test.js @@ -0,0 +1,24 @@ +/* eslint-disable no-unused-vars, no-undef */ +"use strict"; +startWorkerFromWorker(); + +var w; +function startWorkerFromWorker() { + w = new Worker("js_worker-test2.js"); +} + +importScriptsFromWorker(); + +function importScriptsFromWorker() { + try { + importScripts("missing1.js", "missing2.js"); + } catch (e) {} +} + +createJSONRequest(); + +function createJSONRequest() { + const request = new XMLHttpRequest(); + request.open("GET", "missing.json", true); + request.send(null); +} diff --git a/devtools/client/netmonitor/test/js_worker-test2.js b/devtools/client/netmonitor/test/js_worker-test2.js new file mode 100644 index 0000000000000..9ee307f2ec9ab --- /dev/null +++ b/devtools/client/netmonitor/test/js_worker-test2.js @@ -0,0 +1,3 @@ +"use strict"; + +console.log("I AM A WORKER"); From 2e4c92b01c8254eeb9294a8637342e01202ee010 Mon Sep 17 00:00:00 2001 From: Brian Hackett Date: Fri, 19 Apr 2019 07:37:08 -1000 Subject: [PATCH 07/12] Bug 1392411 Part 1 - Report stacks to net monitor when creating web sockets, r=bzbarsky. --HG-- extra : rebase_source : b6327141882dbb2625de0d4ab564ad793c030382 --- dom/websocket/WebSocket.cpp | 28 +++++++++++++++++++++------- 1 file changed, 21 insertions(+), 7 deletions(-) diff --git a/dom/websocket/WebSocket.cpp b/dom/websocket/WebSocket.cpp index 5f4083fa6f7f2..a512f5edfe5bc 100644 --- a/dom/websocket/WebSocket.cpp +++ b/dom/websocket/WebSocket.cpp @@ -18,6 +18,7 @@ #include "mozilla/dom/nsCSPContext.h" #include "mozilla/dom/nsCSPUtils.h" #include "mozilla/dom/ScriptSettings.h" +#include "mozilla/dom/SerializedStackHolder.h" #include "mozilla/dom/WorkerPrivate.h" #include "mozilla/dom/WorkerRef.h" #include "mozilla/dom/WorkerRunnable.h" @@ -124,7 +125,8 @@ class WebSocketImpl final : public nsIInterfaceRequestor, nsresult AsyncOpen(nsIPrincipal* aPrincipal, uint64_t aInnerWindowID, nsITransportProvider* aTransportProvider, - const nsACString& aNegotiatedExtensions); + const nsACString& aNegotiatedExtensions, + UniquePtr aOriginStack); nsresult ParseURL(const nsAString& aURL); nsresult InitializeConnection(nsIPrincipal* aPrincipal, @@ -1119,11 +1121,13 @@ class ConnectRunnable final : public WebSocketMainThreadRunnable { class AsyncOpenRunnable final : public WebSocketMainThreadRunnable { public: - explicit AsyncOpenRunnable(WebSocketImpl* aImpl) + explicit AsyncOpenRunnable(WebSocketImpl* aImpl, + UniquePtr aOriginStack) : WebSocketMainThreadRunnable( aImpl->mWorkerRef->Private(), NS_LITERAL_CSTRING("WebSocket :: AsyncOpen")), mImpl(aImpl), + mOriginStack(std::move(aOriginStack)), mErrorCode(NS_OK) { MOZ_ASSERT(mWorkerPrivate); mWorkerPrivate->AssertIsOnWorkerThread(); @@ -1159,7 +1163,8 @@ class AsyncOpenRunnable final : public WebSocketMainThreadRunnable { windowID = topInner->WindowID(); } - mErrorCode = mImpl->AsyncOpen(principal, windowID, nullptr, EmptyCString()); + mErrorCode = mImpl->AsyncOpen(principal, windowID, nullptr, EmptyCString(), + std::move(mOriginStack)); return true; } @@ -1168,7 +1173,7 @@ class AsyncOpenRunnable final : public WebSocketMainThreadRunnable { MOZ_ASSERT(aTopLevelWorkerPrivate && !aTopLevelWorkerPrivate->GetWindow()); mErrorCode = mImpl->AsyncOpen(aTopLevelWorkerPrivate->GetPrincipal(), 0, - nullptr, EmptyCString()); + nullptr, EmptyCString(), nullptr); return true; } @@ -1176,6 +1181,8 @@ class AsyncOpenRunnable final : public WebSocketMainThreadRunnable { // Raw pointer. This worker runs synchronously. WebSocketImpl* mImpl; + UniquePtr mOriginStack; + nsresult mErrorCode; }; @@ -1355,6 +1362,9 @@ already_AddRefed WebSocket::ConstructorCommon( return nullptr; } + UniquePtr stack = + GetCurrentStackForNetMonitor(aGlobal.Context()); + if (NS_IsMainThread()) { MOZ_ASSERT(principal); @@ -1373,12 +1383,13 @@ already_AddRefed WebSocket::ConstructorCommon( } aRv = webSocket->mImpl->AsyncOpen(principal, windowID, aTransportProvider, - aNegotiatedExtensions); + aNegotiatedExtensions, std::move(stack)); } else { MOZ_ASSERT(!aTransportProvider && aNegotiatedExtensions.IsEmpty(), "not yet implemented"); + RefPtr runnable = - new AsyncOpenRunnable(webSocket->mImpl); + new AsyncOpenRunnable(webSocket->mImpl, std::move(stack)); runnable->Dispatch(Canceling, aRv); if (NS_WARN_IF(aRv.Failed())) { return nullptr; @@ -1632,7 +1643,8 @@ nsresult WebSocketImpl::Init(JSContext* aCx, nsIPrincipal* aLoadingPrincipal, nsresult WebSocketImpl::AsyncOpen(nsIPrincipal* aPrincipal, uint64_t aInnerWindowID, nsITransportProvider* aTransportProvider, - const nsACString& aNegotiatedExtensions) { + const nsACString& aNegotiatedExtensions, + UniquePtr aOriginStack) { MOZ_ASSERT(NS_IsMainThread(), "Not running on main thread"); MOZ_ASSERT_IF(!aTransportProvider, aNegotiatedExtensions.IsEmpty()); @@ -1659,6 +1671,8 @@ nsresult WebSocketImpl::AsyncOpen(nsIPrincipal* aPrincipal, return NS_ERROR_CONTENT_BLOCKED; } + NotifyNetworkMonitorAlternateStack(mChannel, std::move(aOriginStack)); + mInnerWindowID = aInnerWindowID; return NS_OK; From db5154104df90a20ceacf00b5f33366e050732d9 Mon Sep 17 00:00:00 2001 From: Brian Hackett Date: Fri, 19 Apr 2019 07:42:58 -1000 Subject: [PATCH 08/12] Bug 1392411 Part 2 - Report stacks for websocket construction in net monitor, r=ochameau. Differential Revision: https://phabricator.services.mozilla.com/D28229 --HG-- extra : rebase_source : 8335b8d0cfb2e96b88439b241016788deb6fab87 --- devtools/server/actors/network-event.js | 12 +++++++-- devtools/server/actors/network-monitor.js | 17 +++++++++--- .../network-monitor/stack-trace-collector.js | 26 ++++++++++++++----- 3 files changed, 43 insertions(+), 12 deletions(-) diff --git a/devtools/server/actors/network-event.js b/devtools/server/actors/network-event.js index cb722ca1f712a..6790b69dfba1b 100644 --- a/devtools/server/actors/network-event.js +++ b/devtools/server/actors/network-event.js @@ -262,18 +262,26 @@ const NetworkEventActor = protocol.ActorClassWithSpec(networkEventSpec, { // and the stack is available from the content process. // Fetch it lazily from here via the message manager. if (stacktrace && typeof stacktrace == "boolean") { + let id; + if (this._cause.type == "websocket") { + // Convert to a websocket URL, as in onNetworkEvent. + id = this._request.url.replace(/^http/, "ws"); + } else { + id = this._channelId; + } + const messageManager = this.netMonitorActor.messageManager; stacktrace = await new Promise(resolve => { const onMessage = ({ data }) => { const { channelId, stack } = data; - if (channelId == this._channelId) { + if (channelId == id) { messageManager.removeMessageListener("debug:request-stack:response", onMessage); resolve(stack); } }; messageManager.addMessageListener("debug:request-stack:response", onMessage); - messageManager.sendAsyncMessage("debug:request-stack:request", this._channelId); + messageManager.sendAsyncMessage("debug:request-stack:request", id); }); this._stackTrace = stacktrace; } diff --git a/devtools/server/actors/network-monitor.js b/devtools/server/actors/network-monitor.js index 4bfd5519297a1..a30aaa64e0344 100644 --- a/devtools/server/actors/network-monitor.js +++ b/devtools/server/actors/network-monitor.js @@ -216,14 +216,25 @@ const NetworkMonitorActor = ActorClassWithSpec(networkMonitorSpec, { // This method is called by NetworkMonitor instance when a new request is fired onNetworkEvent(event) { - const { channelId } = event; + const { channelId, cause, url } = event; const actor = this.getNetworkEventActor(channelId); this._netEvents.set(channelId, actor); - event.cause.stacktrace = this.stackTraces.has(channelId); + // Find the ID which the stack trace collector will use to save this + // channel's stack trace. + let id; + if (cause.type == "websocket") { + // Use the URL, but convert from the http URL which this channel uses to + // the original websocket URL which triggered this channel's construction. + id = url.replace(/^http/, "ws"); + } else { + id = channelId; + } + + event.cause.stacktrace = this.stackTraces.has(id); if (event.cause.stacktrace) { - this.stackTraces.delete(channelId); + this.stackTraces.delete(id); } actor.init(event); diff --git a/devtools/server/actors/network-monitor/stack-trace-collector.js b/devtools/server/actors/network-monitor/stack-trace-collector.js index 46f59908ce9a2..38c78e9efff62 100644 --- a/devtools/server/actors/network-monitor/stack-trace-collector.js +++ b/devtools/server/actors/network-monitor/stack-trace-collector.js @@ -43,8 +43,8 @@ StackTraceCollector.prototype = { } }, - _saveStackTrace(channel, stacktrace) { - if (this.stacktracesById.has(channel.channelId)) { + _saveStackTrace(id, stacktrace) { + if (this.stacktracesById.has(id)) { // We can get up to two stack traces for the same channel: one each from // the two observer topics we are listening to. Use the first stack trace // which is specified, and ignore any later one. @@ -52,15 +52,27 @@ StackTraceCollector.prototype = { } for (const { messageManager } of this.netmonitors) { messageManager.sendAsyncMessage("debug:request-stack-available", { - channelId: channel.channelId, + channelId: id, stacktrace: stacktrace && stacktrace.length > 0, }); } - this.stacktracesById.set(channel.channelId, stacktrace); + this.stacktracesById.set(id, stacktrace); }, observe(subject, topic, data) { - const channel = subject.QueryInterface(Ci.nsIHttpChannel); + let channel, id; + try { + channel = subject.QueryInterface(Ci.nsIHttpChannel); + id = channel.channelId; + } catch (e) { + // WebSocketChannels do not have IDs, so use the URL. When a WebSocket is + // opened in a content process, a channel is created locally but the HTTP + // channel for the connection lives entirely in the parent process. When + // the server code running in the parent sees that HTTP channel, it will + // look for the creation stack using the websocket's URL. + channel = subject.QueryInterface(Ci.nsIWebSocketChannel); + id = channel.URI.spec; + } if (!matchRequest(channel, this.filters)) { return; @@ -121,7 +133,7 @@ StackTraceCollector.prototype = { throw new Error("Unexpected observe() topic"); } - this._saveStackTrace(channel, stacktrace); + this._saveStackTrace(id, stacktrace); }, // eslint-disable-next-line no-shadow @@ -137,7 +149,7 @@ StackTraceCollector.prototype = { const oldId = oldChannel.channelId; const stacktrace = this.stacktracesById.get(oldId); if (stacktrace) { - this._saveStackTrace(newChannel, stacktrace); + this._saveStackTrace(newChannel.channelId, stacktrace); } }, From 2deee5ecd6b9cc7766b83bab42f6aa1b184bd8fa Mon Sep 17 00:00:00 2001 From: Brian Hackett Date: Fri, 19 Apr 2019 07:50:02 -1000 Subject: [PATCH 09/12] Bug 1392411 Part 3 - Add test for capturing websocket stacks in net monitor, r=ochameau. Differential Revision: https://phabricator.services.mozilla.com/D28231 --HG-- extra : rebase_source : f691b2cf878069795089aa387ae7ef85ba499c68 --- devtools/client/netmonitor/test/browser.ini | 3 + .../test/browser_net_websocket_stacks.js | 75 +++++++++++++++++++ .../test/html_websocket-test-page.html | 10 +++ .../test/js_websocket-worker-test.js | 6 ++ 4 files changed, 94 insertions(+) create mode 100644 devtools/client/netmonitor/test/browser_net_websocket_stacks.js create mode 100644 devtools/client/netmonitor/test/html_websocket-test-page.html create mode 100644 devtools/client/netmonitor/test/js_websocket-worker-test.js diff --git a/devtools/client/netmonitor/test/browser.ini b/devtools/client/netmonitor/test/browser.ini index bf0b1cbf36e11..e6dc25d5595d2 100644 --- a/devtools/client/netmonitor/test/browser.ini +++ b/devtools/client/netmonitor/test/browser.ini @@ -45,8 +45,10 @@ support-files = html_curl-utils.html html_open-request-in-tab.html html_worker-test-page.html + html_websocket-test-page.html js_worker-test.js js_worker-test2.js + js_websocket-worker-test.js sjs_content-type-test-server.sjs sjs_cors-test-server.sjs sjs_https-redirect-test-server.sjs @@ -224,4 +226,5 @@ skip-if = true # TODO: fix the test [browser_net_truncate.js] [browser_net_view-source-debugger.js] [browser_net_waterfall-click.js] +[browser_net_websocket_stacks.js] [browser_net_worker_stacks.js] diff --git a/devtools/client/netmonitor/test/browser_net_websocket_stacks.js b/devtools/client/netmonitor/test/browser_net_websocket_stacks.js new file mode 100644 index 0000000000000..0a89d137bf9aa --- /dev/null +++ b/devtools/client/netmonitor/test/browser_net_websocket_stacks.js @@ -0,0 +1,75 @@ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +// Test that we get stack traces for the network requests made when creating +// web sockets on the main or worker threads. + +const TOP_FILE_NAME = "html_websocket-test-page.html"; +const TOP_URL = EXAMPLE_URL + TOP_FILE_NAME; +const WORKER_FILE_NAME = "js_websocket-worker-test.js"; + +const EXPECTED_REQUESTS = [ + { + method: "GET", + url: TOP_URL, + causeType: "document", + causeUri: null, + stack: true, + }, + { + method: "GET", + url: "http://localhost:8080/", + causeType: "websocket", + causeUri: TOP_URL, + stack: [ + { fn: "openSocket", file: TOP_FILE_NAME, line: 6 }, + { file: TOP_FILE_NAME, line: 3 }, + ], + }, + { + method: "GET", + url: EXAMPLE_URL + WORKER_FILE_NAME, + causeType: "script", + causeUri: TOP_URL, + stack: [ { file: TOP_FILE_NAME, line: 9 } ], + }, + { + method: "GET", + url: "https://localhost:8081/", + causeType: "websocket", + causeUri: TOP_URL, + stack: [ + { fn: "openWorkerSocket", file: WORKER_FILE_NAME, line: 5 }, + { file: WORKER_FILE_NAME, line: 2 }, + ], + }, +]; + +add_task(async function() { + // Load a different URL first to instantiate the network monitor before we + // load the page we're really interested in. + const { tab, monitor } = await initNetMonitor(SIMPLE_URL); + + const { store, windowRequire, connector } = monitor.panelWin; + const { + getSortedRequests, + } = windowRequire("devtools/client/netmonitor/src/selectors/index"); + + BrowserTestUtils.loadURI(tab.linkedBrowser, TOP_URL); + + await waitForNetworkEvents(monitor, EXPECTED_REQUESTS.length); + + is(store.getState().requests.requests.size, EXPECTED_REQUESTS.length, + "All the page events should be recorded."); + + // Wait for stack traces from all requests. + const requests = getSortedRequests(store.getState()); + await Promise.all(requests.map(requestItem => + connector.requestData(requestItem.id, "stackTrace"))); + + validateRequests(EXPECTED_REQUESTS, monitor); + + await teardown(monitor); +}); diff --git a/devtools/client/netmonitor/test/html_websocket-test-page.html b/devtools/client/netmonitor/test/html_websocket-test-page.html new file mode 100644 index 0000000000000..58a62fecef0df --- /dev/null +++ b/devtools/client/netmonitor/test/html_websocket-test-page.html @@ -0,0 +1,10 @@ + diff --git a/devtools/client/netmonitor/test/js_websocket-worker-test.js b/devtools/client/netmonitor/test/js_websocket-worker-test.js new file mode 100644 index 0000000000000..ba23d3f6206ce --- /dev/null +++ b/devtools/client/netmonitor/test/js_websocket-worker-test.js @@ -0,0 +1,6 @@ +"use strict"; +openWorkerSocket(); + +function openWorkerSocket() { + this.ws = new WebSocket("wss://localhost:8081"); +} From 3e97865772440ef7bbf4387f0494d1230ffe2f86 Mon Sep 17 00:00:00 2001 From: Brian Hackett Date: Wed, 8 May 2019 09:31:19 -1000 Subject: [PATCH 10/12] Bug 1546736 Part 4 - Only capture web socket stacks for net monitor when the docshell/worker is being watched by the devtools, r=bzbarsky. --HG-- extra : rebase_source : fa609af6c28fbfea92d7e4acaa794af87bc04f5d --- dom/websocket/WebSocket.cpp | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/dom/websocket/WebSocket.cpp b/dom/websocket/WebSocket.cpp index a512f5edfe5bc..12360f0afc46a 100644 --- a/dom/websocket/WebSocket.cpp +++ b/dom/websocket/WebSocket.cpp @@ -1362,15 +1362,18 @@ already_AddRefed WebSocket::ConstructorCommon( return nullptr; } - UniquePtr stack = - GetCurrentStackForNetMonitor(aGlobal.Context()); - if (NS_IsMainThread()) { MOZ_ASSERT(principal); nsCOMPtr ownerWindow = do_QueryInterface(global); nsPIDOMWindowOuter* outerWindow = ownerWindow->GetOuterWindow(); + UniquePtr stack; + nsIDocShell* docShell = outerWindow->GetDocShell(); + if (docShell && docShell->GetWatchedByDevtools()) { + stack = GetCurrentStackForNetMonitor(aGlobal.Context()); + } + uint64_t windowID = 0; nsCOMPtr topWindow = outerWindow->GetScriptableTop(); nsCOMPtr topInner; @@ -1388,6 +1391,12 @@ already_AddRefed WebSocket::ConstructorCommon( MOZ_ASSERT(!aTransportProvider && aNegotiatedExtensions.IsEmpty(), "not yet implemented"); + UniquePtr stack; + WorkerPrivate* workerPrivate = GetCurrentThreadWorkerPrivate(); + if (workerPrivate->IsWatchedByDevtools()) { + stack = GetCurrentStackForNetMonitor(aGlobal.Context()); + } + RefPtr runnable = new AsyncOpenRunnable(webSocket->mImpl, std::move(stack)); runnable->Dispatch(Canceling, aRv); From 68a6d3ccaa2a3302c9826791c61e749edfc33ad2 Mon Sep 17 00:00:00 2001 From: Csoregi Natalia Date: Fri, 17 May 2019 04:27:56 +0300 Subject: [PATCH 11/12] Backed out 4 changesets (bug 1392411, bug 1546736) for failures on /browser_net_websocket_stacks.js. CLOSED TREE Backed out changeset c37ca68a24e5 (bug 1546736) Backed out changeset 1c23ba0f835f (bug 1392411) Backed out changeset fce11a50c058 (bug 1392411) Backed out changeset 2e2f3fc37e2e (bug 1392411) --- devtools/client/netmonitor/test/browser.ini | 3 - .../test/browser_net_websocket_stacks.js | 75 ------------------- .../test/html_websocket-test-page.html | 10 --- .../test/js_websocket-worker-test.js | 6 -- devtools/server/actors/network-event.js | 12 +-- devtools/server/actors/network-monitor.js | 17 +---- .../network-monitor/stack-trace-collector.js | 26 ++----- dom/websocket/WebSocket.cpp | 37 ++------- 8 files changed, 19 insertions(+), 167 deletions(-) delete mode 100644 devtools/client/netmonitor/test/browser_net_websocket_stacks.js delete mode 100644 devtools/client/netmonitor/test/html_websocket-test-page.html delete mode 100644 devtools/client/netmonitor/test/js_websocket-worker-test.js diff --git a/devtools/client/netmonitor/test/browser.ini b/devtools/client/netmonitor/test/browser.ini index e6dc25d5595d2..bf0b1cbf36e11 100644 --- a/devtools/client/netmonitor/test/browser.ini +++ b/devtools/client/netmonitor/test/browser.ini @@ -45,10 +45,8 @@ support-files = html_curl-utils.html html_open-request-in-tab.html html_worker-test-page.html - html_websocket-test-page.html js_worker-test.js js_worker-test2.js - js_websocket-worker-test.js sjs_content-type-test-server.sjs sjs_cors-test-server.sjs sjs_https-redirect-test-server.sjs @@ -226,5 +224,4 @@ skip-if = true # TODO: fix the test [browser_net_truncate.js] [browser_net_view-source-debugger.js] [browser_net_waterfall-click.js] -[browser_net_websocket_stacks.js] [browser_net_worker_stacks.js] diff --git a/devtools/client/netmonitor/test/browser_net_websocket_stacks.js b/devtools/client/netmonitor/test/browser_net_websocket_stacks.js deleted file mode 100644 index 0a89d137bf9aa..0000000000000 --- a/devtools/client/netmonitor/test/browser_net_websocket_stacks.js +++ /dev/null @@ -1,75 +0,0 @@ -/* Any copyright is dedicated to the Public Domain. - http://creativecommons.org/publicdomain/zero/1.0/ */ - -"use strict"; - -// Test that we get stack traces for the network requests made when creating -// web sockets on the main or worker threads. - -const TOP_FILE_NAME = "html_websocket-test-page.html"; -const TOP_URL = EXAMPLE_URL + TOP_FILE_NAME; -const WORKER_FILE_NAME = "js_websocket-worker-test.js"; - -const EXPECTED_REQUESTS = [ - { - method: "GET", - url: TOP_URL, - causeType: "document", - causeUri: null, - stack: true, - }, - { - method: "GET", - url: "http://localhost:8080/", - causeType: "websocket", - causeUri: TOP_URL, - stack: [ - { fn: "openSocket", file: TOP_FILE_NAME, line: 6 }, - { file: TOP_FILE_NAME, line: 3 }, - ], - }, - { - method: "GET", - url: EXAMPLE_URL + WORKER_FILE_NAME, - causeType: "script", - causeUri: TOP_URL, - stack: [ { file: TOP_FILE_NAME, line: 9 } ], - }, - { - method: "GET", - url: "https://localhost:8081/", - causeType: "websocket", - causeUri: TOP_URL, - stack: [ - { fn: "openWorkerSocket", file: WORKER_FILE_NAME, line: 5 }, - { file: WORKER_FILE_NAME, line: 2 }, - ], - }, -]; - -add_task(async function() { - // Load a different URL first to instantiate the network monitor before we - // load the page we're really interested in. - const { tab, monitor } = await initNetMonitor(SIMPLE_URL); - - const { store, windowRequire, connector } = monitor.panelWin; - const { - getSortedRequests, - } = windowRequire("devtools/client/netmonitor/src/selectors/index"); - - BrowserTestUtils.loadURI(tab.linkedBrowser, TOP_URL); - - await waitForNetworkEvents(monitor, EXPECTED_REQUESTS.length); - - is(store.getState().requests.requests.size, EXPECTED_REQUESTS.length, - "All the page events should be recorded."); - - // Wait for stack traces from all requests. - const requests = getSortedRequests(store.getState()); - await Promise.all(requests.map(requestItem => - connector.requestData(requestItem.id, "stackTrace"))); - - validateRequests(EXPECTED_REQUESTS, monitor); - - await teardown(monitor); -}); diff --git a/devtools/client/netmonitor/test/html_websocket-test-page.html b/devtools/client/netmonitor/test/html_websocket-test-page.html deleted file mode 100644 index 58a62fecef0df..0000000000000 --- a/devtools/client/netmonitor/test/html_websocket-test-page.html +++ /dev/null @@ -1,10 +0,0 @@ - diff --git a/devtools/client/netmonitor/test/js_websocket-worker-test.js b/devtools/client/netmonitor/test/js_websocket-worker-test.js deleted file mode 100644 index ba23d3f6206ce..0000000000000 --- a/devtools/client/netmonitor/test/js_websocket-worker-test.js +++ /dev/null @@ -1,6 +0,0 @@ -"use strict"; -openWorkerSocket(); - -function openWorkerSocket() { - this.ws = new WebSocket("wss://localhost:8081"); -} diff --git a/devtools/server/actors/network-event.js b/devtools/server/actors/network-event.js index 6790b69dfba1b..cb722ca1f712a 100644 --- a/devtools/server/actors/network-event.js +++ b/devtools/server/actors/network-event.js @@ -262,26 +262,18 @@ const NetworkEventActor = protocol.ActorClassWithSpec(networkEventSpec, { // and the stack is available from the content process. // Fetch it lazily from here via the message manager. if (stacktrace && typeof stacktrace == "boolean") { - let id; - if (this._cause.type == "websocket") { - // Convert to a websocket URL, as in onNetworkEvent. - id = this._request.url.replace(/^http/, "ws"); - } else { - id = this._channelId; - } - const messageManager = this.netMonitorActor.messageManager; stacktrace = await new Promise(resolve => { const onMessage = ({ data }) => { const { channelId, stack } = data; - if (channelId == id) { + if (channelId == this._channelId) { messageManager.removeMessageListener("debug:request-stack:response", onMessage); resolve(stack); } }; messageManager.addMessageListener("debug:request-stack:response", onMessage); - messageManager.sendAsyncMessage("debug:request-stack:request", id); + messageManager.sendAsyncMessage("debug:request-stack:request", this._channelId); }); this._stackTrace = stacktrace; } diff --git a/devtools/server/actors/network-monitor.js b/devtools/server/actors/network-monitor.js index a30aaa64e0344..4bfd5519297a1 100644 --- a/devtools/server/actors/network-monitor.js +++ b/devtools/server/actors/network-monitor.js @@ -216,25 +216,14 @@ const NetworkMonitorActor = ActorClassWithSpec(networkMonitorSpec, { // This method is called by NetworkMonitor instance when a new request is fired onNetworkEvent(event) { - const { channelId, cause, url } = event; + const { channelId } = event; const actor = this.getNetworkEventActor(channelId); this._netEvents.set(channelId, actor); - // Find the ID which the stack trace collector will use to save this - // channel's stack trace. - let id; - if (cause.type == "websocket") { - // Use the URL, but convert from the http URL which this channel uses to - // the original websocket URL which triggered this channel's construction. - id = url.replace(/^http/, "ws"); - } else { - id = channelId; - } - - event.cause.stacktrace = this.stackTraces.has(id); + event.cause.stacktrace = this.stackTraces.has(channelId); if (event.cause.stacktrace) { - this.stackTraces.delete(id); + this.stackTraces.delete(channelId); } actor.init(event); diff --git a/devtools/server/actors/network-monitor/stack-trace-collector.js b/devtools/server/actors/network-monitor/stack-trace-collector.js index 38c78e9efff62..46f59908ce9a2 100644 --- a/devtools/server/actors/network-monitor/stack-trace-collector.js +++ b/devtools/server/actors/network-monitor/stack-trace-collector.js @@ -43,8 +43,8 @@ StackTraceCollector.prototype = { } }, - _saveStackTrace(id, stacktrace) { - if (this.stacktracesById.has(id)) { + _saveStackTrace(channel, stacktrace) { + if (this.stacktracesById.has(channel.channelId)) { // We can get up to two stack traces for the same channel: one each from // the two observer topics we are listening to. Use the first stack trace // which is specified, and ignore any later one. @@ -52,27 +52,15 @@ StackTraceCollector.prototype = { } for (const { messageManager } of this.netmonitors) { messageManager.sendAsyncMessage("debug:request-stack-available", { - channelId: id, + channelId: channel.channelId, stacktrace: stacktrace && stacktrace.length > 0, }); } - this.stacktracesById.set(id, stacktrace); + this.stacktracesById.set(channel.channelId, stacktrace); }, observe(subject, topic, data) { - let channel, id; - try { - channel = subject.QueryInterface(Ci.nsIHttpChannel); - id = channel.channelId; - } catch (e) { - // WebSocketChannels do not have IDs, so use the URL. When a WebSocket is - // opened in a content process, a channel is created locally but the HTTP - // channel for the connection lives entirely in the parent process. When - // the server code running in the parent sees that HTTP channel, it will - // look for the creation stack using the websocket's URL. - channel = subject.QueryInterface(Ci.nsIWebSocketChannel); - id = channel.URI.spec; - } + const channel = subject.QueryInterface(Ci.nsIHttpChannel); if (!matchRequest(channel, this.filters)) { return; @@ -133,7 +121,7 @@ StackTraceCollector.prototype = { throw new Error("Unexpected observe() topic"); } - this._saveStackTrace(id, stacktrace); + this._saveStackTrace(channel, stacktrace); }, // eslint-disable-next-line no-shadow @@ -149,7 +137,7 @@ StackTraceCollector.prototype = { const oldId = oldChannel.channelId; const stacktrace = this.stacktracesById.get(oldId); if (stacktrace) { - this._saveStackTrace(newChannel.channelId, stacktrace); + this._saveStackTrace(newChannel, stacktrace); } }, diff --git a/dom/websocket/WebSocket.cpp b/dom/websocket/WebSocket.cpp index 12360f0afc46a..5f4083fa6f7f2 100644 --- a/dom/websocket/WebSocket.cpp +++ b/dom/websocket/WebSocket.cpp @@ -18,7 +18,6 @@ #include "mozilla/dom/nsCSPContext.h" #include "mozilla/dom/nsCSPUtils.h" #include "mozilla/dom/ScriptSettings.h" -#include "mozilla/dom/SerializedStackHolder.h" #include "mozilla/dom/WorkerPrivate.h" #include "mozilla/dom/WorkerRef.h" #include "mozilla/dom/WorkerRunnable.h" @@ -125,8 +124,7 @@ class WebSocketImpl final : public nsIInterfaceRequestor, nsresult AsyncOpen(nsIPrincipal* aPrincipal, uint64_t aInnerWindowID, nsITransportProvider* aTransportProvider, - const nsACString& aNegotiatedExtensions, - UniquePtr aOriginStack); + const nsACString& aNegotiatedExtensions); nsresult ParseURL(const nsAString& aURL); nsresult InitializeConnection(nsIPrincipal* aPrincipal, @@ -1121,13 +1119,11 @@ class ConnectRunnable final : public WebSocketMainThreadRunnable { class AsyncOpenRunnable final : public WebSocketMainThreadRunnable { public: - explicit AsyncOpenRunnable(WebSocketImpl* aImpl, - UniquePtr aOriginStack) + explicit AsyncOpenRunnable(WebSocketImpl* aImpl) : WebSocketMainThreadRunnable( aImpl->mWorkerRef->Private(), NS_LITERAL_CSTRING("WebSocket :: AsyncOpen")), mImpl(aImpl), - mOriginStack(std::move(aOriginStack)), mErrorCode(NS_OK) { MOZ_ASSERT(mWorkerPrivate); mWorkerPrivate->AssertIsOnWorkerThread(); @@ -1163,8 +1159,7 @@ class AsyncOpenRunnable final : public WebSocketMainThreadRunnable { windowID = topInner->WindowID(); } - mErrorCode = mImpl->AsyncOpen(principal, windowID, nullptr, EmptyCString(), - std::move(mOriginStack)); + mErrorCode = mImpl->AsyncOpen(principal, windowID, nullptr, EmptyCString()); return true; } @@ -1173,7 +1168,7 @@ class AsyncOpenRunnable final : public WebSocketMainThreadRunnable { MOZ_ASSERT(aTopLevelWorkerPrivate && !aTopLevelWorkerPrivate->GetWindow()); mErrorCode = mImpl->AsyncOpen(aTopLevelWorkerPrivate->GetPrincipal(), 0, - nullptr, EmptyCString(), nullptr); + nullptr, EmptyCString()); return true; } @@ -1181,8 +1176,6 @@ class AsyncOpenRunnable final : public WebSocketMainThreadRunnable { // Raw pointer. This worker runs synchronously. WebSocketImpl* mImpl; - UniquePtr mOriginStack; - nsresult mErrorCode; }; @@ -1368,12 +1361,6 @@ already_AddRefed WebSocket::ConstructorCommon( nsCOMPtr ownerWindow = do_QueryInterface(global); nsPIDOMWindowOuter* outerWindow = ownerWindow->GetOuterWindow(); - UniquePtr stack; - nsIDocShell* docShell = outerWindow->GetDocShell(); - if (docShell && docShell->GetWatchedByDevtools()) { - stack = GetCurrentStackForNetMonitor(aGlobal.Context()); - } - uint64_t windowID = 0; nsCOMPtr topWindow = outerWindow->GetScriptableTop(); nsCOMPtr topInner; @@ -1386,19 +1373,12 @@ already_AddRefed WebSocket::ConstructorCommon( } aRv = webSocket->mImpl->AsyncOpen(principal, windowID, aTransportProvider, - aNegotiatedExtensions, std::move(stack)); + aNegotiatedExtensions); } else { MOZ_ASSERT(!aTransportProvider && aNegotiatedExtensions.IsEmpty(), "not yet implemented"); - - UniquePtr stack; - WorkerPrivate* workerPrivate = GetCurrentThreadWorkerPrivate(); - if (workerPrivate->IsWatchedByDevtools()) { - stack = GetCurrentStackForNetMonitor(aGlobal.Context()); - } - RefPtr runnable = - new AsyncOpenRunnable(webSocket->mImpl, std::move(stack)); + new AsyncOpenRunnable(webSocket->mImpl); runnable->Dispatch(Canceling, aRv); if (NS_WARN_IF(aRv.Failed())) { return nullptr; @@ -1652,8 +1632,7 @@ nsresult WebSocketImpl::Init(JSContext* aCx, nsIPrincipal* aLoadingPrincipal, nsresult WebSocketImpl::AsyncOpen(nsIPrincipal* aPrincipal, uint64_t aInnerWindowID, nsITransportProvider* aTransportProvider, - const nsACString& aNegotiatedExtensions, - UniquePtr aOriginStack) { + const nsACString& aNegotiatedExtensions) { MOZ_ASSERT(NS_IsMainThread(), "Not running on main thread"); MOZ_ASSERT_IF(!aTransportProvider, aNegotiatedExtensions.IsEmpty()); @@ -1680,8 +1659,6 @@ nsresult WebSocketImpl::AsyncOpen(nsIPrincipal* aPrincipal, return NS_ERROR_CONTENT_BLOCKED; } - NotifyNetworkMonitorAlternateStack(mChannel, std::move(aOriginStack)); - mInnerWindowID = aInnerWindowID; return NS_OK; From cba8f8f3538c8785519dc19cbe46f6c4a9a479c9 Mon Sep 17 00:00:00 2001 From: Matt Woodrow Date: Fri, 17 May 2019 14:33:10 +1200 Subject: [PATCH 12/12] Bug 1551061 - Enable test for bug 1551053 with retained display lists. r=test-only --HG-- extra : amend_source : d78814d86150ebe9097a5a18209a749c2561bedd --- layout/reftests/display-list/reftest.list | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/layout/reftests/display-list/reftest.list b/layout/reftests/display-list/reftest.list index 3ce01d7811726..0856e1760fec2 100644 --- a/layout/reftests/display-list/reftest.list +++ b/layout/reftests/display-list/reftest.list @@ -41,4 +41,4 @@ fuzzy(0-2,0-40000) skip-if(!asyncPan) == 1464288-1.html 1464288-ref.html == 1504233-1.html 1504233-1-ref.html == 1533317-1.html 1533317-1-ref.html == 1544948-1.html 1544948-1-ref.html -skip-if(retainedDisplayList) == 1551053-1.html 1551053-1-ref.html +== 1551053-1.html 1551053-1-ref.html