Changeset 198738 in webkit


Ignore:
Timestamp:
Mar 28, 2016 8:57:23 AM (8 years ago)
Author:
timothy@apple.com
Message:

Web Automation: Add Automation protocol commands to resolve frames as handles

https://bugs.webkit.org/show_bug.cgi?id=155650
rdar://problem/25242422

Reviewed by Brian Burg.

Source/WebCore:

  • page/DOMWindow.h: Marked focus() method as exported so WK2 can use them.
  • page/FrameTree.h: Marked scopedChild() methods as exported so WK2 can use them.

Source/WebKit2:

  • UIProcess/Automation/Automation.json:

Added resolveFrameHandle and resolveParentFrameHandle.

  • UIProcess/Automation/WebAutomationSession.cpp:

(WebKit::WebAutomationSession::webFrameProxyForHandle): Added.
(WebKit::WebAutomationSession::handleForWebFrameID): Added.
(WebKit::WebAutomationSession::handleForWebFrameProxy): Added.
(WebKit::WebAutomationSession::evaluateJavaScriptFunction): Use frame handles now.
(WebKit::WebAutomationSession::resolveChildFrameHandle): Added.
(WebKit::WebAutomationSession::didChildResolveFrame): Added.
(WebKit::WebAutomationSession::resolveParentFrameHandle): Added.
(WebKit::WebAutomationSession::didResolveParentFrame): Added.

  • UIProcess/Automation/WebAutomationSession.h:
  • UIProcess/Automation/WebAutomationSession.messages.in:

(DidResolveChildFrame): Added.
(DidResolveParentFrame): Added.

  • WebProcess/Automation/WebAutomationSessionProxy.cpp:

(WebKit::WebAutomationSessionProxy::elementForNodeHandle): Added.
(WebKit::WebAutomationSessionProxy::resolveChildFrameWithOrdinal): Added.
(WebKit::WebAutomationSessionProxy::resolveChildFrameWithNodeHandle): Added.
(WebKit::WebAutomationSessionProxy::resolveChildFrameWithName): Added.
(WebKit::WebAutomationSessionProxy::resolveParentFrame): Added.
(WebKit::WebAutomationSessionProxy::focusFrame): Added.

  • WebProcess/Automation/WebAutomationSessionProxy.h:
  • WebProcess/Automation/WebAutomationSessionProxy.messages.in:

(ResolveChildFrameWithOrdinal): Added.
(ResolveChildFrameWithNodeHandle): Added.
(ResolveChildFrameWithName): Added.
(ResolveParentFrame): Added.
(FocusFrame): Added.

  • WebProcess/Automation/WebAutomationSessionProxy.js:

(AutomationSessionProxy.prototype.nodeForIdentifier): Added.
Public method that eats the exception thrown by the private method.

