Bug 198923 - Support ITP on a per-session basis
Summary: Support ITP on a per-session basis
Status: RESOLVED FIXED
Alias: None
Product: WebKit
Classification: Unclassified
Component: WebKit2 (show other bugs)
Version: Safari 10
Hardware: Unspecified Unspecified
: P2 Normal
Assignee: Kate Cheney
URL:
Keywords: InRadar
Depends on:
Blocks:
 
Reported: 2019-06-17 10:27 PDT by Brent Fulgham
Modified: 2019-09-16 09:39 PDT (History)
10 users (show)

See Also:


Attachments
Patch (24.66 KB, patch)
2019-08-21 17:31 PDT, Kate Cheney
no flags Details | Formatted Diff | Diff
Patch (26.14 KB, patch)
2019-08-22 16:41 PDT, Kate Cheney
no flags Details | Formatted Diff | Diff
Patch (26.03 KB, patch)
2019-08-23 09:39 PDT, Kate Cheney
no flags Details | Formatted Diff | Diff
Patch (26.05 KB, patch)
2019-08-23 10:27 PDT, Kate Cheney
no flags Details | Formatted Diff | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description Brent Fulgham 2019-06-17 10:27:14 PDT
ITP should be controllable on a per-session basis, for example to allow different ITP behavior for ephemeral sessions. Currently there is only a single global flag controlling behavior.
Comment 1 Radar WebKit Bug Importer 2019-08-12 10:06:08 PDT
<rdar://problem/54213854>
Comment 2 Kate Cheney 2019-08-21 17:31:24 PDT
Created attachment 376954 [details]
Patch
Comment 3 Daniel Bates 2019-08-21 20:04:33 PDT
Comment on attachment 376954 [details]
Patch

This change looks good. In my opinion this patch would benefit by defining a type alias for HashMap<PAL::SessionID, Vector<ResourceLoadStatistics>> because:

1. It’s long to type out this type.
2. Less chance for misspelling with a shorter type => less re-compiles => increase developer productivity.
3. The alias’s name could be more succinct/canonical and easier to refer to both in new code and conversations about this code.
4. Allow us to re-define this type later in one central place, reducing the amount of future code changes.
Comment 4 youenn fablet 2019-08-22 01:49:48 PDT
Comment on attachment 376954 [details]
Patch

Patch looks almost ready to me as well.
A couple of small improvements below.
The main change to consider is whether we really need to transfer a map<sessionID, statistics> from WebProcess to NetworkProcess.
Passing a Vector would probably be more efficient, which could impact the notification callback signature.

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

> Source/WebCore/loader/ResourceLoadObserver.cpp:57
> +void ResourceLoadObserver::setStatisticsUpdatedCallback(WTF::Function<void(HashMap<PAL::SessionID, Vector<ResourceLoadStatistics>>)>&& notificationCallback)

No need for WTF:: here and in setRequestStorageAccessUnderOpenerCallback below.

> Source/WebCore/loader/ResourceLoadObserver.cpp:365
> +        addResult.iterator->value = makeUnique<HashMap<RegistrableDomain, ResourceLoadStatistics>>();

You can use m_perSessionResourceStatisticsMap.ensure here.

> Source/WebCore/loader/ResourceLoadObserver.cpp:400
> +            statistics.uncheckedAppend(WTFMove(statistic));

You move statistic but statistic will stay in m_perSessionResourceStatisticsMap.
Is it by design?
This might be okish here but maybe we can improve things.
1. Copy instead of move although I guess this is not what we want here.
2. Clear m_perSessionResourceStatisticsMap. Probably fine but maybe this is not done for perf reasons?
3. Add a take method to ResourceLoadStatistics and call statistics.uncheckedAppend(statistic.take()) here. The take method will be responsible to move statistic internals and keep it in a proper state.

> Source/WebCore/loader/ResourceLoadObserver.h:76
> +    WEBCORE_EXPORT void setStatisticsUpdatedCallback(WTF::Function<void(HashMap<PAL::SessionID, Vector<ResourceLoadStatistics>>)>&&);

No need for WTF::

> Source/WebKit/NetworkProcess/NetworkConnectionToWebProcess.cpp:715
> +void NetworkConnectionToWebProcess::resourceLoadStatisticsUpdated(HashMap<PAL::SessionID, Vector<ResourceLoadStatistics>>&& statistics)

