Bug 168230 - [GTK] Update cookie manager API to properly work with ephemeral sessions
Summary: [GTK] Update cookie manager API to properly work with ephemeral sessions
Status: RESOLVED FIXED
Alias: None
Product: WebKit
Classification: Unclassified
Component: WebKitGTK (show other bugs)
Version: WebKit Local Build
Hardware: Unspecified Unspecified
: P2 Normal
Assignee: Nobody
URL:
Keywords: Gtk
Depends on: 168229
Blocks:
  Show dependency treegraph
 
Reported: 2017-02-13 05:09 PST by Carlos Garcia Campos
Modified: 2017-02-15 11:00 PST (History)
2 users (show)

See Also:


Attachments
Patch (57.53 KB, patch)
2017-02-13 05:24 PST, Carlos Garcia Campos
mcatanzaro: review-
Details | Formatted Diff | Diff
Patch (57.36 KB, patch)
2017-02-14 03:43 PST, Carlos Garcia Campos
mcatanzaro: review+
Details | Formatted Diff | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description Carlos Garcia Campos 2017-02-13 05:09:14 PST
WebKitCookieManager is associated to a particular WebKitWebContexst and uses the default session ID unconditionally.
Comment 1 Carlos Garcia Campos 2017-02-13 05:24:50 PST
Created attachment 301345 [details]
Patch
Comment 2 Michael Catanzaro 2017-02-13 17:59:45 PST
Comment on attachment 301345 [details]
Patch

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

It looks mostly good, but I'd like to review this one again after you answer my questions about why you used the weak pointer, which I hope was just a mistake.

> Source/WebCore/platform/network/soup/CookieJarSoup.cpp:217
> +    // FIXME: Add support for deleting cookies modified since the given timestamp. It should probably be added to libsoup.
> +    if (timestamp == std::chrono::system_clock::from_time_t(0))
> +        deleteAllCookies(session);

Are you planning to fix this soon? I don't think we should proceed with these API changes if the API does not work properly. At least add a runtime warning using g_warning().

> Source/WebKit2/UIProcess/API/gtk/WebKitCookieManager.cpp:40
> + * The WebKitCookieManager defines how to setup and handle cookies.

setup (noun) -> set up (verb)

> Source/WebKit2/UIProcess/API/gtk/WebKitCookieManager.cpp:43
>   * store cookies, with webkit_cookie_manager_set_persistent_storage(),

Remove the comma

> Source/WebKit2/UIProcess/API/gtk/WebKitCookieManager.cpp:144
> +    g_object_add_weak_pointer(G_OBJECT(dataManager), reinterpret_cast<void**>(&manager->priv->dataManager));

Why is the weak pointer needed? I would expect WebKitCookieManager to be owned by the WebKitWebsiteDataManager, so WebKitWebsiteDataManager would keep a ref to ensure the WebKitCookieManager is never destroyed first. Is there some really good reason you don't do that? I think it should be a normal raw pointer instead.

> Source/WebKit2/UIProcess/API/gtk/WebKitCookieManager.cpp:165
>   * By default, @cookie_manager doesn't store the cookies persistenly, so you need to call this

Preexisting problem, but let's fix it now: persistenly -> persistently

