Changeset 199091 in webkit


Ignore:
Timestamp:
Apr 5, 2016 8:23:18 PM (8 years ago)
Author:
BJ Burg
Message:

Web Automation: add support for getting, deleting, and adding cookies
https://bugs.webkit.org/show_bug.cgi?id=156090
<rdar://problem/25477678>

Reviewed by Timothy Hatcher.

Add protocol commands for manipulating cookies with respect to a given page.
Implement all but the addSingleCookie command, which needs a new WebCore API.

  • UIProcess/Automation/Automation.json:

Copy the Page domain Cookie object. Add new commands.

  • UIProcess/Automation/WebAutomationSession.cpp:

(WebKit::WebAutomationSession::getAllCookies):
(WebKit::buildObjectForCookie): Copied from InspectorPageAgent.
(WebKit::buildArrayForCookies): Copied from InspectorPageAgent.
(WebKit::WebAutomationSession::didGetCookiesForFrame):
(WebKit::WebAutomationSession::deleteSingleCookie):
(WebKit::WebAutomationSession::didDeleteCookie):
(WebKit::WebAutomationSession::addSingleCookie): Added a stub for now.
(WebKit::WebAutomationSession::deleteAllCookies):
This command can use the WebCookieManager supplement directly instead of
proxying through AutomationSession. It doesn't block until the delete is
performed like the other methods do, but this shouldn't be a problem.

  • UIProcess/Automation/WebAutomationSession.h:
  • UIProcess/Automation/WebAutomationSession.messages.in:
  • WebProcess/Automation/WebAutomationSessionProxy.cpp:

(WebKit::WebAutomationSessionProxy::getCookiesForFrame):
(WebKit::WebAutomationSessionProxy::deleteCookie):

  • WebProcess/Automation/WebAutomationSessionProxy.h:
  • WebProcess/Automation/WebAutomationSessionProxy.messages.in:
