<!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>[161358] trunk/Source/WebKit2</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/161358">161358</a></dd>
<dt>Author</dt> <dd>enrica@apple.com</dd>
<dt>Date</dt> <dd>2014-01-06 11:44:32 -0800 (Mon, 06 Jan 2014)</dd>
</dl>

<h3>Log Message</h3>
<pre>Add support to retrieve the autocorrection context.
https://bugs.webkit.org/show_bug.cgi?id=126479

Reviewed by Sam Weinig.
        
We are adding the support to retrieve the input context for autocorrection
and input methods on iOS. The implementation is provided both via synchronous
and asynchronous calls to the WebProcess.

* Platform/IPC/HandleMessage.h: Added template with zero input parameters and six reply parameters.
* UIProcess/API/ios/WKInteractionView.mm:
(autocorrectionData):
(-[WKInteractionView requestAutocorrectionRectsForString:withCompletionHandler:]):
(autocorrectionResult):
(-[WKInteractionView applyAutocorrection:toString:withCompletionHandler:]):
(autocorrectionContext):
(-[WKInteractionView requestAutocorrectionContextWithCompletionHandler:]):
(-[WKInteractionView hasMarkedText]):
(-[WKInteractionView _startAssistingNode]):
(+[WKAutocorrectionContext autocorrectionContextWithData:markedText:selectedText:afterText:selectedRangeInMarkedText:]):
(-[WKAutocorrectionContext dealloc]):
* UIProcess/AutoCorrectionCallback.h:
(WebKit::AutocorrectionContextCallback::create):
(WebKit::AutocorrectionContextCallback::~AutocorrectionContextCallback):
(WebKit::AutocorrectionContextCallback::performCallbackWithReturnValue):
(WebKit::AutocorrectionContextCallback::invalidate):
(WebKit::AutocorrectionContextCallback::AutocorrectionContextCallback):
* UIProcess/WebPageProxy.cpp:
(WebKit::WebPageProxy::resetState):
* UIProcess/WebPageProxy.h:
* UIProcess/WebPageProxy.messages.in:
* UIProcess/ios/WebPageProxyIOS.mm:
(WebKit::WebPageProxy::autocorrectionContextCallback):
(WebKit::WebPageProxy::requestAutocorrectionContext):
(WebKit::WebPageProxy::getAutocorrectionContext):
* WebProcess/WebPage/WebPage.h:
* WebProcess/WebPage/WebPage.messages.in:
* WebProcess/WebPage/ios/WebPageIOS.mm:
(WebKit::computeAutocorrectionContext):
(WebKit::WebPage::requestAutocorrectionContext):
(WebKit::WebPage::getAutocorrectionContext):</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkSourceWebKit2ChangeLog">trunk/Source/WebKit2/ChangeLog</a></li>
<li><a href="#trunkSourceWebKit2PlatformIPCHandleMessageh">trunk/Source/WebKit2/Platform/IPC/HandleMessage.h</a></li>
<li><a href="#trunkSourceWebKit2UIProcessAPIiosWKInteractionViewmm">trunk/Source/WebKit2/UIProcess/API/ios/WKInteractionView.mm</a></li>
<li><a href="#trunkSourceWebKit2UIProcessAutoCorrectionCallbackh">trunk/Source/WebKit2/UIProcess/AutoCorrectionCallback.h</a></li>
<li><a href="#trunkSourceWebKit2UIProcessWebPageProxycpp">trunk/Source/WebKit2/UIProcess/WebPageProxy.cpp</a></li>
<li><a href="#trunkSourceWebKit2UIProcessWebPageProxyh">trunk/Source/WebKit2/UIProcess/WebPageProxy.h</a></li>
<li><a href="#trunkSourceWebKit2UIProcessWebPageProxymessagesin">trunk/Source/WebKit2/UIProcess/WebPageProxy.messages.in</a></li>
<li><a href="#trunkSourceWebKit2UIProcessiosWebPageProxyIOSmm">trunk/Source/WebKit2/UIProcess/ios/WebPageProxyIOS.mm</a></li>
<li><a href="#trunkSourceWebKit2WebProcessWebPageWebPageh">trunk/Source/WebKit2/WebProcess/WebPage/WebPage.h</a></li>
<li><a href="#trunkSourceWebKit2WebProcessWebPageWebPagemessagesin">trunk/Source/WebKit2/WebProcess/WebPage/WebPage.messages.in</a></li>
<li><a href="#trunkSourceWebKit2WebProcessWebPageiosWebPageIOSmm">trunk/Source/WebKit2/WebProcess/WebPage/ios/WebPageIOS.mm</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkSourceWebKit2ChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/ChangeLog (161357 => 161358)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/ChangeLog        2014-01-06 19:29:11 UTC (rev 161357)
+++ trunk/Source/WebKit2/ChangeLog        2014-01-06 19:44:32 UTC (rev 161358)
</span><span class="lines">@@ -1,3 +1,47 @@
</span><ins>+2014-01-06  Enrica Casucci  &lt;enrica@apple.com&gt;
+
+        Add support to retrieve the autocorrection context.
+        https://bugs.webkit.org/show_bug.cgi?id=126479
+
+        Reviewed by Sam Weinig.
+        
+        We are adding the support to retrieve the input context for autocorrection
+        and input methods on iOS. The implementation is provided both via synchronous
+        and asynchronous calls to the WebProcess.
+
+        * Platform/IPC/HandleMessage.h: Added template with zero input parameters and six reply parameters.
+        * UIProcess/API/ios/WKInteractionView.mm:
+        (autocorrectionData):
+        (-[WKInteractionView requestAutocorrectionRectsForString:withCompletionHandler:]):
+        (autocorrectionResult):
+        (-[WKInteractionView applyAutocorrection:toString:withCompletionHandler:]):
+        (autocorrectionContext):
+        (-[WKInteractionView requestAutocorrectionContextWithCompletionHandler:]):
+        (-[WKInteractionView hasMarkedText]):
+        (-[WKInteractionView _startAssistingNode]):
+        (+[WKAutocorrectionContext autocorrectionContextWithData:markedText:selectedText:afterText:selectedRangeInMarkedText:]):
+        (-[WKAutocorrectionContext dealloc]):
+        * UIProcess/AutoCorrectionCallback.h:
+        (WebKit::AutocorrectionContextCallback::create):
+        (WebKit::AutocorrectionContextCallback::~AutocorrectionContextCallback):
+        (WebKit::AutocorrectionContextCallback::performCallbackWithReturnValue):
+        (WebKit::AutocorrectionContextCallback::invalidate):
+        (WebKit::AutocorrectionContextCallback::AutocorrectionContextCallback):
+        * UIProcess/WebPageProxy.cpp:
+        (WebKit::WebPageProxy::resetState):
+        * UIProcess/WebPageProxy.h:
+        * UIProcess/WebPageProxy.messages.in:
+        * UIProcess/ios/WebPageProxyIOS.mm:
+        (WebKit::WebPageProxy::autocorrectionContextCallback):
+        (WebKit::WebPageProxy::requestAutocorrectionContext):
+        (WebKit::WebPageProxy::getAutocorrectionContext):
+        * WebProcess/WebPage/WebPage.h:
+        * WebProcess/WebPage/WebPage.messages.in:
+        * WebProcess/WebPage/ios/WebPageIOS.mm:
+        (WebKit::computeAutocorrectionContext):
+        (WebKit::WebPage::requestAutocorrectionContext):
+        (WebKit::WebPage::getAutocorrectionContext):
+
</ins><span class="cx"> 2014-01-06  Gavin Barraclough  &lt;barraclough@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         Move ViewState to WebCore
</span></span></pre></div>
<a id="trunkSourceWebKit2PlatformIPCHandleMessageh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/Platform/IPC/HandleMessage.h (161357 => 161358)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/Platform/IPC/HandleMessage.h        2014-01-06 19:29:11 UTC (rev 161357)
+++ trunk/Source/WebKit2/Platform/IPC/HandleMessage.h        2014-01-06 19:44:32 UTC (rev 161358)
</span><span class="lines">@@ -88,6 +88,12 @@
</span><span class="cx">     (object-&gt;*function)(std::get&lt;0&gt;(replyArgs), std::get&lt;1&gt;(replyArgs));
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+template&lt;typename C, typename MF, typename R1, typename R2, typename R3, typename R4, typename R5, typename R6&gt;
+void callMemberFunction(std::tuple&lt;&gt;&amp;&amp;, std::tuple&lt;R1, R2, R3, R4, R5, R6&gt;&amp; replyArgs, C* object, MF function)
+{
+    (object-&gt;*function)(std::get&lt;0&gt;(replyArgs), std::get&lt;1&gt;(replyArgs), std::get&lt;2&gt;(replyArgs), std::get&lt;3&gt;(replyArgs), std::get&lt;4&gt;(replyArgs), std::get&lt;5&gt;(replyArgs));
+}
+
</ins><span class="cx"> template&lt;typename C, typename MF, typename P1&gt;
</span><span class="cx"> void callMemberFunction(std::tuple&lt;P1&gt;&amp;&amp; args, std::tuple&lt;&gt;&amp;, C* object, MF function)
</span><span class="cx"> {
</span></span></pre></div>
<a id="trunkSourceWebKit2UIProcessAPIiosWKInteractionViewmm"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/UIProcess/API/ios/WKInteractionView.mm (161357 => 161358)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/UIProcess/API/ios/WKInteractionView.mm        2014-01-06 19:29:11 UTC (rev 161357)
+++ trunk/Source/WebKit2/UIProcess/API/ios/WKInteractionView.mm        2014-01-06 19:44:32 UTC (rev 161358)
</span><span class="lines">@@ -100,6 +100,17 @@
</span><span class="cx"> 
</span><span class="cx"> @end
</span><span class="cx"> 
</span><ins>+@interface WKAutocorrectionContext : UIWKAutocorrectionContext {
+    NSString *_contextBeforeSelection;
+    NSString *_selectedText;
+    NSString *_markedText;
+    NSString *_contextAfterSelection;
+    NSRange _rangeInMarkedText;
+}
+
++ (WKAutocorrectionContext *)autocorrectionContextWithData:(NSString *)beforeText markedText:(NSString *)markedText selectedText:(NSString *)selectedText afterText:(NSString *)afterText selectedRangeInMarkedText:(NSRange)range;
+@end
+
</ins><span class="cx"> @interface UITextInteractionAssistant (UITextInteractionAssistant_Internal)
</span><span class="cx"> // FIXME: this needs to be moved from the internal header to the private.
</span><span class="cx"> - (id)initWithView:(UIResponder &lt;UITextInput&gt; *)view;
</span><span class="lines">@@ -107,6 +118,7 @@
</span><span class="cx"> @end
</span><span class="cx"> 
</span><span class="cx"> typedef void (^UIWKAutocorrectionCompletionHandler)(UIWKAutocorrectionRects *rectsForInput);
</span><ins>+typedef void (^UIWKAutocorrectionContextHandler)(UIWKAutocorrectionContext *autocorrectionContext);
</ins><span class="cx"> 
</span><span class="cx"> struct WKAutoCorrectionData{
</span><span class="cx">     String fontName;
</span><span class="lines">@@ -114,7 +126,8 @@
</span><span class="cx">     uint64_t fontTraits;
</span><span class="cx">     CGRect textFirstRect;
</span><span class="cx">     CGRect textLastRect;
</span><del>-    UIWKAutocorrectionCompletionHandler completionHandler;
</del><ins>+    UIWKAutocorrectionCompletionHandler autocorrectionHandler;
+    UIWKAutocorrectionContextHandler autocorrectionContextHandler;
</ins><span class="cx"> };
</span><span class="cx"> 
</span><span class="cx"> @interface WKInteractionView (Private)
</span><span class="lines">@@ -808,9 +821,9 @@
</span><span class="cx">     autocorrectionData-&gt;textFirstRect = firstRect;
</span><span class="cx">     autocorrectionData-&gt;textLastRect = lastRect;
</span><span class="cx"> 
</span><del>-    autocorrectionData-&gt;completionHandler(rects.size() ? [WKAutocorrectionRects autocorrectionRectsWithRects:firstRect lastRect:lastRect] : nil);
-    [autocorrectionData-&gt;completionHandler release];
-    autocorrectionData-&gt;completionHandler = nil;
</del><ins>+    autocorrectionData-&gt;autocorrectionHandler(rects.size() ? [WKAutocorrectionRects autocorrectionRectsWithRects:firstRect lastRect:lastRect] : nil);
+    [autocorrectionData-&gt;autocorrectionHandler release];
+    autocorrectionData-&gt;autocorrectionHandler = nil;
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> // The completion handler can pass nil if input does not match the actual text preceding the insertion point.
</span><span class="lines">@@ -820,7 +833,7 @@
</span><span class="cx">         completionHandler(nil);
</span><span class="cx">         return;
</span><span class="cx">     }
</span><del>-    _autocorrectionData.completionHandler = [completionHandler copy];
</del><ins>+    _autocorrectionData.autocorrectionHandler = [completionHandler copy];
</ins><span class="cx">     _page-&gt;requestAutocorrectionData(input, AutocorrectionDataCallback::create(self, autocorrectionData));
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="lines">@@ -840,22 +853,44 @@
</span><span class="cx">     ASSERT(view);
</span><span class="cx">     WKAutoCorrectionData *autocorrectionData = view.autocorrectionData;
</span><span class="cx"> 
</span><del>-    autocorrectionData-&gt;completionHandler(correction ? [WKAutocorrectionRects autocorrectionRectsWithRects:autocorrectionData-&gt;textFirstRect lastRect:autocorrectionData-&gt;textLastRect] : nil);
-    [autocorrectionData-&gt;completionHandler release];
-    autocorrectionData-&gt;completionHandler = nil;
</del><ins>+    autocorrectionData-&gt;autocorrectionHandler(correction ? [WKAutocorrectionRects autocorrectionRectsWithRects:autocorrectionData-&gt;textFirstRect lastRect:autocorrectionData-&gt;textLastRect] : nil);
+    [autocorrectionData-&gt;autocorrectionHandler release];
+    autocorrectionData-&gt;autocorrectionHandler = nil;
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> // The completion handler should pass the rect of the correction text after replacing the input text, or nil if the replacement could not be performed.
</span><span class="cx"> - (void)applyAutocorrection:(NSString *)correction toString:(NSString *)input withCompletionHandler:(void (^)(UIWKAutocorrectionRects *rectsForCorrection))completionHandler
</span><span class="cx"> {
</span><del>-    _autocorrectionData.completionHandler = [completionHandler copy];
</del><ins>+    _autocorrectionData.autocorrectionHandler = [completionHandler copy];
</ins><span class="cx">     _page-&gt;applyAutocorrection(correction, input, StringCallback::create(self, autocorrectionResult));
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+static void autocorrectionContext(const String&amp; beforeText, const String&amp; markedText, const String&amp; selectedText, const String&amp; afterText, uint64_t location, uint64_t length, WKErrorRef error, void* context)
+{
+    WKInteractionView* view = static_cast&lt;WKInteractionView*&gt;(context);
+    ASSERT(view);
+    WKAutoCorrectionData *autocorrectionData = view.autocorrectionData;
+    autocorrectionData-&gt;autocorrectionContextHandler([WKAutocorrectionContext autocorrectionContextWithData:beforeText markedText:markedText selectedText:selectedText afterText:afterText selectedRangeInMarkedText:NSMakeRange(location, length)]);
+}
+
</ins><span class="cx"> - (void)requestAutocorrectionContextWithCompletionHandler:(void (^)(UIWKAutocorrectionContext *autocorrectionContext))completionHandler
</span><span class="cx"> {
</span><del>-    // FIXME: Need to retrieve the information from the WebProcess.
-    completionHandler(nil);
</del><ins>+    // FIXME: Remove the synchronous call as soon as Keyboard removes locking of the main thread.
+    const bool useSyncRequest = true;
+
+    if (useSyncRequest) {
+        String beforeText;
+        String markedText;
+        String selectedText;
+        String afterText;
+        uint64_t location;
+        uint64_t length;
+        _page-&gt;getAutocorrectionContext(beforeText, markedText, selectedText, afterText, location, length);
+        completionHandler([WKAutocorrectionContext autocorrectionContextWithData:beforeText markedText:markedText selectedText:selectedText afterText:afterText selectedRangeInMarkedText:NSMakeRange(location, length)]);
+    } else {
+        _autocorrectionData.autocorrectionContextHandler = [completionHandler copy];
+        _page-&gt;requestAutocorrectionContext(AutocorrectionContextCallback::create(self, autocorrectionContext));
+    }
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> // UIWebFormAccessoryDelegate
</span><span class="lines">@@ -944,7 +979,7 @@
</span><span class="cx"> 
</span><span class="cx"> - (BOOL)hasMarkedText
</span><span class="cx"> {
</span><del>-    return _page-&gt;editorState().hasComposition || [_markedText length];
</del><ins>+    return [_markedText length];
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> - (NSString *)markedText
</span><span class="lines">@@ -1386,7 +1421,6 @@
</span><span class="cx"> 
</span><span class="cx">     [self _startAssistingKeyboard];
</span><span class="cx">     [self _updateAccessory];
</span><del>-    [self reloadInputViews];
</del><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> - (void)_stopAssistingNode
</span><span class="lines">@@ -1601,3 +1635,33 @@
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> @end
</span><ins>+
+@implementation WKAutocorrectionContext
+
++ (WKAutocorrectionContext *)autocorrectionContextWithData:(NSString *)beforeText markedText:(NSString *)markedText selectedText:(NSString *)selectedText afterText:(NSString *)afterText selectedRangeInMarkedText:(NSRange)range
+{
+    WKAutocorrectionContext *context = [[WKAutocorrectionContext alloc] init];
+
+    if ([beforeText length])
+        context.contextBeforeSelection = [beforeText copy];
+    if ([selectedText length])
+        context.selectedText = [selectedText copy];
+    if ([markedText length])
+        context.markedText = [markedText copy];
+    if ([afterText length])
+        context.contextAfterSelection = [afterText copy];
+    context.rangeInMarkedText = range;
+    return [context autorelease];
+}
+
+- (void)dealloc
+{
+    [self.contextBeforeSelection release];
+    [self.markedText release];
+    [self.selectedText release];
+    [self.contextAfterSelection release];
+
+    [super dealloc];
+}
+
+@end
</ins></span></pre></div>
<a id="trunkSourceWebKit2UIProcessAutoCorrectionCallbackh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/UIProcess/AutoCorrectionCallback.h (161357 => 161358)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/UIProcess/AutoCorrectionCallback.h        2014-01-06 19:29:11 UTC (rev 161357)
+++ trunk/Source/WebKit2/UIProcess/AutoCorrectionCallback.h        2014-01-06 19:44:32 UTC (rev 161358)
</span><span class="lines">@@ -69,7 +69,6 @@
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx"> private:
</span><del>-
</del><span class="cx">     AutocorrectionDataCallback(void* context, CallbackFunction callback)
</span><span class="cx">         : CallbackBase(context)
</span><span class="cx">         , m_callback(callback)
</span><span class="lines">@@ -80,6 +79,50 @@
</span><span class="cx">     CallbackFunction m_callback;
</span><span class="cx"> };
</span><span class="cx"> 
</span><ins>+class AutocorrectionContextCallback : public CallbackBase {
+public:
+    typedef void (*CallbackFunction)(const String&amp;, const String&amp;, const String&amp;, const String&amp;, uint64_t, uint64_t, WKErrorRef, void*);
+
+    static PassRefPtr&lt;AutocorrectionContextCallback&gt; create(void* context, CallbackFunction callback)
+    {
+        return adoptRef(new AutocorrectionContextCallback(context, callback));
+    }
+
+    virtual ~AutocorrectionContextCallback()
+    {
+        ASSERT(!m_callback);
+    }
+
+    void performCallbackWithReturnValue(const String&amp; returnValue1, const String&amp; returnValue2, const String&amp; returnValue3, const String&amp; returnValue4, uint64_t returnValue5, uint64_t returnValue6)
+    {
+        ASSERT(m_callback);
+
+        m_callback(returnValue1, returnValue2, returnValue3, returnValue4, returnValue5, returnValue6, 0, context());
+
+        m_callback = 0;
+    }
+
+    void invalidate()
+    {
+        ASSERT(m_callback);
+
+        RefPtr&lt;API::Error&gt; error = API::Error::create();
+        m_callback(String(), String(), String(), String(), 0, 0, toAPI(error.get()), context());
+
+        m_callback = 0;
+    }
+
+private:
+    AutocorrectionContextCallback(void* context, CallbackFunction callback)
+        : CallbackBase(context)
+        , m_callback(callback)
+    {
+        ASSERT(m_callback);
+    }
+    
+    CallbackFunction m_callback;
+};
+
</ins><span class="cx"> } // namespace WebKit
</span><span class="cx"> 
</span><span class="cx"> #endif // AutoCorrectionCallback_h
</span></span></pre></div>
<a id="trunkSourceWebKit2UIProcessWebPageProxycpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/UIProcess/WebPageProxy.cpp (161357 => 161358)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/UIProcess/WebPageProxy.cpp        2014-01-06 19:29:11 UTC (rev 161357)
+++ trunk/Source/WebKit2/UIProcess/WebPageProxy.cpp        2014-01-06 19:44:32 UTC (rev 161358)
</span><span class="lines">@@ -3801,6 +3801,7 @@
</span><span class="cx">     invalidateCallbackMap(m_gestureCallbacks);
</span><span class="cx">     invalidateCallbackMap(m_touchesCallbacks);
</span><span class="cx">     invalidateCallbackMap(m_autocorrectionCallbacks);
</span><ins>+    invalidateCallbackMap(m_autocorrectionContextCallbacks);
</ins><span class="cx"> #endif
</span><span class="cx"> #if PLATFORM(GTK)
</span><span class="cx">     invalidateCallbackMap(m_printFinishedCallbacks);
</span></span></pre></div>
<a id="trunkSourceWebKit2UIProcessWebPageProxyh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/UIProcess/WebPageProxy.h (161357 => 161358)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/UIProcess/WebPageProxy.h        2014-01-06 19:29:11 UTC (rev 161357)
+++ trunk/Source/WebKit2/UIProcess/WebPageProxy.h        2014-01-06 19:44:32 UTC (rev 161358)
</span><span class="lines">@@ -437,6 +437,8 @@
</span><span class="cx">     void extendSelection(WebCore::TextGranularity);
</span><span class="cx">     void requestAutocorrectionData(const String&amp; textForAutocorrection, PassRefPtr&lt;AutocorrectionDataCallback&gt;);
</span><span class="cx">     void applyAutocorrection(const String&amp; correction, const String&amp; originalText, PassRefPtr&lt;StringCallback&gt;);
</span><ins>+    void requestAutocorrectionContext(PassRefPtr&lt;AutocorrectionContextCallback&gt;);
+    void getAutocorrectionContext(String&amp; contextBefore, String&amp; markedText, String&amp; selectedText, String&amp; contextAfter, uint64_t&amp; location, uint64_t&amp; length);
</ins><span class="cx"> #endif
</span><span class="cx"> 
</span><span class="cx">     const EditorState&amp; editorState() const { return m_editorState; }
</span><span class="lines">@@ -1082,6 +1084,7 @@
</span><span class="cx">     void gestureCallback(const WebCore::IntPoint&amp;, uint32_t, uint32_t, uint32_t, uint64_t);
</span><span class="cx">     void touchesCallback(const WebCore::IntPoint&amp;, uint32_t, uint64_t);
</span><span class="cx">     void autocorrectionDataCallback(const Vector&lt;WebCore::FloatRect&gt;&amp;, const String&amp;, float, uint64_t, uint64_t);
</span><ins>+    void autocorrectionContextCallback(const String&amp;, const String&amp;, const String&amp;, const String&amp;, uint64_t, uint64_t, uint64_t);
</ins><span class="cx">     void interpretKeyEvent(const EditorState&amp;, bool isCharEvent, bool&amp; handled);
</span><span class="cx"> #endif
</span><span class="cx"> #if PLATFORM(GTK)
</span><span class="lines">@@ -1201,6 +1204,7 @@
</span><span class="cx">     HashMap&lt;uint64_t, RefPtr&lt;GestureCallback&gt;&gt; m_gestureCallbacks;
</span><span class="cx">     HashMap&lt;uint64_t, RefPtr&lt;TouchesCallback&gt;&gt; m_touchesCallbacks;
</span><span class="cx">     HashMap&lt;uint64_t, RefPtr&lt;AutocorrectionDataCallback&gt;&gt; m_autocorrectionCallbacks;
</span><ins>+    HashMap&lt;uint64_t, RefPtr&lt;AutocorrectionContextCallback&gt;&gt; m_autocorrectionContextCallbacks;
</ins><span class="cx"> #endif
</span><span class="cx"> #if PLATFORM(GTK)
</span><span class="cx">     HashMap&lt;uint64_t, RefPtr&lt;PrintFinishedCallback&gt;&gt; m_printFinishedCallbacks;
</span></span></pre></div>
<a id="trunkSourceWebKit2UIProcessWebPageProxymessagesin"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/UIProcess/WebPageProxy.messages.in (161357 => 161358)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/UIProcess/WebPageProxy.messages.in        2014-01-06 19:29:11 UTC (rev 161357)
+++ trunk/Source/WebKit2/UIProcess/WebPageProxy.messages.in        2014-01-06 19:44:32 UTC (rev 161358)
</span><span class="lines">@@ -150,7 +150,8 @@
</span><span class="cx"> #if PLATFORM(IOS)
</span><span class="cx">     GestureCallback(WebCore::IntPoint point, uint32_t gestureType, uint32_t gestureState, uint32_t flags, uint64_t callbackID)
</span><span class="cx">     TouchesCallback(WebCore::IntPoint point, uint32_t touches, uint64_t callbackID)
</span><del>-    AutocorrectionDataCallback(Vector&lt;WebCore::FloatRect&gt; textRects, String fontName, double fontSize, uint64_t traits, uint64_t callbackID);
</del><ins>+    AutocorrectionDataCallback(Vector&lt;WebCore::FloatRect&gt; textRects, String fontName, double fontSize, uint64_t traits, uint64_t callbackID)
+    AutocorrectionContextCallback(String beforeText, String markedText, String selectedText, String afterText, uint64_t location, uint64_t length, uint64_t callbackID)
</ins><span class="cx">     InterpretKeyEvent(WebKit::EditorState state, bool isCharEvent) -&gt; (bool handled)
</span><span class="cx"> #endif
</span><span class="cx"> #if PLATFORM(GTK)
</span></span></pre></div>
<a id="trunkSourceWebKit2UIProcessiosWebPageProxyIOSmm"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/UIProcess/ios/WebPageProxyIOS.mm (161357 => 161358)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/UIProcess/ios/WebPageProxyIOS.mm        2014-01-06 19:29:11 UTC (rev 161357)
+++ trunk/Source/WebKit2/UIProcess/ios/WebPageProxyIOS.mm        2014-01-06 19:44:32 UTC (rev 161358)
</span><span class="lines">@@ -209,6 +209,17 @@
</span><span class="cx">     callback-&gt;performCallbackWithReturnValue(rects, fontName, fontSize, fontTraits);
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+void WebPageProxy::autocorrectionContextCallback(const String&amp; beforeText, const String&amp; markedText, const String&amp; selectedText, const String&amp; afterText, uint64_t location, uint64_t length, uint64_t callbackID)
+{
+    RefPtr&lt;AutocorrectionContextCallback&gt; callback = m_autocorrectionContextCallbacks.take(callbackID);
+    if (!callback) {
+        ASSERT_NOT_REACHED();
+        return;
+    }
+
+    callback-&gt;performCallbackWithReturnValue(beforeText, markedText, selectedText, afterText, location, length);
+}
+
</ins><span class="cx"> void WebPageProxy::selectWithGesture(const WebCore::IntPoint point, WebCore::TextGranularity granularity, uint32_t gestureType, uint32_t gestureState, PassRefPtr&lt;GestureCallback&gt; callback)
</span><span class="cx"> {
</span><span class="cx">     if (!isValid()) {
</span><span class="lines">@@ -257,6 +268,23 @@
</span><span class="cx">     m_process-&gt;send(Messages::WebPage::ApplyAutocorrection(correction, originalText, callbackID), m_pageID);
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+void WebPageProxy::requestAutocorrectionContext(PassRefPtr&lt;AutocorrectionContextCallback&gt; callback)
+{
+    if (!isValid()) {
+        callback-&gt;invalidate();
+        return;
+    }
+
+    uint64_t callbackID = callback-&gt;callbackID();
+    m_autocorrectionContextCallbacks.set(callbackID, callback);
+    m_process-&gt;send(Messages::WebPage::RequestAutocorrectionContext(callbackID), m_pageID);
+}
+
+void WebPageProxy::getAutocorrectionContext(String&amp; beforeContext, String&amp; markedText, String&amp; selectedText, String&amp; afterContext, uint64_t&amp; location, uint64_t&amp; length)
+{
+    m_process-&gt;sendSync(Messages::WebPage::GetAutocorrectionContext(), Messages::WebPage::GetAutocorrectionContext::Reply(beforeContext, markedText, selectedText, afterContext, location, length), m_pageID);
+}
+
</ins><span class="cx"> void WebPageProxy::selectWithTwoTouches(const WebCore::IntPoint from, const WebCore::IntPoint to, uint32_t gestureType, uint32_t gestureState, PassRefPtr&lt;GestureCallback&gt; callback)
</span><span class="cx"> {
</span><span class="cx">     if (!isValid()) {
</span></span></pre></div>
<a id="trunkSourceWebKit2WebProcessWebPageWebPageh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/WebProcess/WebPage/WebPage.h (161357 => 161358)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/WebProcess/WebPage/WebPage.h        2014-01-06 19:29:11 UTC (rev 161357)
+++ trunk/Source/WebKit2/WebProcess/WebPage/WebPage.h        2014-01-06 19:44:32 UTC (rev 161358)
</span><span class="lines">@@ -411,6 +411,8 @@
</span><span class="cx">     void elementDidBlur(WebCore::Node*);
</span><span class="cx">     void requestAutocorrectionData(const String&amp; textForAutocorrection, uint64_t callbackID);
</span><span class="cx">     void applyAutocorrection(const String&amp; correction, const String&amp; originalText, uint64_t callbackID);
</span><ins>+    void requestAutocorrectionContext(uint64_t callbackID);
+    void getAutocorrectionContext(String&amp; beforeText, String&amp; markedText, String&amp; selectedText, String&amp; afterText, uint64_t&amp; location, uint64_t&amp; length);
</ins><span class="cx">     void insertText(const String&amp; text, uint64_t replacementRangeStart, uint64_t replacementRangeEnd);
</span><span class="cx">     void setComposition(const String&amp; text, Vector&lt;WebCore::CompositionUnderline&gt; underlines, uint64_t selectionStart, uint64_t selectionEnd);
</span><span class="cx">     void confirmComposition();
</span></span></pre></div>
<a id="trunkSourceWebKit2WebProcessWebPageWebPagemessagesin"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/WebProcess/WebPage/WebPage.messages.in (161357 => 161358)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/WebProcess/WebPage/WebPage.messages.in        2014-01-06 19:29:11 UTC (rev 161357)
+++ trunk/Source/WebKit2/WebProcess/WebPage/WebPage.messages.in        2014-01-06 19:44:32 UTC (rev 161358)
</span><span class="lines">@@ -48,6 +48,8 @@
</span><span class="cx">     ExtendSelection(uint32_t granularity)
</span><span class="cx">     RequestAutocorrectionData(String textForAutocorrection, uint64_t callbackID)
</span><span class="cx">     ApplyAutocorrection(String correction, String originalText, uint64_t callbackID)
</span><ins>+    RequestAutocorrectionContext(uint64_t callbackID)
+    GetAutocorrectionContext() -&gt; (String beforeContext, String markedText, String selectedText, String afterContext, uint64_t location, uint64_t length) 
</ins><span class="cx">     InsertText(String text, uint64_t replacementRangeStart, uint64_t replacementRangeEnd)
</span><span class="cx">     SetComposition(String text, Vector&lt;WebCore::CompositionUnderline&gt; underlines, uint64_t selectionStart, uint64_t selectionEnd)
</span><span class="cx">     ConfirmComposition()
</span></span></pre></div>
<a id="trunkSourceWebKit2WebProcessWebPageiosWebPageIOSmm"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/WebProcess/WebPage/ios/WebPageIOS.mm (161357 => 161358)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/WebProcess/WebPage/ios/WebPageIOS.mm        2014-01-06 19:29:11 UTC (rev 161357)
+++ trunk/Source/WebKit2/WebProcess/WebPage/ios/WebPageIOS.mm        2014-01-06 19:44:32 UTC (rev 161358)
</span><span class="lines">@@ -722,6 +722,87 @@
</span><span class="cx">     send(Messages::WebPageProxy::StringCallback(correction, callbackID));
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+static void computeAutocorrectionContext(Frame&amp; frame, String&amp; contextBefore, String&amp; markedText, String&amp; selectedText, String&amp; contextAfter, uint64_t&amp; location, uint64_t&amp; length)
+{
+    RefPtr&lt;Range&gt; range;
+    VisiblePosition startPosition = frame.selection().selection().start();
+    VisiblePosition endPosition = frame.selection().selection().end();
+    location = NSNotFound;
+    length = 0;
+    const unsigned minContextWordCount = 3;
+    const unsigned minContextLenght = 12;
+    const unsigned maxContextLength = 30;
+
+    if (frame.selection().isRange())
+        selectedText = plainText(frame.selection().selection().toNormalizedRange().get());
+
+    if (frame.editor().hasComposition()) {
+        range = Range::create(*frame.document(), frame.editor().compositionRange()-&gt;startPosition(), startPosition);
+        String markedTextBefore;
+        if (range)
+            markedTextBefore = plainText(range.get());
+        range = Range::create(*frame.document(), endPosition, frame.editor().compositionRange()-&gt;endPosition());
+        String markedTextAfter;
+        if (range)
+            markedTextAfter = plainText(range.get());
+        markedText = markedTextBefore + selectedText + markedTextAfter;
+        if (!markedText.isEmpty()) {
+            location = markedTextBefore.length();
+            length = selectedText.length();
+        }
+    } else {
+        if (startPosition != startOfEditableContent(startPosition)) {
+            VisiblePosition currentPosition = startPosition;
+            VisiblePosition previousPosition;
+            unsigned totalContextLength = 0;
+            for (unsigned i = 0; i &lt; minContextWordCount; ++i) {
+                if (contextBefore.length() &gt;= minContextLenght)
+                    break;
+                previousPosition = startOfWord(positionOfNextBoundaryOfGranularity(currentPosition, WordGranularity, DirectionBackward));
+                if (previousPosition.isNull())
+                    break;
+                String currentWord = plainText(Range::create(*frame.document(), previousPosition, currentPosition).get());
+                totalContextLength += currentWord.length();
+                if (totalContextLength &gt;= maxContextLength)
+                    break;
+                currentPosition = previousPosition;
+            }
+            if (currentPosition.isNotNull() &amp;&amp; currentPosition != startPosition) {
+                contextBefore = plainText(Range::create(*frame.document(), currentPosition, startPosition).get());
+                if (atBoundaryOfGranularity(currentPosition, ParagraphGranularity, DirectionBackward))
+                    contextBefore = ASCIILiteral(&quot;\n &quot;) + contextBefore;
+            }
+        }
+
+        if (endPosition != endOfEditableContent(endPosition)) {
+            VisiblePosition nextPosition;
+            if (!atBoundaryOfGranularity(endPosition, WordGranularity, DirectionForward) &amp;&amp; withinTextUnitOfGranularity(endPosition, WordGranularity, DirectionForward))
+                nextPosition = positionOfNextBoundaryOfGranularity(endPosition, WordGranularity, DirectionForward);
+            if (nextPosition.isNotNull())
+                contextAfter = plainText(Range::create(*frame.document(), endPosition, nextPosition).get());
+        }
+    }
+}
+
+void WebPage::requestAutocorrectionContext(uint64_t callbackID)
+{
+    String contextBefore;
+    String contextAfter;
+    String selectedText;
+    String markedText;
+    uint64_t location;
+    uint64_t length;
+
+    computeAutocorrectionContext(m_page-&gt;focusController().focusedOrMainFrame(), contextBefore, markedText, selectedText, contextAfter, location, length);
+
+    send(Messages::WebPageProxy::AutocorrectionContextCallback(contextBefore, markedText, selectedText, contextAfter, location, length, callbackID));
+}
+
+void WebPage::getAutocorrectionContext(String&amp; contextBefore, String&amp; markedText, String&amp; selectedText, String&amp; contextAfter, uint64_t&amp; location, uint64_t&amp; length)
+{
+    computeAutocorrectionContext(m_page-&gt;focusController().focusedOrMainFrame(), contextBefore, markedText, selectedText, contextAfter, location, length);
+}
+
</ins><span class="cx"> void WebPage::elementDidFocus(WebCore::Node* node)
</span><span class="cx"> {
</span><span class="cx">     m_assistedNode = node;
</span></span></pre>
</div>
</div>

</body>
</html>