There is no real need to have a HashMap here, a Vector<struct {SessionID, ResourceLoadStatistics}> would be good enough and probably more efficient.

> Source/WebKit/WebProcess/WebProcess.cpp:221
>          ensureNetworkProcessConnection().connection().send(Messages::NetworkConnectionToWebProcess::ResourceLoadStatisticsUpdated(WTFMove(statistics)), 0);

I believe there is no need to WTFMove(statistics) here
Comment 5 Kate Cheney 2019-08-22 11:57:01 PDT
(In reply to youenn fablet from comment #4)
> Comment on attachment 376954 [details]
> Patch
> 
> Patch looks almost ready to me as well.
> A couple of small improvements below.
> The main change to consider is whether we really need to transfer a
> map<sessionID, statistics> from WebProcess to NetworkProcess.
> Passing a Vector would probably be more efficient, which could impact the
> notification callback signature.

Thanks for the feedback! I'm updating the patch now and had some followup questions.

> 
> View in context:
> https://bugs.webkit.org/attachment.cgi?id=376954&action=review
> 
> > Source/WebCore/loader/ResourceLoadObserver.cpp:57
> > +void ResourceLoadObserver::setStatisticsUpdatedCallback(WTF::Function<void(HashMap<PAL::SessionID, Vector<ResourceLoadStatistics>>)>&& notificationCallback)
> 
> No need for WTF:: here and in setRequestStorageAccessUnderOpenerCallback
> below.

Yes, you're right -- thanks.

> 
> > Source/WebCore/loader/ResourceLoadObserver.cpp:365
> > +        addResult.iterator->value = makeUnique<HashMap<RegistrableDomain, ResourceLoadStatistics>>();
> 
> You can use m_perSessionResourceStatisticsMap.ensure here.
> 

I think add is more readable. However, if there is a performance reason to use ensure I will happily change it.

> > Source/WebCore/loader/ResourceLoadObserver.cpp:400
> > +            statistics.uncheckedAppend(WTFMove(statistic));
> 
> You move statistic but statistic will stay in
> m_perSessionResourceStatisticsMap.
> Is it by design?
> This might be okish here but maybe we can improve things.
> 1. Copy instead of move although I guess this is not what we want here.
> 2. Clear m_perSessionResourceStatisticsMap. Probably fine but maybe this is
> not done for perf reasons?
> 3. Add a take method to ResourceLoadStatistics and call
> statistics.uncheckedAppend(statistic.take()) here. The take method will be
> responsible to move statistic internals and keep it in a proper state.
> 

Still looking into this... I agree it is weird. Thanks for the suggestions! 

> > Source/WebCore/loader/ResourceLoadObserver.h:76
> > +    WEBCORE_EXPORT void setStatisticsUpdatedCallback(WTF::Function<void(HashMap<PAL::SessionID, Vector<ResourceLoadStatistics>>)>&&);
> 
> No need for WTF::
> 

Got it. 

> > Source/WebKit/NetworkProcess/NetworkConnectionToWebProcess.cpp:715
> > +void NetworkConnectionToWebProcess::resourceLoadStatisticsUpdated(HashMap<PAL::SessionID, Vector<ResourceLoadStatistics>>&& statistics)
> 
> There is no real need to have a HashMap here, a Vector<struct {SessionID,
> ResourceLoadStatistics}> would be good enough and probably more efficient.
> 

Sounds good. Would a Vector of tuples or pairs be easier than declaring a new struct?

> > Source/WebKit/WebProcess/WebProcess.cpp:221
> >          ensureNetworkProcessConnection().connection().send(Messages::NetworkConnectionToWebProcess::ResourceLoadStatisticsUpdated(WTFMove(statistics)), 0);
> 
> I believe there is no need to WTFMove(statistics) here

Okay. I'm not familiar with why -- can we be sure that statistics won't be copied without the WTFMove?
Comment 6 Chris Dumez 2019-08-22 12:11:51 PDT
Comment on attachment 376954 [details]
Patch

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

>>> Source/WebCore/loader/ResourceLoadObserver.cpp:365
>>> +        addResult.iterator->value = makeUnique<HashMap<RegistrableDomain, ResourceLoadStatistics>>();
>> 
>> You can use m_perSessionResourceStatisticsMap.ensure here.
> 
> I think add is more readable. However, if there is a performance reason to use ensure I will happily change it.

ah ah, I made the same comment than Youenn offline. It feel very weird to add nullptr and then overwrite the value with something else, now that we have ensure(), not to mention this is unnecessary work. I do believe ensure() is faster for this reason, but I have not measured.

> Source/WebCore/loader/ResourceLoadObserver.cpp:380
> +    auto mapIter = m_perSessionResourceStatisticsMap.find(sessionID);

I think this would look better with a get() than a find().

> Source/WebCore/loader/ResourceLoadObserver.cpp:-390
> -    m_resourceStatisticsMap.clear();

Is it me or is m_resourceStatisticsMap no longer cleared now? This seems like a bug.

>>> Source/WebKit/NetworkProcess/NetworkConnectionToWebProcess.cpp:715
>>> +void NetworkConnectionToWebProcess::resourceLoadStatisticsUpdated(HashMap<PAL::SessionID, Vector<ResourceLoadStatistics>>&& statistics)
>> 
>> There is no real need to have a HashMap here, a Vector<struct {SessionID, ResourceLoadStatistics}> would be good enough and probably more efficient.
> 
> Sounds good. Would a Vector of tuples or pairs be easier than declaring a new struct?

Yes, a vector of std::pair would be fine IMO.

>>> Source/WebKit/WebProcess/WebProcess.cpp:221
>>>          ensureNetworkProcessConnection().connection().send(Messages::NetworkConnectionToWebProcess::ResourceLoadStatisticsUpdated(WTFMove(statistics)), 0);
>> 
>> I believe there is no need to WTFMove(statistics) here
> 
> Okay. I'm not familiar with why -- can we be sure that statistics won't be copied without the WTFMove?

The WTFMove() does not hurt here, it also does not do anything. I would just keep it personally.
Comment 7 youenn fablet 2019-08-22 12:50:36 PDT
> >> I believe there is no need to WTFMove(statistics) here
> > 
> > Okay. I'm not familiar with why -- can we be sure that statistics won't be copied without the WTFMove?

The IPC message is taking a const reference so the WTFMove has no runtime impact.

> 
> The WTFMove() does not hurt here, it also does not do anything. I would just
> keep it personally.

Agreed it has no runtime impact but it is misleading when reading the code.
For instance, it gives the false impression that the callback should be given an r-value. In practice, a const ref is sufficient.
I would remove it.
Comment 8 youenn fablet 2019-08-22 12:53:29 PDT
> Sounds good. Would a Vector of tuples or pairs be easier than declaring a
> new struct?

I usually personally prefer a struct over a pair as I find the code easier to read.
In this particular case though, the struct is mainly for IPC and we would need to add encode/decode for these routines.
This is given for free with a pair so a pair is probably the way to go.
Comment 9 Chris Dumez 2019-08-22 13:08:51 PDT
(In reply to youenn fablet from comment #7)
> > >> I believe there is no need to WTFMove(statistics) here
> > > 
> > > Okay. I'm not familiar with why -- can we be sure that statistics won't be copied without the WTFMove?
> 
> The IPC message is taking a const reference so the WTFMove has no runtime
> impact.
> 
> > 
> > The WTFMove() does not hurt here, it also does not do anything. I would just
> > keep it personally.
> 
> Agreed it has no runtime impact but it is misleading when reading the code.
> For instance, it gives the false impression that the callback should be
> given an r-value. In practice, a const ref is sufficient.
> I would remove it.

I don't feel as strongly as you so whatever, but to me WTFMove() is merely a cast indicating to the callee that it may take the value because the current method does not need it anymore. The callee may or may not to do now (or in the future). The point here is that the caller definitely does not need that statistics anymore, it is merely forwarding them to the IPC so I feel WTFMove() is appropriate, even if the particular callee does not leverage the r-value reference right now.
Comment 10 Kate Cheney 2019-08-22 16:41:48 PDT
Created attachment 377075 [details]
Patch
Comment 11 Chris Dumez 2019-08-22 17:05:10 PDT
Comment on attachment 377075 [details]
Patch

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

> Source/WebCore/loader/ResourceLoadObserver.cpp:57
> +void ResourceLoadObserver::setStatisticsUpdatedCallback(Function<void(ResourceLoadObserver::PerSessionResourceLoadData)>&& notificationCallback)

ResourceLoadObserver:: should not be needed.

> Source/WebCore/loader/ResourceLoadObserver.cpp:380
> +    auto resourceStatisticsByDomain = m_perSessionResourceStatisticsMap.get(sessionID);

auto* to make it clear it is a raw pointer.

> Source/WebCore/loader/ResourceLoadObserver.cpp:391
> +ResourceLoadObserver::PerSessionResourceLoadData ResourceLoadObserver::takeStatistics()

I personally like:
auto ResourceLoadObserver::takeStatistics() -> PerSessionResourceLoadData

so that ResourceLoadObserver:: scope is not needed, but your call.

> Source/WebCore/loader/ResourceLoadObserver.cpp:393
> +    ResourceLoadObserver::PerSessionResourceLoadData perSessionStatistics;

ResourceLoadObserver:: should not be needed.

> Source/WebCore/loader/ResourceLoadObserver.cpp:402
> +        perSessionStatistics.uncheckedAppend(std::make_pair(iter.key, WTFMove(statistics)));

uncheckedAppend() is unsafe here since you did not reserve capacity. This should just be an append().

> Source/WebCore/loader/ResourceLoadObserver.h:62
> +    typedef Vector<std::pair<PAL::SessionID, Vector<ResourceLoadStatistics>>> PerSessionResourceLoadData;

I think we like using statements better nowadays:
using PerSessionResourceLoadData = Vector<std::pair<PAL::SessionID, Vector<ResourceLoadStatistics>>>;

> Source/WebCore/loader/ResourceLoadObserver.h:77
> +    WEBCORE_EXPORT void setStatisticsUpdatedCallback(Function<void(PerSessionResourceLoadData)>&&);

PerSessionResourceLoadData&&, not a copy.

> Source/WebKit/NetworkProcess/NetworkConnectionToWebProcess.h:226
> +        void resourceLoadStatisticsUpdated(WebCore::ResourceLoadObserver::PerSessionResourceLoadData&&);

indentation problem

> Source/WebKit/WebProcess/WebProcess.cpp:220
> +    ResourceLoadObserver::shared().setStatisticsUpdatedCallback([this] (ResourceLoadObserver::PerSessionResourceLoadData&& statistics) {

I believe auto&& would work here.
Comment 12 Kate Cheney 2019-08-23 09:39:43 PDT
Created attachment 377129 [details]
Patch
Comment 13 Kate Cheney 2019-08-23 09:40:14 PDT
Thanks Chris!
Comment 14 Chris Dumez 2019-08-23 10:19:21 PDT
Comment on attachment 377129 [details]
Patch

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

r=me with fix.

> Source/WebCore/loader/ResourceLoadObserver.cpp:403
> +        iter.value->clear();

Rather than doing this, I would do m_perSessionResourceStatisticsMap.clear() *after* the loop. No reason to keep the sessionIDs in the map.
Comment 15 Kate Cheney 2019-08-23 10:27:03 PDT
Created attachment 377133 [details]
Patch
Comment 16 Chris Dumez 2019-08-23 10:32:15 PDT
Comment on attachment 377133 [details]
Patch

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

> Source/WebCore/ChangeLog:6
> +        Reviewed by NOBODY (OOPS!).

Once you get a r+ with changes, you can already put the reviewer's name in the change logs so that the reviewer does not have to r+ again. Just so you know in the future, I will r+ again here.
Comment 17 Kate Cheney 2019-08-23 10:34:10 PDT
(In reply to Chris Dumez from comment #16)
> Comment on attachment 377133 [details]
> Patch
> 
> View in context:
> https://bugs.webkit.org/attachment.cgi?id=377133&action=review
> 
> > Source/WebCore/ChangeLog:6
> > +        Reviewed by NOBODY (OOPS!).
> 
> Once you get a r+ with changes, you can already put the reviewer's name in
> the change logs so that the reviewer does not have to r+ again. Just so you
> know in the future, I will r+ again here.

Thanks! I'll make sure to do this next time
Comment 18 WebKit Commit Bot 2019-08-23 11:14:49 PDT
Comment on attachment 377133 [details]
Patch

Clearing flags on attachment: 377133

Committed r249056: <https://trac.webkit.org/changeset/249056>
Comment 19 WebKit Commit Bot 2019-08-23 11:14:51 PDT
All reviewed patches have been landed.  Closing bug.