<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head><meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>[198738] trunk/Source</title>
</head>
<body>

<style type="text/css"><!--
#msg dl.meta { border: 1px #006 solid; background: #369; padding: 6px; color: #fff; }
#msg dl.meta dt { float: left; width: 6em; font-weight: bold; }
#msg dt:after { content:':';}
#msg dl, #msg dt, #msg ul, #msg li, #header, #footer, #logmsg { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt;  }
#msg dl a { font-weight: bold}
#msg dl a:link    { color:#fc3; }
#msg dl a:active  { color:#ff0; }
#msg dl a:visited { color:#cc6; }
h3 { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; font-weight: bold; }
#msg pre { overflow: auto; background: #ffc; border: 1px #fa0 solid; padding: 6px; }
#logmsg { background: #ffc; border: 1px #fa0 solid; padding: 1em 1em 0 1em; }
#logmsg p, #logmsg pre, #logmsg blockquote { margin: 0 0 1em 0; }
#logmsg p, #logmsg li, #logmsg dt, #logmsg dd { line-height: 14pt; }
#logmsg h1, #logmsg h2, #logmsg h3, #logmsg h4, #logmsg h5, #logmsg h6 { margin: .5em 0; }
#logmsg h1:first-child, #logmsg h2:first-child, #logmsg h3:first-child, #logmsg h4:first-child, #logmsg h5:first-child, #logmsg h6:first-child { margin-top: 0; }
#logmsg ul, #logmsg ol { padding: 0; list-style-position: inside; margin: 0 0 0 1em; }
#logmsg ul { text-indent: -1em; padding-left: 1em; }#logmsg ol { text-indent: -1.5em; padding-left: 1.5em; }
#logmsg > ul, #logmsg > ol { margin: 0 0 1em 0; }
#logmsg pre { background: #eee; padding: 1em; }
#logmsg blockquote { border: 1px solid #fa0; border-left-width: 10px; padding: 1em 1em 0 1em; background: white;}
#logmsg dl { margin: 0; }
#logmsg dt { font-weight: bold; }
#logmsg dd { margin: 0; padding: 0 0 0.5em 0; }
#logmsg dd:before { content:'\00bb';}
#logmsg table { border-spacing: 0px; border-collapse: collapse; border-top: 4px solid #fa0; border-bottom: 1px solid #fa0; background: #fff; }
#logmsg table th { text-align: left; font-weight: normal; padding: 0.2em 0.5em; border-top: 1px dotted #fa0; }
#logmsg table td { text-align: right; border-top: 1px dotted #fa0; padding: 0.2em 0.5em; }
#logmsg table thead th { text-align: center; border-bottom: 1px solid #fa0; }
#logmsg table th.Corner { text-align: left; }
#logmsg hr { border: none 0; border-top: 2px dashed #fa0; height: 1px; }
#header, #footer { color: #fff; background: #636; border: 1px #300 solid; padding: 6px; }
#patch { width: 100%; }
#patch h4 {font-family: verdana,arial,helvetica,sans-serif;font-size:10pt;padding:8px;background:#369;color:#fff;margin:0;}
#patch .propset h4, #patch .binary h4 {margin:0;}
#patch pre {padding:0;line-height:1.2em;margin:0;}
#patch .diff {width:100%;background:#eee;padding: 0 0 10px 0;overflow:auto;}
#patch .propset .diff, #patch .binary .diff  {padding:10px 0;}
#patch span {display:block;padding:0 10px;}
#patch .modfile, #patch .addfile, #patch .delfile, #patch .propset, #patch .binary, #patch .copfile {border:1px solid #ccc;margin:10px 0;}
#patch ins {background:#dfd;text-decoration:none;display:block;padding:0 10px;}
#patch del {background:#fdd;text-decoration:none;display:block;padding:0 10px;}
#patch .lines, .info {color:#888;background:#fff;}
--></style>
<div id="msg">
<dl class="meta">
<dt>Revision</dt> <dd><a href="http://trac.webkit.org/projects/webkit/changeset/198738">198738</a></dd>
<dt>Author</dt> <dd>timothy@apple.com</dd>
<dt>Date</dt> <dd>2016-03-28 08:57:23 -0700 (Mon, 28 Mar 2016)</dd>
</dl>