> Source/WebKit2/UIProcess/API/gtk/WebKitCookieManager.cpp:176
> +    for (auto* processPool : webkitWebsiteDataManagerGetProcessPools(manager->priv->dataManager)) {

This is a big problem. Either manager->priv->dataManager can be legitimately null here, or you should not have used a weak pointer.

> Source/WebKit2/UIProcess/API/gtk/WebKitCookieManager.cpp:197
> +    g_return_if_fail(WEBKIT_IS_WEBSITE_DATA_MANAGER(manager->priv->dataManager));

Ditto. If you're going to use the weak pointer, then the entire class needs to be prepared to deal with the WebKitWebsiteDataManager being null. There's no point to the weak pointer otherwise.

> Source/WebKit2/UIProcess/API/gtk/WebKitWebContext.cpp:82
>   * webkit_web_context_get_security_manager() for that.

Remove "for that": the sentence works better without them.

> Source/WebKit2/UIProcess/API/gtk/WebKitWebContext.cpp:698
>  WebKitCookieManager* webkit_web_context_get_cookie_manager(WebKitWebContext* context)

I think you should document that this function returns the WebKitCookieManager of this context's WebKitWebsiteDataManager. I know it's an implementation detail, but otherwise I think it's kind of confusing why both WebKitWebContext and WebKitWebsiteDataManager have a WebKitCookieManager.

> Source/WebKit2/UIProcess/API/gtk/WebKitWebView.cpp:2286
> + * Get the #WebKitWebsiteDataManager associated to @web_view. If @web_view is not ephemeral

Add a comma after "ephemeral"

> Source/WebKit2/UIProcess/API/gtk/WebKitWebView.cpp:2287
> + * the returned #WebKitWebsiteDataManager will be the same as the #WebKitWebView:web-context one.

"the #WebKitWebView:web-context one" doesn't sound great. I would write: "will be the same as the #WebKitWebsiteDataManager of @web_view's #WebKitWebContext."

> Source/WebKit2/UIProcess/API/gtk/WebKitWebsiteDataManager.cpp:103
> +    GRefPtr<WebKitCookieManager> cookieManager;

Aha, so you do keep a ref! Good! Then you don't need the weak pointer in WebKitCookieManager, right? Surely the WebKitCookieManager cannot outlive the WebKitWebsiteDataManager due to this ref.

> Source/WebKit2/UIProcess/API/gtk/WebKitWebsiteDataManager.cpp:104
> +    Vector<WebProcessPool*> processPools;

Is it possible to use Vector<WebProcessPool&> to clarify that the process pools are not null?

> Source/WebKit2/UIProcess/WebsiteData/WebsiteDataRecord.cpp:54
> +#if PLATFORM(GTK)
> +    if (hostName == "localhost")
> +        return hostName;
> +#endif

I think this should be an #else condition, not a GTK-specific condition.
Comment 3 Michael Catanzaro 2017-02-13 18:08:07 PST
Comment on attachment 301345 [details]
Patch

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

>> Source/WebCore/platform/network/soup/CookieJarSoup.cpp:217
>> +        deleteAllCookies(session);
> 
> Are you planning to fix this soon? I don't think we should proceed with these API changes if the API does not work properly. At least add a runtime warning using g_warning().

(Sad OK if you add the g_warning().)

> Source/WebKit2/UIProcess/API/gtk/WebKitCookieManager.cpp:115
> +    if (manager->priv->dataManager) {
> +        g_object_remove_weak_pointer(G_OBJECT(manager->priv->dataManager), reinterpret_cast<void**>(&manager->priv->dataManager));
> +
> +        auto sessionID = webkitWebsiteDataManagerGetDataStore(manager->priv->dataManager).websiteDataStore().sessionID();
> +        for (auto* processPool : webkitWebsiteDataManagerGetProcessPools(manager->priv->dataManager))
> +            processPool->supplement<WebCookieManagerProxy>()->stopObservingCookieChanges(sessionID);
> +
> +        manager->priv->dataManager = nullptr;
> +    }

Actually, I wonder if we should do this in ~_WebKitCookieManagerPrivate() instead of dispose. Because the object should technically be left in valid state after dispose, but all of the functions are going to hit criticals if priv->dataManager is null. Since we're not keeping a strong reference to it, it can't be involved in a reference cycle, so it should be safer to do in the destructor instead of dispose.
Comment 4 Carlos Garcia Campos 2017-02-14 03:37:14 PST
(In reply to comment #2)
> Comment on attachment 301345 [details]
> Patch
> 
> View in context:
> https://bugs.webkit.org/attachment.cgi?id=301345&action=review
> 
> It looks mostly good, but I'd like to review this one again after you answer
> my questions about why you used the weak pointer, which I hope was just a
> mistake.
> 
> > Source/WebCore/platform/network/soup/CookieJarSoup.cpp:217
> > +    // FIXME: Add support for deleting cookies modified since the given timestamp. It should probably be added to libsoup.
> > +    if (timestamp == std::chrono::system_clock::from_time_t(0))
> > +        deleteAllCookies(session);
> 
> Are you planning to fix this soon? I don't think we should proceed with
> these API changes if the API does not work properly. At least add a runtime
> warning using g_warning().

No, I don't have time, I'll add the warning.

> > Source/WebKit2/UIProcess/API/gtk/WebKitCookieManager.cpp:40
> > + * The WebKitCookieManager defines how to setup and handle cookies.
> 
> setup (noun) -> set up (verb)
> 
> > Source/WebKit2/UIProcess/API/gtk/WebKitCookieManager.cpp:43
> >   * store cookies, with webkit_cookie_manager_set_persistent_storage(),
> 
> Remove the comma
> 
> > Source/WebKit2/UIProcess/API/gtk/WebKitCookieManager.cpp:144
> > +    g_object_add_weak_pointer(G_OBJECT(dataManager), reinterpret_cast<void**>(&manager->priv->dataManager));
> 
> Why is the weak pointer needed? I would expect WebKitCookieManager to be
> owned by the WebKitWebsiteDataManager, so WebKitWebsiteDataManager would
> keep a ref to ensure the WebKitCookieManager is never destroyed first. Is
> there some really good reason you don't do that? I think it should be a
> normal raw pointer instead.

The cookie manager can't be created by the user, it's always created and owned by the website data manager. However, nothing prevents the user from taking a ref to the returned cookie manager. It's a programmer error to use the cookie manager after the data manager is destroyed, that's why all methods are protected with g_return_if_fail(WEBKIT_IS_WEBSITE_DATA_MANAGER(manager->priv->dataManager)). I don't want to take a reference to the data manager. Maybe it isn't worth it just to handle a corner case, so I can simply remove the weak point and use a plan pointer. Users will get a crash sooner or layer in both cases I'm afraid.

> > Source/WebKit2/UIProcess/API/gtk/WebKitCookieManager.cpp:165
> >   * By default, @cookie_manager doesn't store the cookies persistenly, so you need to call this
> 
> Preexisting problem, but let's fix it now: persistenly -> persistently
> 
> > Source/WebKit2/UIProcess/API/gtk/WebKitCookieManager.cpp:176
> > +    for (auto* processPool : webkitWebsiteDataManagerGetProcessPools(manager->priv->dataManager)) {
> 
> This is a big problem. Either manager->priv->dataManager can be legitimately
> null here, or you should not have used a weak pointer.
> 
> > Source/WebKit2/UIProcess/API/gtk/WebKitCookieManager.cpp:197
> > +    g_return_if_fail(WEBKIT_IS_WEBSITE_DATA_MANAGER(manager->priv->dataManager));
> 
> Ditto. If you're going to use the weak pointer, then the entire class needs
> to be prepared to deal with the WebKitWebsiteDataManager being null. There's
> no point to the weak pointer otherwise.

It deals with that already, but using g_return macros.

> > Source/WebKit2/UIProcess/API/gtk/WebKitWebContext.cpp:82
> >   * webkit_web_context_get_security_manager() for that.
> 
> Remove "for that": the sentence works better without them.
> 
> > Source/WebKit2/UIProcess/API/gtk/WebKitWebContext.cpp:698
> >  WebKitCookieManager* webkit_web_context_get_cookie_manager(WebKitWebContext* context)
> 
> I think you should document that this function returns the
> WebKitCookieManager of this context's WebKitWebsiteDataManager. I know it's
> an implementation detail, but otherwise I think it's kind of confusing why
> both WebKitWebContext and WebKitWebsiteDataManager have a
> WebKitCookieManager.
> 
> > Source/WebKit2/UIProcess/API/gtk/WebKitWebView.cpp:2286
> > + * Get the #WebKitWebsiteDataManager associated to @web_view. If @web_view is not ephemeral
> 
> Add a comma after "ephemeral"
> 
> > Source/WebKit2/UIProcess/API/gtk/WebKitWebView.cpp:2287
> > + * the returned #WebKitWebsiteDataManager will be the same as the #WebKitWebView:web-context one.
> 
> "the #WebKitWebView:web-context one" doesn't sound great. I would write:
> "will be the same as the #WebKitWebsiteDataManager of @web_view's
> #WebKitWebContext."
> 
> > Source/WebKit2/UIProcess/API/gtk/WebKitWebsiteDataManager.cpp:103
> > +    GRefPtr<WebKitCookieManager> cookieManager;
> 
> Aha, so you do keep a ref! Good! Then you don't need the weak pointer in
> WebKitCookieManager, right? Surely the WebKitCookieManager cannot outlive
> the WebKitWebsiteDataManager due to this ref.

Not surely, but I guess we should assume it, yes.

> > Source/WebKit2/UIProcess/API/gtk/WebKitWebsiteDataManager.cpp:104
> > +    Vector<WebProcessPool*> processPools;
> 
> Is it possible to use Vector<WebProcessPool&> to clarify that the process
> pools are not null?

No, I don't think Vector can contain references.

> > Source/WebKit2/UIProcess/WebsiteData/WebsiteDataRecord.cpp:54
> > +#if PLATFORM(GTK)
> > +    if (hostName == "localhost")
> > +        return hostName;
> > +#endif
> 
> I think this should be an #else condition, not a GTK-specific condition.
Comment 5 Carlos Garcia Campos 2017-02-14 03:39:13 PST
(In reply to comment #3)
> Comment on attachment 301345 [details]
> Patch
> 
> View in context:
> https://bugs.webkit.org/attachment.cgi?id=301345&action=review
> 
> >> Source/WebCore/platform/network/soup/CookieJarSoup.cpp:217
> >> +        deleteAllCookies(session);
> > 
> > Are you planning to fix this soon? I don't think we should proceed with these API changes if the API does not work properly. At least add a runtime warning using g_warning().
> 
> (Sad OK if you add the g_warning().)
> 
> > Source/WebKit2/UIProcess/API/gtk/WebKitCookieManager.cpp:115
> > +    if (manager->priv->dataManager) {
> > +        g_object_remove_weak_pointer(G_OBJECT(manager->priv->dataManager), reinterpret_cast<void**>(&manager->priv->dataManager));
> > +
> > +        auto sessionID = webkitWebsiteDataManagerGetDataStore(manager->priv->dataManager).websiteDataStore().sessionID();
> > +        for (auto* processPool : webkitWebsiteDataManagerGetProcessPools(manager->priv->dataManager))
> > +            processPool->supplement<WebCookieManagerProxy>()->stopObservingCookieChanges(sessionID);
> > +
> > +        manager->priv->dataManager = nullptr;
> > +    }
> 
> Actually, I wonder if we should do this in ~_WebKitCookieManagerPrivate()
> instead of dispose. Because the object should technically be left in valid
> state after dispose, but all of the functions are going to hit criticals if
> priv->dataManager is null. Since we're not keeping a strong reference to it,
> it can't be involved in a reference cycle, so it should be safer to do in
> the destructor instead of dispose.

I want to stop observing cookie changes asap, and I need to nullify the pointer to ensure it doesn't happen twice.
Comment 6 Carlos Garcia Campos 2017-02-14 03:43:45 PST
Created attachment 301483 [details]
Patch
Comment 7 Michael Catanzaro 2017-02-14 08:46:08 PST
Comment on attachment 301483 [details]
Patch

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

> Source/WebKit2/ChangeLog:8
> +        WebKitCookieManager is associated to a particular WebKitWebContexst and uses the default session ID

WebKitWebContext

> Source/WebKit2/UIProcess/WebsiteData/WebsiteDataRecord.cpp:52
>  #if PLATFORM(COCOA)
>      if (hostName == String(kCFHTTPCookieLocalFileDomain))
>          return displayNameForLocalFiles();
> +#elif PLATFORM(GTK)
> +    if (hostName == "localhost")
> +        return hostName;
>  #endif

Why not use #else? All non-cocoa ports must want this.
Comment 8 Michael Catanzaro 2017-02-14 11:45:58 PST
I would put the weak pointer back, with a comment explaining why it's there. It's not great, but I don't have a better solution, and it seems safer than using a raw pointer. Believe it or not, I just didn't consider that the user could ref the SoupCookieManager.
Comment 9 Carlos Garcia Campos 2017-02-14 23:36:50 PST
Committed r212345: <http://trac.webkit.org/changeset/212345>