Bug 202061

Summary: SubFrameSOAuthorizationSession should ensure messages are posted in the right order to the parent frame
Product: WebKit Reporter: Jiewen Tan <jiewen_tan>
Component: WebKit Misc.Assignee: Jiewen Tan <jiewen_tan>
Status: NEW ---    
Severity: Normal CC: cdumez, commit-queue, jiewen_tan, webkit-bug-importer, youennf
Priority: P2 Keywords: InRadar
Version: WebKit Nightly Build   
Hardware: Unspecified   
OS: Unspecified   
Attachments:
Description Flags
Patch
none
Patch
none
Patch
youennf: review+
Patch for landing none

Description Jiewen Tan 2019-09-20 15:53:28 PDT
SubFrameSOAuthorizationSession should ensure messages are posted in order to the parent frame.
Comment 1 Jiewen Tan 2019-09-20 15:54:20 PDT
<rdar://problem/55485666>
Comment 2 Jiewen Tan 2019-09-20 16:41:17 PDT
Created attachment 379283 [details]
Patch
Comment 3 youenn fablet 2019-09-25 06:56:29 PDT
Comment on attachment 379283 [details]
Patch

View in context: https://bugs.webkit.org/attachment.cgi?id=379283&action=review

> Source/WebKit/UIProcess/Cocoa/SOAuthorization/SubFrameSOAuthorizationSession.mm:66
> +    if (auto* frame = page->process().webFrame(*m_frameID))

What guarantees that m_frameID is not null?

> Source/WebKit/UIProcess/Cocoa/SOAuthorization/SubFrameSOAuthorizationSession.mm:73
> +    appendRequestToLoad(URL(navigationAction()->request().url()), IPC::DataReference(reinterpret_cast<const uint8_t*>(soAuthorizationPostDidCancelMessageToParent), strlen(soAuthorizationPostDidCancelMessageToParent)).vector());

Is there a more direct way to create a Vector<uint8_t> from a null terminated string?
If not, I would add a static routine to ease readability since this is also used below.

> Source/WebKit/UIProcess/Cocoa/SOAuthorization/SubFrameSOAuthorizationSession.mm:74
> +    appendRequestToLoad(URL(navigationAction()->request().url()), String(navigationAction()->request().httpReferrer()));

Should soAuthorizationPostDidCancelMessageToParent do both the postMessage and the navigation (through window.location for instance)  or do we prefer to have them as two different tasks?

> Source/WebKit/UIProcess/Cocoa/SOAuthorization/SubFrameSOAuthorizationSession.mm:100
> +    if (m_requestsToLoad.first().first != url)

I think this is ok but just in case, are we 100% sure m_requestsToLoad cannot be empty here?

> Source/WebKit/UIProcess/FrameLoadState.h:78
> +    HashMap<Observer*, WeakPtr<Observer>> m_observers;

Can we use a WeakHashSet?
Comment 4 Jiewen Tan 2019-09-25 12:18:01 PDT
Comment on attachment 379283 [details]
Patch

View in context: https://bugs.webkit.org/attachment.cgi?id=379283&action=review

Thanks Youenn for taking a look.

>> Source/WebKit/UIProcess/Cocoa/SOAuthorization/SubFrameSOAuthorizationSession.mm:66
>> +    if (auto* frame = page->process().webFrame(*m_frameID))
> 
> What guarantees that m_frameID is not null?

Right, thanks for pointing it out.

>> Source/WebKit/UIProcess/Cocoa/SOAuthorization/SubFrameSOAuthorizationSession.mm:73
>> +    appendRequestToLoad(URL(navigationAction()->request().url()), IPC::DataReference(reinterpret_cast<const uint8_t*>(soAuthorizationPostDidCancelMessageToParent), strlen(soAuthorizationPostDidCancelMessageToParent)).vector());
> 
> Is there a more direct way to create a Vector<uint8_t> from a null terminated string?
> If not, I would add a static routine to ease readability since this is also used below.

Sure, I will make a static helper that replicates what the method is doing. Maybe we should consider a Vector constructor that do the magic.