<h3>Log Message</h3>
<pre>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.</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkSourceWebCoreChangeLog">trunk/Source/WebCore/ChangeLog</a></li>
<li><a href="#trunkSourceWebCorepageDOMWindowh">trunk/Source/WebCore/page/DOMWindow.h</a></li>
<li><a href="#trunkSourceWebCorepageFrameTreeh">trunk/Source/WebCore/page/FrameTree.h</a></li>
<li><a href="#trunkSourceWebKit2ChangeLog">trunk/Source/WebKit2/ChangeLog</a></li>
<li><a href="#trunkSourceWebKit2UIProcessAutomationAutomationjson">trunk/Source/WebKit2/UIProcess/Automation/Automation.json</a></li>
<li><a href="#trunkSourceWebKit2UIProcessAutomationWebAutomationSessioncpp">trunk/Source/WebKit2/UIProcess/Automation/WebAutomationSession.cpp</a></li>
<li><a href="#trunkSourceWebKit2UIProcessAutomationWebAutomationSessionh">trunk/Source/WebKit2/UIProcess/Automation/WebAutomationSession.h</a></li>
<li><a href="#trunkSourceWebKit2UIProcessAutomationWebAutomationSessionmessagesin">trunk/Source/WebKit2/UIProcess/Automation/WebAutomationSession.messages.in</a></li>
<li><a href="#trunkSourceWebKit2WebProcessAutomationWebAutomationSessionProxycpp">trunk/Source/WebKit2/WebProcess/Automation/WebAutomationSessionProxy.cpp</a></li>
<li><a href="#trunkSourceWebKit2WebProcessAutomationWebAutomationSessionProxyh">trunk/Source/WebKit2/WebProcess/Automation/WebAutomationSessionProxy.h</a></li>
<li><a href="#trunkSourceWebKit2WebProcessAutomationWebAutomationSessionProxyjs">trunk/Source/WebKit2/WebProcess/Automation/WebAutomationSessionProxy.js</a></li>
<li><a href="#trunkSourceWebKit2WebProcessAutomationWebAutomationSessionProxymessagesin">trunk/Source/WebKit2/WebProcess/Automation/WebAutomationSessionProxy.messages.in</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkSourceWebCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/ChangeLog (198737 => 198738)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/ChangeLog        2016-03-28 15:57:06 UTC (rev 198737)
+++ trunk/Source/WebCore/ChangeLog        2016-03-28 15:57:23 UTC (rev 198738)
</span><span class="lines">@@ -1,3 +1,15 @@
</span><ins>+2016-03-18  Timothy Hatcher  &lt;timothy@apple.com&gt;
+
+        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.
+
+        * 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.
+
</ins><span class="cx"> 2016-03-28  Konstantin Tokarev  &lt;annulen@yandex.ru&gt;
</span><span class="cx"> 
</span><span class="cx">         Remove USE(TEXTURE_MAPPER) guards inside TextureMapper sources.
</span></span></pre></div>
<a id="trunkSourceWebCorepageDOMWindowh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/page/DOMWindow.h (198737 => 198738)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/page/DOMWindow.h        2016-03-28 15:57:06 UTC (rev 198737)
+++ trunk/Source/WebCore/page/DOMWindow.h        2016-03-28 15:57:23 UTC (rev 198738)
</span><span class="lines">@@ -160,7 +160,7 @@
</span><span class="cx"> 
</span><span class="cx">         Element* frameElement() const;
</span><span class="cx"> 
</span><del>-        void focus(bool allowFocus = false);
</del><ins>+        WEBCORE_EXPORT void focus(bool allowFocus = false);
</ins><span class="cx">         void focus(Document&amp;);
</span><span class="cx">         void blur();
</span><span class="cx">         WEBCORE_EXPORT void close();
</span></span></pre></div>
<a id="trunkSourceWebCorepageFrameTreeh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/page/FrameTree.h (198737 => 198738)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/page/FrameTree.h        2016-03-28 15:57:06 UTC (rev 198737)
+++ trunk/Source/WebCore/page/FrameTree.h        2016-03-28 15:57:23 UTC (rev 198738)
</span><span class="lines">@@ -80,8 +80,8 @@
</span><span class="cx"> 
</span><span class="cx">         WEBCORE_EXPORT Frame&amp; top() const;
</span><span class="cx"> 
</span><del>-        Frame* scopedChild(unsigned index) const;
-        Frame* scopedChild(const AtomicString&amp; name) const;
</del><ins>+        WEBCORE_EXPORT Frame* scopedChild(unsigned index) const;
+        WEBCORE_EXPORT Frame* scopedChild(const AtomicString&amp; name) const;
</ins><span class="cx">         unsigned scopedChildCount() const;
</span><span class="cx"> 
</span><span class="cx">         unsigned indexInParent() const;
</span></span></pre></div>
<a id="trunkSourceWebKit2ChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/ChangeLog (198737 => 198738)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/ChangeLog        2016-03-28 15:57:06 UTC (rev 198737)
+++ trunk/Source/WebKit2/ChangeLog        2016-03-28 15:57:23 UTC (rev 198738)
</span><span class="lines">@@ -1,3 +1,48 @@
</span><ins>+2016-03-18  Timothy Hatcher  &lt;timothy@apple.com&gt;
+
+        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.
+
+        * 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.
+
</ins><span class="cx"> 2016-03-17  Timothy Hatcher  &lt;timothy@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         Web Automation: Add Automation.evaluateJavaScriptFunction
</span></span></pre></div>
<a id="trunkSourceWebKit2UIProcessAutomationAutomationjson"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/UIProcess/Automation/Automation.json (198737 => 198738)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/UIProcess/Automation/Automation.json        2016-03-28 15:57:06 UTC (rev 198737)
+++ trunk/Source/WebKit2/UIProcess/Automation/Automation.json        2016-03-28 15:57:23 UTC (rev 198738)
</span><span class="lines">@@ -8,6 +8,16 @@
</span><span class="cx">             &quot;description&quot;: &quot;An opaque identifier for a browsing context.&quot;
</span><span class="cx">         },
</span><span class="cx">         {
</span><ins>+            &quot;id&quot;: &quot;FrameHandle&quot;,
+            &quot;type&quot;: &quot;string&quot;,
+            &quot;description&quot;: &quot;An opaque identifier for a frame in a page.&quot;
+        },
+        {
+            &quot;id&quot;: &quot;NodeHandle&quot;,
+            &quot;type&quot;: &quot;string&quot;,
+            &quot;description&quot;: &quot;An opaque identifier for a node in a page.&quot;
+        },
+        {
</ins><span class="cx">             &quot;id&quot;: &quot;ErrorMessage&quot;,
</span><span class="cx">             &quot;type&quot;: &quot;string&quot;,
</span><span class="cx">             &quot;description&quot;: &quot;This enum contains predefined error messages that can be used to signal a well-defined error condition, such as a missing implementation, unknown window handle, and so forth. The backend signals one of these errors by using it as a prefix of the commands's error message (the errorString argument in generated C++ backend dispatchers). This will be reported to the frontend as a protocol error with a JSON-RPC error code of 'ServerError'. It is up to the frontend whether and how to deal with errors.&quot;,
</span><span class="lines">@@ -15,8 +25,10 @@
</span><span class="cx">                 &quot;InternalError&quot;,
</span><span class="cx">                 &quot;JavaScriptError&quot;,
</span><span class="cx">                 &quot;WindowNotFound&quot;,
</span><ins>+                &quot;FrameNotFound&quot;,
</ins><span class="cx">                 &quot;NodeNotFound&quot;,
</span><del>-                &quot;NotImplemented&quot;
</del><ins>+                &quot;NotImplemented&quot;,
+                &quot;MissingParameter&quot;
</ins><span class="cx">             ]
</span><span class="cx">         },
</span><span class="cx">         {
</span><span class="lines">@@ -64,9 +76,10 @@
</span><span class="cx">         },
</span><span class="cx">         {
</span><span class="cx">             &quot;name&quot;: &quot;switchToBrowsingContext&quot;,
</span><del>-            &quot;description&quot;: &quot;Activates the specified browsing context.&quot;,
</del><ins>+            &quot;description&quot;: &quot;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).&quot;,
</ins><span class="cx">             &quot;parameters&quot;: [
</span><del>-                { &quot;name&quot;: &quot;handle&quot;, &quot;$ref&quot;: &quot;BrowsingContextHandle&quot;, &quot;description&quot;: &quot;The handle for the browsing context that should be made active.&quot; }
</del><ins>+                { &quot;name&quot;: &quot;browsingContextHandle&quot;, &quot;$ref&quot;: &quot;BrowsingContextHandle&quot;, &quot;description&quot;: &quot;The handle for the browsing context that should be made focused.&quot; },
+                { &quot;name&quot;: &quot;frameHandle&quot;, &quot;$ref&quot;: &quot;FrameHandle&quot;, &quot;optional&quot;: true, &quot;description&quot;: &quot;The handle for the frame that should be focused. Defaults to the main frame if omitted.&quot; }
</ins><span class="cx">             ]
</span><span class="cx">         },
</span><span class="cx">         {
</span><span class="lines">@@ -102,8 +115,9 @@
</span><span class="cx">             &quot;name&quot;: &quot;evaluateJavaScriptFunction&quot;,
</span><span class="cx">             &quot;description&quot;: &quot;Evaluates a script function in a browsing context and calls it with the supplied arguments.&quot;,
</span><span class="cx">             &quot;parameters&quot;: [
</span><del>-                { &quot;name&quot;: &quot;handle&quot;, &quot;$ref&quot;: &quot;BrowsingContextHandle&quot;, &quot;description&quot;: &quot;The handle for the browsing context the script should be evaluated.&quot; },
-                { &quot;name&quot;: &quot;function&quot;, &quot;type&quot;: &quot;string&quot;, &quot;description&quot;: &quot;The script to evaluate in the browsing context. The script is expected to be a function declaration, or otherwise evaluate to a function result.&quot; },
</del><ins>+                { &quot;name&quot;: &quot;browsingContextHandle&quot;, &quot;$ref&quot;: &quot;BrowsingContextHandle&quot;, &quot;description&quot;: &quot;The handle for the browsing context the script should be evaluated.&quot; },
+                { &quot;name&quot;: &quot;frameHandle&quot;, &quot;$ref&quot;: &quot;FrameHandle&quot;, &quot;optional&quot;: true, &quot;description&quot;: &quot;The handle for the frame the script should be evaluated. The main frame is used if this parameter empty string or excluded.&quot; },
+                { &quot;name&quot;: &quot;function&quot;, &quot;type&quot;: &quot;string&quot;, &quot;description&quot;: &quot;The script to evaluate in the browsing context. It must be a function result.&quot; },
</ins><span class="cx">                 { &quot;name&quot;: &quot;arguments&quot;, &quot;type&quot;: &quot;array&quot;, &quot;items&quot;: { &quot;type&quot;: &quot;string&quot; }, &quot;description&quot;: &quot;The arguments to pass to the function when called. They will be parsed as JSON before calling the function.&quot; },
</span><span class="cx">                 { &quot;name&quot;: &quot;expectsImplicitCallbackArgument&quot;, &quot;type&quot;: &quot;boolean&quot;, &quot;description&quot;: &quot;The function expects a callback function as the last argument. It is expected to call this callback with a result.&quot; }
</span><span class="cx">             ],
</span><span class="lines">@@ -111,6 +125,33 @@
</span><span class="cx">                 { &quot;name&quot;: &quot;result&quot;, &quot;type&quot;: &quot;string&quot;, &quot;description&quot;: &quot;The result returned by the called function. It is JSON encoded after the function returns or calls the callback.&quot; }
</span><span class="cx">             ],
</span><span class="cx">             &quot;async&quot;: true
</span><ins>+        },
+        {
+            &quot;name&quot;: &quot;resolveChildFrameHandle&quot;,
+            &quot;description&quot;: &quot;Determines the &lt;code&gt;FrameHandle&lt;/code&gt; based on the ordinal, name or node handle of a child frame.&quot;,
+            &quot;parameters&quot;: [
+                { &quot;name&quot;: &quot;browsingContextHandle&quot;, &quot;$ref&quot;: &quot;BrowsingContextHandle&quot;, &quot;description&quot;: &quot;The handle for the browsing context in which to search for the frame.&quot; },
+                { &quot;name&quot;: &quot;frameHandle&quot;, &quot;$ref&quot;: &quot;FrameHandle&quot;, &quot;optional&quot;: true, &quot;description&quot;: &quot;The handle for the frame in which to search for the frame. The main frame is used if this parameter empty string or excluded.&quot; },
+                { &quot;name&quot;: &quot;ordinal&quot;, &quot;type&quot;: &quot;integer&quot;, &quot;optional&quot;: true, &quot;description&quot;: &quot;The ordinal of the child frame to resolve as a &lt;code&gt;FrameHandle&lt;/code&gt;. This is analogous to 'window.frames[ordinal]' in JavaScript.&quot; },
+                { &quot;name&quot;: &quot;name&quot;, &quot;type&quot;: &quot;string&quot;, &quot;optional&quot;: true, &quot;description&quot;: &quot;The name of the child frame to resolve as a &lt;code&gt;FrameHandle&lt;/code&gt;. This is analogous to 'window.frames[name]' in JavaScript.&quot; },
+                { &quot;name&quot;: &quot;nodeHandle&quot;, &quot;$ref&quot;: &quot;NodeHandle&quot;, &quot;optional&quot;: true, &quot;description&quot;: &quot;The handle of the child frame owner element to resolve as a &lt;code&gt;FrameHandle&lt;/code&gt;.&quot; }
+            ],
+            &quot;returns&quot;: [
+                { &quot;name&quot;: &quot;result&quot;, &quot;$ref&quot;: &quot;FrameHandle&quot;, &quot;description&quot;: &quot;The &lt;code&gt;FrameHandle&lt;/code&gt; for the requested frame.&quot; }
+            ],
+            &quot;async&quot;: true
+        },
+        {
+            &quot;name&quot;: &quot;resolveParentFrameHandle&quot;,
+            &quot;description&quot;: &quot;Determines the &lt;code&gt;FrameHandle&lt;/code&gt; for the parent frame of the supplied &lt;code&gt;FrameHandle&lt;/code&gt;.&quot;,
+            &quot;parameters&quot;: [
+                { &quot;name&quot;: &quot;browsingContextHandle&quot;, &quot;$ref&quot;: &quot;BrowsingContextHandle&quot;, &quot;description&quot;: &quot;The handle for the browsing context the frame is located.&quot; },
+                { &quot;name&quot;: &quot;frameHandle&quot;, &quot;$ref&quot;: &quot;FrameHandle&quot;, &quot;description&quot;: &quot;The handle for the frame that should resolve its parent frame.&quot; }
+            ],
+            &quot;returns&quot;: [
+                { &quot;name&quot;: &quot;result&quot;, &quot;$ref&quot;: &quot;FrameHandle&quot;, &quot;description&quot;: &quot;The &lt;code&gt;FrameHandle&lt;/code&gt; for the requested frame.&quot; }
+            ],
+            &quot;async&quot;: true
</ins><span class="cx">         }
</span><span class="cx">     ]
</span><span class="cx"> }
</span></span></pre></div>
<a id="trunkSourceWebKit2UIProcessAutomationWebAutomationSessioncpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/UIProcess/Automation/WebAutomationSession.cpp (198737 => 198738)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/UIProcess/Automation/WebAutomationSession.cpp        2016-03-28 15:57:06 UTC (rev 198737)
+++ trunk/Source/WebKit2/UIProcess/Automation/WebAutomationSession.cpp        2016-03-28 15:57:23 UTC (rev 198738)
</span><span class="lines">@@ -125,25 +125,71 @@
</span><span class="cx">     return WebProcessProxy::webPage(iter-&gt;value);
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-String WebAutomationSession::handleForWebPageProxy(WebPageProxy* webPageProxy)
</del><ins>+String WebAutomationSession::handleForWebPageProxy(const WebPageProxy&amp; webPageProxy)
</ins><span class="cx"> {
</span><del>-    auto iter = m_webPageHandleMap.find(webPageProxy-&gt;pageID());
</del><ins>+    auto iter = m_webPageHandleMap.find(webPageProxy.pageID());
</ins><span class="cx">     if (iter != m_webPageHandleMap.end())
</span><span class="cx">         return iter-&gt;value;
</span><span class="cx"> 
</span><del>-    String handle = WebCore::createCanonicalUUIDString().convertToASCIIUppercase();
</del><ins>+    String handle = &quot;page-&quot; + WebCore::createCanonicalUUIDString().convertToASCIIUppercase();
</ins><span class="cx"> 
</span><del>-    auto firstAddResult = m_webPageHandleMap.add(webPageProxy-&gt;pageID(), handle);
</del><ins>+    auto firstAddResult = m_webPageHandleMap.add(webPageProxy.pageID(), handle);
</ins><span class="cx">     RELEASE_ASSERT(firstAddResult.isNewEntry);
</span><span class="cx"> 
</span><del>-    auto secondAddResult = m_handleWebPageMap.add(handle, webPageProxy-&gt;pageID());
</del><ins>+    auto secondAddResult = m_handleWebPageMap.add(handle, webPageProxy.pageID());
</ins><span class="cx">     RELEASE_ASSERT(secondAddResult.isNewEntry);
</span><span class="cx"> 
</span><span class="cx">     return handle;
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-// Inspector::AutomationBackendDispatcherHandler API
</del><ins>+WebFrameProxy* WebAutomationSession::webFrameProxyForHandle(const String&amp; handle, WebPageProxy&amp; page)
+{
+    if (handle.isEmpty())
+        return page.mainFrame();
</ins><span class="cx"> 
</span><ins>+    auto iter = m_handleWebFrameMap.find(handle);
+    if (iter == m_handleWebFrameMap.end())
+        return nullptr;
+
+    if (WebFrameProxy* frame = page.process().webFrame(iter-&gt;value))
+        return frame;
+
+    return nullptr;
+}
+
+String WebAutomationSession::handleForWebFrameID(uint64_t frameID)
+{
+    if (!frameID)
+        return emptyString();
+
+    for (auto&amp; process : m_processPool-&gt;processes()) {
+        if (WebFrameProxy* frame = process-&gt;webFrame(frameID)) {
+            if (frame-&gt;isMainFrame())
+                return emptyString();
+            break;
+        }
+    }
+
+    auto iter = m_webFrameHandleMap.find(frameID);
+    if (iter != m_webFrameHandleMap.end())
+        return iter-&gt;value;
+
+    String handle = &quot;frame-&quot; + WebCore::createCanonicalUUIDString().convertToASCIIUppercase();
+
+    auto firstAddResult = m_webFrameHandleMap.add(frameID, handle);
+    RELEASE_ASSERT(firstAddResult.isNewEntry);
+
+    auto secondAddResult = m_handleWebFrameMap.add(handle, frameID);
+    RELEASE_ASSERT(secondAddResult.isNewEntry);
+
+    return handle;
+}
+
+String WebAutomationSession::handleForWebFrameProxy(const WebFrameProxy&amp; webFrameProxy)
+{
+    return handleForWebFrameID(webFrameProxy.frameID());
+}
+
</ins><span class="cx"> void WebAutomationSession::getBrowsingContexts(Inspector::ErrorString&amp; errorString, RefPtr&lt;Inspector::Protocol::Array&lt;Inspector::Protocol::Automation::BrowsingContext&gt;&gt;&amp; contexts)
</span><span class="cx"> {
</span><span class="cx">     contexts = Inspector::Protocol::Array&lt;Inspector::Protocol::Automation::BrowsingContext&gt;::create();
</span><span class="lines">@@ -153,10 +199,10 @@
</span><span class="cx">             if (!page-&gt;isControlledByAutomation())
</span><span class="cx">                 continue;
</span><span class="cx"> 
</span><del>-            String handle = handleForWebPageProxy(page);
</del><ins>+            String handle = handleForWebPageProxy(*page);
</ins><span class="cx"> 
</span><span class="cx">             auto browsingContext = Inspector::Protocol::Automation::BrowsingContext::create()
</span><del>-                .setHandle(handleForWebPageProxy(page))
</del><ins>+                .setHandle(handleForWebPageProxy(*page))
</ins><span class="cx">                 .setActive(m_activeBrowsingContextHandle == handle)
</span><span class="cx">                 .setUrl(page-&gt;pageLoadState().activeURL())
</span><span class="cx">                 .release();
</span><span class="lines">@@ -173,7 +219,7 @@
</span><span class="cx">         FAIL_WITH_PREDEFINED_ERROR_MESSAGE(WindowNotFound);
</span><span class="cx"> 
</span><span class="cx">     context = Inspector::Protocol::Automation::BrowsingContext::create()
</span><del>-        .setHandle(handleForWebPageProxy(page))
</del><ins>+        .setHandle(handleForWebPageProxy(*page))
</ins><span class="cx">         .setActive(m_activeBrowsingContextHandle == handle)
</span><span class="cx">         .setUrl(page-&gt;pageLoadState().activeURL())
</span><span class="cx">         .release();
</span><span class="lines">@@ -189,7 +235,7 @@
</span><span class="cx">     if (!page)
</span><span class="cx">         FAIL_WITH_PREDEFINED_ERROR_MESSAGE(InternalError);
</span><span class="cx"> 
</span><del>-    m_activeBrowsingContextHandle = *handle = handleForWebPageProxy(page);
</del><ins>+    m_activeBrowsingContextHandle = *handle = handleForWebPageProxy(*page);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void WebAutomationSession::closeBrowsingContext(Inspector::ErrorString&amp; errorString, const String&amp; handle)
</span><span class="lines">@@ -204,17 +250,21 @@
</span><span class="cx">     page-&gt;closePage(false);
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-void WebAutomationSession::switchToBrowsingContext(Inspector::ErrorString&amp; errorString, const String&amp; handle)
</del><ins>+void WebAutomationSession::switchToBrowsingContext(Inspector::ErrorString&amp; errorString, const String&amp; browsingContextHandle, const String* optionalFrameHandle)
</ins><span class="cx"> {
</span><del>-    WebPageProxy* page = webPageProxyForHandle(handle);
</del><ins>+    WebPageProxy* page = webPageProxyForHandle(browsingContextHandle);
</ins><span class="cx">     if (!page)
</span><span class="cx">         FAIL_WITH_PREDEFINED_ERROR_MESSAGE(WindowNotFound);
</span><span class="cx"> 
</span><del>-    m_activeBrowsingContextHandle = handle;
</del><ins>+    WebFrameProxy* frame = webFrameProxyForHandle(optionalFrameHandle ? *optionalFrameHandle : emptyString(), *page);
+    if (!frame)
+        FAIL_WITH_PREDEFINED_ERROR_MESSAGE(FrameNotFound);
</ins><span class="cx"> 
</span><del>-    // FIXME: Verify this is enough. We still might want to go through the AutomationSessionClient
-    // to get closer a user pressing focusing the window / page.
</del><ins>+    // FIXME: We don't need to track this in WK2. Remove in a follow up.
+    m_activeBrowsingContextHandle = browsingContextHandle;
+
</ins><span class="cx">     page-&gt;setFocus(true);
</span><ins>+    page-&gt;process().send(Messages::WebAutomationSessionProxy::FocusFrame(frame-&gt;frameID()), 0);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void WebAutomationSession::navigateBrowsingContext(Inspector::ErrorString&amp; errorString, const String&amp; handle, const String&amp; url)
</span><span class="lines">@@ -255,13 +305,16 @@
</span><span class="cx">     page-&gt;reload(reloadFromOrigin, contentBlockersEnabled);
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-void WebAutomationSession::evaluateJavaScriptFunction(Inspector::ErrorString&amp; errorString, const String&amp; handle, const String&amp; function, const Inspector::InspectorArray&amp; arguments, bool expectsImplicitCallbackArgument, Ref&lt;EvaluateJavaScriptFunctionCallback&gt;&amp;&amp; callback)
</del><ins>+void WebAutomationSession::evaluateJavaScriptFunction(Inspector::ErrorString&amp; errorString, const String&amp; browsingContextHandle, const String* optionalFrameHandle, const String&amp; function, const Inspector::InspectorArray&amp; arguments, bool expectsImplicitCallbackArgument, Ref&lt;EvaluateJavaScriptFunctionCallback&gt;&amp;&amp; callback)
</ins><span class="cx"> {
</span><del>-    // FIXME 24172439: This should be a frame handle, not a page handle. Change this once we have frame support.
-    WebPageProxy* page = webPageProxyForHandle(handle);
</del><ins>+    WebPageProxy* page = webPageProxyForHandle(browsingContextHandle);
</ins><span class="cx">     if (!page)
</span><span class="cx">         FAIL_WITH_PREDEFINED_ERROR_MESSAGE(WindowNotFound);
</span><span class="cx"> 
</span><ins>+    WebFrameProxy* frame = webFrameProxyForHandle(optionalFrameHandle ? *optionalFrameHandle : emptyString(), *page);
+    if (!frame)
+        FAIL_WITH_PREDEFINED_ERROR_MESSAGE(FrameNotFound);
+
</ins><span class="cx">     Vector&lt;String&gt; argumentsVector;
</span><span class="cx">     argumentsVector.reserveCapacity(arguments.length());
</span><span class="cx"> 
</span><span class="lines">@@ -274,7 +327,7 @@
</span><span class="cx">     uint64_t callbackID = m_nextEvaluateJavaScriptCallbackID++;
</span><span class="cx">     m_evaluateJavaScriptFunctionCallbacks.set(callbackID, WTFMove(callback));
</span><span class="cx"> 
</span><del>-    page-&gt;process().send(Messages::WebAutomationSessionProxy::EvaluateJavaScriptFunction(page-&gt;mainFrame()-&gt;frameID(), function, argumentsVector, expectsImplicitCallbackArgument, callbackID), 0);
</del><ins>+    page-&gt;process().send(Messages::WebAutomationSessionProxy::EvaluateJavaScriptFunction(frame-&gt;frameID(), function, argumentsVector, expectsImplicitCallbackArgument, callbackID), 0);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void WebAutomationSession::didEvaluateJavaScriptFunction(uint64_t callbackID, const String&amp; result, const String&amp; errorType)
</span><span class="lines">@@ -290,4 +343,78 @@
</span><span class="cx">         callback-&gt;sendSuccess(result);
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+void WebAutomationSession::resolveChildFrameHandle(Inspector::ErrorString&amp; errorString, const String&amp; browsingContextHandle, const String* optionalFrameHandle, const int* optionalOrdinal, const String* optionalName, const String* optionalNodeHandle, Ref&lt;ResolveChildFrameHandleCallback&gt;&amp;&amp; callback)
+{
+    if (!optionalOrdinal &amp;&amp; !optionalName &amp;&amp; !optionalNodeHandle)
+        FAIL_WITH_PREDEFINED_ERROR_MESSAGE(MissingParameter);
+
+    WebPageProxy* page = webPageProxyForHandle(browsingContextHandle);
+    if (!page)
+        FAIL_WITH_PREDEFINED_ERROR_MESSAGE(WindowNotFound);
+
+    WebFrameProxy* frame = webFrameProxyForHandle(optionalFrameHandle ? *optionalFrameHandle : emptyString(), *page);
+    if (!frame)
+        FAIL_WITH_PREDEFINED_ERROR_MESSAGE(FrameNotFound);
+
+    uint64_t callbackID = m_nextResolveFrameCallbackID++;
+    m_resolveChildFrameHandleCallbacks.set(callbackID, WTFMove(callback));
+
+    if (optionalNodeHandle) {
+        page-&gt;process().send(Messages::WebAutomationSessionProxy::ResolveChildFrameWithNodeHandle(frame-&gt;frameID(), *optionalNodeHandle, callbackID), 0);
+        return;
+    }
+
+    if (optionalName) {
+        page-&gt;process().send(Messages::WebAutomationSessionProxy::ResolveChildFrameWithName(frame-&gt;frameID(), *optionalName, callbackID), 0);
+        return;
+    }
+
+    if (optionalOrdinal) {
+        page-&gt;process().send(Messages::WebAutomationSessionProxy::ResolveChildFrameWithOrdinal(frame-&gt;frameID(), *optionalOrdinal, callbackID), 0);
+        return;
+    }
+
+    ASSERT_NOT_REACHED();
+}
+
+void WebAutomationSession::didResolveChildFrame(uint64_t callbackID, uint64_t frameID, const String&amp; errorType)
+{
+    auto callback = m_resolveChildFrameHandleCallbacks.take(callbackID);
+    if (!callback)
+        return;
+
+    if (!errorType.isEmpty())
+        callback-&gt;sendFailure(errorType);
+    else
+        callback-&gt;sendSuccess(handleForWebFrameID(frameID));
+}
+
+void WebAutomationSession::resolveParentFrameHandle(Inspector::ErrorString&amp; errorString, const String&amp; browsingContextHandle, const String&amp; frameHandle, Ref&lt;ResolveParentFrameHandleCallback&gt;&amp;&amp; callback)
+{
+    WebPageProxy* page = webPageProxyForHandle(browsingContextHandle);
+    if (!page)
+        FAIL_WITH_PREDEFINED_ERROR_MESSAGE(WindowNotFound);
+
+    WebFrameProxy* frame = webFrameProxyForHandle(frameHandle, *page);
+    if (!frame)
+        FAIL_WITH_PREDEFINED_ERROR_MESSAGE(FrameNotFound);
+
+    uint64_t callbackID = m_nextResolveParentFrameCallbackID++;
+    m_resolveParentFrameHandleCallbacks.set(callbackID, WTFMove(callback));
+
+    page-&gt;process().send(Messages::WebAutomationSessionProxy::ResolveParentFrame(frame-&gt;frameID(), callbackID), 0);
+}
+
+void WebAutomationSession::didResolveParentFrame(uint64_t callbackID, uint64_t frameID, const String&amp; errorType)
+{
+    auto callback = m_resolveParentFrameHandleCallbacks.take(callbackID);
+    if (!callback)
+        return;
+
+    if (!errorType.isEmpty())
+        callback-&gt;sendFailure(errorType);
+    else
+        callback-&gt;sendSuccess(handleForWebFrameID(frameID));
+}
+
</ins><span class="cx"> } // namespace WebKit
</span></span></pre></div>
<a id="trunkSourceWebKit2UIProcessAutomationWebAutomationSessionh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/UIProcess/Automation/WebAutomationSession.h (198737 => 198738)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/UIProcess/Automation/WebAutomationSession.h        2016-03-28 15:57:06 UTC (rev 198737)
+++ trunk/Source/WebKit2/UIProcess/Automation/WebAutomationSession.h        2016-03-28 15:57:23 UTC (rev 198738)
</span><span class="lines">@@ -47,6 +47,7 @@
</span><span class="cx"> namespace WebKit {
</span><span class="cx"> 
</span><span class="cx"> class WebAutomationSessionClient;
</span><ins>+class WebFrameProxy;
</ins><span class="cx"> class WebPageProxy;
</span><span class="cx"> class WebProcessPool;
</span><span class="cx"> 
</span><span class="lines">@@ -57,9 +58,6 @@
</span><span class="cx">     , public Inspector::AutomationBackendDispatcherHandler
</span><span class="cx"> {
</span><span class="cx"> public:
</span><del>-    typedef HashMap&lt;uint64_t, String&gt; WebPageHandleMap;
-    typedef HashMap&lt;String, uint64_t&gt; HandleWebPageMap;
-
</del><span class="cx">     WebAutomationSession();
</span><span class="cx">     ~WebAutomationSession();
</span><span class="cx"> 
</span><span class="lines">@@ -68,8 +66,8 @@
</span><span class="cx">     void setSessionIdentifier(const String&amp; sessionIdentifier) { m_sessionIdentifier = sessionIdentifier; }
</span><span class="cx">     String sessionIdentifier() const { return m_sessionIdentifier; }
</span><span class="cx"> 
</span><del>-    WebKit::WebProcessPool* processPool() const { return m_processPool; }
-    void setProcessPool(WebKit::WebProcessPool*);
</del><ins>+    WebProcessPool* processPool() const { return m_processPool; }
+    void setProcessPool(WebProcessPool*);
</ins><span class="cx"> 
</span><span class="cx"> #if ENABLE(REMOTE_INSPECTOR)
</span><span class="cx">     // Inspector::RemoteAutomationTarget API
</span><span class="lines">@@ -84,37 +82,55 @@
</span><span class="cx">     void getBrowsingContext(Inspector::ErrorString&amp;, const String&amp;, RefPtr&lt;Inspector::Protocol::Automation::BrowsingContext&gt;&amp;) override;
</span><span class="cx">     void createBrowsingContext(Inspector::ErrorString&amp;, String*) override;
</span><span class="cx">     void closeBrowsingContext(Inspector::ErrorString&amp;, const String&amp;) override;
</span><del>-    void switchToBrowsingContext(Inspector::ErrorString&amp;, const String&amp;) override;
</del><ins>+    void switchToBrowsingContext(Inspector::ErrorString&amp;, const String&amp; browsingContextHandle, const String* optionalFrameHandle) override;
</ins><span class="cx">     void navigateBrowsingContext(Inspector::ErrorString&amp;, const String&amp; handle, const String&amp; url) override;
</span><span class="cx">     void goBackInBrowsingContext(Inspector::ErrorString&amp;, const String&amp;) override;
</span><span class="cx">     void goForwardInBrowsingContext(Inspector::ErrorString&amp;, const String&amp;) override;
</span><span class="cx">     void reloadBrowsingContext(Inspector::ErrorString&amp;, const String&amp;) override;
</span><del>-    void evaluateJavaScriptFunction(Inspector::ErrorString&amp;, const String&amp; handle, const String&amp; function, const Inspector::InspectorArray&amp; arguments, bool expectsImplicitCallbackArgument, Ref&lt;Inspector::AutomationBackendDispatcherHandler::EvaluateJavaScriptFunctionCallback&gt;&amp;&amp;) override;
</del><ins>+    void evaluateJavaScriptFunction(Inspector::ErrorString&amp;, const String&amp; browsingContextHandle, const String* optionalFrameHandle, const String&amp; function, const Inspector::InspectorArray&amp; arguments, bool expectsImplicitCallbackArgument, Ref&lt;Inspector::AutomationBackendDispatcherHandler::EvaluateJavaScriptFunctionCallback&gt;&amp;&amp;) override;
+    void resolveChildFrameHandle(Inspector::ErrorString&amp;, const String&amp; browsingContextHandle, const String* optionalFrameHandle, const int* optionalOrdinal, const String* optionalName, const String* optionalNodeHandle, Ref&lt;ResolveChildFrameHandleCallback&gt;&amp;&amp;) override;
+    void resolveParentFrameHandle(Inspector::ErrorString&amp;, const String&amp; browsingContextHandle, const String&amp; frameHandle, Ref&lt;ResolveParentFrameHandleCallback&gt;&amp;&amp;) override;
</ins><span class="cx"> 
</span><span class="cx"> private:
</span><del>-    WebKit::WebPageProxy* webPageProxyForHandle(const String&amp;);
-    String handleForWebPageProxy(WebKit::WebPageProxy*);
</del><ins>+    WebPageProxy* webPageProxyForHandle(const String&amp;);
+    String handleForWebPageProxy(const WebPageProxy&amp;);
</ins><span class="cx"> 
</span><ins>+    WebFrameProxy* webFrameProxyForHandle(const String&amp;, WebPageProxy&amp;);
+    String handleForWebFrameID(uint64_t frameID);
+    String handleForWebFrameProxy(const WebFrameProxy&amp;);
+
</ins><span class="cx">     // Implemented in generated WebAutomationSessionMessageReceiver.cpp
</span><span class="cx">     void didReceiveMessage(IPC::Connection&amp;, IPC::MessageDecoder&amp;) override;
</span><span class="cx"> 
</span><span class="cx">     // Called by WebAutomationSession messages
</span><span class="cx">     void didEvaluateJavaScriptFunction(uint64_t callbackID, const String&amp; result, const String&amp; errorType);
</span><ins>+    void didResolveChildFrame(uint64_t callbackID, uint64_t frameID, const String&amp; errorType);
+    void didResolveParentFrame(uint64_t callbackID, uint64_t frameID, const String&amp; errorType);
</ins><span class="cx"> 
</span><del>-    WebKit::WebProcessPool* m_processPool { nullptr };
</del><ins>+    WebProcessPool* m_processPool { nullptr };
+
</ins><span class="cx">     std::unique_ptr&lt;API::AutomationSessionClient&gt; m_client;
</span><span class="cx">     String m_sessionIdentifier { ASCIILiteral(&quot;Untitled Session&quot;) };
</span><span class="cx">     Ref&lt;Inspector::FrontendRouter&gt; m_frontendRouter;
</span><span class="cx">     Ref&lt;Inspector::BackendDispatcher&gt; m_backendDispatcher;
</span><span class="cx">     Ref&lt;Inspector::AutomationBackendDispatcher&gt; m_domainDispatcher;
</span><span class="cx"> 
</span><del>-    WebPageHandleMap m_webPageHandleMap;
-    HandleWebPageMap m_handleWebPageMap;
</del><ins>+    HashMap&lt;uint64_t, String&gt; m_webPageHandleMap;
+    HashMap&lt;String, uint64_t&gt; m_handleWebPageMap;
</ins><span class="cx">     String m_activeBrowsingContextHandle;
</span><span class="cx"> 
</span><ins>+    HashMap&lt;uint64_t, String&gt; m_webFrameHandleMap;
+    HashMap&lt;String, uint64_t&gt; m_handleWebFrameMap;
+
</ins><span class="cx">     uint64_t m_nextEvaluateJavaScriptCallbackID { 1 };
</span><span class="cx">     HashMap&lt;uint64_t, RefPtr&lt;Inspector::AutomationBackendDispatcherHandler::EvaluateJavaScriptFunctionCallback&gt;&gt; m_evaluateJavaScriptFunctionCallbacks;
</span><span class="cx"> 
</span><ins>+    uint64_t m_nextResolveFrameCallbackID { 1 };
+    HashMap&lt;uint64_t, RefPtr&lt;Inspector::AutomationBackendDispatcherHandler::ResolveChildFrameHandleCallback&gt;&gt; m_resolveChildFrameHandleCallbacks;
+
+    uint64_t m_nextResolveParentFrameCallbackID { 1 };
+    HashMap&lt;uint64_t, RefPtr&lt;Inspector::AutomationBackendDispatcherHandler::ResolveParentFrameHandleCallback&gt;&gt; m_resolveParentFrameHandleCallbacks;
+
</ins><span class="cx"> #if ENABLE(REMOTE_INSPECTOR)
</span><span class="cx">     Inspector::FrontendChannel* m_remoteChannel { nullptr };
</span><span class="cx"> #endif
</span></span></pre></div>
<a id="trunkSourceWebKit2UIProcessAutomationWebAutomationSessionmessagesin"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/UIProcess/Automation/WebAutomationSession.messages.in (198737 => 198738)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/UIProcess/Automation/WebAutomationSession.messages.in        2016-03-28 15:57:06 UTC (rev 198737)
+++ trunk/Source/WebKit2/UIProcess/Automation/WebAutomationSession.messages.in        2016-03-28 15:57:23 UTC (rev 198738)
</span><span class="lines">@@ -22,4 +22,7 @@
</span><span class="cx"> 
</span><span class="cx"> messages -&gt; WebAutomationSession {
</span><span class="cx">     DidEvaluateJavaScriptFunction(uint64_t callbackID, String result, String errorType)
</span><ins>+
+    DidResolveChildFrame(uint64_t callbackID, uint64_t frameID, String errorType)
+    DidResolveParentFrame(uint64_t callbackID, uint64_t frameID, String errorType)
</ins><span class="cx"> }
</span></span></pre></div>
<a id="trunkSourceWebKit2WebProcessAutomationWebAutomationSessionProxycpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/WebProcess/Automation/WebAutomationSessionProxy.cpp (198737 => 198738)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/WebProcess/Automation/WebAutomationSessionProxy.cpp        2016-03-28 15:57:06 UTC (rev 198737)
+++ trunk/Source/WebKit2/WebProcess/Automation/WebAutomationSessionProxy.cpp        2016-03-28 15:57:23 UTC (rev 198738)
</span><span class="lines">@@ -33,9 +33,17 @@
</span><span class="cx"> #include &quot;WebFrame.h&quot;
</span><span class="cx"> #include &quot;WebPage.h&quot;
</span><span class="cx"> #include &quot;WebProcess.h&quot;
</span><ins>+#include &lt;JavaScriptCore/APICast.h&gt;
+#include &lt;JavaScriptCore/JSObject.h&gt;
</ins><span class="cx"> #include &lt;JavaScriptCore/JSRetainPtr.h&gt;
</span><span class="cx"> #include &lt;JavaScriptCore/JSStringRefPrivate.h&gt;
</span><span class="cx"> #include &lt;JavaScriptCore/OpaqueJSString.h&gt;
</span><ins>+#include &lt;WebCore/DOMWindow.h&gt;
+#include &lt;WebCore/Frame.h&gt;
+#include &lt;WebCore/FrameTree.h&gt;
+#include &lt;WebCore/HTMLFrameElementBase.h&gt;
+#include &lt;WebCore/JSElement.h&gt;
+#include &lt;WebCore/MainFrame.h&gt;
</ins><span class="cx"> #include &lt;WebCore/UUID.h&gt;
</span><span class="cx"> 
</span><span class="cx"> namespace WebKit {
</span><span class="lines">@@ -161,6 +169,33 @@
</span><span class="cx">     return scriptObject;
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+WebCore::Element* WebAutomationSessionProxy::elementForNodeHandle(WebFrame&amp; frame, const String&amp; nodeHandle)
+{
+    // Don't use scriptObjectForFrame() since we can assume if the script object
+    // does not exist, there are no nodes mapped to handles. Using scriptObjectForFrame()
+    // will make a new script object if it can't find one, preventing us from returning fast.
+    JSObjectRef scriptObject = m_webFrameScriptObjectMap.get(frame.frameID());
+    if (!scriptObject)
+        return nullptr;
+
+    JSGlobalContextRef context = frame.jsContext();
+
+    JSValueRef functionArguments[] = {
+        toJSValue(context, nodeHandle)
+    };
+
+    JSValueRef result = callPropertyFunction(context, scriptObject, ASCIILiteral(&quot;nodeForIdentifier&quot;), WTF_ARRAY_LENGTH(functionArguments), functionArguments, nullptr);
+    JSObjectRef element = JSValueToObject(context, result, nullptr);
+    if (!element)
+        return nullptr;
+
+    auto elementWrapper = JSC::jsDynamicCast&lt;WebCore::JSElement*&gt;(toJS(element));
+    if (!elementWrapper)
+        return nullptr;
+
+    return &amp;elementWrapper-&gt;wrapped();
+}
+
</ins><span class="cx"> void WebAutomationSessionProxy::didClearWindowObjectForFrame(WebFrame&amp; frame)
</span><span class="cx"> {
</span><span class="cx">     uint64_t frameID = frame.frameID();
</span><span class="lines">@@ -239,4 +274,137 @@
</span><span class="cx">     WebProcess::singleton().parentProcessConnection()-&gt;send(Messages::WebAutomationSession::DidEvaluateJavaScriptFunction(callbackID, result, errorType), 0);
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+void WebAutomationSessionProxy::resolveChildFrameWithOrdinal(uint64_t frameID, uint32_t ordinal, uint64_t callbackID)
+{
+    String frameNotFoundErrorType = Inspector::Protocol::getEnumConstantValue(Inspector::Protocol::Automation::ErrorMessage::FrameNotFound);
+
+    WebFrame* frame = WebProcess::singleton().webFrame(frameID);
+    if (!frame) {
+        WebProcess::singleton().parentProcessConnection()-&gt;send(Messages::WebAutomationSession::DidResolveChildFrame(callbackID, 0, frameNotFoundErrorType), 0);
+        return;
+    }
+
+    WebCore::Frame* coreFrame = frame-&gt;coreFrame();
+    if (!coreFrame) {
+        WebProcess::singleton().parentProcessConnection()-&gt;send(Messages::WebAutomationSession::DidResolveChildFrame(callbackID, 0, frameNotFoundErrorType), 0);
+        return;
+    }
+
+    WebCore::Frame* coreChildFrame = coreFrame-&gt;tree().scopedChild(ordinal);
+    if (!coreChildFrame) {
+        WebProcess::singleton().parentProcessConnection()-&gt;send(Messages::WebAutomationSession::DidResolveChildFrame(callbackID, 0, frameNotFoundErrorType), 0);
+        return;
+    }
+
+    WebFrame* childFrame = WebFrame::fromCoreFrame(*coreChildFrame);
+    if (!childFrame) {
+        WebProcess::singleton().parentProcessConnection()-&gt;send(Messages::WebAutomationSession::DidResolveChildFrame(callbackID, 0, frameNotFoundErrorType), 0);
+        return;
+    }
+
+    WebProcess::singleton().parentProcessConnection()-&gt;send(Messages::WebAutomationSession::DidResolveChildFrame(callbackID, childFrame-&gt;frameID(), emptyString()), 0);
+}
+
+void WebAutomationSessionProxy::resolveChildFrameWithNodeHandle(uint64_t frameID, const String&amp; nodeHandle, uint64_t callbackID)
+{
+    String frameNotFoundErrorType = Inspector::Protocol::getEnumConstantValue(Inspector::Protocol::Automation::ErrorMessage::FrameNotFound);
+
+    WebFrame* frame = WebProcess::singleton().webFrame(frameID);
+    if (!frame) {
+        WebProcess::singleton().parentProcessConnection()-&gt;send(Messages::WebAutomationSession::DidResolveChildFrame(callbackID, 0, frameNotFoundErrorType), 0);
+        return;
+    }
+
+    WebCore::Element* coreElement = elementForNodeHandle(*frame, nodeHandle);
+    if (!coreElement || !coreElement-&gt;isFrameElementBase()) {
+        WebProcess::singleton().parentProcessConnection()-&gt;send(Messages::WebAutomationSession::DidResolveChildFrame(callbackID, 0, frameNotFoundErrorType), 0);
+        return;
+    }
+
+    WebCore::Frame* coreFrameFromElement = static_cast&lt;WebCore::HTMLFrameElementBase*&gt;(coreElement)-&gt;contentFrame();
+    if (!coreFrameFromElement) {
+        WebProcess::singleton().parentProcessConnection()-&gt;send(Messages::WebAutomationSession::DidResolveChildFrame(callbackID, 0, frameNotFoundErrorType), 0);
+        return;
+    }
+
+    WebFrame* frameFromElement = WebFrame::fromCoreFrame(*coreFrameFromElement);
+    if (!frameFromElement) {
+        WebProcess::singleton().parentProcessConnection()-&gt;send(Messages::WebAutomationSession::DidResolveChildFrame(callbackID, 0, frameNotFoundErrorType), 0);
+        return;
+    }
+
+    WebProcess::singleton().parentProcessConnection()-&gt;send(Messages::WebAutomationSession::DidResolveChildFrame(callbackID, frameFromElement-&gt;frameID(), emptyString()), 0);
+}
+
+void WebAutomationSessionProxy::resolveChildFrameWithName(uint64_t frameID, const String&amp; name, uint64_t callbackID)
+{
+    String frameNotFoundErrorType = Inspector::Protocol::getEnumConstantValue(Inspector::Protocol::Automation::ErrorMessage::FrameNotFound);
+
+    WebFrame* frame = WebProcess::singleton().webFrame(frameID);
+    if (!frame) {
+        WebProcess::singleton().parentProcessConnection()-&gt;send(Messages::WebAutomationSession::DidResolveChildFrame(callbackID, 0, frameNotFoundErrorType), 0);
+        return;
+    }
+
+    WebCore::Frame* coreFrame = frame-&gt;coreFrame();
+    if (!coreFrame) {
+        WebProcess::singleton().parentProcessConnection()-&gt;send(Messages::WebAutomationSession::DidResolveChildFrame(callbackID, 0, frameNotFoundErrorType), 0);
+        return;
+    }
+
+    WebCore::Frame* coreChildFrame = coreFrame-&gt;tree().scopedChild(name);
+    if (!coreChildFrame) {
+        WebProcess::singleton().parentProcessConnection()-&gt;send(Messages::WebAutomationSession::DidResolveChildFrame(callbackID, 0, frameNotFoundErrorType), 0);
+        return;
+    }
+
+    WebFrame* childFrame = WebFrame::fromCoreFrame(*coreChildFrame);
+    if (!childFrame) {
+        WebProcess::singleton().parentProcessConnection()-&gt;send(Messages::WebAutomationSession::DidResolveChildFrame(callbackID, 0, frameNotFoundErrorType), 0);
+        return;
+    }
+
+    WebProcess::singleton().parentProcessConnection()-&gt;send(Messages::WebAutomationSession::DidResolveChildFrame(callbackID, childFrame-&gt;frameID(), emptyString()), 0);
+}
+
+void WebAutomationSessionProxy::resolveParentFrame(uint64_t frameID, uint64_t callbackID)
+{
+    String frameNotFoundErrorType = Inspector::Protocol::getEnumConstantValue(Inspector::Protocol::Automation::ErrorMessage::FrameNotFound);
+
+    WebFrame* frame = WebProcess::singleton().webFrame(frameID);
+    if (!frame) {
+        WebProcess::singleton().parentProcessConnection()-&gt;send(Messages::WebAutomationSession::DidResolveParentFrame(callbackID, 0, frameNotFoundErrorType), 0);
+        return;
+    }
+
+    WebFrame* parentFrame = frame-&gt;parentFrame();
+    if (!parentFrame) {
+        WebProcess::singleton().parentProcessConnection()-&gt;send(Messages::WebAutomationSession::DidResolveParentFrame(callbackID, 0, frameNotFoundErrorType), 0);
+        return;
+    }
+
+    WebProcess::singleton().parentProcessConnection()-&gt;send(Messages::WebAutomationSession::DidResolveParentFrame(callbackID, parentFrame-&gt;frameID(), emptyString()), 0);
+}
+
+void WebAutomationSessionProxy::focusFrame(uint64_t frameID)
+{
+    WebFrame* frame = WebProcess::singleton().webFrame(frameID);
+    if (!frame)
+        return;
+
+    WebCore::Frame* coreFrame = frame-&gt;coreFrame();
+    if (!coreFrame)
+        return;
+
+    WebCore::Document* coreDocument = coreFrame-&gt;document();
+    if (!coreDocument)
+        return;
+
+    WebCore::DOMWindow* coreDOMWindow = coreDocument-&gt;domWindow();
+    if (!coreDOMWindow)
+        return;
+
+    coreDOMWindow-&gt;focus(true);
+}
+
</ins><span class="cx"> } // namespace WebKit
</span></span></pre></div>
<a id="trunkSourceWebKit2WebProcessAutomationWebAutomationSessionProxyh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/WebProcess/Automation/WebAutomationSessionProxy.h (198737 => 198738)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/WebProcess/Automation/WebAutomationSessionProxy.h        2016-03-28 15:57:06 UTC (rev 198737)
+++ trunk/Source/WebKit2/WebProcess/Automation/WebAutomationSessionProxy.h        2016-03-28 15:57:23 UTC (rev 198738)
</span><span class="lines">@@ -29,6 +29,10 @@
</span><span class="cx"> #include &quot;Connection.h&quot;
</span><span class="cx"> #include &lt;JavaScriptCore/JSBase.h&gt;
</span><span class="cx"> 
</span><ins>+namespace WebCore {
+class Element;
+}
+
</ins><span class="cx"> namespace WebKit {
</span><span class="cx"> 
</span><span class="cx"> class WebFrame;
</span><span class="lines">@@ -47,12 +51,18 @@
</span><span class="cx"> 
</span><span class="cx"> private:
</span><span class="cx">     JSObjectRef scriptObjectForFrame(WebFrame&amp;);
</span><ins>+    WebCore::Element* elementForNodeHandle(WebFrame&amp;, const String&amp;);
</ins><span class="cx"> 
</span><span class="cx">     // Implemented in generated WebAutomationSessionProxyMessageReceiver.cpp
</span><span class="cx">     void didReceiveMessage(IPC::Connection&amp;, IPC::MessageDecoder&amp;);
</span><span class="cx"> 
</span><span class="cx">     // Called by WebAutomationSessionProxy messages
</span><span class="cx">     void evaluateJavaScriptFunction(uint64_t frameID, const String&amp; function, Vector&lt;String&gt; arguments, bool expectsImplicitCallbackArgument, uint64_t callbackID);
</span><ins>+    void resolveChildFrameWithOrdinal(uint64_t frameID, uint32_t ordinal, uint64_t callbackID);
+    void resolveChildFrameWithNodeHandle(uint64_t frameID, const String&amp; nodeHandle, uint64_t callbackID);
+    void resolveChildFrameWithName(uint64_t frameID, const String&amp; name, uint64_t callbackID);
+    void resolveParentFrame(uint64_t frameID, uint64_t callbackID);
+    void focusFrame(uint64_t frameID);
</ins><span class="cx"> 
</span><span class="cx">     String m_sessionIdentifier;
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceWebKit2WebProcessAutomationWebAutomationSessionProxyjs"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/WebProcess/Automation/WebAutomationSessionProxy.js (198737 => 198738)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/WebProcess/Automation/WebAutomationSessionProxy.js        2016-03-28 15:57:06 UTC (rev 198737)
+++ trunk/Source/WebKit2/WebProcess/Automation/WebAutomationSessionProxy.js        2016-03-28 15:57:23 UTC (rev 198738)
</span><span class="lines">@@ -56,6 +56,15 @@
</span><span class="cx">             callback(functionValue.apply(null, argumentValues));
</span><span class="cx">     }
</span><span class="cx"> 
</span><ins>+    nodeForIdentifier(identifier)
+    {
+        try {
+            return this._nodeForIdentifier(identifier);
+        } catch (error) {
+            return null;
+        }
+    }
+
</ins><span class="cx">     // Private
</span><span class="cx"> 
</span><span class="cx">     _jsonParse(string)
</span></span></pre></div>
<a id="trunkSourceWebKit2WebProcessAutomationWebAutomationSessionProxymessagesin"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/WebProcess/Automation/WebAutomationSessionProxy.messages.in (198737 => 198738)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/WebProcess/Automation/WebAutomationSessionProxy.messages.in        2016-03-28 15:57:06 UTC (rev 198737)
+++ trunk/Source/WebKit2/WebProcess/Automation/WebAutomationSessionProxy.messages.in        2016-03-28 15:57:23 UTC (rev 198738)
</span><span class="lines">@@ -21,5 +21,12 @@
</span><span class="cx"> # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
</span><span class="cx"> 
</span><span class="cx"> messages -&gt; WebAutomationSessionProxy {
</span><del>-    EvaluateJavaScriptFunction(uint64_t frame, String function, Vector&lt;String&gt; arguments, bool expectsImplicitCallbackArgument, uint64_t callbackID)
</del><ins>+    EvaluateJavaScriptFunction(uint64_t frameID, String function, Vector&lt;String&gt; arguments, bool expectsImplicitCallbackArgument, uint64_t callbackID)
+
+    ResolveChildFrameWithOrdinal(uint64_t frameID, uint32_t ordinal, uint64_t callbackID)
+    ResolveChildFrameWithNodeHandle(uint64_t frameID, String nodeHandle, uint64_t callbackID)
+    ResolveChildFrameWithName(uint64_t frameID, String name, uint64_t callbackID)
+    ResolveParentFrame(uint64_t frameID, uint64_t callbackID)
+
+    FocusFrame(uint64_t frameID)
</ins><span class="cx"> }
</span></span></pre>
</div>
</div>

</body>
</html>