Location:
trunk/Source/WebKit2
Files:
8 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/WebKit2/ChangeLog

    r199090 r199091  
     12016-04-05  Brian Burg  <bburg@apple.com>
     2
     3        Web Automation: add support for getting, deleting, and adding cookies
     4        https://bugs.webkit.org/show_bug.cgi?id=156090
     5        <rdar://problem/25477678>
     6
     7        Reviewed by Timothy Hatcher.
     8
     9        Add protocol commands for manipulating cookies with respect to a given page.
     10        Implement all but the addSingleCookie command, which needs a new WebCore API.
     11
     12        * UIProcess/Automation/Automation.json:
     13        Copy the Page domain Cookie object. Add new commands.
     14
     15        * UIProcess/Automation/WebAutomationSession.cpp:
     16        (WebKit::WebAutomationSession::getAllCookies):
     17        (WebKit::buildObjectForCookie): Copied from InspectorPageAgent.
     18        (WebKit::buildArrayForCookies): Copied from InspectorPageAgent.
     19        (WebKit::WebAutomationSession::didGetCookiesForFrame):
     20        (WebKit::WebAutomationSession::deleteSingleCookie):
     21        (WebKit::WebAutomationSession::didDeleteCookie):
     22        (WebKit::WebAutomationSession::addSingleCookie): Added a stub for now.
     23        (WebKit::WebAutomationSession::deleteAllCookies):
     24        This command can use the WebCookieManager supplement directly instead of
     25        proxying through AutomationSession. It doesn't block until the delete is
     26        performed like the other methods do, but this shouldn't be a problem.
     27
     28        * UIProcess/Automation/WebAutomationSession.h:
     29        * UIProcess/Automation/WebAutomationSession.messages.in:
     30        * WebProcess/Automation/WebAutomationSessionProxy.cpp:
     31        (WebKit::WebAutomationSessionProxy::getCookiesForFrame):
     32        (WebKit::WebAutomationSessionProxy::deleteCookie):
     33        * WebProcess/Automation/WebAutomationSessionProxy.h:
     34        * WebProcess/Automation/WebAutomationSessionProxy.messages.in:
     35
    1362016-04-05  Alex Christensen  <achristensen@webkit.org>
    237
  • trunk/Source/WebKit2/UIProcess/Automation/Automation.json

    r198914 r199091  
    188188                { "name": "text", "type": "string", "optional": true, "description": "A unicode string to be delivered to the page. The sequence of key events is determined by splitting the string at grapheme cluster boundaries." }
    189189            ]
     190        },
     191        {
     192            "id": "Cookie",
     193            "type": "object",
     194            "properties": [
     195                { "name": "name", "type": "string", "description": "Cookie name." },
     196                { "name": "value", "type": "string", "description": "Cookie value." },
     197                { "name": "domain", "type": "string", "description": "Cookie domain. If empty, the domain is inherited from the relevant browsing context." },
     198                { "name": "path", "type": "string", "description": "Cookie path." },
     199                { "name": "expires", "type": "number", "description": "Cookie expires." },
     200                { "name": "size", "type": "integer", "description": "Cookie size." },
     201                { "name": "httpOnly", "type": "boolean", "description": "True if cookie is http-only." },
     202                { "name": "secure", "type": "boolean", "description": "True if cookie is secure." },
     203                { "name": "session", "type": "boolean", "description": "True in case of session cookie." }
     204            ]
    190205        }
    191206    ],
     
    411426                { "name": "userInput", "type": "string", "description": "The text to enter in the prompt." }
    412427            ]
     428        },
     429        {
     430            "name": "getAllCookies",
     431            "description": "Returns all cookies visible to the specified browsing context.",
     432            "parameters": [
     433                { "name": "browsingContextHandle", "$ref": "BrowsingContextHandle", "description": "The handle for the browsing context." }
     434            ],
     435            "returns": [
     436                { "name": "cookies", "type": "array", "items": { "$ref": "Cookie" }, "description": "Array of cookie objects." }
     437            ],
     438            "async": true
     439        },
     440        {
     441            "name": "deleteSingleCookie",
     442            "description": "Deletes a cookie with the given name if visible to the specified browsing context.",
     443            "parameters": [
     444                { "name": "browsingContextHandle", "$ref": "BrowsingContextHandle", "description": "The handle for the browsing context." },
     445                { "name": "cookieName", "type": "string", "description": "Name of the cookie to remove." }
     446            ],
     447            "async": true
     448        },
     449        {
     450            "name": "addSingleCookie",
     451            "description": "Add a cookie to cookie storage for the specified browsing context.",
     452            "parameters": [
     453                { "name": "browsingContextHandle", "$ref": "BrowsingContextHandle", "description": "The handle for the browsing context." },
     454                { "name": "cookie", "$ref": "Cookie", "description": "The cookie that should be added to storage." }
     455            ],
     456            "async": true
     457        },
     458        {
     459            "name": "deleteAllCookies",
     460            "description": "Delete all cookies that are visible to the specified browsing context.",
     461            "parameters": [
     462                { "name": "browsingContextHandle", "$ref": "BrowsingContextHandle", "description": "The handle for the browsing context." }
     463            ],
     464            "async": true
    413465        }
    414466    ]
  • trunk/Source/WebKit2/UIProcess/Automation/WebAutomationSession.cpp

    r199005 r199091  
    3131#include "WebAutomationSessionMessages.h"
    3232#include "WebAutomationSessionProxyMessages.h"
     33#include "WebCookieManagerProxy.h"
    3334#include "WebProcessPool.h"
    3435#include <JavaScriptCore/InspectorBackendDispatcher.h>
     
    656657
    657658    m_client->setUserInputForCurrentJavaScriptPromptOnPage(this, page, promptValue);
     659}
     660
     661void WebAutomationSession::getAllCookies(ErrorString& errorString, const String& browsingContextHandle, Ref<GetAllCookiesCallback>&& callback)
     662{
     663    WebPageProxy* page = webPageProxyForHandle(browsingContextHandle);
     664    if (!page)
     665        FAIL_WITH_PREDEFINED_ERROR_MESSAGE(WindowNotFound);
     666
     667    WebFrameProxy* mainFrame = page->mainFrame();
     668    ASSERT(mainFrame);
     669    if (!mainFrame)
     670        FAIL_WITH_PREDEFINED_ERROR_MESSAGE(WindowNotFound);
     671
     672    uint64_t callbackID = m_nextGetCookiesCallbackID++;
     673    m_getCookieCallbacks.set(callbackID, WTFMove(callback));
     674
     675    page->process().send(Messages::WebAutomationSessionProxy::GetCookiesForFrame(mainFrame->frameID(), callbackID), 0);
     676}
     677
     678static Ref<Inspector::Protocol::Automation::Cookie> buildObjectForCookie(const WebCore::Cookie& cookie)
     679{
     680    return Inspector::Protocol::Automation::Cookie::create()
     681        .setName(cookie.name)
     682        .setValue(cookie.value)
     683        .setDomain(cookie.domain)
     684        .setPath(cookie.path)
     685        .setExpires(cookie.expires)
     686        .setSize((cookie.name.length() + cookie.value.length()))
     687        .setHttpOnly(cookie.httpOnly)
     688        .setSecure(cookie.secure)
     689        .setSession(cookie.session)
     690        .release();
     691}
     692
     693static Ref<Inspector::Protocol::Array<Inspector::Protocol::Automation::Cookie>> buildArrayForCookies(Vector<WebCore::Cookie>& cookiesList)
     694{
     695    auto cookies = Inspector::Protocol::Array<Inspector::Protocol::Automation::Cookie>::create();
     696
     697    for (const auto& cookie : cookiesList)
     698        cookies->addItem(buildObjectForCookie(cookie));
     699
     700    return cookies;
     701}
     702
     703void WebAutomationSession::didGetCookiesForFrame(uint64_t callbackID, Vector<WebCore::Cookie> cookies, const String& errorType)
     704{
     705    auto callback = m_getCookieCallbacks.take(callbackID);
     706    if (!callback)
     707        return;
     708
     709    if (!errorType.isEmpty()) {
     710        callback->sendFailure(errorType);
     711        return;
     712    }
     713
     714    callback->sendSuccess(buildArrayForCookies(cookies));
     715}
     716
     717void WebAutomationSession::deleteSingleCookie(ErrorString& errorString, const String& browsingContextHandle, const String& cookieName, Ref<DeleteSingleCookieCallback>&& callback)
     718{
     719    WebPageProxy* page = webPageProxyForHandle(browsingContextHandle);
     720    if (!page)
     721        FAIL_WITH_PREDEFINED_ERROR_MESSAGE(WindowNotFound);
     722
     723    WebFrameProxy* mainFrame = page->mainFrame();
     724    ASSERT(mainFrame);
     725    if (!mainFrame)
     726        FAIL_WITH_PREDEFINED_ERROR_MESSAGE(WindowNotFound);
     727
     728    uint64_t callbackID = m_nextDeleteCookieCallbackID++;
     729    m_deleteCookieCallbacks.set(callbackID, WTFMove(callback));
     730
     731    page->process().send(Messages::WebAutomationSessionProxy::DeleteCookie(mainFrame->frameID(), cookieName, callbackID), 0);
     732}
     733
     734void WebAutomationSession::didDeleteCookie(uint64_t callbackID, const String& errorType)
     735{
     736    auto callback = m_deleteCookieCallbacks.take(callbackID);
     737    if (!callback)
     738        return;
     739
     740    if (!errorType.isEmpty()) {
     741        callback->sendFailure(errorType);
     742        return;
     743    }
     744
     745    callback->sendSuccess();
     746}
     747
     748void WebAutomationSession::addSingleCookie(ErrorString& errorString, const String& browsingContextHandle, const Inspector::InspectorObject& cookie, Ref<AddSingleCookieCallback>&& callback)
     749{
     750    // FIXME: Implementing this command requires a new CookieJar API <https://webkit.org/b/156091>
     751    UNUSED_PARAM(browsingContextHandle);
     752    // FIXME: if the incoming cookie's domain is the string '(inherit)',
     753    // then it should be inherited from the main frame's domain.
     754    UNUSED_PARAM(cookie);
     755    UNUSED_PARAM(callback);
     756
     757    FAIL_WITH_PREDEFINED_ERROR_MESSAGE(NotImplemented);
     758}
     759
     760void WebAutomationSession::deleteAllCookies(ErrorString& errorString, const String& browsingContextHandle, Ref<DeleteAllCookiesCallback>&& callback)
     761{
     762    WebPageProxy* page = webPageProxyForHandle(browsingContextHandle);
     763    if (!page)
     764        FAIL_WITH_PREDEFINED_ERROR_MESSAGE(WindowNotFound);
     765
     766    WebCore::URL activeURL = WebCore::URL(WebCore::URL(), page->pageLoadState().activeURL());
     767    ASSERT(activeURL.isValid());
     768
     769    WebCookieManagerProxy* cookieManager = m_processPool->supplement<WebCookieManagerProxy>();
     770    cookieManager->deleteCookiesForHostname(activeURL.host());
    658771}
    659772
  • trunk/Source/WebKit2/UIProcess/Automation/WebAutomationSession.h

    r198914 r199091  
    4747
    4848namespace WebCore {
     49class IntPoint;
    4950class IntRect;
    50 }
    51 
    52 namespace WebCore {
    53 class IntPoint;
     51
     52struct Cookie;
    5453}
    5554
     
    118117    void messageOfCurrentJavaScriptDialog(Inspector::ErrorString&, const String& browsingContextHandle, String* text) override;
    119118    void setUserInputForCurrentJavaScriptPrompt(Inspector::ErrorString&, const String& browsingContextHandle, const String& text) override;
    120 
     119    void getAllCookies(Inspector::ErrorString&, const String& browsingContextHandle, Ref<GetAllCookiesCallback>&&) override;
     120    void deleteSingleCookie(Inspector::ErrorString&, const String& browsingContextHandle, const String& cookieName, Ref<DeleteSingleCookieCallback>&&) override;
     121    void addSingleCookie(Inspector::ErrorString&, const String& browsingContextHandle, const Inspector::InspectorObject& cookie, Ref<AddSingleCookieCallback>&&) override;
     122    void deleteAllCookies(Inspector::ErrorString&, const String& browsingContextHandle, Ref<DeleteAllCookiesCallback>&&) override;
    121123#if USE(APPKIT)
    122124    bool wasEventSynthesizedForAutomation(NSEvent *);
     
    141143    void didComputeElementLayout(uint64_t callbackID, WebCore::IntRect, const String& errorType);
    142144    void didTakeScreenshot(uint64_t callbackID, const ShareableBitmap::Handle&, const String& errorType);
     145    void didGetCookiesForFrame(uint64_t callbackID, Vector<WebCore::Cookie>, const String& errorType);
     146    void didDeleteCookie(uint64_t callbackID, const String& errorType);
    143147
    144148    // Platform-specific helper methods.
     
    187191    HashMap<uint64_t, RefPtr<Inspector::AutomationBackendDispatcherHandler::TakeScreenshotCallback>> m_screenshotCallbacks;
    188192
     193    uint64_t m_nextGetCookiesCallbackID { 1 };
     194    HashMap<uint64_t, RefPtr<Inspector::AutomationBackendDispatcherHandler::GetAllCookiesCallback>> m_getCookieCallbacks;
     195
     196    uint64_t m_nextDeleteCookieCallbackID { 1 };
     197    HashMap<uint64_t, RefPtr<Inspector::AutomationBackendDispatcherHandler::DeleteSingleCookieCallback>> m_deleteCookieCallbacks;
     198
    189199#if ENABLE(REMOTE_INSPECTOR)
    190200    Inspector::FrontendChannel* m_remoteChannel { nullptr };
  • trunk/Source/WebKit2/UIProcess/Automation/WebAutomationSession.messages.in

    r198907 r199091  
    3030
    3131    DidTakeScreenshot(uint64_t callbackID, WebKit::ShareableBitmap::Handle imageDataHandle, String errorType)
     32
     33    DidGetCookiesForFrame(uint64_t callbackID, Vector<WebCore::Cookie> cookies, String errorType)
     34    DidDeleteCookie(uint64_t callbackID, String errorType)
    3235}
  • trunk/Source/WebKit2/WebProcess/Automation/WebAutomationSessionProxy.cpp

    r199005 r199091  
    4040#include <JavaScriptCore/JSStringRefPrivate.h>
    4141#include <JavaScriptCore/OpaqueJSString.h>
     42#include <WebCore/CookieJar.h>
    4243#include <WebCore/DOMWindow.h>
    4344#include <WebCore/Frame.h>
     
    493494}
    494495
     496void WebAutomationSessionProxy::getCookiesForFrame(uint64_t frameID, uint64_t callbackID)
     497{
     498    String frameNotFoundErrorType = Inspector::Protocol::AutomationHelpers::getEnumConstantValue(Inspector::Protocol::Automation::ErrorMessage::FrameNotFound);
     499
     500    WebFrame* frame = WebProcess::singleton().webFrame(frameID);
     501    if (!frame || !frame->coreFrame() || !frame->coreFrame()->document()) {
     502        WebProcess::singleton().parentProcessConnection()->send(Messages::WebAutomationSession::DidGetCookiesForFrame(callbackID, Vector<WebCore::Cookie>(), frameNotFoundErrorType), 0);
     503        return;
     504    }
     505
     506    // This returns the same list of cookies as when evaluating `document.cookies` in JavaScript.
     507    WebCore::Document* document = frame->coreFrame()->document();
     508    Vector<WebCore::Cookie> foundCookies;
     509    WebCore::getRawCookies(document, document->cookieURL(), foundCookies);
     510
     511    WebProcess::singleton().parentProcessConnection()->send(Messages::WebAutomationSession::DidGetCookiesForFrame(callbackID, foundCookies, String()), 0);
     512}
     513
     514void WebAutomationSessionProxy::deleteCookie(uint64_t frameID, String cookieName, uint64_t callbackID)
     515{
     516    String frameNotFoundErrorType = Inspector::Protocol::AutomationHelpers::getEnumConstantValue(Inspector::Protocol::Automation::ErrorMessage::FrameNotFound);
     517
     518    WebFrame* frame = WebProcess::singleton().webFrame(frameID);
     519    if (!frame || !frame->coreFrame() || !frame->coreFrame()->document()) {
     520        WebProcess::singleton().parentProcessConnection()->send(Messages::WebAutomationSession::DidDeleteCookie(callbackID, frameNotFoundErrorType), 0);
     521        return;
     522    }
     523
     524    WebCore::Document* document = frame->coreFrame()->document();
     525    WebCore::deleteCookie(document, document->cookieURL(), cookieName);
     526
     527    WebProcess::singleton().parentProcessConnection()->send(Messages::WebAutomationSession::DidDeleteCookie(callbackID, String()), 0);
     528}
     529
    495530} // namespace WebKit
  • trunk/Source/WebKit2/WebProcess/Automation/WebAutomationSessionProxy.h

    r198913 r199091  
    6767    void computeElementLayout(uint64_t frameID, String nodeHandle, bool scrollIntoViewIfNeeded, bool useViewportCoordinates, uint64_t callbackID);
    6868    void takeScreenshot(uint64_t pageID, uint64_t callbackID);
     69    void getCookiesForFrame(uint64_t frameID, uint64_t callbackID);
     70    void deleteCookie(uint64_t frameID, String cookieName, uint64_t callbackID);
    6971
    7072    String m_sessionIdentifier;
  • trunk/Source/WebKit2/WebProcess/Automation/WebAutomationSessionProxy.messages.in

    r198913 r199091  
    3434
    3535    TakeScreenshot(uint64_t pageID, uint64_t callbackID)
     36
     37    GetCookiesForFrame(uint64_t frameID, uint64_t callbackID)
     38    DeleteCookie(uint64_t frameID, String cookieName, uint64_t callbackID)
    3639}
Note: See TracChangeset for help on using the changeset viewer.