>> Source/WebKit/UIProcess/Cocoa/SOAuthorization/SubFrameSOAuthorizationSession.mm:74
>> +    appendRequestToLoad(URL(navigationAction()->request().url()), String(navigationAction()->request().httpReferrer()));
> 
> Should soAuthorizationPostDidCancelMessageToParent do both the postMessage and the navigation (through window.location for instance)  or do we prefer to have them as two different tasks?

Not sure if there is a way to preserve the http referrer in JS.

>> Source/WebKit/UIProcess/Cocoa/SOAuthorization/SubFrameSOAuthorizationSession.mm:100
>> +    if (m_requestsToLoad.first().first != url)
> 
> I think this is ok but just in case, are we 100% sure m_requestsToLoad cannot be empty here?

By design, yes. I will add an assertion.

> Source/WebKit/UIProcess/FrameLoadState.h:47
> +        virtual void didFinishLoad(const URL&) = 0;

Maybe we don't need to pass a URL?

>> Source/WebKit/UIProcess/FrameLoadState.h:78
>> +    HashMap<Observer*, WeakPtr<Observer>> m_observers;
> 
> Can we use a WeakHashSet?

I like new wtf helpers!!!
Comment 5 Jiewen Tan 2019-09-25 15:29:56 PDT
Comment on attachment 379283 [details]
Patch

View in context: https://bugs.webkit.org/attachment.cgi?id=379283&action=review

>>> Source/WebKit/UIProcess/FrameLoadState.h:78
>>> +    HashMap<Observer*, WeakPtr<Observer>> m_observers;
>> 
>> Can we use a WeakHashSet?
> 
> I like new wtf helpers!!!

It looks like WeakHashSet can't be copied. And nether does HashSet. Not sure why. And also not sure if I should make WeakHashSet copiable.
Comment 6 Jiewen Tan 2019-09-25 15:56:35 PDT
Comment on attachment 379283 [details]
Patch

View in context: https://bugs.webkit.org/attachment.cgi?id=379283&action=review

>>>> Source/WebKit/UIProcess/FrameLoadState.h:78
>>>> +    HashMap<Observer*, WeakPtr<Observer>> m_observers;
>>> 
>>> Can we use a WeakHashSet?
>> 
>> I like new wtf helpers!!!
> 
> It looks like WeakHashSet can't be copied. And nether does HashSet. Not sure why. And also not sure if I should make WeakHashSet copiable.

Filed Bug 202248 as a follow up.
Comment 7 Jiewen Tan 2019-09-25 16:00:01 PDT
Created attachment 379587 [details]
Patch
Comment 8 youenn fablet 2019-09-26 01:19:25 PDT
Comment on attachment 379587 [details]
Patch

View in context: https://bugs.webkit.org/attachment.cgi?id=379587&action=review

