WebKit Bugzilla
New
Browse
Log In
×
Sign in with GitHub
or
Remember my login
Create Account
·
Forgot Password
Forgotten password account recovery
RESOLVED FIXED
202704
Web Inspector: notify inspector when provisional page is created, committed and destroyed
https://bugs.webkit.org/show_bug.cgi?id=202704
Summary
Web Inspector: notify inspector when provisional page is created, committed a...
Yury Semikhatsky
Reported
2019-10-08 13:36:51 PDT
This is first step to attaching to provisional pages early during process swap on navigation (PSON). New (provisional) target should be created for provisional pages so that inspector front-end can start inspecting it earlier.
Attachments
Patch
(79.36 KB, patch)
2019-10-08 15:03 PDT
,
Yury Semikhatsky
no flags
Details
Formatted Diff
Diff
Patch
(80.23 KB, patch)
2019-10-08 16:57 PDT
,
Yury Semikhatsky
no flags
Details
Formatted Diff
Diff
Patch
(82.33 KB, patch)
2019-10-09 11:45 PDT
,
Yury Semikhatsky
no flags
Details
Formatted Diff
Diff
Patch
(83.92 KB, patch)
2019-10-14 11:17 PDT
,
Yury Semikhatsky
no flags
Details
Formatted Diff
Diff
Patch
(84.77 KB, patch)
2019-10-14 16:25 PDT
,
Yury Semikhatsky
no flags
Details
Formatted Diff
Diff
Patch
(85.34 KB, patch)
2019-10-21 11:14 PDT
,
Yury Semikhatsky
no flags
Details
Formatted Diff
Diff
Patch for landing
(84.14 KB, patch)
2019-10-23 11:12 PDT
,
Yury Semikhatsky
no flags
Details
Formatted Diff
Diff
Show Obsolete
(6)
View All
Add attachment
proposed patch, testcase, etc.
Yury Semikhatsky
Comment 1
2019-10-08 15:03:50 PDT
Created
attachment 380469
[details]
Patch
EWS Watchlist
Comment 2
2019-10-08 15:04:25 PDT
This patch modifies the inspector protocol. Please ensure that any frontend changes appropriately use feature checks for new protocol features.
Yury Semikhatsky
Comment 3
2019-10-08 16:57:45 PDT
Created
attachment 380480
[details]
Patch
Yury Semikhatsky
Comment 4
2019-10-09 11:43:17 PDT
View in context:
https://bugs.webkit.org/attachment.cgi?id=379967&action=review
>>>>>>> Source/WebKit/WebProcess/WebPage/WebPageInspectorTargetFrontendChannel.h:41 >>>>>>> + ~WebPageInspectorTargetFrontendChannel() override = default; >>>>>> >>>>>> `virtual ~WebPageInspectorTargetFrontendChannel() = default;` >>>>> >>>>> Why? It overrides virtual destructor in its superclass. >>>> >>>> We have never done this anywhere in WebKit. It's also a bit weird, because this doesn't "technically" override the destructor, as the super class' destructor will still get called. >>> >>> Well, overriding method in general is free to call super class's implementation I don't see any issues with that. >>> >>> Here is an excerpt from the WebKit style guide (
https://webkit.org/code-style-guidelines/#override-methods
) which clearly says that overriding methods should be annotated as either override or final: >>> "All subclasses of that class must either specify the override keyword when overriding the virtual method or the final keyword when overriding the virtual method and requiring that no further subclasses can override it." >>> >>> I believe the reason there is still a lot of code that violates the rule is that they predate c++11 usage in WebKit and nobody bothered updating them. Maybe worth bringing this up on webkit-dev. Annotating the destructor with override protects against a nasty error when super destructor accidentally not not marked as virtual but the clients try to destroy the object using its superclass interface. >> >> That may be the case, but for now I'd ask you to use `virtual`, as it seems like that's what we use everywhere else in WebKit. Personally, I would also argue that constructors and destructors are considered a different "type" of method than other member functions, so that affects my stance on this too. Feel free to broach the subject on webkit-dev. > > Raised this on webkit-dev, let's discuss there and I'll update the patch to follow the conclusion.
Would be nice if you posted your arguments over there. I don't see enough interest from the community in fixing this, I also don't want this to be a blocker, so changing to virtual ~WebPageInspectorTargetFrontendChannel() = default;
Yury Semikhatsky
Comment 5
2019-10-09 11:45:44 PDT
Created
attachment 380548
[details]
Patch
Yury Semikhatsky
Comment 6
2019-10-09 11:47:27 PDT
(In reply to Yury Semikhatsky from
comment #5
)
> Created
attachment 380548
[details]
> Patch
Fixed compilation error on Apple platforms: /Volumes/Data/worker/macOS-High-Sierra-Release-Build-EWS/build/Source/WebKit/UIProcess/API/APIWebAuthenticationPanel.cpp:41:7: error: no matching constructor for initialization of 'WTF::String' : m_rpId(rpId) ^ ~~~~ Unrelated to this patch but somehow triggered through transitive dependencies and unified build I believe.
Devin Rousso
Comment 7
2019-10-11 17:26:53 PDT
Comment on
attachment 380469
[details]
Patch View in context:
https://bugs.webkit.org/attachment.cgi?id=380469&action=review
This is looking really good! I'd like to read it over again to make sure I'm really understanding it, but I think we're basically there (minus the build failures) :)
> Source/JavaScriptCore/inspector/InspectorTarget.h:51 > + virtual String previousTargetID() const { return String(); }
Style: we normally use "Id", not "ID"
> Source/JavaScriptCore/inspector/agents/InspectorTargetAgent.cpp:106 > + result->setPreviousTargetId(target.previousTargetID());
We should only bother sending this to the frontend when the frontend actually needs it, which is in `Target.event.didCommitProvisionalTarget`. Otherwise, we're wasting bandwidth. I know we discussed this in <
https://webkit.org/b/202219
>, but I'd prefer you keep it as a parameter on `Target.event.didCommitProvisionalTarget` so it's clearer where it's actually used, rather than an optional parameter that may always be set.
> Source/JavaScriptCore/inspector/agents/InspectorTargetAgent.cpp:146 > + targetInfo->setPreviousTargetId(oldTargetID);
Will `oldTargetId` ever be different from `target.previousTargetID()`? You're overriding the call to `setPreviousTargetId` in `buildTargetInfoObject`, which is odd.
> Source/WebCore/inspector/InspectorController.cpp:347 > void InspectorController::setIsUnderTest(bool value)
I thought you were going to move this to 'InspectorController.h'?
> Source/WebInspectorUI/UserInterface/Controllers/TargetManager.js:144 > + this._provisionalTargetIds.delete(targetInfo.targetId);
NIT: I'd move this above the `targetCreated` call so we can add a `console.assert(!this._provisionalTargetIds.has(targetInfo.targetId));` inside `targetCreated`
> Source/WebInspectorUI/UserInterface/Controllers/TargetManager.js:297 > + if (WI.quickConsole) > + WI.quickConsole.initializeMainExecutionContextPathComponent();
This is a layering violation. `WI.quickConsole` is a view object, whereas this is in the model/controller layer. Also, this won't exist for tests, so we probably should avoid even making references to it. Thinking more about this, given how much these functions touch other managers and global state, perhaps it was better to keep it inside 'Main.js' and just duplicate it inside 'Test.js'. I'm fine with either approach (minus the layering violation), so I'll leave the choice up to you.
> Source/WebInspectorUI/UserInterface/Protocol/Target.js:208 > + isDestroyed()
Style: we can make this into a one-line getter ``` get isDestroyed() { return this._isDestroyed; } ```
> Source/WebInspectorUI/UserInterface/Protocol/TargetObserver.js:29 > + constructor()
This isn't needed
> Source/WebKit/UIProcess/InspectorTargetProxy.cpp:100 > + return !!m_provisionalPage;
You should be able to drop the `!!`.
> Source/WebKit/UIProcess/InspectorTargetProxy.cpp:103 > +String InspectorTargetProxy::previousTargetID() const
So if I understand correctly, the `provisionalPageProxy.webPageID()` is the "current" target, and the `provisionalPageProxy.page().webPageID()` is the "previous" target? As I mentioned earlier (InspectorTargetAgent.cpp:145), will this ever be different than the `oldTargetId` that's given to `InspectorTargetAgent::didCommitProvisionalTarget`?
> Source/WebKit/UIProcess/WebPageInspectorController.cpp:44 > +static String getTargetID(const ProvisionalPageProxy& provisionalPage)
This is only used twice, so I think we should just inline this in both places. It's fairly straightforward anyways.
> Source/WebKit/UIProcess/WebPageInspectorController.cpp:-46 > - auto targetAgent = makeUnique<WebPageInspectorTargetAgent>(m_frontendRouter.get(), m_backendDispatcher.get());
I think we can delay the creation of `m_targetAgent` until inside `WebPageInspectorController::init`. It's probably not that big of a difference since we create the `WebPageInspectorController` in the same function as we call `WebPageInspectorController::init `, but it can't hurt.
> Source/WebKit/UIProcess/WebPageInspectorController.cpp:191 > + // FIXME: do not destroy targets that belong to the committed page.
Please make a bug for this and include it's URL here
> LayoutTests/http/tests/inspector/target/target-events-for-provisional-page.html:18 > + TargetAgent.dispatcher = new Proxy(TargetAgent.dispatcher, {
I'm a bit confused as to why you can't use a protocol test for this. It seems like all you really need to do is check the event payloads, and not necessarily do much else. Can you explain why we can't use a protocol test?
Devin Rousso
Comment 8
2019-10-11 17:27:42 PDT
(In reply to Devin Rousso from
comment #7
)
> This is looking really good! I'd like to read it over again to make sure I'm really understanding it, but I think we're basically there (minus the build failures) :)
I think I was looking at an outdated run, because there are no more build failures :P
Yury Semikhatsky
Comment 9
2019-10-14 11:16:30 PDT
Comment on
attachment 380469
[details]
Patch View in context:
https://bugs.webkit.org/attachment.cgi?id=380469&action=review
>> Source/JavaScriptCore/inspector/InspectorTarget.h:51 >> + virtual String previousTargetID() const { return String(); } > > Style: we normally use "Id", not "ID"
From WebKit style guide (
https://webkit.org/code-style-guidelines/#names-basic
): "Capitalize the first letter, including all letters in an acronym". Look for ID in WebPageProxy for example. I believe there is some divergence from that rule in front-end code where 'Id' is used more often but in C++ the rule is unambiguous.
>> Source/JavaScriptCore/inspector/agents/InspectorTargetAgent.cpp:106 >> + result->setPreviousTargetId(target.previousTargetID()); > > We should only bother sending this to the frontend when the frontend actually needs it, which is in `Target.event.didCommitProvisionalTarget`. Otherwise, we're wasting bandwidth. > > I know we discussed this in <
https://webkit.org/b/202219
>, but I'd prefer you keep it as a parameter on `Target.event.didCommitProvisionalTarget` so it's clearer where it's actually used, rather than an optional parameter that may always be set.
This event is sent only once per target life cycle events, it won't save you anything. If bandwidth is a concern there are better ways to improve it than doing premature optimizations. The reason I want to have it here is that once client attaches to the backend and requests all existing targets it will have to learn which of the targets are provisional and for what parent pages. So this data structure actually describes current state of a target. Or do you suggest I add them as a separate parameter to each of targetCreated and didCommitProvisionalTarget be events? What are we saving then?
>> Source/JavaScriptCore/inspector/agents/InspectorTargetAgent.cpp:146 >> + targetInfo->setPreviousTargetId(oldTargetID); > > Will `oldTargetId` ever be different from `target.previousTargetID()`? You're overriding the call to `setPreviousTargetId` in `buildTargetInfoObject`, which is odd.
By this time target.previousTargetID has already been cleared as the target is committed. Alternatively, we could store a copy of previousTargetID after the commit. I didn't quite like that but if you think it'd be better I can ad InspectedTargetProxy::m_previousTargetID. I'm open to suggestions.
>> Source/WebCore/inspector/InspectorController.cpp:347 >> void InspectorController::setIsUnderTest(bool value) > > I thought you were going to move this to 'InspectorController.h'?
Hmm, in my local state it is in the header. Probably I haven't uploaded the most recent version. Done.
>> Source/WebInspectorUI/UserInterface/Controllers/TargetManager.js:144 >> + this._provisionalTargetIds.delete(targetInfo.targetId); > > NIT: I'd move this above the `targetCreated` call so we can add a `console.assert(!this._provisionalTargetIds.has(targetInfo.targetId));` inside `targetCreated`
Done.
>> Source/WebInspectorUI/UserInterface/Controllers/TargetManager.js:297 >> + WI.quickConsole.initializeMainExecutionContextPathComponent(); > > This is a layering violation. `WI.quickConsole` is a view object, whereas this is in the model/controller layer. Also, this won't exist for tests, so we probably should avoid even making references to it. > > Thinking more about this, given how much these functions touch other managers and global state, perhaps it was better to keep it inside 'Main.js' and just duplicate it inside 'Test.js'. I'm fine with either approach (minus the layering violation), so I'll leave the choice up to you.
Done. Moved the code to a listener in QuickConsole. I think it's a positive change to reduce code duplication between the Test.js and Main.js. As a next step these methods can be turned into listeners of the target manager. I'd much rather do it in a separate change to keep this one focused on the primary goal.
>> Source/WebInspectorUI/UserInterface/Protocol/Target.js:208 >> + isDestroyed() > > Style: we can make this into a one-line getter > ``` > get isDestroyed() { return this._isDestroyed; } > ```
Done.
>> Source/WebInspectorUI/UserInterface/Protocol/TargetObserver.js:29 >> + constructor() > > This isn't needed
Removed.
>> Source/WebKit/UIProcess/InspectorTargetProxy.cpp:100 >> + return !!m_provisionalPage; > > You should be able to drop the `!!`.
bool() operator on WeakPtr is explicit, so it'd cause compilation error.
>> Source/WebKit/UIProcess/InspectorTargetProxy.cpp:103 >> +String InspectorTargetProxy::previousTargetID() const > > So if I understand correctly, the `provisionalPageProxy.webPageID()` is the "current" target, and the `provisionalPageProxy.page().webPageID()` is the "previous" target? As I mentioned earlier (InspectorTargetAgent.cpp:145), will this ever be different than the `oldTargetId` that's given to `InspectorTargetAgent::didCommitProvisionalTarget`?
After commit provisional page becomes current page and the old page id is overwritten.
>> Source/WebKit/UIProcess/WebPageInspectorController.cpp:44 >> +static String getTargetID(const ProvisionalPageProxy& provisionalPage) > > This is only used twice, so I think we should just inline this in both places. It's fairly straightforward anyways.
In addition to reducing code duplication it makes the call sites much shorter and more readable so I'd rather leave it this way.
>> Source/WebKit/UIProcess/WebPageInspectorController.cpp:-46 >> - auto targetAgent = makeUnique<WebPageInspectorTargetAgent>(m_frontendRouter.get(), m_backendDispatcher.get()); > > I think we can delay the creation of `m_targetAgent` until inside `WebPageInspectorController::init`. It's probably not that big of a difference since we create the `WebPageInspectorController` in the same function as we call `WebPageInspectorController::init `, but it can't hurt.
Done.
>> Source/WebKit/UIProcess/WebPageInspectorController.cpp:191 >> + // FIXME: do not destroy targets that belong to the committed page. > > Please make a bug for this and include it's URL here
Filed webtkit.org/b/202937
>> LayoutTests/http/tests/inspector/target/target-events-for-provisional-page.html:18 >> + TargetAgent.dispatcher = new Proxy(TargetAgent.dispatcher, { > > I'm a bit confused as to why you can't use a protocol test for this. It seems like all you really need to do is check the event payloads, and not necessarily do much else. Can you explain why we can't use a protocol test?
Protocol tests use a shortcut when connecting to the inspected page: they are opened in a dummy front-end page (openDummyInspectorFrontend) and all messages are routed directly between the two pages. From the inspected page to front-end via window.postMessage and via InspectorFrontendClientLocal::sendMessageToBackend in the reverse direction. These messages don't utilize Target domain at all and my goal is to test Target domain. This is why I say it'd be nice to get rid of the dummy inspector front-end altogether and host protocol tests' front-end in the same inspector window as inspector UI tests. It would route all messages through the UIProcess and its target agent in case of WK2.
Yury Semikhatsky
Comment 10
2019-10-14 11:16:34 PDT
View in context:
https://bugs.webkit.org/attachment.cgi?id=380469&action=review
>> Source/JavaScriptCore/inspector/InspectorTarget.h:51 >> + virtual String previousTargetID() const { return String(); } > > Style: we normally use "Id", not "ID"
From WebKit style guide (
https://webkit.org/code-style-guidelines/#names-basic
): "Capitalize the first letter, including all letters in an acronym". Look for ID in WebPageProxy for example. I believe there is some divergence from that rule in front-end code where 'Id' is used more often but in C++ the rule is unambiguous.
>> Source/JavaScriptCore/inspector/agents/InspectorTargetAgent.cpp:106 >> + result->setPreviousTargetId(target.previousTargetID()); > > We should only bother sending this to the frontend when the frontend actually needs it, which is in `Target.event.didCommitProvisionalTarget`. Otherwise, we're wasting bandwidth. > > I know we discussed this in <
https://webkit.org/b/202219
>, but I'd prefer you keep it as a parameter on `Target.event.didCommitProvisionalTarget` so it's clearer where it's actually used, rather than an optional parameter that may always be set.
This event is sent only once per target life cycle events, it won't save you anything. If bandwidth is a concern there are better ways to improve it than doing premature optimizations. The reason I want to have it here is that once client attaches to the backend and requests all existing targets it will have to learn which of the targets are provisional and for what parent pages. So this data structure actually describes current state of a target. Or do you suggest I add them as a separate parameter to each of targetCreated and didCommitProvisionalTarget be events? What are we saving then?
>> Source/JavaScriptCore/inspector/agents/InspectorTargetAgent.cpp:146 >> + targetInfo->setPreviousTargetId(oldTargetID); > > Will `oldTargetId` ever be different from `target.previousTargetID()`? You're overriding the call to `setPreviousTargetId` in `buildTargetInfoObject`, which is odd.
By this time target.previousTargetID has already been cleared as the target is committed. Alternatively, we could store a copy of previousTargetID after the commit. I didn't quite like that but if you think it'd be better I can ad InspectedTargetProxy::m_previousTargetID. I'm open to suggestions.
>> Source/WebCore/inspector/InspectorController.cpp:347 >> void InspectorController::setIsUnderTest(bool value) > > I thought you were going to move this to 'InspectorController.h'?
Hmm, in my local state it is in the header. Probably I haven't uploaded the most recent version. Done.
>> Source/WebInspectorUI/UserInterface/Controllers/TargetManager.js:144 >> + this._provisionalTargetIds.delete(targetInfo.targetId); > > NIT: I'd move this above the `targetCreated` call so we can add a `console.assert(!this._provisionalTargetIds.has(targetInfo.targetId));` inside `targetCreated`
Done.
>> Source/WebInspectorUI/UserInterface/Controllers/TargetManager.js:297 >> + WI.quickConsole.initializeMainExecutionContextPathComponent(); > > This is a layering violation. `WI.quickConsole` is a view object, whereas this is in the model/controller layer. Also, this won't exist for tests, so we probably should avoid even making references to it. > > Thinking more about this, given how much these functions touch other managers and global state, perhaps it was better to keep it inside 'Main.js' and just duplicate it inside 'Test.js'. I'm fine with either approach (minus the layering violation), so I'll leave the choice up to you.
Done. Moved the code to a listener in QuickConsole. I think it's a positive change to reduce code duplication between the Test.js and Main.js. As a next step these methods can be turned into listeners of the target manager. I'd much rather do it in a separate change to keep this one focused on the primary goal.
>> Source/WebInspectorUI/UserInterface/Protocol/Target.js:208 >> + isDestroyed() > > Style: we can make this into a one-line getter > ``` > get isDestroyed() { return this._isDestroyed; } > ```
Done.
>> Source/WebInspectorUI/UserInterface/Protocol/TargetObserver.js:29 >> + constructor() > > This isn't needed
Removed.
>> Source/WebKit/UIProcess/InspectorTargetProxy.cpp:100 >> + return !!m_provisionalPage; > > You should be able to drop the `!!`.
bool() operator on WeakPtr is explicit, so it'd cause compilation error.
>> Source/WebKit/UIProcess/InspectorTargetProxy.cpp:103 >> +String InspectorTargetProxy::previousTargetID() const > > So if I understand correctly, the `provisionalPageProxy.webPageID()` is the "current" target, and the `provisionalPageProxy.page().webPageID()` is the "previous" target? As I mentioned earlier (InspectorTargetAgent.cpp:145), will this ever be different than the `oldTargetId` that's given to `InspectorTargetAgent::didCommitProvisionalTarget`?
After commit provisional page becomes current page and the old page id is overwritten.
>> Source/WebKit/UIProcess/WebPageInspectorController.cpp:44 >> +static String getTargetID(const ProvisionalPageProxy& provisionalPage) > > This is only used twice, so I think we should just inline this in both places. It's fairly straightforward anyways.
In addition to reducing code duplication it makes the call sites much shorter and more readable so I'd rather leave it this way.
>> Source/WebKit/UIProcess/WebPageInspectorController.cpp:-46 >> - auto targetAgent = makeUnique<WebPageInspectorTargetAgent>(m_frontendRouter.get(), m_backendDispatcher.get()); > > I think we can delay the creation of `m_targetAgent` until inside `WebPageInspectorController::init`. It's probably not that big of a difference since we create the `WebPageInspectorController` in the same function as we call `WebPageInspectorController::init `, but it can't hurt.
Done.
>> Source/WebKit/UIProcess/WebPageInspectorController.cpp:191 >> + // FIXME: do not destroy targets that belong to the committed page. > > Please make a bug for this and include it's URL here
Filed webtkit.org/b/202937
>> LayoutTests/http/tests/inspector/target/target-events-for-provisional-page.html:18 >> + TargetAgent.dispatcher = new Proxy(TargetAgent.dispatcher, { > > I'm a bit confused as to why you can't use a protocol test for this. It seems like all you really need to do is check the event payloads, and not necessarily do much else. Can you explain why we can't use a protocol test?
Protocol tests use a shortcut when connecting to the inspected page: they are opened in a dummy front-end page (openDummyInspectorFrontend) and all messages are routed directly between the two pages. From the inspected page to front-end via window.postMessage and via InspectorFrontendClientLocal::sendMessageToBackend in the reverse direction. These messages don't utilize Target domain at all and my goal is to test Target domain. This is why I say it'd be nice to get rid of the dummy inspector front-end altogether and host protocol tests' front-end in the same inspector window as inspector UI tests. It would route all messages through the UIProcess and its target agent in case of WK2.
Yury Semikhatsky
Comment 11
2019-10-14 11:17:34 PDT
Created
attachment 380898
[details]
Patch
Devin Rousso
Comment 12
2019-10-14 12:51:51 PDT
Comment on
attachment 380469
[details]
Patch View in context:
https://bugs.webkit.org/attachment.cgi?id=380469&action=review
>>> Source/JavaScriptCore/inspector/agents/InspectorTargetAgent.cpp:106 >>> + result->setPreviousTargetId(target.previousTargetID()); >> >> We should only bother sending this to the frontend when the frontend actually needs it, which is in `Target.event.didCommitProvisionalTarget`. Otherwise, we're wasting bandwidth. >> >> I know we discussed this in <
https://webkit.org/b/202219
>, but I'd prefer you keep it as a parameter on `Target.event.didCommitProvisionalTarget` so it's clearer where it's actually used, rather than an optional parameter that may always be set. > > This event is sent only once per target life cycle events, it won't save you anything. If bandwidth is a concern there are better ways to improve it than doing premature optimizations. > > The reason I want to have it here is that once client attaches to the backend and requests all existing targets it will have to learn which of the targets are provisional and for what parent pages. So this data structure actually describes current state of a target. Or do you suggest I add them as a separate parameter to each of targetCreated and didCommitProvisionalTarget be events? What are we saving then?
I was referring specifically to `previousTargetId`. I completely agree that we should have `isProvisional` be part of `Target.TargetInfo`. Unless you have future plans for it (which I am unaware of), it looks like the only time `previousTargetId` is ever used is when we're committing a provisional target, so in your example of needing to get the current state of all targets when Web Inspector connects, it wouldn't be needed as nothing is being "committed" during that initial broadcast. This isn't a "premature optimization" so much as it's a code cleanliness. We should strive to keep things as localized and concise as possible.
>>> Source/JavaScriptCore/inspector/agents/InspectorTargetAgent.cpp:146 >>> + targetInfo->setPreviousTargetId(oldTargetID); >> >> Will `oldTargetId` ever be different from `target.previousTargetID()`? You're overriding the call to `setPreviousTargetId` in `buildTargetInfoObject`, which is odd. > > By this time target.previousTargetID has already been cleared as the target is committed. Alternatively, we could store a copy of previousTargetID after the commit. I didn't quite like that but if you think it'd be better I can ad InspectedTargetProxy::m_previousTargetID. I'm open to suggestions.
If it's been cleared by this point then we shouldn't even be using it at all. I'm fine with passing in the `oldTargetID` to this function, I just don't want to see two different calls to `setPreviousTargetId` one after the other.
>>> Source/WebInspectorUI/UserInterface/Controllers/TargetManager.js:297 >>> + WI.quickConsole.initializeMainExecutionContextPathComponent(); >> >> This is a layering violation. `WI.quickConsole` is a view object, whereas this is in the model/controller layer. Also, this won't exist for tests, so we probably should avoid even making references to it. >> >> Thinking more about this, given how much these functions touch other managers and global state, perhaps it was better to keep it inside 'Main.js' and just duplicate it inside 'Test.js'. I'm fine with either approach (minus the layering violation), so I'll leave the choice up to you. > > Done. Moved the code to a listener in QuickConsole. I think it's a positive change to reduce code duplication between the Test.js and Main.js. As a next step these methods can be turned into listeners of the target manager. I'd much rather do it in a separate change to keep this one focused on the primary goal.
Nice! One thing to keep in mind here is that `WI.Object`'s event listeners are fired in the order that they're added. We _should_ avoid any situation where that ordering matters, but there may be some subtle bugs as a result of this.
>>> LayoutTests/http/tests/inspector/target/target-events-for-provisional-page.html:18 >>> + TargetAgent.dispatcher = new Proxy(TargetAgent.dispatcher, { >> >> I'm a bit confused as to why you can't use a protocol test for this. It seems like all you really need to do is check the event payloads, and not necessarily do much else. Can you explain why we can't use a protocol test? > > Protocol tests use a shortcut when connecting to the inspected page: they are opened in a dummy front-end page (openDummyInspectorFrontend) and all messages are routed directly between the two pages. > From the inspected page to front-end via window.postMessage and via > InspectorFrontendClientLocal::sendMessageToBackend in the reverse direction. > These messages don't utilize Target domain at all and my goal is to test Target domain. > > > This is why I say it'd be nice to get rid of the dummy inspector front-end altogether and host protocol tests' front-end in the same inspector window as inspector UI tests. It would route all messages through the UIProcess and its target agent in case of WK2.
Aaahhh, right the dummy frontend. We should get rid of that at some point. My concern with this approach is that you're only modifying the Target dispatcher for the main target, not every target. This was why I'd suggested modifying `WI.TargetManager` in previous reviews, as that _would_ handle every target, and not require the use of a `Proxy` or any other "hacky" behavior. I'd rather have a more comprehensive test that handles _all_ target messages, instead of just for the main target (I realize that we won't have a Target domain for any other target, but the principle of the test should be to get as much coverage, now and in the future, as possible). Regardless, what you have here is valid, so I'm not disagreeing with the concept of the test, or even what it's testing, just how it goes about doing that.
Yury Semikhatsky
Comment 13
2019-10-14 16:24:59 PDT
Comment on
attachment 380469
[details]
Patch View in context:
https://bugs.webkit.org/attachment.cgi?id=380469&action=review
>>>> Source/JavaScriptCore/inspector/agents/InspectorTargetAgent.cpp:106 >>>> + result->setPreviousTargetId(target.previousTargetID()); >>> >>> We should only bother sending this to the frontend when the frontend actually needs it, which is in `Target.event.didCommitProvisionalTarget`. Otherwise, we're wasting bandwidth. >>> >>> I know we discussed this in <
https://webkit.org/b/202219
>, but I'd prefer you keep it as a parameter on `Target.event.didCommitProvisionalTarget` so it's clearer where it's actually used, rather than an optional parameter that may always be set. >> >> This event is sent only once per target life cycle events, it won't save you anything. If bandwidth is a concern there are better ways to improve it than doing premature optimizations. >> >> The reason I want to have it here is that once client attaches to the backend and requests all existing targets it will have to learn which of the targets are provisional and for what parent pages. So this data structure actually describes current state of a target. Or do you suggest I add them as a separate parameter to each of targetCreated and didCommitProvisionalTarget be events? What are we saving then? > > I was referring specifically to `previousTargetId`. I completely agree that we should have `isProvisional` be part of `Target.TargetInfo`. Unless you have future plans for it (which I am unaware of), it looks like the only time `previousTargetId` is ever used is when we're committing a provisional target, so in your example of needing to get the current state of all targets when Web Inspector connects, it wouldn't be needed as nothing is being "committed" during that initial broadcast. > > This isn't a "premature optimization" so much as it's a code cleanliness. We should strive to keep things as localized and concise as possible.
Consider the world where target domain is per inspected App rather than per tab as we discussed some time ago on irc. In that case the client would connect to the browser, receive all target events and then be able to pick and choose which of them to inspect. In that world if the client observes targetCreated event for a provisional target it has to know whether it's a navigation in one of the pages it's currently inspecting or it's irrelevant and safe to ignore. Without previousTargetId it would have to conservatively assume that each provisional target could be relevant to the inspected pages. This becomes even more important if you may have more than one provisional target for a page because of e.g. preloads. previousTargetId could be passed a separate parameter in didCommitProvisionalTarget for now but then it means we'd have to add it to targetCreated event later and overall the result IMO is worse because we'd end up passing the information separately from TargetInfo in each instance. Please let me know what you think about this. If you feel like it's better to add it later I will change the code to pass old target id as a separate parameter in didCommitProvisionalTarget.
>>>> Source/JavaScriptCore/inspector/agents/InspectorTargetAgent.cpp:146 >>>> + targetInfo->setPreviousTargetId(oldTargetID); >>> >>> Will `oldTargetId` ever be different from `target.previousTargetID()`? You're overriding the call to `setPreviousTargetId` in `buildTargetInfoObject`, which is odd. >> >> By this time target.previousTargetID has already been cleared as the target is committed. Alternatively, we could store a copy of previousTargetID after the commit. I didn't quite like that but if you think it'd be better I can ad InspectedTargetProxy::m_previousTargetID. I'm open to suggestions. > > If it's been cleared by this point then we shouldn't even be using it at all. I'm fine with passing in the `oldTargetID` to this function, I just don't want to see two different calls to `setPreviousTargetId` one after the other.
oldTargetID is only set if the target is not provisional, I moved the logic inside the buildTargetInfoObject.
>>>> Source/WebInspectorUI/UserInterface/Controllers/TargetManager.js:297 >>>> + WI.quickConsole.initializeMainExecutionContextPathComponent(); >>> >>> This is a layering violation. `WI.quickConsole` is a view object, whereas this is in the model/controller layer. Also, this won't exist for tests, so we probably should avoid even making references to it. >>> >>> Thinking more about this, given how much these functions touch other managers and global state, perhaps it was better to keep it inside 'Main.js' and just duplicate it inside 'Test.js'. I'm fine with either approach (minus the layering violation), so I'll leave the choice up to you. >> >> Done. Moved the code to a listener in QuickConsole. I think it's a positive change to reduce code duplication between the Test.js and Main.js. As a next step these methods can be turned into listeners of the target manager. I'd much rather do it in a separate change to keep this one focused on the primary goal. > > Nice! One thing to keep in mind here is that `WI.Object`'s event listeners are fired in the order that they're added. We _should_ avoid any situation where that ordering matters, but there may be some subtle bugs as a result of this.
At first glance initializeMainExecutionContextPathComponent() doesn't depend on runtimeManager.activeExecutionContex, am I missing something? Do you have a concrete suggestion how to improve the code or current approach is fine? Please clarify.
>>>> LayoutTests/http/tests/inspector/target/target-events-for-provisional-page.html:18 >>>> + TargetAgent.dispatcher = new Proxy(TargetAgent.dispatcher, { >>> >>> I'm a bit confused as to why you can't use a protocol test for this. It seems like all you really need to do is check the event payloads, and not necessarily do much else. Can you explain why we can't use a protocol test? >> >> Protocol tests use a shortcut when connecting to the inspected page: they are opened in a dummy front-end page (openDummyInspectorFrontend) and all messages are routed directly between the two pages. >> From the inspected page to front-end via window.postMessage and via >> InspectorFrontendClientLocal::sendMessageToBackend in the reverse direction. >> These messages don't utilize Target domain at all and my goal is to test Target domain. >> >> >> This is why I say it'd be nice to get rid of the dummy inspector front-end altogether and host protocol tests' front-end in the same inspector window as inspector UI tests. It would route all messages through the UIProcess and its target agent in case of WK2. > > Aaahhh, right the dummy frontend. We should get rid of that at some point. > > My concern with this approach is that you're only modifying the Target dispatcher for the main target, not every target. This was why I'd suggested modifying `WI.TargetManager` in previous reviews, as that _would_ handle every target, and not require the use of a `Proxy` or any other "hacky" behavior. I'd rather have a more comprehensive test that handles _all_ target messages, instead of just for the main target (I realize that we won't have a Target domain for any other target, but the principle of the test should be to get as much coverage, now and in the future, as possible). > > Regardless, what you have here is valid, so I'm not disagreeing with the concept of the test, or even what it's testing, just how it goes about doing that.
I've added events on TargetManager for each of the protocol events as you suggested. Tried to replace TargetManaget with a test subclass but it didn't quite work: first of all we'd have to copy current state of existing instance TargetManager, then it may already be added as a listener to some objects. Having explicit events looks cleaner.
Yury Semikhatsky
Comment 14
2019-10-14 16:25:44 PDT
Created
attachment 380930
[details]
Patch
Devin Rousso
Comment 15
2019-10-17 21:26:24 PDT
Comment on
attachment 380469
[details]
Patch View in context:
https://bugs.webkit.org/attachment.cgi?id=380469&action=review
Now that <
https://webkit.org/b/200384
> has landed, this patch will need a rebase. Sorry I couldn't get to reviewing this again sooner :(
>>>>> Source/JavaScriptCore/inspector/agents/InspectorTargetAgent.cpp:106 >>>>> + result->setPreviousTargetId(target.previousTargetID()); >>>> >>>> We should only bother sending this to the frontend when the frontend actually needs it, which is in `Target.event.didCommitProvisionalTarget`. Otherwise, we're wasting bandwidth. >>>> >>>> I know we discussed this in <
https://webkit.org/b/202219
>, but I'd prefer you keep it as a parameter on `Target.event.didCommitProvisionalTarget` so it's clearer where it's actually used, rather than an optional parameter that may always be set. >>> >>> This event is sent only once per target life cycle events, it won't save you anything. If bandwidth is a concern there are better ways to improve it than doing premature optimizations. >>> >>> The reason I want to have it here is that once client attaches to the backend and requests all existing targets it will have to learn which of the targets are provisional and for what parent pages. So this data structure actually describes current state of a target. Or do you suggest I add them as a separate parameter to each of targetCreated and didCommitProvisionalTarget be events? What are we saving then? >> >> I was referring specifically to `previousTargetId`. I completely agree that we should have `isProvisional` be part of `Target.TargetInfo`. Unless you have future plans for it (which I am unaware of), it looks like the only time `previousTargetId` is ever used is when we're committing a provisional target, so in your example of needing to get the current state of all targets when Web Inspector connects, it wouldn't be needed as nothing is being "committed" during that initial broadcast. >> >> This isn't a "premature optimization" so much as it's a code cleanliness. We should strive to keep things as localized and concise as possible. > > Consider the world where target domain is per inspected App rather than per tab as we discussed some time ago on irc. In that case the client would connect to the browser, receive all target events and then be able to pick and choose which of them to inspect. In that world if the client observes targetCreated event for a provisional target it has to know whether it's a navigation in one of the pages it's currently inspecting or it's irrelevant and safe to ignore. Without previousTargetId it would have to conservatively assume that each provisional target could be relevant to the inspected pages. This becomes even more important if you may have more than one provisional target for a page because of e.g. preloads. > > previousTargetId could be passed a separate parameter in didCommitProvisionalTarget for now but then it means we'd have to add it to targetCreated event later and overall the result IMO is worse because we'd end up passing the information separately from TargetInfo in each instance. > > Please let me know what you think about this. If you feel like it's better to add it later I will change the code to pass old target id as a separate parameter in didCommitProvisionalTarget.
As we discussed on IRC, this is not the direction we'd like to take Web Inspector. If you want to connect to a browser, there should be a separate `Browser` domain, preferably behind a build flag. The `Target` domain is meant for inspecting a single web page (and any associated targets). Furthermore, what you're describing seems more to me like a `parentTargetId` or `relatedTargetId`, not `previousTargetId`. I'd be fine having a `relatedTargetId` as part of `Target.TargetInfo`, but not `previousTargetId` as the only time that the `targetId` should be "moved" to the `previousTargetId` is when we're transitioning a provisional target, which is why it should be a second parameter to the event, not a generalized item that could be part of every `Target.TargetInfo`.
>>>>> Source/WebInspectorUI/UserInterface/Controllers/TargetManager.js:297 >>>>> + WI.quickConsole.initializeMainExecutionContextPathComponent(); >>>> >>>> This is a layering violation. `WI.quickConsole` is a view object, whereas this is in the model/controller layer. Also, this won't exist for tests, so we probably should avoid even making references to it. >>>> >>>> Thinking more about this, given how much these functions touch other managers and global state, perhaps it was better to keep it inside 'Main.js' and just duplicate it inside 'Test.js'. I'm fine with either approach (minus the layering violation), so I'll leave the choice up to you. >>> >>> Done. Moved the code to a listener in QuickConsole. I think it's a positive change to reduce code duplication between the Test.js and Main.js. As a next step these methods can be turned into listeners of the target manager. I'd much rather do it in a separate change to keep this one focused on the primary goal. >> >> Nice! One thing to keep in mind here is that `WI.Object`'s event listeners are fired in the order that they're added. We _should_ avoid any situation where that ordering matters, but there may be some subtle bugs as a result of this. > > At first glance initializeMainExecutionContextPathComponent() doesn't depend on runtimeManager.activeExecutionContex, am I missing something? > > Do you have a concrete suggestion how to improve the code or current approach is fine? Please clarify.
I was making a more general comment, not necessarily specific to this situation. If you created an entirely new event, there will be no problem (especially since our event listeners fire synchronously). If you're using an existing event, there _may_ be issues with the ordering as I mentioned, but I'm not saying there are for sure as I'd have to look. Ideally, the order in which event listeners are fired shouldn't matter (excluding `stopPropagation`), but reality isn't always ideal :(
Yury Semikhatsky
Comment 16
2019-10-21 11:12:32 PDT
Comment on
attachment 380469
[details]
Patch View in context:
https://bugs.webkit.org/attachment.cgi?id=380469&action=review
>>>>>> Source/JavaScriptCore/inspector/agents/InspectorTargetAgent.cpp:106 >>>>>> + result->setPreviousTargetId(target.previousTargetID()); >>>>> >>>>> We should only bother sending this to the frontend when the frontend actually needs it, which is in `Target.event.didCommitProvisionalTarget`. Otherwise, we're wasting bandwidth. >>>>> >>>>> I know we discussed this in <
https://webkit.org/b/202219
>, but I'd prefer you keep it as a parameter on `Target.event.didCommitProvisionalTarget` so it's clearer where it's actually used, rather than an optional parameter that may always be set. >>>> >>>> This event is sent only once per target life cycle events, it won't save you anything. If bandwidth is a concern there are better ways to improve it than doing premature optimizations. >>>> >>>> The reason I want to have it here is that once client attaches to the backend and requests all existing targets it will have to learn which of the targets are provisional and for what parent pages. So this data structure actually describes current state of a target. Or do you suggest I add them as a separate parameter to each of targetCreated and didCommitProvisionalTarget be events? What are we saving then? >>> >>> I was referring specifically to `previousTargetId`. I completely agree that we should have `isProvisional` be part of `Target.TargetInfo`. Unless you have future plans for it (which I am unaware of), it looks like the only time `previousTargetId` is ever used is when we're committing a provisional target, so in your example of needing to get the current state of all targets when Web Inspector connects, it wouldn't be needed as nothing is being "committed" during that initial broadcast. >>> >>> This isn't a "premature optimization" so much as it's a code cleanliness. We should strive to keep things as localized and concise as possible. >> >> Consider the world where target domain is per inspected App rather than per tab as we discussed some time ago on irc. In that case the client would connect to the browser, receive all target events and then be able to pick and choose which of them to inspect. In that world if the client observes targetCreated event for a provisional target it has to know whether it's a navigation in one of the pages it's currently inspecting or it's irrelevant and safe to ignore. Without previousTargetId it would have to conservatively assume that each provisional target could be relevant to the inspected pages. This becomes even more important if you may have more than one provisional target for a page because of e.g. preloads. >> >> previousTargetId could be passed a separate parameter in didCommitProvisionalTarget for now but then it means we'd have to add it to targetCreated event later and overall the result IMO is worse because we'd end up passing the information separately from TargetInfo in each instance. >> >> Please let me know what you think about this. If you feel like it's better to add it later I will change the code to pass old target id as a separate parameter in didCommitProvisionalTarget. > > As we discussed on IRC, this is not the direction we'd like to take Web Inspector. If you want to connect to a browser, there should be a separate `Browser` domain, preferably behind a build flag. The `Target` domain is meant for inspecting a single web page (and any associated targets). > > Furthermore, what you're describing seems more to me like a `parentTargetId` or `relatedTargetId`, not `previousTargetId`. I'd be fine having a `relatedTargetId` as part of `Target.TargetInfo`, but not `previousTargetId` as the only time that the `targetId` should be "moved" to the `previousTargetId` is when we're transitioning a provisional target, which is why it should be a second parameter to the event, not a generalized item that could be part of every `Target.TargetInfo`.
Done.
>>>>>> Source/WebInspectorUI/UserInterface/Controllers/TargetManager.js:297 >>>>>> + WI.quickConsole.initializeMainExecutionContextPathComponent(); >>>>> >>>>> This is a layering violation. `WI.quickConsole` is a view object, whereas this is in the model/controller layer. Also, this won't exist for tests, so we probably should avoid even making references to it. >>>>> >>>>> Thinking more about this, given how much these functions touch other managers and global state, perhaps it was better to keep it inside 'Main.js' and just duplicate it inside 'Test.js'. I'm fine with either approach (minus the layering violation), so I'll leave the choice up to you. >>>> >>>> Done. Moved the code to a listener in QuickConsole. I think it's a positive change to reduce code duplication between the Test.js and Main.js. As a next step these methods can be turned into listeners of the target manager. I'd much rather do it in a separate change to keep this one focused on the primary goal. >>> >>> Nice! One thing to keep in mind here is that `WI.Object`'s event listeners are fired in the order that they're added. We _should_ avoid any situation where that ordering matters, but there may be some subtle bugs as a result of this. >> >> At first glance initializeMainExecutionContextPathComponent() doesn't depend on runtimeManager.activeExecutionContex, am I missing something? >> >> Do you have a concrete suggestion how to improve the code or current approach is fine? Please clarify. > > I was making a more general comment, not necessarily specific to this situation. If you created an entirely new event, there will be no problem (especially since our event listeners fire synchronously). If you're using an existing event, there _may_ be issues with the ordering as I mentioned, but I'm not saying there are for sure as I'd have to look. Ideally, the order in which event listeners are fired shouldn't matter (excluding `stopPropagation`), but reality isn't always ideal :(
OK, let me know if you are concerned about some particular flow and we can rearrange the code, TransitionPageTarget in this case seems safe to me. Also if listeners order matters they'd better be delegates with predictable invocation sequence. In this particular case we don't rely on the order in which the notification listeners are called.
Yury Semikhatsky
Comment 17
2019-10-21 11:14:28 PDT
Created
attachment 381421
[details]
Patch
Devin Rousso
Comment 18
2019-10-21 17:53:59 PDT
Comment on
attachment 381421
[details]
Patch View in context:
https://bugs.webkit.org/attachment.cgi?id=381421&action=review
r=me, awesome work!
> Source/JavaScriptCore/inspector/agents/InspectorTargetAgent.cpp:135 > + m_frontendDispatcher->didCommitProvisionalTarget(oldTargetID, buildTargetInfoObject(*target));
Would we ever expect the `type` to change? If not, couldn't we simplify this to just send the `oldTargetID` and `newTargetID` and have the frontend reuse the same `WI.Target` by changing it's `_identifier`?
> Source/JavaScriptCore/inspector/protocol/Target.json:13 > + { "name": "isProvisional", "type": "boolean", "optional": true, "description": "Whether this is a provisional page target." }
This doesn't explain what a "provisional" target is. I'd expect some explanation of what that is.
> Source/JavaScriptCore/inspector/protocol/Target.json:43 > + { "name": "previousTargetId", "type": "string", "description": "ID of the target committed target is swapped with." },
This is an awkward sentence description. Please rephrase it.
> Source/JavaScriptCore/inspector/protocol/Target.json:44 > + { "name": "targetInfo", "$ref": "TargetInfo", "description": "Committed target info." }
These types of descriptions aren't very useful. I'd either add more information or remove it.
> Source/WebInspectorUI/UserInterface/Controllers/TargetManager.js:125 > + this.dispatchEventToListeners(WI.TargetManager.Event.TargetCreated, {targetInfo});
Rather than pass the `targetInfo`, can we instead pass the new `WI.Target`? That way, we could use it in non-test code as well (if needed). We could pass `isProvisional` as a separate argument in the object since it's not saved on `WI.Target`. NIT: you can drop the `WI` from `WI.TargetManager` since it's in the same class.
> Source/WebInspectorUI/UserInterface/Controllers/TargetManager.js:131 > + this._provisionalTargetIds.delete(targetInfo.targetId);
We should assert that it was previously in the `Set`
> Source/WebInspectorUI/UserInterface/Controllers/TargetManager.js:133 > + this._swappedTargetIds.add(previousTargetId);
We should assert that it wasn't already in the `Set`
> Source/WebInspectorUI/UserInterface/Controllers/TargetManager.js:135 > + this.dispatchEventToListeners(WI.TargetManager.Event.DidCommitProvisionalTarget, {previousTargetId, targetInfo});
Ditto (125)
> Source/WebInspectorUI/UserInterface/Controllers/TargetManager.js:142 > + this.dispatchEventToListeners(WI.TargetManager.Event.TargetDestroyed, {targetId});
To test even more correctness, we could keep a copy of the `WI.Target` and pass it in here instead of `targetId` so the test can confirm that `isDestroyed` is the right value. Although we may not always have a `WI.Target`, such as in the case of `didCommitProvisionalTarget`, so maybe not.
> Source/WebInspectorUI/UserInterface/Controllers/TargetManager.js:145 > + _targetCreated(parentTarget, targetInfo)
We should name this function and `_targetDestroyed` to be more active instead of looking/sounding like an event listener callback: - `_targetCreated` => `_createTarget` (merging with the existing `_createTarget`) - `_targetDestroyed` => `_destroyTarget` This way, it also won't be as confusing trying to differentiate between `targetCreated` and `_targetCreated`. Also, this function and `_destroyTarget` should be moved into the `// Private` section below.
> Source/WebInspectorUI/UserInterface/Controllers/TargetManager.js:152 > + console.assert(!this._provisionalTargetIds.has(targetInfo.targetId));
I would actually move this assertion before the `if`, because we wouldn't want the same provisional `targetId` to be added twice.
> Source/WebInspectorUI/UserInterface/Controllers/TargetManager.js:168 > + return; > let target = this._targets.get(targetId);
Style: missing newline
> Source/WebInspectorUI/UserInterface/Controllers/TargetManager.js:177 > + return; > let target = this._targets.get(targetId);
Style: missing newline
> Source/WebInspectorUI/UserInterface/Controllers/TargetManager.js:310 > + // Events below are triggered only by corresponding protocol events.
This comment isn't really necessary.
> Source/WebInspectorUI/UserInterface/Controllers/TargetManager.js:313 > + TargetCreated: Symbol("target-manager-target-created"), > + DidCommitProvisionalTarget: Symbol("target-manager-provisional-target-committed"), > + TargetDestroyed: Symbol("target-manager-target-detroyed"),
NIT: I know that the other events are `Symbol`, but we really don't need to do that, so please just make these strings.
> Source/WebInspectorUI/UserInterface/Protocol/Connection.js:324 > + // Command may be sent after target is already destroyed on backend, > + // ignore such errors.
We can simplify this to be on one line ``` // Ignore errors if the target was destroyed after the command was dispatched. ```
> Source/WebInspectorUI/UserInterface/Protocol/Target.js:165 > + destroy() { this._isDestroyed = true; }
Style: we only put functions onto a single line if they're simple getters. Since this is a function, please put the body on separate lines and move it to be below all of the rest of the getters (I'd put this between `addScript` and `hasDomain`).
> Source/WebInspectorUI/UserInterface/Views/QuickConsole.js:115 > + _pageTargetTransisioned()
Typo: `_pageTargetTransisioned` => `_pageTargetTransitioned`
> Source/WebKit/UIProcess/API/APIWebAuthenticationPanel.cpp:37 > +Ref<WebAuthenticationPanel> WebAuthenticationPanel::create(const AuthenticatorManager& manager, const WTF::String& rpId)
This should definitely be in a separate change. Also, I think the more "correct" solution would be to add an `#include <wtf/text/WTFString.h>` in the .cpp and `#include <wtf/Forward.h>` in the .h
> Source/WebKit/UIProcess/WebPageInspectorController.cpp:191 > + // FIXME(
webkit.org/b/202937
): do not destroy targets that belong to the committed page.
NIT: our usual style is `// FIXME: <
https://webkit.org/b/202937
> do not destroy targets that belong to the committed page`
> Source/WebKit/WebKit.xcodeproj/project.pbxproj:6271 > + 37B47E2C1D64DB76005F4EFF /* objcSPI.h */,
Where did this come from?
> Source/WebKit/WebKit.xcodeproj/project.pbxproj:-9412 > - 7AA746D523593D8100095050 /* SecItemSPI.h in Headers */,
Ditto (6271)
> LayoutTests/http/tests/inspector/target/target-events-for-provisional-page.html:21 > + let targetInfo = event.data.targetInfo;
NIT: you can destructure this as `let {targetInfo} = event.data;` as you do below
> LayoutTests/http/tests/inspector/target/target-events-for-provisional-page.html:35 > + let targetId = event.data.targetId;
Ditto (21)
> LayoutTests/http/tests/inspector/target/target-events-for-provisional-page.html:39 > + // Wait for page reload event to avoid race between test results flushing and the test completion. > + reloadPromise.then(resolve);
Nice catch! NIT: I'd add a newline before the comment.
Yury Semikhatsky
Comment 19
2019-10-23 11:11:45 PDT
Comment on
attachment 381421
[details]
Patch View in context:
https://bugs.webkit.org/attachment.cgi?id=381421&action=review
>> Source/JavaScriptCore/inspector/agents/InspectorTargetAgent.cpp:135 >> + m_frontendDispatcher->didCommitProvisionalTarget(oldTargetID, buildTargetInfoObject(*target)); > > Would we ever expect the `type` to change? If not, couldn't we simplify this to just send the `oldTargetID` and `newTargetID` and have the frontend reuse the same `WI.Target` by changing it's `_identifier`?
Currently I can't think of any cases where the type would have to change. Changed the event to pass newTargetId instead and reusing TargetInfo from preceding targetCreated events. I don't want to reuse WI.Target instance though as in the next step we'll want to have agents talking to the provisional page before it is committed.
>> Source/JavaScriptCore/inspector/protocol/Target.json:13 >> + { "name": "isProvisional", "type": "boolean", "optional": true, "description": "Whether this is a provisional page target." } > > This doesn't explain what a "provisional" target is. I'd expect some explanation of what that is.
Done.
>> Source/JavaScriptCore/inspector/protocol/Target.json:43 >> + { "name": "previousTargetId", "type": "string", "description": "ID of the target committed target is swapped with." }, > > This is an awkward sentence description. Please rephrase it.
Done.
>> Source/JavaScriptCore/inspector/protocol/Target.json:44 >> + { "name": "targetInfo", "$ref": "TargetInfo", "description": "Committed target info." } > > These types of descriptions aren't very useful. I'd either add more information or remove it.
Changed this to newTargetId instead.
>> Source/WebInspectorUI/UserInterface/Controllers/TargetManager.js:125 >> + this.dispatchEventToListeners(WI.TargetManager.Event.TargetCreated, {targetInfo}); > > Rather than pass the `targetInfo`, can we instead pass the new `WI.Target`? That way, we could use it in non-test code as well (if needed). We could pass `isProvisional` as a separate argument in the object since it's not saved on `WI.Target`. > > NIT: you can drop the `WI` from `WI.TargetManager` since it's in the same class.
We don't create WI.Target for provisional pages yet so there is nothing to pass for them at the moment. We can change the event arguments later depending on the use cases we have. As for WI.TargetManager. prefix, I don't think we can drop it even being in the same class, reference resolution would fail.
>> Source/WebInspectorUI/UserInterface/Controllers/TargetManager.js:131 >> + this._provisionalTargetIds.delete(targetInfo.targetId); > > We should assert that it was previously in the `Set`
Done.
>> Source/WebInspectorUI/UserInterface/Controllers/TargetManager.js:133 >> + this._swappedTargetIds.add(previousTargetId); > > We should assert that it wasn't already in the `Set`
Done.
>> Source/WebInspectorUI/UserInterface/Controllers/TargetManager.js:135 >> + this.dispatchEventToListeners(WI.TargetManager.Event.DidCommitProvisionalTarget, {previousTargetId, targetInfo}); > > Ditto (125)
It wouldn't work. See above.
>> Source/WebInspectorUI/UserInterface/Controllers/TargetManager.js:142 >> + this.dispatchEventToListeners(WI.TargetManager.Event.TargetDestroyed, {targetId}); > > To test even more correctness, we could keep a copy of the `WI.Target` and pass it in here instead of `targetId` so the test can confirm that `isDestroyed` is the right value. > > Although we may not always have a `WI.Target`, such as in the case of `didCommitProvisionalTarget`, so maybe not.
Yeah, the problem with it is that sometimes we don't have target instance here.
>> Source/WebInspectorUI/UserInterface/Controllers/TargetManager.js:145 >> + _targetCreated(parentTarget, targetInfo) > > We should name this function and `_targetDestroyed` to be more active instead of looking/sounding like an event listener callback: > - `_targetCreated` => `_createTarget` (merging with the existing `_createTarget`) > - `_targetDestroyed` => `_destroyTarget` > This way, it also won't be as confusing trying to differentiate between `targetCreated` and `_targetCreated`. > > Also, this function and `_destroyTarget` should be moved into the `// Private` section below.
Good point. Done.
>> Source/WebInspectorUI/UserInterface/Controllers/TargetManager.js:152 >> + console.assert(!this._provisionalTargetIds.has(targetInfo.targetId)); > > I would actually move this assertion before the `if`, because we wouldn't want the same provisional `targetId` to be added twice.
Good point. Done.
>> Source/WebInspectorUI/UserInterface/Controllers/TargetManager.js:168 >> let target = this._targets.get(targetId); > > Style: missing newline
Done.
>> Source/WebInspectorUI/UserInterface/Controllers/TargetManager.js:177 >> let target = this._targets.get(targetId); > > Style: missing newline
Done.
>> Source/WebInspectorUI/UserInterface/Controllers/TargetManager.js:310 >> + // Events below are triggered only by corresponding protocol events. > > This comment isn't really necessary.
Removed.
>> Source/WebInspectorUI/UserInterface/Controllers/TargetManager.js:313 >> + TargetDestroyed: Symbol("target-manager-target-detroyed"), > > NIT: I know that the other events are `Symbol`, but we really don't need to do that, so please just make these strings.
Removed. I'm curious what's the rationale for not using symbols, can you elaborate? Also should we change other event names in WI.TargetManager.Event to be strings for consistency? One advantage of symbols that I see is that it forces clients to use the named constants rather than raw event names when adding listeners.
>> Source/WebInspectorUI/UserInterface/Protocol/Connection.js:324 >> + // ignore such errors. > > We can simplify this to be on one line > ``` > // Ignore errors if the target was destroyed after the command was dispatched. > ```
Done.
>> Source/WebInspectorUI/UserInterface/Protocol/Target.js:165 >> + destroy() { this._isDestroyed = true; } > > Style: we only put functions onto a single line if they're simple getters. Since this is a function, please put the body on separate lines and move it to be below all of the rest of the getters (I'd put this between `addScript` and `hasDomain`).
Done.
>> Source/WebInspectorUI/UserInterface/Views/QuickConsole.js:115 >> + _pageTargetTransisioned() > > Typo: `_pageTargetTransisioned` => `_pageTargetTransitioned`
Done.
>> Source/WebKit/UIProcess/API/APIWebAuthenticationPanel.cpp:37 >> +Ref<WebAuthenticationPanel> WebAuthenticationPanel::create(const AuthenticatorManager& manager, const WTF::String& rpId) > > This should definitely be in a separate change. Also, I think the more "correct" solution would be to add an `#include <wtf/text/WTFString.h>` in the .cpp and `#include <wtf/Forward.h>` in the .h
It is part of this change because otherwise WebKit would fail to compile and it builds fine without my change (so it'd make less sense in isolation). The error is a consequence of WebKit C++ relying on transitive includes. In this case `#include <wtf/Forward.h>` cannot be used in the header because there is a member of type WTF::String in the class. The compiler needs to know full declaration of the string class for the declaration of WebAuthenticationPanel.
>> Source/WebKit/UIProcess/WebPageInspectorController.cpp:191 >> + // FIXME(
webkit.org/b/202937
): do not destroy targets that belong to the committed page. > > NIT: our usual style is `// FIXME: <
https://webkit.org/b/202937
> do not destroy targets that belong to the committed page`
Done.
>> Source/WebKit/WebKit.xcodeproj/project.pbxproj:6271 >> + 37B47E2C1D64DB76005F4EFF /* objcSPI.h */, > > Where did this come from?
Dunno. Current diff with master doesn't have this change.
>> Source/WebKit/WebKit.xcodeproj/project.pbxproj:-9412 >> - 7AA746D523593D8100095050 /* SecItemSPI.h in Headers */, > > Ditto (6271)
Reverted.Done.
>> LayoutTests/http/tests/inspector/target/target-events-for-provisional-page.html:21 >> + let targetInfo = event.data.targetInfo; > > NIT: you can destructure this as `let {targetInfo} = event.data;` as you do below
Done.
>> LayoutTests/http/tests/inspector/target/target-events-for-provisional-page.html:35 >> + let targetId = event.data.targetId; > > Ditto (21)
Done.
>> LayoutTests/http/tests/inspector/target/target-events-for-provisional-page.html:39 >> + reloadPromise.then(resolve); > > Nice catch! > > NIT: I'd add a newline before the comment.
Done.
Yury Semikhatsky
Comment 20
2019-10-23 11:12:55 PDT
Created
attachment 381701
[details]
Patch for landing
Yury Semikhatsky
Comment 21
2019-10-23 11:15:40 PDT
(In reply to Yury Semikhatsky from
comment #20
)
> Created
attachment 381701
[details]
> Patch for landing
I'll wait for
https://webkit.org/b/203262
to land before committing this change.
Devin Rousso
Comment 22
2019-10-23 11:29:28 PDT
Comment on
attachment 381421
[details]
Patch View in context:
https://bugs.webkit.org/attachment.cgi?id=381421&action=review
>>> Source/WebInspectorUI/UserInterface/Controllers/TargetManager.js:313 >>> + TargetDestroyed: Symbol("target-manager-target-detroyed"), >> >> NIT: I know that the other events are `Symbol`, but we really don't need to do that, so please just make these strings. > > Removed. I'm curious what's the rationale for not using symbols, can you elaborate? > > Also should we change other event names in WI.TargetManager.Event to be strings for consistency? > > One advantage of symbols that I see is that it forces clients to use the named constants rather than raw event names when adding listeners.
There's no real need to add the extra overhead of constructing a `Symbol`, especially since all of these are evaluated when Web Inspector first opens. We already force clients to use the named constants through our (informal) style guide, so there's no real benefit there either.
WebKit Commit Bot
Comment 23
2019-10-23 13:14:59 PDT
The commit-queue encountered the following flaky tests while processing
attachment 381701
[details]
: media/modern-media-controls/compact-media-controls/compact-media-controls-constructor.html
bug 193587
(author:
graouts@apple.com
) The commit-queue is continuing to process your patch.
WebKit Commit Bot
Comment 24
2019-10-23 13:16:08 PDT
Comment on
attachment 381701
[details]
Patch for landing Clearing flags on attachment: 381701 Committed
r251494
: <
https://trac.webkit.org/changeset/251494
>
WebKit Commit Bot
Comment 25
2019-10-23 13:16:11 PDT
All reviewed patches have been landed. Closing bug.
Radar WebKit Bug Importer
Comment 26
2019-10-23 13:17:15 PDT
<
rdar://problem/56551422
>
Truitt Savell
Comment 27
2019-11-04 16:01:25 PST
The new test http/tests/inspector/target/target-events-for-provisional-page.html added in
https://trac.webkit.org/changeset/251494/webkit
is a flakey failure:
https://results.webkit.org/?suite=layout-tests&test=http%2Ftests%2Finspector%2Ftarget%2Ftarget-events-for-provisional-page.html
Diff: --- /Volumes/Data/slave/mojave-release-tests-wk2/build/layout-test-results/http/tests/inspector/target/target-events-for-provisional-page-expected.txt +++ /Volumes/Data/slave/mojave-release-tests-wk2/build/layout-test-results/http/tests/inspector/target/target-events-for-provisional-page-actual.txt @@ -6,11 +6,5 @@ == Running test suite: Target.PSON -- Running test case: ProvisionalPageTarget -PASS: Should receive targetCreated event. -PASS: Target should be provisional. -PASS: Should receive didCommitProvisionalTarget event. -PASS: Previous target should be the current one. -PASS: Committed target should match provisional target. -PASS: Should receive targetDestroyed event. -PASS: Destroyed target should be previous target. +!! TIMEOUT: took longer than 10000ms
Yury Semikhatsky
Comment 28
2019-11-07 09:53:59 PST
(In reply to Truitt Savell from
comment #27
)
> The new test > http/tests/inspector/target/target-events-for-provisional-page.html > > added in
https://trac.webkit.org/changeset/251494/webkit
> > is a flakey failure: >
https://results.webkit.org/?suite=layout
- > tests&test=http%2Ftests%2Finspector%2Ftarget%2Ftarget-events-for-provisional- > page.html > > Diff: > --- > /Volumes/Data/slave/mojave-release-tests-wk2/build/layout-test-results/http/ > tests/inspector/target/target-events-for-provisional-page-expected.txt > +++ > /Volumes/Data/slave/mojave-release-tests-wk2/build/layout-test-results/http/ > tests/inspector/target/target-events-for-provisional-page-actual.txt > @@ -6,11 +6,5 @@ > > == Running test suite: Target.PSON > -- Running test case: ProvisionalPageTarget > -PASS: Should receive targetCreated event. > -PASS: Target should be provisional. > -PASS: Should receive didCommitProvisionalTarget event. > -PASS: Previous target should be the current one. > -PASS: Committed target should match provisional target. > -PASS: Should receive targetDestroyed event. > -PASS: Destroyed target should be previous target. > +!! TIMEOUT: took longer than 10000ms
Filed
https://bugs.webkit.org/show_bug.cgi?id=203965
for tracking this. Looks like one of the previous tests disables PSON in the inspected page.
Note
You need to
log in
before you can comment on or make changes to this bug.
Top of Page
Format For Printing
XML
Clone This Bug