Location:
trunk/Source
Files:
12 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/WebCore/ChangeLog

    r198735 r198738  
     12016-03-18  Timothy Hatcher  <timothy@apple.com>
     2
     3        Web Automation: Add Automation protocol commands to resolve frames as handles
     4
     5        https://bugs.webkit.org/show_bug.cgi?id=155650
     6        rdar://problem/25242422
     7
     8        Reviewed by Brian Burg.
     9
     10        * page/DOMWindow.h: Marked focus() method as exported so WK2 can use them.
     11        * page/FrameTree.h: Marked scopedChild() methods as exported so WK2 can use them.
     12
    1132016-03-28  Konstantin Tokarev  <annulen@yandex.ru>
    214
  • trunk/Source/WebCore/page/DOMWindow.h

    r198102 r198738  
    161161        Element* frameElement() const;
    162162
    163         void focus(bool allowFocus = false);
     163        WEBCORE_EXPORT void focus(bool allowFocus = false);
    164164        void focus(Document&);
    165165        void blur();
  • trunk/Source/WebCore/page/FrameTree.h

    r190752 r198738  
    8181        WEBCORE_EXPORT Frame& top() const;
    8282
    83         Frame* scopedChild(unsigned index) const;
    84         Frame* scopedChild(const AtomicString& name) const;
     83        WEBCORE_EXPORT Frame* scopedChild(unsigned index) const;
     84        WEBCORE_EXPORT Frame* scopedChild(const AtomicString& name) const;
    8585        unsigned scopedChildCount() const;
    8686
  • trunk/Source/WebKit2/ChangeLog

    r198737 r198738  
     12016-03-18  Timothy Hatcher  <timothy@apple.com>
     2
     3        Web Automation: Add Automation protocol commands to resolve frames as handles
     4
     5        https://bugs.webkit.org/show_bug.cgi?id=155650
     6        rdar://problem/25242422
     7
     8        Reviewed by Brian Burg.
     9
     10        * UIProcess/Automation/Automation.json:
     11        Added resolveFrameHandle and resolveParentFrameHandle.
     12
     13        * UIProcess/Automation/WebAutomationSession.cpp:
     14        (WebKit::WebAutomationSession::webFrameProxyForHandle): Added.
     15        (WebKit::WebAutomationSession::handleForWebFrameID): Added.
     16        (WebKit::WebAutomationSession::handleForWebFrameProxy): Added.
     17        (WebKit::WebAutomationSession::evaluateJavaScriptFunction): Use frame handles now.
     18        (WebKit::WebAutomationSession::resolveChildFrameHandle): Added.
     19        (WebKit::WebAutomationSession::didChildResolveFrame): Added.
     20        (WebKit::WebAutomationSession::resolveParentFrameHandle): Added.
     21        (WebKit::WebAutomationSession::didResolveParentFrame): Added.
     22        * UIProcess/Automation/WebAutomationSession.h:
     23        * UIProcess/Automation/WebAutomationSession.messages.in:
     24        (DidResolveChildFrame): Added.
     25        (DidResolveParentFrame): Added.
     26
     27        * WebProcess/Automation/WebAutomationSessionProxy.cpp:
     28        (WebKit::WebAutomationSessionProxy::elementForNodeHandle): Added.
     29        (WebKit::WebAutomationSessionProxy::resolveChildFrameWithOrdinal): Added.
     30        (WebKit::WebAutomationSessionProxy::resolveChildFrameWithNodeHandle): Added.
     31        (WebKit::WebAutomationSessionProxy::resolveChildFrameWithName): Added.
     32        (WebKit::WebAutomationSessionProxy::resolveParentFrame): Added.
     33        (WebKit::WebAutomationSessionProxy::focusFrame): Added.
     34        * WebProcess/Automation/WebAutomationSessionProxy.h:
     35        * WebProcess/Automation/WebAutomationSessionProxy.messages.in:
     36        (ResolveChildFrameWithOrdinal): Added.
     37        (ResolveChildFrameWithNodeHandle): Added.
     38        (ResolveChildFrameWithName): Added.
     39        (ResolveParentFrame): Added.
     40        (FocusFrame): Added.
     41
     42        * WebProcess/Automation/WebAutomationSessionProxy.js:
     43        (AutomationSessionProxy.prototype.nodeForIdentifier): Added.
     44        Public method that eats the exception thrown by the private method.
     45
    1462016-03-17  Timothy Hatcher  <timothy@apple.com>
    247
  • trunk/Source/WebKit2/UIProcess/Automation/Automation.json

    r198737 r198738  
    99        },
    1010        {
     11            "id": "FrameHandle",
     12            "type": "string",
     13            "description": "An opaque identifier for a frame in a page."
     14        },
     15        {
     16            "id": "NodeHandle",
     17            "type": "string",
     18            "description": "An opaque identifier for a node in a page."
     19        },
     20        {
    1121            "id": "ErrorMessage",
    1222            "type": "string",
     
    1626                "JavaScriptError",
    1727                "WindowNotFound",
     28                "FrameNotFound",
    1829                "NodeNotFound",
    19                 "NotImplemented"
     30                "NotImplemented",
     31                "MissingParameter"
    2032            ]
    2133        },
     
    6577        {
    6678            "name": "switchToBrowsingContext",
    67             "description": "Activates the specified browsing context.",
     79            "description": "Activates the specified browsing context and optional frame, which gives them focus (causing the 'focus' DOM event to fire, and 'blur' DOM event to fire for the previous browsing context and frame).",
    6880            "parameters": [
    69                 { "name": "handle", "$ref": "BrowsingContextHandle", "description": "The handle for the browsing context that should be made active." }
     81                { "name": "browsingContextHandle", "$ref": "BrowsingContextHandle", "description": "The handle for the browsing context that should be made focused." },
     82                { "name": "frameHandle", "$ref": "FrameHandle", "optional": true, "description": "The handle for the frame that should be focused. Defaults to the main frame if omitted." }
    7083            ]
    7184        },
     
    103116            "description": "Evaluates a script function in a browsing context and calls it with the supplied arguments.",
    104117            "parameters": [
    105                 { "name": "handle", "$ref": "BrowsingContextHandle", "description": "The handle for the browsing context the script should be evaluated." },
    106                 { "name": "function", "type": "string", "description": "The script to evaluate in the browsing context. The script is expected to be a function declaration, or otherwise evaluate to a function result." },
     118                { "name": "browsingContextHandle", "$ref": "BrowsingContextHandle", "description": "The handle for the browsing context the script should be evaluated." },
     119                { "name": "frameHandle", "$ref": "FrameHandle", "optional": true, "description": "The handle for the frame the script should be evaluated. The main frame is used if this parameter empty string or excluded." },
     120                { "name": "function", "type": "string", "description": "The script to evaluate in the browsing context. It must be a function result." },
    107121                { "name": "arguments", "type": "array", "items": { "type": "string" }, "description": "The arguments to pass to the function when called. They will be parsed as JSON before calling the function." },
    108122                { "name": "expectsImplicitCallbackArgument", "type": "boolean", "description": "The function expects a callback function as the last argument. It is expected to call this callback with a result." }
     
    112126            ],
    113127            "async": true
     128        },
     129        {
     130            "name": "resolveChildFrameHandle",
     131            "description": "Determines the <code>FrameHandle</code> based on the ordinal, name or node handle of a child frame.",
     132            "parameters": [
     133                { "name": "browsingContextHandle", "$ref": "BrowsingContextHandle", "description": "The handle for the browsing context in which to search for the frame." },
     134                { "name": "frameHandle", "$ref": "FrameHandle", "optional": true, "description": "The handle for the frame in which to search for the frame. The main frame is used if this parameter empty string or excluded." },
     135                { "name": "ordinal", "type": "integer", "optional": true, "description": "The ordinal of the child frame to resolve as a <code>FrameHandle</code>. This is analogous to 'window.frames[ordinal]' in JavaScript." },
     136                { "name": "name", "type": "string", "optional": true, "description": "The name of the child frame to resolve as a <code>FrameHandle</code>. This is analogous to 'window.frames[name]' in JavaScript." },
     137                { "name": "nodeHandle", "$ref": "NodeHandle", "optional": true, "description": "The handle of the child frame owner element to resolve as a <code>FrameHandle</code>." }
     138            ],
     139            "returns": [
     140                { "name": "result", "$ref": "FrameHandle", "description": "The <code>FrameHandle</code> for the requested frame." }
     141            ],
     142            "async": true
     143        },
     144        {
     145            "name": "resolveParentFrameHandle",
     146            "description": "Determines the <code>FrameHandle</code> for the parent frame of the supplied <code>FrameHandle</code>.",
     147            "parameters": [
     148                { "name": "browsingContextHandle", "$ref": "BrowsingContextHandle", "description": "The handle for the browsing context the frame is located." },
     149                { "name": "frameHandle", "$ref": "FrameHandle", "description": "The handle for the frame that should resolve its parent frame." }
     150            ],
     151            "returns": [
     152                { "name": "result", "$ref": "FrameHandle", "description": "The <code>FrameHandle</code> for the requested frame." }
     153            ],
     154            "async": true
    114155        }
    115156    ]
  • trunk/Source/WebKit2/UIProcess/Automation/WebAutomationSession.cpp

    r198737 r198738  
    126126}
    127127
    128 String WebAutomationSession::handleForWebPageProxy(WebPageProxy* webPageProxy)
    129 {
    130     auto iter = m_webPageHandleMap.find(webPageProxy->pageID());
     128String WebAutomationSession::handleForWebPageProxy(const WebPageProxy& webPageProxy)
     129{
     130    auto iter = m_webPageHandleMap.find(webPageProxy.pageID());
    131131    if (iter != m_webPageHandleMap.end())
    132132        return iter->value;
    133133
    134     String handle = WebCore::createCanonicalUUIDString().convertToASCIIUppercase();
    135 
    136     auto firstAddResult = m_webPageHandleMap.add(webPageProxy->pageID(), handle);
     134    String handle = "page-" + WebCore::createCanonicalUUIDString().convertToASCIIUppercase();
     135
     136    auto firstAddResult = m_webPageHandleMap.add(webPageProxy.pageID(), handle);
    137137    RELEASE_ASSERT(firstAddResult.isNewEntry);
    138138
    139     auto secondAddResult = m_handleWebPageMap.add(handle, webPageProxy->pageID());
     139    auto secondAddResult = m_handleWebPageMap.add(handle, webPageProxy.pageID());
    140140    RELEASE_ASSERT(secondAddResult.isNewEntry);
    141141
     
    143143}
    144144
    145 // Inspector::AutomationBackendDispatcherHandler API
     145WebFrameProxy* WebAutomationSession::webFrameProxyForHandle(const String& handle, WebPageProxy& page)
     146{
     147    if (handle.isEmpty())
     148        return page.mainFrame();
     149
     150    auto iter = m_handleWebFrameMap.find(handle);
     151    if (iter == m_handleWebFrameMap.end())
     152        return nullptr;
     153
     154    if (WebFrameProxy* frame = page.process().webFrame(iter->value))
     155        return frame;
     156
     157    return nullptr;
     158}
     159
     160String WebAutomationSession::handleForWebFrameID(uint64_t frameID)
     161{
     162    if (!frameID)
     163        return emptyString();
     164
     165    for (auto& process : m_processPool->processes()) {
     166        if (WebFrameProxy* frame = process->webFrame(frameID)) {
     167            if (frame->isMainFrame())
     168                return emptyString();
     169            break;
     170        }
     171    }
     172
     173    auto iter = m_webFrameHandleMap.find(frameID);
     174    if (iter != m_webFrameHandleMap.end())
     175        return iter->value;
     176
     177    String handle = "frame-" + WebCore::createCanonicalUUIDString().convertToASCIIUppercase();
     178
     179    auto firstAddResult = m_webFrameHandleMap.add(frameID, handle);
     180    RELEASE_ASSERT(firstAddResult.isNewEntry);
     181
     182    auto secondAddResult = m_handleWebFrameMap.add(handle, frameID);
     183    RELEASE_ASSERT(secondAddResult.isNewEntry);
     184
     185    return handle;
     186}
     187
     188String WebAutomationSession::handleForWebFrameProxy(const WebFrameProxy& webFrameProxy)
     189{
     190    return handleForWebFrameID(webFrameProxy.frameID());
     191}
    146192
    147193void WebAutomationSession::getBrowsingContexts(Inspector::ErrorString& errorString, RefPtr<Inspector::Protocol::Array<Inspector::Protocol::Automation::BrowsingContext>>& contexts)
     
    154200                continue;
    155201
    156             String handle = handleForWebPageProxy(page);
     202            String handle = handleForWebPageProxy(*page);
    157203
    158204            auto browsingContext = Inspector::Protocol::Automation::BrowsingContext::create()
    159                 .setHandle(handleForWebPageProxy(page))
     205                .setHandle(handleForWebPageProxy(*page))
    160206                .setActive(m_activeBrowsingContextHandle == handle)
    161207                .setUrl(page->pageLoadState().activeURL())
     
    174220
    175221    context = Inspector::Protocol::Automation::BrowsingContext::create()
    176         .setHandle(handleForWebPageProxy(page))
     222        .setHandle(handleForWebPageProxy(*page))
    177223        .setActive(m_activeBrowsingContextHandle == handle)
    178224        .setUrl(page->pageLoadState().activeURL())
     
    190236        FAIL_WITH_PREDEFINED_ERROR_MESSAGE(InternalError);
    191237
    192     m_activeBrowsingContextHandle = *handle = handleForWebPageProxy(page);
     238    m_activeBrowsingContextHandle = *handle = handleForWebPageProxy(*page);
    193239}
    194240
     
    205251}
    206252
    207 void WebAutomationSession::switchToBrowsingContext(Inspector::ErrorString& errorString, const String& handle)
    208 {
    209     WebPageProxy* page = webPageProxyForHandle(handle);
    210     if (!page)
    211         FAIL_WITH_PREDEFINED_ERROR_MESSAGE(WindowNotFound);
    212 
    213     m_activeBrowsingContextHandle = handle;
    214 
    215     // FIXME: Verify this is enough. We still might want to go through the AutomationSessionClient
    216     // to get closer a user pressing focusing the window / page.
     253void WebAutomationSession::switchToBrowsingContext(Inspector::ErrorString& errorString, const String& browsingContextHandle, const String* optionalFrameHandle)
     254{
     255    WebPageProxy* page = webPageProxyForHandle(browsingContextHandle);
     256    if (!page)
     257        FAIL_WITH_PREDEFINED_ERROR_MESSAGE(WindowNotFound);
     258
     259    WebFrameProxy* frame = webFrameProxyForHandle(optionalFrameHandle ? *optionalFrameHandle : emptyString(), *page);
     260    if (!frame)
     261        FAIL_WITH_PREDEFINED_ERROR_MESSAGE(FrameNotFound);
     262
     263    // FIXME: We don't need to track this in WK2. Remove in a follow up.
     264    m_activeBrowsingContextHandle = browsingContextHandle;
     265
    217266    page->setFocus(true);
     267    page->process().send(Messages::WebAutomationSessionProxy::FocusFrame(frame->frameID()), 0);
    218268}
    219269
     
    256306}
    257307
    258 void WebAutomationSession::evaluateJavaScriptFunction(Inspector::ErrorString& errorString, const String& handle, const String& function, const Inspector::InspectorArray& arguments, bool expectsImplicitCallbackArgument, Ref<EvaluateJavaScriptFunctionCallback>&& callback)
    259 {
    260     // FIXME 24172439: This should be a frame handle, not a page handle. Change this once we have frame support.
    261     WebPageProxy* page = webPageProxyForHandle(handle);
    262     if (!page)
    263         FAIL_WITH_PREDEFINED_ERROR_MESSAGE(WindowNotFound);
     308void WebAutomationSession::evaluateJavaScriptFunction(Inspector::ErrorString& errorString, const String& browsingContextHandle, const String* optionalFrameHandle, const String& function, const Inspector::InspectorArray& arguments, bool expectsImplicitCallbackArgument, Ref<EvaluateJavaScriptFunctionCallback>&& callback)
     309{
     310    WebPageProxy* page = webPageProxyForHandle(browsingContextHandle);
     311    if (!page)
     312        FAIL_WITH_PREDEFINED_ERROR_MESSAGE(WindowNotFound);
     313
     314    WebFrameProxy* frame = webFrameProxyForHandle(optionalFrameHandle ? *optionalFrameHandle : emptyString(), *page);
     315    if (!frame)
     316        FAIL_WITH_PREDEFINED_ERROR_MESSAGE(FrameNotFound);
    264317
    265318    Vector<String> argumentsVector;
     
    275328    m_evaluateJavaScriptFunctionCallbacks.set(callbackID, WTFMove(callback));
    276329
    277     page->process().send(Messages::WebAutomationSessionProxy::EvaluateJavaScriptFunction(page->mainFrame()->frameID(), function, argumentsVector, expectsImplicitCallbackArgument, callbackID), 0);
     330    page->process().send(Messages::WebAutomationSessionProxy::EvaluateJavaScriptFunction(frame->frameID(), function, argumentsVector, expectsImplicitCallbackArgument, callbackID), 0);
    278331}
    279332
     
    291344}
    292345
     346void WebAutomationSession::resolveChildFrameHandle(Inspector::ErrorString& errorString, const String& browsingContextHandle, const String* optionalFrameHandle, const int* optionalOrdinal, const String* optionalName, const String* optionalNodeHandle, Ref<ResolveChildFrameHandleCallback>&& callback)
     347{
     348    if (!optionalOrdinal && !optionalName && !optionalNodeHandle)
     349        FAIL_WITH_PREDEFINED_ERROR_MESSAGE(MissingParameter);
     350
     351    WebPageProxy* page = webPageProxyForHandle(browsingContextHandle);
     352    if (!page)
     353        FAIL_WITH_PREDEFINED_ERROR_MESSAGE(WindowNotFound);
     354
     355    WebFrameProxy* frame = webFrameProxyForHandle(optionalFrameHandle ? *optionalFrameHandle : emptyString(), *page);
     356    if (!frame)
     357        FAIL_WITH_PREDEFINED_ERROR_MESSAGE(FrameNotFound);
     358
     359    uint64_t callbackID = m_nextResolveFrameCallbackID++;
     360    m_resolveChildFrameHandleCallbacks.set(callbackID, WTFMove(callback));
     361
     362    if (optionalNodeHandle) {
     363        page->process().send(Messages::WebAutomationSessionProxy::ResolveChildFrameWithNodeHandle(frame->frameID(), *optionalNodeHandle, callbackID), 0);
     364        return;
     365    }
     366
     367    if (optionalName) {
     368        page->process().send(Messages::WebAutomationSessionProxy::ResolveChildFrameWithName(frame->frameID(), *optionalName, callbackID), 0);
     369        return;
     370    }
     371
     372    if (optionalOrdinal) {
     373        page->process().send(Messages::WebAutomationSessionProxy::ResolveChildFrameWithOrdinal(frame->frameID(), *optionalOrdinal, callbackID), 0);
     374        return;
     375    }
     376
     377    ASSERT_NOT_REACHED();
     378}
     379
     380void WebAutomationSession::didResolveChildFrame(uint64_t callbackID, uint64_t frameID, const String& errorType)
     381{
     382    auto callback = m_resolveChildFrameHandleCallbacks.take(callbackID);
     383    if (!callback)
     384        return;
     385
     386    if (!errorType.isEmpty())
     387        callback->sendFailure(errorType);
     388    else
     389        callback->sendSuccess(handleForWebFrameID(frameID));
     390}
     391
     392void WebAutomationSession::resolveParentFrameHandle(Inspector::ErrorString& errorString, const String& browsingContextHandle, const String& frameHandle, Ref<ResolveParentFrameHandleCallback>&& callback)
     393{
     394    WebPageProxy* page = webPageProxyForHandle(browsingContextHandle);
     395    if (!page)
     396        FAIL_WITH_PREDEFINED_ERROR_MESSAGE(WindowNotFound);
     397
     398    WebFrameProxy* frame = webFrameProxyForHandle(frameHandle, *page);
     399    if (!frame)
     400        FAIL_WITH_PREDEFINED_ERROR_MESSAGE(FrameNotFound);
     401
     402    uint64_t callbackID = m_nextResolveParentFrameCallbackID++;
     403    m_resolveParentFrameHandleCallbacks.set(callbackID, WTFMove(callback));
     404
     405    page->process().send(Messages::WebAutomationSessionProxy::ResolveParentFrame(frame->frameID(), callbackID), 0);
     406}
     407
     408void WebAutomationSession::didResolveParentFrame(uint64_t callbackID, uint64_t frameID, const String& errorType)
     409{
     410    auto callback = m_resolveParentFrameHandleCallbacks.take(callbackID);
     411    if (!callback)
     412        return;
     413
     414    if (!errorType.isEmpty())
     415        callback->sendFailure(errorType);
     416    else
     417        callback->sendSuccess(handleForWebFrameID(frameID));
     418}
     419
    293420} // namespace WebKit
  • trunk/Source/WebKit2/UIProcess/Automation/WebAutomationSession.h

    r198737 r198738  
    4848
    4949class WebAutomationSessionClient;
     50class WebFrameProxy;
    5051class WebPageProxy;
    5152class WebProcessPool;
     
    5859{
    5960public:
    60     typedef HashMap<uint64_t, String> WebPageHandleMap;
    61     typedef HashMap<String, uint64_t> HandleWebPageMap;
    62 
    6361    WebAutomationSession();
    6462    ~WebAutomationSession();
     
    6967    String sessionIdentifier() const { return m_sessionIdentifier; }
    7068
    71     WebKit::WebProcessPool* processPool() const { return m_processPool; }
    72     void setProcessPool(WebKit::WebProcessPool*);
     69    WebProcessPool* processPool() const { return m_processPool; }
     70    void setProcessPool(WebProcessPool*);
    7371
    7472#if ENABLE(REMOTE_INSPECTOR)
     
    8583    void createBrowsingContext(Inspector::ErrorString&, String*) override;
    8684    void closeBrowsingContext(Inspector::ErrorString&, const String&) override;
    87     void switchToBrowsingContext(Inspector::ErrorString&, const String&) override;
     85    void switchToBrowsingContext(Inspector::ErrorString&, const String& browsingContextHandle, const String* optionalFrameHandle) override;
    8886    void navigateBrowsingContext(Inspector::ErrorString&, const String& handle, const String& url) override;
    8987    void goBackInBrowsingContext(Inspector::ErrorString&, const String&) override;
    9088    void goForwardInBrowsingContext(Inspector::ErrorString&, const String&) override;
    9189    void reloadBrowsingContext(Inspector::ErrorString&, const String&) override;
    92     void evaluateJavaScriptFunction(Inspector::ErrorString&, const String& handle, const String& function, const Inspector::InspectorArray& arguments, bool expectsImplicitCallbackArgument, Ref<Inspector::AutomationBackendDispatcherHandler::EvaluateJavaScriptFunctionCallback>&&) override;
     90    void evaluateJavaScriptFunction(Inspector::ErrorString&, const String& browsingContextHandle, const String* optionalFrameHandle, const String& function, const Inspector::InspectorArray& arguments, bool expectsImplicitCallbackArgument, Ref<Inspector::AutomationBackendDispatcherHandler::EvaluateJavaScriptFunctionCallback>&&) override;
     91    void resolveChildFrameHandle(Inspector::ErrorString&, const String& browsingContextHandle, const String* optionalFrameHandle, const int* optionalOrdinal, const String* optionalName, const String* optionalNodeHandle, Ref<ResolveChildFrameHandleCallback>&&) override;
     92    void resolveParentFrameHandle(Inspector::ErrorString&, const String& browsingContextHandle, const String& frameHandle, Ref<ResolveParentFrameHandleCallback>&&) override;
    9393
    9494private:
    95     WebKit::WebPageProxy* webPageProxyForHandle(const String&);
    96     String handleForWebPageProxy(WebKit::WebPageProxy*);
     95    WebPageProxy* webPageProxyForHandle(const String&);
     96    String handleForWebPageProxy(const WebPageProxy&);
     97
     98    WebFrameProxy* webFrameProxyForHandle(const String&, WebPageProxy&);
     99    String handleForWebFrameID(uint64_t frameID);
     100    String handleForWebFrameProxy(const WebFrameProxy&);
    97101
    98102    // Implemented in generated WebAutomationSessionMessageReceiver.cpp
     
    101105    // Called by WebAutomationSession messages
    102106    void didEvaluateJavaScriptFunction(uint64_t callbackID, const String& result, const String& errorType);
     107    void didResolveChildFrame(uint64_t callbackID, uint64_t frameID, const String& errorType);
     108    void didResolveParentFrame(uint64_t callbackID, uint64_t frameID, const String& errorType);
    103109
    104     WebKit::WebProcessPool* m_processPool { nullptr };
     110    WebProcessPool* m_processPool { nullptr };
     111
    105112    std::unique_ptr<API::AutomationSessionClient> m_client;
    106113    String m_sessionIdentifier { ASCIILiteral("Untitled Session") };
     
    109116    Ref<Inspector::AutomationBackendDispatcher> m_domainDispatcher;
    110117
    111     WebPageHandleMap m_webPageHandleMap;
    112     HandleWebPageMap m_handleWebPageMap;
     118    HashMap<uint64_t, String> m_webPageHandleMap;
     119    HashMap<String, uint64_t> m_handleWebPageMap;
    113120    String m_activeBrowsingContextHandle;
     121
     122    HashMap<uint64_t, String> m_webFrameHandleMap;
     123    HashMap<String, uint64_t> m_handleWebFrameMap;
    114124
    115125    uint64_t m_nextEvaluateJavaScriptCallbackID { 1 };
    116126    HashMap<uint64_t, RefPtr<Inspector::AutomationBackendDispatcherHandler::EvaluateJavaScriptFunctionCallback>> m_evaluateJavaScriptFunctionCallbacks;
     127
     128    uint64_t m_nextResolveFrameCallbackID { 1 };
     129    HashMap<uint64_t, RefPtr<Inspector::AutomationBackendDispatcherHandler::ResolveChildFrameHandleCallback>> m_resolveChildFrameHandleCallbacks;
     130
     131    uint64_t m_nextResolveParentFrameCallbackID { 1 };
     132    HashMap<uint64_t, RefPtr<Inspector::AutomationBackendDispatcherHandler::ResolveParentFrameHandleCallback>> m_resolveParentFrameHandleCallbacks;
    117133
    118134#if ENABLE(REMOTE_INSPECTOR)
  • trunk/Source/WebKit2/UIProcess/Automation/WebAutomationSession.messages.in

    r198737 r198738  
    2323messages -> WebAutomationSession {
    2424    DidEvaluateJavaScriptFunction(uint64_t callbackID, String result, String errorType)
     25
     26    DidResolveChildFrame(uint64_t callbackID, uint64_t frameID, String errorType)
     27    DidResolveParentFrame(uint64_t callbackID, uint64_t frameID, String errorType)
    2528}
  • trunk/Source/WebKit2/WebProcess/Automation/WebAutomationSessionProxy.cpp

    r198737 r198738  
    3434#include "WebPage.h"
    3535#include "WebProcess.h"
     36#include <JavaScriptCore/APICast.h>
     37#include <JavaScriptCore/JSObject.h>
    3638#include <JavaScriptCore/JSRetainPtr.h>
    3739#include <JavaScriptCore/JSStringRefPrivate.h>
    3840#include <JavaScriptCore/OpaqueJSString.h>
     41#include <WebCore/DOMWindow.h>
     42#include <WebCore/Frame.h>
     43#include <WebCore/FrameTree.h>
     44#include <WebCore/HTMLFrameElementBase.h>
     45#include <WebCore/JSElement.h>
     46#include <WebCore/MainFrame.h>
    3947#include <WebCore/UUID.h>
    4048
     
    160168
    161169    return scriptObject;
     170}
     171
     172WebCore::Element* WebAutomationSessionProxy::elementForNodeHandle(WebFrame& frame, const String& nodeHandle)
     173{
     174    // Don't use scriptObjectForFrame() since we can assume if the script object
     175    // does not exist, there are no nodes mapped to handles. Using scriptObjectForFrame()
     176    // will make a new script object if it can't find one, preventing us from returning fast.
     177    JSObjectRef scriptObject = m_webFrameScriptObjectMap.get(frame.frameID());
     178    if (!scriptObject)
     179        return nullptr;
     180
     181    JSGlobalContextRef context = frame.jsContext();
     182
     183    JSValueRef functionArguments[] = {
     184        toJSValue(context, nodeHandle)
     185    };
     186
     187    JSValueRef result = callPropertyFunction(context, scriptObject, ASCIILiteral("nodeForIdentifier"), WTF_ARRAY_LENGTH(functionArguments), functionArguments, nullptr);
     188    JSObjectRef element = JSValueToObject(context, result, nullptr);
     189    if (!element)
     190        return nullptr;
     191
     192    auto elementWrapper = JSC::jsDynamicCast<WebCore::JSElement*>(toJS(element));
     193    if (!elementWrapper)
     194        return nullptr;
     195
     196    return &elementWrapper->wrapped();
    162197}
    163198
     
    240275}
    241276
     277void WebAutomationSessionProxy::resolveChildFrameWithOrdinal(uint64_t frameID, uint32_t ordinal, uint64_t callbackID)
     278{
     279    String frameNotFoundErrorType = Inspector::Protocol::getEnumConstantValue(Inspector::Protocol::Automation::ErrorMessage::FrameNotFound);
     280
     281    WebFrame* frame = WebProcess::singleton().webFrame(frameID);
     282    if (!frame) {
     283        WebProcess::singleton().parentProcessConnection()->send(Messages::WebAutomationSession::DidResolveChildFrame(callbackID, 0, frameNotFoundErrorType), 0);
     284        return;
     285    }
     286
     287    WebCore::Frame* coreFrame = frame->coreFrame();
     288    if (!coreFrame) {
     289        WebProcess::singleton().parentProcessConnection()->send(Messages::WebAutomationSession::DidResolveChildFrame(callbackID, 0, frameNotFoundErrorType), 0);
     290        return;
     291    }
     292
     293    WebCore::Frame* coreChildFrame = coreFrame->tree().scopedChild(ordinal);
     294    if (!coreChildFrame) {
     295        WebProcess::singleton().parentProcessConnection()->send(Messages::WebAutomationSession::DidResolveChildFrame(callbackID, 0, frameNotFoundErrorType), 0);
     296        return;
     297    }
     298
     299    WebFrame* childFrame = WebFrame::fromCoreFrame(*coreChildFrame);
     300    if (!childFrame) {
     301        WebProcess::singleton().parentProcessConnection()->send(Messages::WebAutomationSession::DidResolveChildFrame(callbackID, 0, frameNotFoundErrorType), 0);
     302        return;
     303    }
     304
     305    WebProcess::singleton().parentProcessConnection()->send(Messages::WebAutomationSession::DidResolveChildFrame(callbackID, childFrame->frameID(), emptyString()), 0);
     306}
     307
     308void WebAutomationSessionProxy::resolveChildFrameWithNodeHandle(uint64_t frameID, const String& nodeHandle, uint64_t callbackID)
     309{
     310    String frameNotFoundErrorType = Inspector::Protocol::getEnumConstantValue(Inspector::Protocol::Automation::ErrorMessage::FrameNotFound);
     311
     312    WebFrame* frame = WebProcess::singleton().webFrame(frameID);
     313    if (!frame) {
     314        WebProcess::singleton().parentProcessConnection()->send(Messages::WebAutomationSession::DidResolveChildFrame(callbackID, 0, frameNotFoundErrorType), 0);
     315        return;
     316    }
     317
     318    WebCore::Element* coreElement = elementForNodeHandle(*frame, nodeHandle);
     319    if (!coreElement || !coreElement->isFrameElementBase()) {
     320        WebProcess::singleton().parentProcessConnection()->send(Messages::WebAutomationSession::DidResolveChildFrame(callbackID, 0, frameNotFoundErrorType), 0);
     321        return;
     322    }
     323
     324    WebCore::Frame* coreFrameFromElement = static_cast<WebCore::HTMLFrameElementBase*>(coreElement)->contentFrame();
     325    if (!coreFrameFromElement) {
     326        WebProcess::singleton().parentProcessConnection()->send(Messages::WebAutomationSession::DidResolveChildFrame(callbackID, 0, frameNotFoundErrorType), 0);
     327        return;
     328    }
     329
     330    WebFrame* frameFromElement = WebFrame::fromCoreFrame(*coreFrameFromElement);
     331    if (!frameFromElement) {
     332        WebProcess::singleton().parentProcessConnection()->send(Messages::WebAutomationSession::DidResolveChildFrame(callbackID, 0, frameNotFoundErrorType), 0);
     333        return;
     334    }
     335
     336    WebProcess::singleton().parentProcessConnection()->send(Messages::WebAutomationSession::DidResolveChildFrame(callbackID, frameFromElement->frameID(), emptyString()), 0);
     337}
     338
     339void WebAutomationSessionProxy::resolveChildFrameWithName(uint64_t frameID, const String& name, uint64_t callbackID)
     340{
     341    String frameNotFoundErrorType = Inspector::Protocol::getEnumConstantValue(Inspector::Protocol::Automation::ErrorMessage::FrameNotFound);
     342
     343    WebFrame* frame = WebProcess::singleton().webFrame(frameID);
     344    if (!frame) {
     345        WebProcess::singleton().parentProcessConnection()->send(Messages::WebAutomationSession::DidResolveChildFrame(callbackID, 0, frameNotFoundErrorType), 0);
     346        return;
     347    }
     348
     349    WebCore::Frame* coreFrame = frame->coreFrame();
     350    if (!coreFrame) {
     351        WebProcess::singleton().parentProcessConnection()->send(Messages::WebAutomationSession::DidResolveChildFrame(callbackID, 0, frameNotFoundErrorType), 0);
     352        return;
     353    }
     354
     355    WebCore::Frame* coreChildFrame = coreFrame->tree().scopedChild(name);
     356    if (!coreChildFrame) {
     357        WebProcess::singleton().parentProcessConnection()->send(Messages::WebAutomationSession::DidResolveChildFrame(callbackID, 0, frameNotFoundErrorType), 0);
     358        return;
     359    }
     360
     361    WebFrame* childFrame = WebFrame::fromCoreFrame(*coreChildFrame);
     362    if (!childFrame) {
     363        WebProcess::singleton().parentProcessConnection()->send(Messages::WebAutomationSession::DidResolveChildFrame(callbackID, 0, frameNotFoundErrorType), 0);
     364        return;
     365    }
     366
     367    WebProcess::singleton().parentProcessConnection()->send(Messages::WebAutomationSession::DidResolveChildFrame(callbackID, childFrame->frameID(), emptyString()), 0);
     368}
     369
     370void WebAutomationSessionProxy::resolveParentFrame(uint64_t frameID, uint64_t callbackID)
     371{
     372    String frameNotFoundErrorType = Inspector::Protocol::getEnumConstantValue(Inspector::Protocol::Automation::ErrorMessage::FrameNotFound);
     373
     374    WebFrame* frame = WebProcess::singleton().webFrame(frameID);
     375    if (!frame) {
     376        WebProcess::singleton().parentProcessConnection()->send(Messages::WebAutomationSession::DidResolveParentFrame(callbackID, 0, frameNotFoundErrorType), 0);
     377        return;
     378    }
     379
     380    WebFrame* parentFrame = frame->parentFrame();
     381    if (!parentFrame) {
     382        WebProcess::singleton().parentProcessConnection()->send(Messages::WebAutomationSession::DidResolveParentFrame(callbackID, 0, frameNotFoundErrorType), 0);
     383        return;
     384    }
     385
     386    WebProcess::singleton().parentProcessConnection()->send(Messages::WebAutomationSession::DidResolveParentFrame(callbackID, parentFrame->frameID(), emptyString()), 0);
     387}
     388
     389void WebAutomationSessionProxy::focusFrame(uint64_t frameID)
     390{
     391    WebFrame* frame = WebProcess::singleton().webFrame(frameID);
     392    if (!frame)
     393        return;
     394
     395    WebCore::Frame* coreFrame = frame->coreFrame();
     396    if (!coreFrame)
     397        return;
     398
     399    WebCore::Document* coreDocument = coreFrame->document();
     400    if (!coreDocument)
     401        return;
     402
     403    WebCore::DOMWindow* coreDOMWindow = coreDocument->domWindow();
     404    if (!coreDOMWindow)
     405        return;
     406
     407    coreDOMWindow->focus(true);
     408}
     409
    242410} // namespace WebKit
  • trunk/Source/WebKit2/WebProcess/Automation/WebAutomationSessionProxy.h

    r198737 r198738  
    3030#include <JavaScriptCore/JSBase.h>
    3131
     32namespace WebCore {
     33class Element;
     34}
     35
    3236namespace WebKit {
    3337
     
    4852private:
    4953    JSObjectRef scriptObjectForFrame(WebFrame&);
     54    WebCore::Element* elementForNodeHandle(WebFrame&, const String&);
    5055
    5156    // Implemented in generated WebAutomationSessionProxyMessageReceiver.cpp
     
    5459    // Called by WebAutomationSessionProxy messages
    5560    void evaluateJavaScriptFunction(uint64_t frameID, const String& function, Vector<String> arguments, bool expectsImplicitCallbackArgument, uint64_t callbackID);
     61    void resolveChildFrameWithOrdinal(uint64_t frameID, uint32_t ordinal, uint64_t callbackID);
     62    void resolveChildFrameWithNodeHandle(uint64_t frameID, const String& nodeHandle, uint64_t callbackID);
     63    void resolveChildFrameWithName(uint64_t frameID, const String& name, uint64_t callbackID);
     64    void resolveParentFrame(uint64_t frameID, uint64_t callbackID);
     65    void focusFrame(uint64_t frameID);
    5666
    5767    String m_sessionIdentifier;
  • trunk/Source/WebKit2/WebProcess/Automation/WebAutomationSessionProxy.js

    r198737 r198738  
    5555        } else
    5656            callback(functionValue.apply(null, argumentValues));
     57    }
     58
     59    nodeForIdentifier(identifier)
     60    {
     61        try {
     62            return this._nodeForIdentifier(identifier);
     63        } catch (error) {
     64            return null;
     65        }
    5766    }
    5867
  • trunk/Source/WebKit2/WebProcess/Automation/WebAutomationSessionProxy.messages.in

    r198737 r198738  
    2222
    2323messages -> WebAutomationSessionProxy {
    24     EvaluateJavaScriptFunction(uint64_t frame, String function, Vector<String> arguments, bool expectsImplicitCallbackArgument, uint64_t callbackID)
     24    EvaluateJavaScriptFunction(uint64_t frameID, String function, Vector<String> arguments, bool expectsImplicitCallbackArgument, uint64_t callbackID)
     25
     26    ResolveChildFrameWithOrdinal(uint64_t frameID, uint32_t ordinal, uint64_t callbackID)
     27    ResolveChildFrameWithNodeHandle(uint64_t frameID, String nodeHandle, uint64_t callbackID)
     28    ResolveChildFrameWithName(uint64_t frameID, String name, uint64_t callbackID)
     29    ResolveParentFrame(uint64_t frameID, uint64_t callbackID)
     30
     31    FocusFrame(uint64_t frameID)
    2532}
Note: See TracChangeset for help on using the changeset viewer.