> Source/WebKit/UIProcess/Cocoa/SOAuthorization/SubFrameSOAuthorizationSession.mm:65
> +    if (auto* targetFrame = this->navigationAction()->targetFrame()) {

Looking at SubFrameSOAuthorizationSession::create, I believe we always have a FrameID.
It might be simpler to pass it as a parameter and make m_frameID not Optional.

> Source/WebKit/UIProcess/Cocoa/SOAuthorization/SubFrameSOAuthorizationSession.mm:98
> +    appendRequestToLoad(URL(response.url()), IPC::DataReference(reinterpret_cast<const uint8_t*>(data.bytes), data.length).vector());

Could use convertBytesToVector

> Source/WebKit/UIProcess/FrameLoadState.cpp:93
> +    auto observersCopy = m_observers;

A hashmap copy is probably more expensive than creating a Vector of values.
Maybe we could use a WeakHashSet for m_observers and a Vector<Observer*> for observersCopy.

> Source/WebKit/UIProcess/WebProcessPool.cpp:44
> +#include "LegacyGlobalSettings.h"

Is it needed?
Comment 9 Jiewen Tan 2019-09-26 02:50:15 PDT
Comment on attachment 379587 [details]
Patch

View in context: https://bugs.webkit.org/attachment.cgi?id=379587&action=review

>> Source/WebKit/UIProcess/Cocoa/SOAuthorization/SubFrameSOAuthorizationSession.mm:65
>> +    if (auto* targetFrame = this->navigationAction()->targetFrame()) {
> 
> Looking at SubFrameSOAuthorizationSession::create, I believe we always have a FrameID.
> It might be simpler to pass it as a parameter and make m_frameID not Optional.

Sounds good. Fixed.

>> Source/WebKit/UIProcess/Cocoa/SOAuthorization/SubFrameSOAuthorizationSession.mm:98
>> +    appendRequestToLoad(URL(response.url()), IPC::DataReference(reinterpret_cast<const uint8_t*>(data.bytes), data.length).vector());
> 
> Could use convertBytesToVector

Good catch!

>> Source/WebKit/UIProcess/FrameLoadState.cpp:93
>> +    auto observersCopy = m_observers;
> 
> A hashmap copy is probably more expensive than creating a Vector of values.
> Maybe we could use a WeakHashSet for m_observers and a Vector<Observer*> for observersCopy.

Fixed. A good idea!

>> Source/WebKit/UIProcess/WebProcessPool.cpp:44
>> +#include "LegacyGlobalSettings.h"
> 
> Is it needed?

I made some arrangement of Sources.txt during the development and discover this lack of header. Just did it for someone else's convenience.
Comment 10 Jiewen Tan 2019-09-26 02:52:14 PDT
Created attachment 379628 [details]
Patch
Comment 11 youenn fablet 2019-09-26 22:49:14 PDT
Comment on attachment 379628 [details]
Patch

View in context: https://bugs.webkit.org/attachment.cgi?id=379628&action=review

> Source/WebKit/UIProcess/Cocoa/SOAuthorization/SubFrameSOAuthorizationSession.mm:-107
> -    if (!page || !navigationActionPtr)

We were doing a page check here and no longer now.
Might be safer to keep it.

> Source/WebKit/UIProcess/FrameLoadState.cpp:95
> +        observersCopy.append(&observer);

We can use uncheckedAppend/resverInitialCapacity.
Or better, just use copyToVector if working or WTF::map(m_observers, [](auto& observer) { return observer.get(); });
Comment 12 Jiewen Tan 2019-09-26 23:00:36 PDT
Comment on attachment 379628 [details]
Patch

View in context: https://bugs.webkit.org/attachment.cgi?id=379628&action=review

Thanks Youenn for r+ the patch.

>> Source/WebKit/UIProcess/Cocoa/SOAuthorization/SubFrameSOAuthorizationSession.mm:-107
>> -    if (!page || !navigationActionPtr)
> 
> We were doing a page check here and no longer now.
> Might be safer to keep it.

Sure.

>> Source/WebKit/UIProcess/FrameLoadState.cpp:95
>> +        observersCopy.append(&observer);
> 
> We can use uncheckedAppend/resverInitialCapacity.
> Or better, just use copyToVector if working or WTF::map(m_observers, [](auto& observer) { return observer.get(); });

I was thinking about Vector.appendRange but then it doesn't work. It definitely looks much better!
Comment 13 Jiewen Tan 2019-09-26 23:26:17 PDT
Comment on attachment 379628 [details]
Patch

View in context: https://bugs.webkit.org/attachment.cgi?id=379628&action=review

>>> Source/WebKit/UIProcess/FrameLoadState.cpp:95
>>> +        observersCopy.append(&observer);
>> 
>> We can use uncheckedAppend/resverInitialCapacity.
>> Or better, just use copyToVector if working or WTF::map(m_observers, [](auto& observer) { return observer.get(); });
> 
> I was thinking about Vector.appendRange but then it doesn't work. It definitely looks much better!

WeakHashSet uses computeSize() instead of size(), and therefore WTF::map doesn't work.
Comment 14 Jiewen Tan 2019-09-26 23:29:25 PDT
Created attachment 379713 [details]
Patch for landing
Comment 15 WebKit Commit Bot 2019-09-27 00:14:03 PDT
Comment on attachment 379713 [details]
Patch for landing

Clearing flags on attachment: 379713

Committed r250416: <https://trac.webkit.org/changeset/250416>