<!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>[174524] 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/174524">174524</a></dd>
<dt>Author</dt> <dd>timothy_horton@apple.com</dd>
<dt>Date</dt> <dd>2014-10-09 13:53:02 -0700 (Thu, 09 Oct 2014)</dd>
</dl>

<h3>Log Message</h3>
<pre>Move ServicesOverlayController to WebCore
https://bugs.webkit.org/show_bug.cgi?id=137416
&lt;rdar://problem/18546283&gt;

Reviewed by Anders Carlsson.

Move ServicesOverlayController from WebKit2 to WebCore, as it can be used by both Legacy WebKit and WebKit2.

* Platform/Logging.h:
Move Services logging channel to WebCore.

* WebKit2.xcodeproj/project.pbxproj:
* WebProcess/WebCoreSupport/WebChromeClient.cpp:
(WebKit::WebChromeClient::handleTelephoneNumberClick):
(WebKit::WebChromeClient::handleSelectionServiceClick):
(WebKit::WebChromeClient::hasRelevantSelectionServices):
Implement services-related ChromeClient callbacks.
Clicks are forwarded to WebPageMac where they do what they used to;
hasRelevantSelectionServices is implemented as it was when it lived
inside ServicesOverlayController.

* WebProcess/WebCoreSupport/WebChromeClient.h:
* WebProcess/WebCoreSupport/WebEditorClient.cpp:
(WebKit::WebEditorClient::selectedTelephoneNumberRangesChanged): Deleted.
(WebKit::WebEditorClient::selectionRectsDidChange): Deleted.
* WebProcess/WebCoreSupport/WebEditorClient.h:
Remove WebEditorClient overrides for now-removed functions.

* WebProcess/WebPage/WebPage.cpp:
(WebKit::WebPage::WebPage):
(WebKit::WebPage::updatePreferences):
Forward serviceControlsEnabled setting to WebCore.

(WebKit::WebPage::servicesOverlayController): Deleted.
* WebProcess/WebPage/WebPage.h:
(WebKit::WebPage::serviceControlsEnabled): Deleted.

* WebCore.xcodeproj/project.pbxproj:
* editing/Editor.cpp:
(WebCore::Editor::scanSelectionForTelephoneNumbers):
* editing/SelectionRectGatherer.cpp:
(WebCore::SelectionRectGatherer::Notifier::~Notifier):
Notify ServicesOverlayController of changes via Page instead of EditorClient.

* page/ChromeClient.h:
(WebCore::ChromeClient::handleTelephoneNumberClick):
(WebCore::ChromeClient::handleSelectionServiceClick):
(WebCore::ChromeClient::hasRelevantSelectionServices):
Add ChromeClient functions for services actions.

* page/EditorClient.h:
(WebCore::EditorClient::selectedTelephoneNumberRangesChanged): Deleted.
(WebCore::EditorClient::selectionRectsDidChange): Deleted.
Remove EditorClient functions for notifying ServicesOverlayController of changes,
because it lives in WebCore proper now.

* page/Page.cpp:
(WebCore::Page::Page):
* page/Page.h:
(WebCore::Page::servicesOverlayController):
Keep a ServicesOverlayController on Page.

* page/PageOverlay.cpp:
(WebCore::PageOverlay::mouseEvent):
Use windowToContents instead of rootViewToContents; events come in in window coordinates.

* page/PageOverlayController.cpp:
(WebCore::PageOverlayController::updateSettingsForLayer):
Get Settings from MainFrame, not Page.

* page/Settings.in:
Add servicesControlsEnabled setting.

* page/mac/ServicesOverlayController.h: Renamed from Source/WebKit2/WebProcess/WebPage/ServicesOverlayController.h.
* page/mac/ServicesOverlayController.mm: Renamed from Source/WebKit2/WebProcess/WebPage/mac/ServicesOverlayController.mm.
Moved from WebKit2. Mostly mechanical changes, plus:
    - Use windowToContents instead of rootViewToContents; events come in in window coordinates.
    - Cut off rebuild* if serviceControlsEnabled setting is false
    - Don't create the overlay if serviceControlsEnabled setting is false
    - Send click events via ChromeClient.
    - Tie our lifetime to MainFrame instead of Page, and get lots of things from MainFrame instead.

* platform/Logging.h:
Add Services logging channel (moved from WebKit2).</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkSourceWebCoreChangeLog">trunk/Source/WebCore/ChangeLog</a></li>
<li><a href="#trunkSourceWebCoreWebCorexcodeprojprojectpbxproj">trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj</a></li>
<li><a href="#trunkSourceWebCoreeditingEditorcpp">trunk/Source/WebCore/editing/Editor.cpp</a></li>
<li><a href="#trunkSourceWebCoreeditingSelectionRectGatherercpp">trunk/Source/WebCore/editing/SelectionRectGatherer.cpp</a></li>
<li><a href="#trunkSourceWebCorepageChromeClienth">trunk/Source/WebCore/page/ChromeClient.h</a></li>
<li><a href="#trunkSourceWebCorepageEditorClienth">trunk/Source/WebCore/page/EditorClient.h</a></li>
<li><a href="#trunkSourceWebCorepageMainFramecpp">trunk/Source/WebCore/page/MainFrame.cpp</a></li>
<li><a href="#trunkSourceWebCorepageMainFrameh">trunk/Source/WebCore/page/MainFrame.h</a></li>
<li><a href="#trunkSourceWebCorepagePageOverlaycpp">trunk/Source/WebCore/page/PageOverlay.cpp</a></li>
<li><a href="#trunkSourceWebCorepagePageOverlayControllercpp">trunk/Source/WebCore/page/PageOverlayController.cpp</a></li>
<li><a href="#trunkSourceWebCorepageSettingsin">trunk/Source/WebCore/page/Settings.in</a></li>
<li><a href="#trunkSourceWebCoreplatformLoggingh">trunk/Source/WebCore/platform/Logging.h</a></li>
<li><a href="#trunkSourceWebKit2ChangeLog">trunk/Source/WebKit2/ChangeLog</a></li>
<li><a href="#trunkSourceWebKit2PlatformLoggingh">trunk/Source/WebKit2/Platform/Logging.h</a></li>
<li><a href="#trunkSourceWebKit2WebKit2xcodeprojprojectpbxproj">trunk/Source/WebKit2/WebKit2.xcodeproj/project.pbxproj</a></li>
<li><a href="#trunkSourceWebKit2WebProcessWebCoreSupportWebChromeClientcpp">trunk/Source/WebKit2/WebProcess/WebCoreSupport/WebChromeClient.cpp</a></li>
<li><a href="#trunkSourceWebKit2WebProcessWebCoreSupportWebChromeClienth">trunk/Source/WebKit2/WebProcess/WebCoreSupport/WebChromeClient.h</a></li>
<li><a href="#trunkSourceWebKit2WebProcessWebCoreSupportWebEditorClientcpp">trunk/Source/WebKit2/WebProcess/WebCoreSupport/WebEditorClient.cpp</a></li>
<li><a href="#trunkSourceWebKit2WebProcessWebCoreSupportWebEditorClienth">trunk/Source/WebKit2/WebProcess/WebCoreSupport/WebEditorClient.h</a></li>
<li><a href="#trunkSourceWebKit2WebProcessWebPageWebPagecpp">trunk/Source/WebKit2/WebProcess/WebPage/WebPage.cpp</a></li>
<li><a href="#trunkSourceWebKit2WebProcessWebPageWebPageh">trunk/Source/WebKit2/WebProcess/WebPage/WebPage.h</a></li>
</ul>

<h3>Added Paths</h3>
<ul>
<li><a href="#trunkSourceWebCorepagemacServicesOverlayControllerh">trunk/Source/WebCore/page/mac/ServicesOverlayController.h</a></li>
<li><a href="#trunkSourceWebCorepagemacServicesOverlayControllermm">trunk/Source/WebCore/page/mac/ServicesOverlayController.mm</a></li>
</ul>

<h3>Removed Paths</h3>
<ul>
<li><a href="#trunkSourceWebKit2WebProcessWebPageServicesOverlayControllerh">trunk/Source/WebKit2/WebProcess/WebPage/ServicesOverlayController.h</a></li>
<li><a href="#trunkSourceWebKit2WebProcessWebPagemacServicesOverlayControllermm">trunk/Source/WebKit2/WebProcess/WebPage/mac/ServicesOverlayController.mm</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkSourceWebCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/ChangeLog (174523 => 174524)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/ChangeLog        2014-10-09 20:51:55 UTC (rev 174523)
+++ trunk/Source/WebCore/ChangeLog        2014-10-09 20:53:02 UTC (rev 174524)
</span><span class="lines">@@ -1,3 +1,61 @@
</span><ins>+2014-10-09  Tim Horton  &lt;timothy_horton@apple.com&gt;
+
+        Move ServicesOverlayController to WebCore
+        https://bugs.webkit.org/show_bug.cgi?id=137416
+        &lt;rdar://problem/18546283&gt;
+
+        Reviewed by Anders Carlsson.
+
+        Move ServicesOverlayController from WebKit2 to WebCore, as it can be used by both Legacy WebKit and WebKit2.
+
+        * WebCore.xcodeproj/project.pbxproj:
+        * editing/Editor.cpp:
+        (WebCore::Editor::scanSelectionForTelephoneNumbers):
+        * editing/SelectionRectGatherer.cpp:
+        (WebCore::SelectionRectGatherer::Notifier::~Notifier):
+        Notify ServicesOverlayController of changes via Page instead of EditorClient.
+
+        * page/ChromeClient.h:
+        (WebCore::ChromeClient::handleTelephoneNumberClick):
+        (WebCore::ChromeClient::handleSelectionServiceClick):
+        (WebCore::ChromeClient::hasRelevantSelectionServices):
+        Add ChromeClient functions for services actions.
+
+        * page/EditorClient.h:
+        (WebCore::EditorClient::selectedTelephoneNumberRangesChanged): Deleted.
+        (WebCore::EditorClient::selectionRectsDidChange): Deleted.
+        Remove EditorClient functions for notifying ServicesOverlayController of changes,
+        because it lives in WebCore proper now.
+
+        * page/Page.cpp:
+        (WebCore::Page::Page):
+        * page/Page.h:
+        (WebCore::Page::servicesOverlayController):
+        Keep a ServicesOverlayController on Page.
+
+        * page/PageOverlay.cpp:
+        (WebCore::PageOverlay::mouseEvent):
+        Use windowToContents instead of rootViewToContents; events come in in window coordinates.
+
+        * page/PageOverlayController.cpp:
+        (WebCore::PageOverlayController::updateSettingsForLayer):
+        Get Settings from MainFrame, not Page.
+
+        * page/Settings.in:
+        Add servicesControlsEnabled setting.
+
+        * page/mac/ServicesOverlayController.h: Renamed from Source/WebKit2/WebProcess/WebPage/ServicesOverlayController.h.
+        * page/mac/ServicesOverlayController.mm: Renamed from Source/WebKit2/WebProcess/WebPage/mac/ServicesOverlayController.mm.
+        Moved from WebKit2. Mostly mechanical changes, plus:
+            - Use windowToContents instead of rootViewToContents; events come in in window coordinates.
+            - Cut off rebuild* if serviceControlsEnabled setting is false
+            - Don't create the overlay if serviceControlsEnabled setting is false
+            - Send click events via ChromeClient.
+            - Tie our lifetime to MainFrame instead of Page, and get lots of things from MainFrame instead.
+
+        * platform/Logging.h:
+        Add Services logging channel (moved from WebKit2).
+
</ins><span class="cx"> 2014-10-09  Brent Fulgham  &lt;bfulgham@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         [Win] Unreviewed build fix: Revert r174378
</span></span></pre></div>
<a id="trunkSourceWebCoreWebCorexcodeprojprojectpbxproj"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj (174523 => 174524)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj        2014-10-09 20:51:55 UTC (rev 174523)
+++ trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj        2014-10-09 20:53:02 UTC (rev 174524)
</span><span class="lines">@@ -1106,6 +1106,8 @@
</span><span class="cx">                 2D8FEBDD143E3EF70072502B /* CSSCrossfadeValue.h in Headers */ = {isa = PBXBuildFile; fileRef = 2D8FEBDB143E3EF70072502B /* CSSCrossfadeValue.h */; };
</span><span class="cx">                 2D9066060BE141D400956998 /* LayoutState.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2D9066040BE141D400956998 /* LayoutState.cpp */; };
</span><span class="cx">                 2D9066070BE141D400956998 /* LayoutState.h in Headers */ = {isa = PBXBuildFile; fileRef = 2D9066050BE141D400956998 /* LayoutState.h */; settings = {ATTRIBUTES = (Private, ); }; };
</span><ins>+                2D93AEE319DF5641002A86C3 /* ServicesOverlayController.h in Headers */ = {isa = PBXBuildFile; fileRef = 2D93AEE119DF5641002A86C3 /* ServicesOverlayController.h */; };
+                2D93AEE419DF5641002A86C3 /* ServicesOverlayController.mm in Sources */ = {isa = PBXBuildFile; fileRef = 2D93AEE219DF5641002A86C3 /* ServicesOverlayController.mm */; };
</ins><span class="cx">                 2D97F04719DD413C001EE9C3 /* MockPageOverlayClient.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2DAAE32C19DCAF6000E002D2 /* MockPageOverlayClient.cpp */; };
</span><span class="cx">                 2D97F04819DD4140001EE9C3 /* MockPageOverlayClient.h in Headers */ = {isa = PBXBuildFile; fileRef = 2DAAE32D19DCAF6000E002D2 /* MockPageOverlayClient.h */; };
</span><span class="cx">                 2D9A246E15B9BD0000D34527 /* DOMSecurityPolicy.h in Headers */ = {isa = PBXBuildFile; fileRef = 2D9A246B15B9BBDD00D34527 /* DOMSecurityPolicy.h */; };
</span><span class="lines">@@ -8106,6 +8108,8 @@
</span><span class="cx">                 2D9066040BE141D400956998 /* LayoutState.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = LayoutState.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 2D9066050BE141D400956998 /* LayoutState.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = LayoutState.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 2D90660C0665D937006B6F1A /* DataTransferMac.mm */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = DataTransferMac.mm; sourceTree = &quot;&lt;group&gt;&quot;; tabWidth = 8; usesTabs = 0; };
</span><ins>+                2D93AEE119DF5641002A86C3 /* ServicesOverlayController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ServicesOverlayController.h; sourceTree = &quot;&lt;group&gt;&quot;; };
+                2D93AEE219DF5641002A86C3 /* ServicesOverlayController.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = ServicesOverlayController.mm; sourceTree = &quot;&lt;group&gt;&quot;; };
</ins><span class="cx">                 2D9A246A15B9BBDD00D34527 /* DOMSecurityPolicy.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = DOMSecurityPolicy.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 2D9A246B15B9BBDD00D34527 /* DOMSecurityPolicy.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DOMSecurityPolicy.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 2D9A247015B9C29500D34527 /* DOMDOMSecurityPolicy.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DOMDOMSecurityPolicy.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="lines">@@ -17553,6 +17557,8 @@
</span><span class="cx">                                 A718788F0B2D04AC00A16ECE /* DragControllerMac.mm */,
</span><span class="cx">                                 93C09A7E0B064EEF005ABD4D /* EventHandlerMac.mm */,
</span><span class="cx">                                 1C26497B0D7E24EC00BD10F2 /* PageMac.cpp */,
</span><ins>+                                2D93AEE119DF5641002A86C3 /* ServicesOverlayController.h */,
+                                2D93AEE219DF5641002A86C3 /* ServicesOverlayController.mm */,
</ins><span class="cx">                                 E1C2F2481533A2120083F974 /* SettingsMac.mm */,
</span><span class="cx">                                 26255F0218878E110006E1FD /* UserAgentMac.mm */,
</span><span class="cx">                                 F587854C02DE375901EA4122 /* WebCoreFrameView.h */,
</span><span class="lines">@@ -23494,6 +23500,7 @@
</span><span class="cx">                                 FD315FFF12B0267600C1A359 /* ChannelMergerNode.h in Headers */,
</span><span class="cx">                                 FD31600212B0267600C1A359 /* ChannelSplitterNode.h in Headers */,
</span><span class="cx">                                 6550B6A0099DF0270090D781 /* CharacterData.h in Headers */,
</span><ins>+                                2D93AEE319DF5641002A86C3 /* ServicesOverlayController.h in Headers */,
</ins><span class="cx">                                 97B8FFD116AE7F960038388D /* CharacterReferenceParserInlines.h in Headers */,
</span><span class="cx">                                 B2C3DA2A0D006C1D00EF6F26 /* CharsetData.h in Headers */,
</span><span class="cx">                                 F55B3DB21251F12D003EF269 /* CheckboxInputType.h in Headers */,
</span><span class="lines">@@ -28400,6 +28407,7 @@
</span><span class="cx">                                 E1A5F99B0E7EAA2500AF85EA /* JSMessageChannelCustom.cpp in Sources */,
</span><span class="cx">                                 75793EC80D0CE72D007FC0AC /* JSMessageEvent.cpp in Sources */,
</span><span class="cx">                                 410B7E721045FAB000D8224F /* JSMessageEventCustom.cpp in Sources */,
</span><ins>+                                2D93AEE419DF5641002A86C3 /* ServicesOverlayController.mm in Sources */,
</ins><span class="cx">                                 E1ADEDDB0E76BD93004A1A5E /* JSMessagePort.cpp in Sources */,
</span><span class="cx">                                 E1ADED470E76B8DD004A1A5E /* JSMessagePortCustom.cpp in Sources */,
</span><span class="cx">                                 A86629D209DA2B48009633A5 /* JSMouseEvent.cpp in Sources */,
</span></span></pre></div>
<a id="trunkSourceWebCoreeditingEditorcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/editing/Editor.cpp (174523 => 174524)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/editing/Editor.cpp        2014-10-09 20:51:55 UTC (rev 174523)
+++ trunk/Source/WebCore/editing/Editor.cpp        2014-10-09 20:53:02 UTC (rev 174524)
</span><span class="lines">@@ -61,6 +61,7 @@
</span><span class="cx"> #include &quot;InsertListCommand.h&quot;
</span><span class="cx"> #include &quot;KeyboardEvent.h&quot;
</span><span class="cx"> #include &quot;KillRing.h&quot;
</span><ins>+#include &quot;MainFrame.h&quot;
</ins><span class="cx"> #include &quot;ModifySelectionListLevel.h&quot;
</span><span class="cx"> #include &quot;NodeList.h&quot;
</span><span class="cx"> #include &quot;NodeTraversal.h&quot;
</span><span class="lines">@@ -102,6 +103,10 @@
</span><span class="cx"> #include &lt;wtf/text/WTFString.h&gt;
</span><span class="cx"> #endif
</span><span class="cx"> 
</span><ins>+#if PLATFORM(MAC)
+#include &quot;ServicesOverlayController.h&quot;
+#endif
+
</ins><span class="cx"> namespace WebCore {
</span><span class="cx"> 
</span><span class="cx"> class ClearTextCommand : public DeleteSelectionCommand {
</span><span class="lines">@@ -3348,7 +3353,7 @@
</span><span class="cx"> 
</span><span class="cx">     FrameSelection&amp; frameSelection = m_frame.selection();
</span><span class="cx">     if (!frameSelection.isRange()) {
</span><del>-        client()-&gt;selectedTelephoneNumberRangesChanged();
</del><ins>+        m_frame.mainFrame().servicesOverlayController().selectedTelephoneNumberRangesChanged();
</ins><span class="cx">         return;
</span><span class="cx">     }
</span><span class="cx">     RefPtr&lt;Range&gt; selectedRange = frameSelection.toNormalizedRange();
</span><span class="lines">@@ -3376,7 +3381,7 @@
</span><span class="cx">     RefPtr&lt;Range&gt; extendedRange = extendedSelection.toNormalizedRange();
</span><span class="cx"> 
</span><span class="cx">     if (!extendedRange) {
</span><del>-        client()-&gt;selectedTelephoneNumberRangesChanged();
</del><ins>+        m_frame.mainFrame().servicesOverlayController().selectedTelephoneNumberRangesChanged();
</ins><span class="cx">         return;
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="lines">@@ -3388,7 +3393,7 @@
</span><span class="cx">             m_detectedTelephoneNumberRanges.append(range);
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    client()-&gt;selectedTelephoneNumberRangesChanged();
</del><ins>+    m_frame.mainFrame().servicesOverlayController().selectedTelephoneNumberRangesChanged();
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void Editor::scanRangeForTelephoneNumbers(Range&amp; range, const StringView&amp; stringView, Vector&lt;RefPtr&lt;Range&gt;&gt;&amp; markedRanges)
</span></span></pre></div>
<a id="trunkSourceWebCoreeditingSelectionRectGatherercpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/editing/SelectionRectGatherer.cpp (174523 => 174524)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/editing/SelectionRectGatherer.cpp        2014-10-09 20:51:55 UTC (rev 174523)
+++ trunk/Source/WebCore/editing/SelectionRectGatherer.cpp        2014-10-09 20:53:02 UTC (rev 174524)
</span><span class="lines">@@ -26,13 +26,15 @@
</span><span class="cx"> #include &quot;config.h&quot;
</span><span class="cx"> #include &quot;SelectionRectGatherer.h&quot;
</span><span class="cx"> 
</span><ins>+#if ENABLE(SERVICE_CONTROLS)
+
</ins><span class="cx"> #include &quot;Editor.h&quot;
</span><span class="cx"> #include &quot;EditorClient.h&quot;
</span><span class="cx"> #include &quot;Frame.h&quot;
</span><ins>+#include &quot;MainFrame.h&quot;
</ins><span class="cx"> #include &quot;RenderView.h&quot;
</span><ins>+#include &quot;ServicesOverlayController.h&quot;
</ins><span class="cx"> 
</span><del>-#if ENABLE(SERVICE_CONTROLS)
-
</del><span class="cx"> namespace WebCore {
</span><span class="cx"> 
</span><span class="cx"> SelectionRectGatherer::SelectionRectGatherer(RenderView&amp; renderView)
</span><span class="lines">@@ -70,8 +72,7 @@
</span><span class="cx"> 
</span><span class="cx"> SelectionRectGatherer::Notifier::~Notifier()
</span><span class="cx"> {
</span><del>-    if (EditorClient* client = m_gatherer.m_renderView.view().frame().editor().client())
-        client-&gt;selectionRectsDidChange(m_gatherer.m_rects, m_gatherer.m_gapRects, m_gatherer.isTextOnly());
</del><ins>+    m_gatherer.m_renderView.view().frame().mainFrame().servicesOverlayController().selectionRectsDidChange(m_gatherer.m_rects, m_gatherer.m_gapRects, m_gatherer.isTextOnly());
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> std::unique_ptr&lt;SelectionRectGatherer::Notifier&gt; SelectionRectGatherer::clearAndCreateNotifier()
</span></span></pre></div>
<a id="trunkSourceWebCorepageChromeClienth"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/page/ChromeClient.h (174523 => 174524)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/page/ChromeClient.h        2014-10-09 20:51:55 UTC (rev 174523)
+++ trunk/Source/WebCore/page/ChromeClient.h        2014-10-09 20:53:02 UTC (rev 174524)
</span><span class="lines">@@ -438,6 +438,14 @@
</span><span class="cx">     virtual bool unwrapCryptoKey(const Vector&lt;uint8_t&gt;&amp;, Vector&lt;uint8_t&gt;&amp;) const { return false; }
</span><span class="cx"> #endif
</span><span class="cx"> 
</span><ins>+#if ENABLE(TELEPHONE_NUMBER_DETECTION) &amp;&amp; PLATFORM(MAC)
+    virtual void handleTelephoneNumberClick(const String&amp;, const WebCore::IntPoint&amp;) { }
+#endif
+#if ENABLE(SERVICE_CONTROLS)
+    virtual void handleSelectionServiceClick(WebCore::FrameSelection&amp;, const Vector&lt;String&gt;&amp;, const WebCore::IntPoint&amp;) { }
+    virtual bool hasRelevantSelectionServices(bool /* isTextOnly */) const { return false; }
+#endif
+
</ins><span class="cx"> protected:
</span><span class="cx">     virtual ~ChromeClient() { }
</span><span class="cx"> };
</span></span></pre></div>
<a id="trunkSourceWebCorepageEditorClienth"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/page/EditorClient.h (174523 => 174524)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/page/EditorClient.h        2014-10-09 20:51:55 UTC (rev 174523)
+++ trunk/Source/WebCore/page/EditorClient.h        2014-10-09 20:53:02 UTC (rev 174524)
</span><span class="lines">@@ -181,11 +181,6 @@
</span><span class="cx">     virtual void willSetInputMethodState() = 0;
</span><span class="cx">     virtual void setInputMethodState(bool enabled) = 0;
</span><span class="cx"> 
</span><del>-#if ENABLE(SERVICE_CONTROLS) || ENABLE(TELEPHONE_NUMBER_DETECTION)
-    virtual void selectedTelephoneNumberRangesChanged() { }
-    virtual void selectionRectsDidChange(const Vector&lt;LayoutRect&gt;&amp;, const Vector&lt;GapRects&gt;&amp;, bool) { }
-#endif
-
</del><span class="cx">     // Support for global selections, used on platforms like the X Window System that treat
</span><span class="cx">     // selection as a type of clipboard.
</span><span class="cx">     virtual bool supportsGlobalSelection() { return false; }
</span></span></pre></div>
<a id="trunkSourceWebCorepageMainFramecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/page/MainFrame.cpp (174523 => 174524)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/page/MainFrame.cpp        2014-10-09 20:51:55 UTC (rev 174523)
+++ trunk/Source/WebCore/page/MainFrame.cpp        2014-10-09 20:53:02 UTC (rev 174524)
</span><span class="lines">@@ -30,6 +30,10 @@
</span><span class="cx"> #include &quot;ScrollLatchingState.h&quot;
</span><span class="cx"> #include &quot;WheelEventDeltaTracker.h&quot;
</span><span class="cx"> 
</span><ins>+#if PLATFORM(MAC)
+#include &quot;ServicesOverlayController.h&quot;
+#endif
+
</ins><span class="cx"> namespace WebCore {
</span><span class="cx"> 
</span><span class="cx"> inline MainFrame::MainFrame(Page&amp; page, FrameLoaderClient&amp; client)
</span><span class="lines">@@ -37,7 +41,10 @@
</span><span class="cx">     , m_selfOnlyRefCount(0)
</span><span class="cx"> #if PLATFORM(MAC)
</span><span class="cx">     , m_latchingState(std::make_unique&lt;ScrollLatchingState&gt;())
</span><ins>+#if ENABLE(SERVICE_CONTROLS) || ENABLE(TELEPHONE_NUMBER_DETECTION)
+    , m_servicesOverlayController(std::make_unique&lt;ServicesOverlayController&gt;(*this))
</ins><span class="cx"> #endif
</span><ins>+#endif
</ins><span class="cx">     , m_recentWheelEventDeltaTracker(std::make_unique&lt;WheelEventDeltaTracker&gt;())
</span><span class="cx">     , m_pageOverlayController(std::make_unique&lt;PageOverlayController&gt;(*this))
</span><span class="cx"> {
</span></span></pre></div>
<a id="trunkSourceWebCorepageMainFrameh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/page/MainFrame.h (174523 => 174524)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/page/MainFrame.h        2014-10-09 20:51:55 UTC (rev 174523)
+++ trunk/Source/WebCore/page/MainFrame.h        2014-10-09 20:53:02 UTC (rev 174524)
</span><span class="lines">@@ -32,6 +32,7 @@
</span><span class="cx"> 
</span><span class="cx"> class PageOverlayController;
</span><span class="cx"> class ScrollLatchingState;
</span><ins>+class ServicesOverlayController;
</ins><span class="cx"> class WheelEventDeltaTracker;
</span><span class="cx"> 
</span><span class="cx"> class MainFrame final : public Frame {
</span><span class="lines">@@ -47,9 +48,13 @@
</span><span class="cx">     PageOverlayController&amp; pageOverlayController() { return *m_pageOverlayController; }
</span><span class="cx"> 
</span><span class="cx"> #if PLATFORM(MAC)
</span><ins>+#if ENABLE(SERVICE_CONTROLS) || ENABLE(TELEPHONE_NUMBER_DETECTION)
+    ServicesOverlayController&amp; servicesOverlayController() { return *m_servicesOverlayController; }
+#endif // ENABLE(SERVICE_CONTROLS) || ENABLE(TELEPHONE_NUMBER_DETECTION)
+
</ins><span class="cx">     ScrollLatchingState* latchingState() { return m_latchingState.get(); }
</span><span class="cx">     void resetLatchingState();
</span><del>-#endif
</del><ins>+#endif // PLATFORM(MAC)
</ins><span class="cx"> 
</span><span class="cx"> private:
</span><span class="cx">     MainFrame(Page&amp;, FrameLoaderClient&amp;);
</span><span class="lines">@@ -60,7 +65,10 @@
</span><span class="cx"> 
</span><span class="cx"> #if PLATFORM(MAC)
</span><span class="cx">     std::unique_ptr&lt;ScrollLatchingState&gt; m_latchingState;
</span><ins>+#if ENABLE(SERVICE_CONTROLS) || ENABLE(TELEPHONE_NUMBER_DETECTION)
+    std::unique_ptr&lt;ServicesOverlayController&gt; m_servicesOverlayController;
</ins><span class="cx"> #endif
</span><ins>+#endif
</ins><span class="cx">     std::unique_ptr&lt;WheelEventDeltaTracker&gt; m_recentWheelEventDeltaTracker;
</span><span class="cx">     std::unique_ptr&lt;PageOverlayController&gt; m_pageOverlayController;
</span><span class="cx"> };
</span></span></pre></div>
<a id="trunkSourceWebCorepagePageOverlaycpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/page/PageOverlay.cpp (174523 => 174524)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/page/PageOverlay.cpp        2014-10-09 20:51:55 UTC (rev 174523)
+++ trunk/Source/WebCore/page/PageOverlay.cpp        2014-10-09 20:53:02 UTC (rev 174524)
</span><span class="lines">@@ -168,7 +168,7 @@
</span><span class="cx">     IntPoint mousePositionInOverlayCoordinates(mouseEvent.position());
</span><span class="cx"> 
</span><span class="cx">     if (m_overlayType == PageOverlay::OverlayType::Document)
</span><del>-        mousePositionInOverlayCoordinates = m_page-&gt;mainFrame().view()-&gt;rootViewToContents(mousePositionInOverlayCoordinates);
</del><ins>+        mousePositionInOverlayCoordinates = m_page-&gt;mainFrame().view()-&gt;windowToContents(mousePositionInOverlayCoordinates);
</ins><span class="cx"> 
</span><span class="cx">     // Ignore events outside the bounds.
</span><span class="cx">     if (!bounds().contains(mousePositionInOverlayCoordinates))
</span></span></pre></div>
<a id="trunkSourceWebCorepagePageOverlayControllercpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/page/PageOverlayController.cpp (174523 => 174524)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/page/PageOverlayController.cpp        2014-10-09 20:51:55 UTC (rev 174523)
+++ trunk/Source/WebCore/page/PageOverlayController.cpp        2014-10-09 20:53:02 UTC (rev 174524)
</span><span class="lines">@@ -260,7 +260,7 @@
</span><span class="cx"> 
</span><span class="cx"> void PageOverlayController::updateSettingsForLayer(GraphicsLayer&amp; layer)
</span><span class="cx"> {
</span><del>-    Settings&amp; settings = m_mainFrame.page()-&gt;settings();
</del><ins>+    Settings&amp; settings = m_mainFrame.settings();
</ins><span class="cx">     layer.setAcceleratesDrawing(settings.acceleratedDrawingEnabled());
</span><span class="cx">     layer.setShowDebugBorder(settings.showDebugBorders());
</span><span class="cx">     layer.setShowRepaintCounter(settings.showRepaintCounter());
</span></span></pre></div>
<a id="trunkSourceWebCorepageSettingsin"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/page/Settings.in (174523 => 174524)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/page/Settings.in        2014-10-09 20:51:55 UTC (rev 174523)
+++ trunk/Source/WebCore/page/Settings.in        2014-10-09 20:53:02 UTC (rev 174524)
</span><span class="lines">@@ -231,3 +231,5 @@
</span><span class="cx"> maximumSourceBufferSize type=int, initial=318767104, conditional=MEDIA_SOURCE
</span><span class="cx"> 
</span><span class="cx"> longMousePressEnabled initial=false
</span><ins>+
+serviceControlsEnabled initial=false, conditional=SERVICE_CONTROLS
</ins></span></pre></div>
<a id="trunkSourceWebCorepagemacServicesOverlayControllerh"></a>
<div class="addfile"><h4>Added: trunk/Source/WebCore/page/mac/ServicesOverlayController.h (0 => 174524)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/page/mac/ServicesOverlayController.h                                (rev 0)
+++ trunk/Source/WebCore/page/mac/ServicesOverlayController.h        2014-10-09 20:53:02 UTC (rev 174524)
</span><span class="lines">@@ -0,0 +1,165 @@
</span><ins>+/*
+ * Copyright (C) 2014 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef ServicesOverlayController_h
+#define ServicesOverlayController_h
+
+#if (ENABLE(SERVICE_CONTROLS) || ENABLE(TELEPHONE_NUMBER_DETECTION)) &amp;&amp; PLATFORM(MAC)
+
+#include &quot;GraphicsLayerClient.h&quot;
+#include &quot;PageOverlay.h&quot;
+#include &quot;Range.h&quot;
+#include &quot;Timer.h&quot;
+#include &lt;wtf/RefCounted.h&gt;
+
+typedef struct __DDHighlight DDHighlight, *DDHighlightRef;
+
+namespace WebCore {
+class LayoutRect;
+class MainFrame;
+struct GapRects;
+}
+
+namespace WebCore {
+
+class ServicesOverlayController : private PageOverlay::Client {
+public:
+    explicit ServicesOverlayController(MainFrame&amp;);
+    ~ServicesOverlayController();
+
+    void selectedTelephoneNumberRangesChanged();
+    void selectionRectsDidChange(const Vector&lt;LayoutRect&gt;&amp;, const Vector&lt;GapRects&gt;&amp;, bool isTextOnly);
+
+private:
+    class Highlight : public RefCounted&lt;Highlight&gt;, private GraphicsLayerClient {
+        WTF_MAKE_NONCOPYABLE(Highlight);
+    public:
+        static PassRefPtr&lt;Highlight&gt; createForSelection(ServicesOverlayController&amp;, RetainPtr&lt;DDHighlightRef&gt;, PassRefPtr&lt;Range&gt;);
+        static PassRefPtr&lt;Highlight&gt; createForTelephoneNumber(ServicesOverlayController&amp;, RetainPtr&lt;DDHighlightRef&gt;, PassRefPtr&lt;Range&gt;);
+        ~Highlight();
+
+        void invalidate();
+
+        DDHighlightRef ddHighlight() const { return m_ddHighlight.get(); }
+        Range* range() const { return m_range.get(); }
+        GraphicsLayer* layer() const { return m_graphicsLayer.get(); }
+
+        enum class Type {
+            TelephoneNumber,
+            Selection
+        };
+        Type type() const { return m_type; }
+
+        void fadeIn();
+        void fadeOut();
+
+        void setDDHighlight(DDHighlightRef);
+
+    private:
+        explicit Highlight(ServicesOverlayController&amp;, Type, RetainPtr&lt;DDHighlightRef&gt;, PassRefPtr&lt;Range&gt;);
+
+        // GraphicsLayerClient
+        virtual void notifyFlushRequired(const GraphicsLayer*) override;
+        virtual void paintContents(const GraphicsLayer*, GraphicsContext&amp;, GraphicsLayerPaintingPhase, const FloatRect&amp; inClip) override;
+        virtual float deviceScaleFactor() const override;
+
+        void didFinishFadeOutAnimation();
+
+        RetainPtr&lt;DDHighlightRef&gt; m_ddHighlight;
+        RefPtr&lt;Range&gt; m_range;
+        std::unique_ptr&lt;GraphicsLayer&gt; m_graphicsLayer;
+        Type m_type;
+        ServicesOverlayController* m_controller;
+    };
+
+    // PageOverlay::Client
+    virtual void pageOverlayDestroyed(PageOverlay&amp;) override;
+    virtual void willMoveToPage(PageOverlay&amp;, Page*) override;
+    virtual void didMoveToPage(PageOverlay&amp;, Page*) override;
+    virtual void drawRect(PageOverlay&amp;, GraphicsContext&amp;, const IntRect&amp; dirtyRect) override;
+    virtual bool mouseEvent(PageOverlay&amp;, const PlatformMouseEvent&amp;) override;
+    virtual void didScrollFrame(PageOverlay&amp;, Frame&amp;) override;
+
+    void createOverlayIfNeeded();
+    void handleClick(const IntPoint&amp;, Highlight&amp;);
+
+    void drawHighlight(Highlight&amp;, GraphicsContext&amp;);
+
+    void replaceHighlightsOfTypePreservingEquivalentHighlights(HashSet&lt;RefPtr&lt;Highlight&gt;&gt;&amp;, Highlight::Type);
+    void removeAllPotentialHighlightsOfType(Highlight::Type);
+    void buildPhoneNumberHighlights();
+    void buildSelectionHighlight();
+    void didRebuildPotentialHighlights();
+
+    void determineActiveHighlight(bool&amp; mouseIsOverButton);
+    void clearActiveHighlight();
+    Highlight* activeHighlight() const { return m_activeHighlight.get(); }
+
+    Highlight* findTelephoneNumberHighlightContainingSelectionHighlight(Highlight&amp;);
+
+    bool hasRelevantSelectionServices();
+
+    bool mouseIsOverHighlight(Highlight&amp;, bool&amp; mouseIsOverButton) const;
+    std::chrono::milliseconds remainingTimeUntilHighlightShouldBeShown(Highlight*) const;
+    void determineActiveHighlightTimerFired(Timer&lt;ServicesOverlayController&gt;&amp;);
+
+    static bool highlightsAreEquivalent(const Highlight* a, const Highlight* b);
+
+    Vector&lt;RefPtr&lt;Range&gt;&gt; telephoneNumberRangesForFocusedFrame();
+
+    void didCreateHighlight(Highlight*);
+    void willDestroyHighlight(Highlight*);
+    void didFinishFadingOutHighlight(Highlight*);
+
+    MainFrame&amp; mainFrame() const { return m_mainFrame; }
+
+    MainFrame&amp; m_mainFrame;
+    PageOverlay* m_servicesOverlay;
+
+    RefPtr&lt;Highlight&gt; m_activeHighlight;
+    RefPtr&lt;Highlight&gt; m_nextActiveHighlight;
+    HashSet&lt;RefPtr&lt;Highlight&gt;&gt; m_potentialHighlights;
+    HashSet&lt;RefPtr&lt;Highlight&gt;&gt; m_animatingHighlights;
+
+    HashSet&lt;Highlight*&gt; m_highlights;
+
+    // FIXME: These should move onto Highlight.
+    Vector&lt;LayoutRect&gt; m_currentSelectionRects;
+    bool m_isTextOnly;
+
+    std::chrono::steady_clock::time_point m_lastSelectionChangeTime;
+    std::chrono::steady_clock::time_point m_nextActiveHighlightChangeTime;
+    std::chrono::steady_clock::time_point m_lastMouseUpTime;
+
+    RefPtr&lt;Highlight&gt; m_currentMouseDownOnButtonHighlight;
+    IntPoint m_mousePosition;
+
+    Timer&lt;ServicesOverlayController&gt; m_determineActiveHighlightTimer;
+};
+
+} // namespace WebKit
+
+#endif // (ENABLE(SERVICE_CONTROLS) || ENABLE(TELEPHONE_NUMBER_DETECTION)) &amp;&amp; PLATFORM(MAC)
+#endif // ServicesOverlayController_h
</ins></span></pre></div>
<a id="trunkSourceWebCorepagemacServicesOverlayControllermm"></a>
<div class="addfile"><h4>Added: trunk/Source/WebCore/page/mac/ServicesOverlayController.mm (0 => 174524)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/page/mac/ServicesOverlayController.mm                                (rev 0)
+++ trunk/Source/WebCore/page/mac/ServicesOverlayController.mm        2014-10-09 20:53:02 UTC (rev 174524)
</span><span class="lines">@@ -0,0 +1,855 @@
</span><ins>+/*
+ * Copyright (C) 2014 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#import &quot;config.h&quot;
+#import &quot;ServicesOverlayController.h&quot;
+
+#if (ENABLE(SERVICE_CONTROLS) || ENABLE(TELEPHONE_NUMBER_DETECTION)) &amp;&amp; PLATFORM(MAC)
+
+#import &quot;Chrome.h&quot;
+#import &quot;ChromeClient.h&quot;
+#import &quot;Document.h&quot;
+#import &quot;Editor.h&quot;
+#import &quot;EventHandler.h&quot;
+#import &quot;FloatQuad.h&quot;
+#import &quot;FocusController.h&quot;
+#import &quot;FrameSelection.h&quot;
+#import &quot;FrameView.h&quot;
+#import &quot;GapRects.h&quot;
+#import &quot;GraphicsContext.h&quot;
+#import &quot;GraphicsLayer.h&quot;
+#import &quot;GraphicsLayerCA.h&quot;
+#import &quot;Logging.h&quot;
+#import &quot;MainFrame.h&quot;
+#import &quot;Page.h&quot;
+#import &quot;PageOverlayController.h&quot;
+#import &quot;PlatformCAAnimationMac.h&quot;
+#import &quot;Settings.h&quot;
+#import &quot;SoftLinking.h&quot;
+#import &lt;QuartzCore/QuartzCore.h&gt;
+
+#if __has_include(&lt;DataDetectors/DDHighlightDrawing.h&gt;)
+#import &lt;DataDetectors/DDHighlightDrawing.h&gt;
+#else
+typedef struct __DDHighlight DDHighlight, *DDHighlightRef;
+#endif
+
+#if __has_include(&lt;DataDetectors/DDHighlightDrawing_Private.h&gt;)
+#import &lt;DataDetectors/DDHighlightDrawing_Private.h&gt;
+#endif
+
+const float highlightFadeAnimationDuration = 0.3;
+
+typedef NSUInteger DDHighlightStyle;
+static const DDHighlightStyle DDHighlightNoOutlineWithArrow = (1 &lt;&lt; 16);
+static const DDHighlightStyle DDHighlightOutlineWithArrow = (1 &lt;&lt; 16) | 1;
+
+SOFT_LINK_PRIVATE_FRAMEWORK_OPTIONAL(DataDetectors)
+SOFT_LINK(DataDetectors, DDHighlightCreateWithRectsInVisibleRectWithStyleAndDirection, DDHighlightRef, (CFAllocatorRef allocator, CGRect* rects, CFIndex count, CGRect globalVisibleRect, DDHighlightStyle style, Boolean withArrow, NSWritingDirection writingDirection, Boolean endsWithEOL, Boolean flipped), (allocator, rects, count, globalVisibleRect, style, withArrow, writingDirection, endsWithEOL, flipped))
+SOFT_LINK(DataDetectors, DDHighlightGetLayerWithContext, CGLayerRef, (DDHighlightRef highlight, CGContextRef context), (highlight, context))
+SOFT_LINK(DataDetectors, DDHighlightGetBoundingRect, CGRect, (DDHighlightRef highlight), (highlight))
+SOFT_LINK(DataDetectors, DDHighlightPointIsOnHighlight, Boolean, (DDHighlightRef highlight, CGPoint point, Boolean* onButton), (highlight, point, onButton))
+
+namespace WebCore {
+
+PassRefPtr&lt;ServicesOverlayController::Highlight&gt; ServicesOverlayController::Highlight::createForSelection(ServicesOverlayController&amp; controller, RetainPtr&lt;DDHighlightRef&gt; ddHighlight, PassRefPtr&lt;Range&gt; range)
+{
+    return adoptRef(new Highlight(controller, Type::Selection, ddHighlight, range));
+}
+
+PassRefPtr&lt;ServicesOverlayController::Highlight&gt; ServicesOverlayController::Highlight::createForTelephoneNumber(ServicesOverlayController&amp; controller, RetainPtr&lt;DDHighlightRef&gt; ddHighlight, PassRefPtr&lt;Range&gt; range)
+{
+    return adoptRef(new Highlight(controller, Type::TelephoneNumber, ddHighlight, range));
+}
+
+ServicesOverlayController::Highlight::Highlight(ServicesOverlayController&amp; controller, Type type, RetainPtr&lt;DDHighlightRef&gt; ddHighlight, PassRefPtr&lt;WebCore::Range&gt; range)
+    : m_range(range)
+    , m_type(type)
+    , m_controller(&amp;controller)
+{
+    ASSERT(ddHighlight);
+    ASSERT(m_range);
+
+    Page* page = controller.mainFrame().page();
+    m_graphicsLayer = GraphicsLayer::create(page ? page-&gt;chrome().client().graphicsLayerFactory() : nullptr, *this);
+    m_graphicsLayer-&gt;setDrawsContent(true);
+
+    setDDHighlight(ddHighlight.get());
+
+    // Set directly on the PlatformCALayer so that when we leave the 'from' value implicit
+    // in our animations, we get the right initial value regardless of flush timing.
+    toGraphicsLayerCA(layer())-&gt;platformCALayer()-&gt;setOpacity(0);
+
+    controller.didCreateHighlight(this);
+}
+
+ServicesOverlayController::Highlight::~Highlight()
+{
+    if (m_controller)
+        m_controller-&gt;willDestroyHighlight(this);
+}
+
+void ServicesOverlayController::Highlight::setDDHighlight(DDHighlightRef highlight)
+{
+    if (!m_controller)
+        return;
+
+    m_ddHighlight = highlight;
+
+    if (!m_ddHighlight)
+        return;
+
+    CGRect highlightBoundingRect = DDHighlightGetBoundingRect(m_ddHighlight.get());
+    m_graphicsLayer-&gt;setPosition(FloatPoint(highlightBoundingRect.origin));
+    m_graphicsLayer-&gt;setSize(FloatSize(highlightBoundingRect.size));
+
+    m_graphicsLayer-&gt;setNeedsDisplay();
+}
+
+void ServicesOverlayController::Highlight::invalidate()
+{
+    layer()-&gt;removeFromParent();
+    m_controller = nullptr;
+}
+
+void ServicesOverlayController::Highlight::notifyFlushRequired(const GraphicsLayer*)
+{
+    if (!m_controller)
+        return;
+
+    Page* page = m_controller-&gt;mainFrame().page();
+    if (!page)
+        return;
+
+    page-&gt;chrome().client().scheduleCompositingLayerFlush();
+}
+
+void ServicesOverlayController::Highlight::paintContents(const GraphicsLayer*, GraphicsContext&amp; graphicsContext, GraphicsLayerPaintingPhase, const FloatRect&amp;)
+{
+    CGContextRef cgContext = graphicsContext.platformContext();
+
+    CGLayerRef highlightLayer = DDHighlightGetLayerWithContext(ddHighlight(), cgContext);
+    CGRect highlightBoundingRect = DDHighlightGetBoundingRect(ddHighlight());
+    highlightBoundingRect.origin = CGPointZero;
+
+    CGContextDrawLayerInRect(cgContext, highlightBoundingRect, highlightLayer);
+}
+
+float ServicesOverlayController::Highlight::deviceScaleFactor() const
+{
+    if (!m_controller)
+        return 1;
+
+    Page* page = m_controller-&gt;mainFrame().page();
+    if (!page)
+        return 1;
+
+    return page-&gt;deviceScaleFactor();
+}
+
+void ServicesOverlayController::Highlight::fadeIn()
+{
+    RetainPtr&lt;CABasicAnimation&gt; animation = [CABasicAnimation animationWithKeyPath:@&quot;opacity&quot;];
+    [animation setDuration:highlightFadeAnimationDuration];
+    [animation setFillMode:kCAFillModeForwards];
+    [animation setRemovedOnCompletion:false];
+    [animation setToValue:@1];
+
+    RefPtr&lt;PlatformCAAnimation&gt; platformAnimation = PlatformCAAnimationMac::create(animation.get());
+    toGraphicsLayerCA(layer())-&gt;platformCALayer()-&gt;addAnimationForKey(&quot;FadeHighlightIn&quot;, platformAnimation.get());
+}
+
+void ServicesOverlayController::Highlight::fadeOut()
+{
+    RetainPtr&lt;CABasicAnimation&gt; animation = [CABasicAnimation animationWithKeyPath:@&quot;opacity&quot;];
+    [animation setDuration:highlightFadeAnimationDuration];
+    [animation setFillMode:kCAFillModeForwards];
+    [animation setRemovedOnCompletion:false];
+    [animation setToValue:@0];
+
+    RefPtr&lt;Highlight&gt; retainedSelf = this;
+    [CATransaction begin];
+    [CATransaction setCompletionBlock:[retainedSelf] () {
+        retainedSelf-&gt;didFinishFadeOutAnimation();
+    }];
+
+    RefPtr&lt;PlatformCAAnimation&gt; platformAnimation = PlatformCAAnimationMac::create(animation.get());
+    toGraphicsLayerCA(layer())-&gt;platformCALayer()-&gt;addAnimationForKey(&quot;FadeHighlightOut&quot;, platformAnimation.get());
+    [CATransaction commit];
+}
+
+void ServicesOverlayController::Highlight::didFinishFadeOutAnimation()
+{
+    if (!m_controller)
+        return;
+
+    if (m_controller-&gt;activeHighlight() == this)
+        return;
+
+    layer()-&gt;removeFromParent();
+}
+
+static IntRect textQuadsToBoundingRectForRange(Range&amp; range)
+{
+    Vector&lt;FloatQuad&gt; textQuads;
+    range.textQuads(textQuads);
+    FloatRect boundingRect;
+    for (auto&amp; quad : textQuads)
+        boundingRect.unite(quad.boundingBox());
+    return enclosingIntRect(boundingRect);
+}
+
+ServicesOverlayController::ServicesOverlayController(MainFrame&amp; mainFrame)
+    : m_mainFrame(mainFrame)
+    , m_servicesOverlay(nullptr)
+    , m_isTextOnly(false)
+    , m_determineActiveHighlightTimer(this, &amp;ServicesOverlayController::determineActiveHighlightTimerFired)
+{
+}
+
+ServicesOverlayController::~ServicesOverlayController()
+{
+    for (auto&amp; highlight : m_highlights)
+        highlight-&gt;invalidate();
+}
+
+void ServicesOverlayController::pageOverlayDestroyed(PageOverlay&amp;)
+{
+    // Before the overlay is destroyed, it should have moved out of the Page,
+    // at which point we already cleared our back pointer.
+    ASSERT(!m_servicesOverlay);
+}
+
+void ServicesOverlayController::willMoveToPage(PageOverlay&amp;, Page* page)
+{
+    if (page)
+        return;
+
+    ASSERT(m_servicesOverlay);
+    m_servicesOverlay = nullptr;
+}
+
+void ServicesOverlayController::didMoveToPage(PageOverlay&amp;, Page*)
+{
+}
+
+static const uint8_t AlignmentNone = 0;
+static const uint8_t AlignmentLeft = 1 &lt;&lt; 0;
+static const uint8_t AlignmentRight = 1 &lt;&lt; 1;
+
+static void expandForGap(Vector&lt;LayoutRect&gt;&amp; rects, uint8_t* alignments, const GapRects&amp; gap)
+{
+    if (!gap.left().isEmpty()) {
+        LayoutUnit leftEdge = gap.left().x();
+        for (unsigned i = 0; i &lt; rects.size(); ++i) {
+            if (alignments[i] &amp; AlignmentLeft)
+                rects[i].shiftXEdgeTo(leftEdge);
+        }
+    }
+
+    if (!gap.right().isEmpty()) {
+        LayoutUnit rightEdge = gap.right().maxX();
+        for (unsigned i = 0; i &lt; rects.size(); ++i) {
+            if (alignments[i] &amp; AlignmentRight)
+                rects[i].shiftMaxXEdgeTo(rightEdge);
+        }
+    }
+}
+
+static inline void stitchRects(Vector&lt;LayoutRect&gt;&amp; rects)
+{
+    if (rects.size() &lt;= 1)
+        return;
+    
+    Vector&lt;LayoutRect&gt; newRects;
+    
+    // FIXME: Need to support vertical layout.
+    // First stitch together all the rects on the first line of the selection.
+    size_t indexFromStart = 0;
+    LayoutUnit firstTop = rects[indexFromStart].y();
+    LayoutRect&amp; currentRect = rects[indexFromStart];
+    while (indexFromStart &lt; rects.size() &amp;&amp; rects[indexFromStart].y() == firstTop)
+        currentRect.unite(rects[indexFromStart++]);
+    
+    newRects.append(currentRect);
+    if (indexFromStart == rects.size()) {
+        // All the rects are on one line. There is nothing else to do.
+        rects.swap(newRects);
+        return;
+    }
+    
+    // Next stitch together all the rects on the last line of the selection.
+    size_t indexFromEnd = rects.size() - 1;
+    LayoutUnit lastTop = rects[indexFromEnd].y();
+    LayoutRect lastRect = rects[indexFromEnd];
+    while (indexFromEnd &gt;= indexFromStart &amp;&amp; rects[indexFromEnd].y() == lastTop)
+        lastRect.unite(rects[indexFromEnd--]);
+    
+    // indexFromStart is the index of the first rectangle on the second line.
+    // indexFromEnd is the index of the last rectangle on the second to the last line.
+    // if they are equal, there is one additional rectangle for the line in the middle.
+    if (indexFromEnd == indexFromStart)
+        newRects.append(rects[indexFromStart]);
+    
+    if (indexFromEnd &lt;= indexFromStart) {
+        // There are no more rects to stitch. Just append the last line.
+        newRects.append(lastRect);
+        rects.swap(newRects);
+        return;
+    }
+    
+    // Stitch together all the rects after the first line until the second to the last included.
+    currentRect = rects[indexFromStart];
+    while (indexFromStart != indexFromEnd)
+        currentRect.unite(rects[++indexFromStart]);
+    
+    newRects.append(currentRect);
+    newRects.append(lastRect);
+
+    rects.swap(newRects);
+}
+
+static void compactRectsWithGapRects(Vector&lt;LayoutRect&gt;&amp; rects, const Vector&lt;GapRects&gt;&amp; gapRects)
+{
+    stitchRects(rects);
+    
+    // FIXME: The following alignments are correct for LTR text.
+    // We should also account for RTL.
+    uint8_t alignments[3];
+    if (rects.size() == 1) {
+        alignments[0] = AlignmentLeft | AlignmentRight;
+        alignments[1] = AlignmentNone;
+        alignments[2] = AlignmentNone;
+    } else if (rects.size() == 2) {
+        alignments[0] = AlignmentRight;
+        alignments[1] = AlignmentLeft;
+        alignments[2] = AlignmentNone;
+    } else {
+        alignments[0] = AlignmentRight;
+        alignments[1] = AlignmentLeft | AlignmentRight;
+        alignments[2] = AlignmentLeft;
+    }
+
+    // Account for each GapRects by extending the edge of certain LayoutRects to meet the gap.
+    for (auto&amp; gap : gapRects)
+        expandForGap(rects, alignments, gap);
+
+    // If we have 3 rects we might need one final GapRects to align the edges.
+    if (rects.size() == 3) {
+        LayoutRect left;
+        LayoutRect right;
+        for (unsigned i = 0; i &lt; 3; ++i) {
+            if (alignments[i] &amp; AlignmentLeft) {
+                if (left.isEmpty())
+                    left = rects[i];
+                else if (rects[i].x() &lt; left.x())
+                    left = rects[i];
+            }
+            if (alignments[i] &amp; AlignmentRight) {
+                if (right.isEmpty())
+                    right = rects[i];
+                else if ((rects[i].x() + rects[i].width()) &gt; (right.x() + right.width()))
+                    right = rects[i];
+            }
+        }
+
+        if (!left.isEmpty() || !right.isEmpty()) {
+            GapRects gap;
+            gap.uniteLeft(left);
+            gap.uniteRight(right);
+            expandForGap(rects, alignments, gap);
+        }
+    }
+}
+
+void ServicesOverlayController::selectionRectsDidChange(const Vector&lt;LayoutRect&gt;&amp; rects, const Vector&lt;GapRects&gt;&amp; gapRects, bool isTextOnly)
+{
+#if PLATFORM(MAC) &amp;&amp; __MAC_OS_X_VERSION_MIN_REQUIRED &gt; 1090
+    m_currentSelectionRects = rects;
+    m_isTextOnly = isTextOnly;
+
+    m_lastSelectionChangeTime = std::chrono::steady_clock::now();
+
+    compactRectsWithGapRects(m_currentSelectionRects, gapRects);
+
+    // DataDetectors needs these reversed in order to place the arrow in the right location.
+    m_currentSelectionRects.reverse();
+
+    LOG(Services, &quot;ServicesOverlayController - Selection rects changed - Now have %lu\n&quot;, rects.size());
+
+    buildSelectionHighlight();
+#else
+    UNUSED_PARAM(rects);
+    UNUSED_PARAM(gapRects);
+    UNUSED_PARAM(isTextOnly);
+#endif
+}
+
+void ServicesOverlayController::selectedTelephoneNumberRangesChanged()
+{
+#if PLATFORM(MAC) &amp;&amp; __MAC_OS_X_VERSION_MIN_REQUIRED &gt; 1090
+    LOG(Services, &quot;ServicesOverlayController - Telephone number ranges changed\n&quot;);
+    buildPhoneNumberHighlights();
+#endif
+}
+
+bool ServicesOverlayController::mouseIsOverHighlight(Highlight&amp; highlight, bool&amp; mouseIsOverButton) const
+{
+    Boolean onButton;
+    bool hovered = DDHighlightPointIsOnHighlight(highlight.ddHighlight(), (CGPoint)m_mousePosition, &amp;onButton);
+    mouseIsOverButton = onButton;
+    return hovered;
+}
+
+std::chrono::milliseconds ServicesOverlayController::remainingTimeUntilHighlightShouldBeShown(Highlight* highlight) const
+{
+    if (!highlight)
+        return std::chrono::milliseconds::zero();
+
+    auto minimumTimeUntilHighlightShouldBeShown = 200_ms;
+    Page* page = m_mainFrame.page();
+    if (page &amp;&amp; page-&gt;focusController().focusedOrMainFrame().selection().selection().isContentEditable())
+        minimumTimeUntilHighlightShouldBeShown = 1000_ms;
+
+    bool mousePressed = m_mainFrame.eventHandler().mousePressed();
+
+    // Highlight hysteresis is only for selection services, because telephone number highlights are already much more stable
+    // by virtue of being expanded to include the entire telephone number. However, we will still avoid highlighting
+    // telephone numbers while the mouse is down.
+    if (highlight-&gt;type() == Highlight::Type::TelephoneNumber)
+        return mousePressed ? minimumTimeUntilHighlightShouldBeShown : 0_ms;
+
+    auto now = std::chrono::steady_clock::now();
+    auto timeSinceLastSelectionChange = now - m_lastSelectionChangeTime;
+    auto timeSinceHighlightBecameActive = now - m_nextActiveHighlightChangeTime;
+    auto timeSinceLastMouseUp = mousePressed ? 0_ms : now - m_lastMouseUpTime;
+
+    auto remainingDelay = minimumTimeUntilHighlightShouldBeShown - std::min(std::min(timeSinceLastSelectionChange, timeSinceHighlightBecameActive), timeSinceLastMouseUp);
+    return std::chrono::duration_cast&lt;std::chrono::milliseconds&gt;(remainingDelay);
+}
+
+void ServicesOverlayController::determineActiveHighlightTimerFired(Timer&lt;ServicesOverlayController&gt;&amp;)
+{
+    bool mouseIsOverButton;
+    determineActiveHighlight(mouseIsOverButton);
+}
+
+void ServicesOverlayController::drawRect(PageOverlay&amp;, GraphicsContext&amp;, const IntRect&amp;)
+{
+}
+
+void ServicesOverlayController::clearActiveHighlight()
+{
+    if (!m_activeHighlight)
+        return;
+
+    if (m_currentMouseDownOnButtonHighlight == m_activeHighlight)
+        m_currentMouseDownOnButtonHighlight = nullptr;
+    m_activeHighlight = nullptr;
+}
+
+void ServicesOverlayController::removeAllPotentialHighlightsOfType(Highlight::Type type)
+{
+    Vector&lt;RefPtr&lt;Highlight&gt;&gt; highlightsToRemove;
+    for (auto&amp; highlight : m_potentialHighlights) {
+        if (highlight-&gt;type() == type)
+            highlightsToRemove.append(highlight);
+    }
+
+    while (!highlightsToRemove.isEmpty())
+        m_potentialHighlights.remove(highlightsToRemove.takeLast());
+}
+
+void ServicesOverlayController::buildPhoneNumberHighlights()
+{
+    if (!DataDetectorsLibrary())
+        return;
+
+    if (!m_mainFrame.settings().serviceControlsEnabled())
+        return;
+
+    HashSet&lt;RefPtr&lt;Highlight&gt;&gt; newPotentialHighlights;
+
+    FrameView&amp; mainFrameView = *m_mainFrame.view();
+
+    for (Frame* frame = &amp;m_mainFrame; frame; frame = frame-&gt;tree().traverseNext()) {
+        auto&amp; ranges = frame-&gt;editor().detectedTelephoneNumberRanges();
+        for (auto&amp; range : ranges) {
+            // FIXME: This will choke if the range wraps around the edge of the view.
+            // What should we do in that case?
+            IntRect rect = textQuadsToBoundingRectForRange(*range);
+
+            // Convert to the main document's coordinate space.
+            // FIXME: It's a little crazy to call contentsToWindow and then windowToContents in order to get the right coordinate space.
+            // We should consider adding conversion functions to ScrollView for contentsToDocument(). Right now, contentsToRootView() is
+            // not equivalent to what we need when you have a topContentInset or a header banner.
+            FrameView* viewForRange = range-&gt;ownerDocument().view();
+            if (!viewForRange)
+                continue;
+            rect.setLocation(mainFrameView.windowToContents(viewForRange-&gt;contentsToWindow(rect.location())));
+
+            CGRect cgRect = rect;
+            RetainPtr&lt;DDHighlightRef&gt; ddHighlight = adoptCF(DDHighlightCreateWithRectsInVisibleRectWithStyleAndDirection(nullptr, &amp;cgRect, 1, mainFrameView.visibleContentRect(), DDHighlightOutlineWithArrow, YES, NSWritingDirectionNatural, NO, YES));
+
+            newPotentialHighlights.add(Highlight::createForTelephoneNumber(*this, ddHighlight, range));
+        }
+    }
+
+    replaceHighlightsOfTypePreservingEquivalentHighlights(newPotentialHighlights, Highlight::Type::TelephoneNumber);
+
+    didRebuildPotentialHighlights();
+}
+
+void ServicesOverlayController::buildSelectionHighlight()
+{
+    if (!DataDetectorsLibrary())
+        return;
+
+    if (!m_mainFrame.settings().serviceControlsEnabled())
+        return;
+
+    Page* page = m_mainFrame.page();
+    if (!page)
+        return;
+
+    HashSet&lt;RefPtr&lt;Highlight&gt;&gt; newPotentialHighlights;
+
+    Vector&lt;CGRect&gt; cgRects;
+    cgRects.reserveCapacity(m_currentSelectionRects.size());
+
+    RefPtr&lt;Range&gt; selectionRange = page-&gt;selection().firstRange();
+    if (selectionRange) {
+        FrameView* mainFrameView = m_mainFrame.view();
+        if (!mainFrameView)
+            return;
+
+        FrameView* viewForRange = selectionRange-&gt;ownerDocument().view();
+
+        for (auto&amp; rect : m_currentSelectionRects) {
+            IntRect currentRect = snappedIntRect(rect);
+            currentRect.setLocation(mainFrameView-&gt;windowToContents(viewForRange-&gt;contentsToWindow(currentRect.location())));
+            cgRects.append((CGRect)currentRect);
+        }
+
+        if (!cgRects.isEmpty()) {
+            CGRect visibleRect = mainFrameView-&gt;visibleContentRect();
+            RetainPtr&lt;DDHighlightRef&gt; ddHighlight = adoptCF(DDHighlightCreateWithRectsInVisibleRectWithStyleAndDirection(nullptr, cgRects.begin(), cgRects.size(), visibleRect, DDHighlightNoOutlineWithArrow, YES, NSWritingDirectionNatural, NO, YES));
+            
+            newPotentialHighlights.add(Highlight::createForSelection(*this, ddHighlight, selectionRange));
+        }
+    }
+
+    replaceHighlightsOfTypePreservingEquivalentHighlights(newPotentialHighlights, Highlight::Type::Selection);
+
+    didRebuildPotentialHighlights();
+}
+
+void ServicesOverlayController::replaceHighlightsOfTypePreservingEquivalentHighlights(HashSet&lt;RefPtr&lt;Highlight&gt;&gt;&amp; newPotentialHighlights, Highlight::Type type)
+{
+    // If any old Highlights are equivalent (by Range) to a new Highlight, reuse the old
+    // one so that any metadata is retained.
+    HashSet&lt;RefPtr&lt;Highlight&gt;&gt; reusedPotentialHighlights;
+
+    for (auto&amp; oldHighlight : m_potentialHighlights) {
+        if (oldHighlight-&gt;type() != type)
+            continue;
+
+        for (auto&amp; newHighlight : newPotentialHighlights) {
+            if (highlightsAreEquivalent(oldHighlight.get(), newHighlight.get())) {
+                oldHighlight-&gt;setDDHighlight(newHighlight-&gt;ddHighlight());
+
+                reusedPotentialHighlights.add(oldHighlight);
+                newPotentialHighlights.remove(newHighlight);
+
+                break;
+            }
+        }
+    }
+
+    removeAllPotentialHighlightsOfType(type);
+
+    m_potentialHighlights.add(newPotentialHighlights.begin(), newPotentialHighlights.end());
+    m_potentialHighlights.add(reusedPotentialHighlights.begin(), reusedPotentialHighlights.end());
+}
+
+bool ServicesOverlayController::hasRelevantSelectionServices()
+{
+    if (Page* page = m_mainFrame.page())
+        return page-&gt;chrome().client().hasRelevantSelectionServices(m_isTextOnly);
+    return false;
+}
+
+void ServicesOverlayController::didRebuildPotentialHighlights()
+{
+    if (m_potentialHighlights.isEmpty()) {
+        if (m_servicesOverlay)
+            m_mainFrame.pageOverlayController().uninstallPageOverlay(m_servicesOverlay, PageOverlay::FadeMode::DoNotFade);
+        return;
+    }
+
+    if (telephoneNumberRangesForFocusedFrame().isEmpty() &amp;&amp; !hasRelevantSelectionServices())
+        return;
+
+    createOverlayIfNeeded();
+
+    bool mouseIsOverButton;
+    determineActiveHighlight(mouseIsOverButton);
+}
+
+void ServicesOverlayController::createOverlayIfNeeded()
+{
+    if (m_servicesOverlay)
+        return;
+
+    if (!m_mainFrame.settings().serviceControlsEnabled())
+        return;
+
+    RefPtr&lt;PageOverlay&gt; overlay = PageOverlay::create(*this, PageOverlay::OverlayType::Document);
+    m_servicesOverlay = overlay.get();
+    m_mainFrame.pageOverlayController().installPageOverlay(overlay.release(), PageOverlay::FadeMode::DoNotFade);
+}
+
+Vector&lt;RefPtr&lt;Range&gt;&gt; ServicesOverlayController::telephoneNumberRangesForFocusedFrame()
+{
+    Page* page = m_mainFrame.page();
+    if (!page)
+        return { };
+
+    return page-&gt;focusController().focusedOrMainFrame().editor().detectedTelephoneNumberRanges();
+}
+
+bool ServicesOverlayController::highlightsAreEquivalent(const Highlight* a, const Highlight* b)
+{
+    if (a == b)
+        return true;
+
+    if (!a || !b)
+        return false;
+
+    if (a-&gt;type() == b-&gt;type() &amp;&amp; areRangesEqual(a-&gt;range(), b-&gt;range()))
+        return true;
+
+    return false;
+}
+
+ServicesOverlayController::Highlight* ServicesOverlayController::findTelephoneNumberHighlightContainingSelectionHighlight(Highlight&amp; selectionHighlight)
+{
+    if (selectionHighlight.type() != Highlight::Type::Selection)
+        return nullptr;
+
+    Page* page = m_mainFrame.page();
+    if (!page)
+        return nullptr;
+
+    const VisibleSelection&amp; selection = page-&gt;selection();
+    if (!selection.isRange())
+        return nullptr;
+
+    RefPtr&lt;Range&gt; activeSelectionRange = selection.toNormalizedRange();
+    if (!activeSelectionRange)
+        return nullptr;
+
+    for (auto&amp; highlight : m_potentialHighlights) {
+        if (highlight-&gt;type() != Highlight::Type::TelephoneNumber)
+            continue;
+
+        if (highlight-&gt;range()-&gt;contains(*activeSelectionRange))
+            return highlight.get();
+    }
+
+    return nullptr;
+}
+
+void ServicesOverlayController::determineActiveHighlight(bool&amp; mouseIsOverActiveHighlightButton)
+{
+    mouseIsOverActiveHighlightButton = false;
+
+    RefPtr&lt;Highlight&gt; newActiveHighlight;
+
+    for (auto&amp; highlight : m_potentialHighlights) {
+        if (highlight-&gt;type() == Highlight::Type::Selection) {
+            // If we've already found a new active highlight, and it's
+            // a telephone number highlight, prefer that over this selection highlight.
+            if (newActiveHighlight &amp;&amp; newActiveHighlight-&gt;type() == Highlight::Type::TelephoneNumber)
+                continue;
+
+            // If this highlight has no compatible services, it can't be active.
+            if (!hasRelevantSelectionServices())
+                continue;
+        }
+
+        // If this highlight isn't hovered, it can't be active.
+        bool mouseIsOverButton;
+        if (!mouseIsOverHighlight(*highlight, mouseIsOverButton))
+            continue;
+
+        newActiveHighlight = highlight;
+        mouseIsOverActiveHighlightButton = mouseIsOverButton;
+    }
+
+    // If our new active highlight is a selection highlight that is completely contained
+    // by one of the phone number highlights, we'll make the phone number highlight active even if it's not hovered.
+    if (newActiveHighlight &amp;&amp; newActiveHighlight-&gt;type() == Highlight::Type::Selection) {
+        if (Highlight* containedTelephoneNumberHighlight = findTelephoneNumberHighlightContainingSelectionHighlight(*newActiveHighlight)) {
+            newActiveHighlight = containedTelephoneNumberHighlight;
+
+            // We will always initially choose the telephone number highlight over the selection highlight if the
+            // mouse is over the telephone number highlight's button, so we know that it's not hovered if we got here.
+            mouseIsOverActiveHighlightButton = false;
+        }
+    }
+
+    if (!this-&gt;highlightsAreEquivalent(m_activeHighlight.get(), newActiveHighlight.get())) {
+        // When transitioning to a new highlight, we might end up in determineActiveHighlight multiple times
+        // before the new highlight actually becomes active. Keep track of the last next-but-not-yet-active
+        // highlight, and only reset the active highlight hysteresis when that changes.
+        if (m_nextActiveHighlight != newActiveHighlight) {
+            m_nextActiveHighlight = newActiveHighlight;
+            m_nextActiveHighlightChangeTime = std::chrono::steady_clock::now();
+        }
+
+        m_currentMouseDownOnButtonHighlight = nullptr;
+
+        if (m_activeHighlight) {
+            m_activeHighlight-&gt;fadeOut();
+            m_activeHighlight = nullptr;
+        }
+
+        auto remainingTimeUntilHighlightShouldBeShown = this-&gt;remainingTimeUntilHighlightShouldBeShown(newActiveHighlight.get());
+        if (remainingTimeUntilHighlightShouldBeShown &gt; std::chrono::steady_clock::duration::zero()) {
+            m_determineActiveHighlightTimer.startOneShot(remainingTimeUntilHighlightShouldBeShown);
+            return;
+        }
+
+        m_activeHighlight = m_nextActiveHighlight.release();
+
+        if (m_activeHighlight) {
+            m_servicesOverlay-&gt;layer().addChild(m_activeHighlight-&gt;layer());
+            m_activeHighlight-&gt;fadeIn();
+        }
+    }
+}
+
+bool ServicesOverlayController::mouseEvent(PageOverlay&amp;, const PlatformMouseEvent&amp; event)
+{
+    m_mousePosition = m_mainFrame.view()-&gt;windowToContents(event.position());
+
+    bool mouseIsOverActiveHighlightButton = false;
+    determineActiveHighlight(mouseIsOverActiveHighlightButton);
+
+    // Cancel the potential click if any button other than the left button changes state, and ignore the event.
+    if (event.button() != MouseButton::LeftButton) {
+        m_currentMouseDownOnButtonHighlight = nullptr;
+        return false;
+    }
+
+    // If the mouse lifted while still over the highlight button that it went down on, then that is a click.
+    if (event.type() == PlatformEvent::MouseReleased) {
+        RefPtr&lt;Highlight&gt; mouseDownHighlight = m_currentMouseDownOnButtonHighlight;
+        m_currentMouseDownOnButtonHighlight = nullptr;
+
+        m_lastMouseUpTime = std::chrono::steady_clock::now();
+
+        if (mouseIsOverActiveHighlightButton &amp;&amp; mouseDownHighlight) {
+            handleClick(m_mousePosition, *mouseDownHighlight);
+            return true;
+        }
+        
+        return false;
+    }
+
+    // If the mouse moved outside of the button tracking a potential click, stop tracking the click.
+    if (event.type() == PlatformEvent::MouseMoved) {
+        if (m_currentMouseDownOnButtonHighlight &amp;&amp; mouseIsOverActiveHighlightButton)
+            return true;
+
+        m_currentMouseDownOnButtonHighlight = nullptr;
+        return false;
+    }
+
+    // If the mouse went down over the active highlight's button, track this as a potential click.
+    if (event.type() == PlatformEvent::MousePressed) {
+        if (m_activeHighlight &amp;&amp; mouseIsOverActiveHighlightButton) {
+            m_currentMouseDownOnButtonHighlight = m_activeHighlight;
+            return true;
+        }
+
+        return false;
+    }
+
+    return false;
+}
+
+void ServicesOverlayController::didScrollFrame(PageOverlay&amp;, Frame&amp; frame)
+{
+    if (frame.isMainFrame())
+        return;
+
+    buildPhoneNumberHighlights();
+    buildSelectionHighlight();
+
+    bool mouseIsOverActiveHighlightButton;
+    determineActiveHighlight(mouseIsOverActiveHighlightButton);
+}
+
+void ServicesOverlayController::handleClick(const IntPoint&amp; clickPoint, Highlight&amp; highlight)
+{
+    FrameView* frameView = m_mainFrame.view();
+    if (!frameView)
+        return;
+
+    Page* page = m_mainFrame.page();
+    if (!page)
+        return;
+
+    IntPoint windowPoint = frameView-&gt;contentsToWindow(clickPoint);
+
+    if (highlight.type() == Highlight::Type::Selection) {
+        auto telephoneNumberRanges = telephoneNumberRangesForFocusedFrame();
+        Vector&lt;String&gt; selectedTelephoneNumbers;
+        selectedTelephoneNumbers.reserveCapacity(telephoneNumberRanges.size());
+        for (auto&amp; range : telephoneNumberRanges)
+            selectedTelephoneNumbers.append(range-&gt;text());
+
+        page-&gt;chrome().client().handleSelectionServiceClick(page-&gt;focusController().focusedOrMainFrame().selection(), selectedTelephoneNumbers, windowPoint);
+    } else if (highlight.type() == Highlight::Type::TelephoneNumber)
+        page-&gt;chrome().client().handleTelephoneNumberClick(highlight.range()-&gt;text(), windowPoint);
+}
+
+void ServicesOverlayController::didCreateHighlight(Highlight* highlight)
+{
+    ASSERT(!m_highlights.contains(highlight));
+    m_highlights.add(highlight);
+}
+
+void ServicesOverlayController::willDestroyHighlight(Highlight* highlight)
+{
+    ASSERT(m_highlights.contains(highlight));
+    m_highlights.remove(highlight);
+}
+
+} // namespace WebKit
+
+#endif // (ENABLE(SERVICE_CONTROLS) || ENABLE(TELEPHONE_NUMBER_DETECTION)) &amp;&amp; PLATFORM(MAC)
</ins></span></pre></div>
<a id="trunkSourceWebCoreplatformLoggingh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/Logging.h (174523 => 174524)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/Logging.h        2014-10-09 20:51:55 UTC (rev 174523)
+++ trunk/Source/WebCore/platform/Logging.h        2014-10-09 20:53:02 UTC (rev 174524)
</span><span class="lines">@@ -72,6 +72,7 @@
</span><span class="cx">     M(WebAudio) \
</span><span class="cx">     M(WebGL) \
</span><span class="cx">     M(WebReplay) \
</span><ins>+    M(Services) \
</ins><span class="cx"> 
</span><span class="cx"> #define DECLARE_LOG_CHANNEL(name) \
</span><span class="cx">     extern WTFLogChannel JOIN_LOG_CHANNEL_WITH_PREFIX(LOG_CHANNEL_PREFIX, name);
</span></span></pre></div>
<a id="trunkSourceWebKit2ChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/ChangeLog (174523 => 174524)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/ChangeLog        2014-10-09 20:51:55 UTC (rev 174523)
+++ trunk/Source/WebKit2/ChangeLog        2014-10-09 20:53:02 UTC (rev 174524)
</span><span class="lines">@@ -1,3 +1,40 @@
</span><ins>+2014-10-09  Tim Horton  &lt;timothy_horton@apple.com&gt;
+
+        Move ServicesOverlayController to WebCore
+        https://bugs.webkit.org/show_bug.cgi?id=137416
+        &lt;rdar://problem/18546283&gt;
+
+        Reviewed by Anders Carlsson.
+
+        * Platform/Logging.h:
+        Move Services logging channel to WebCore.
+
+        * WebKit2.xcodeproj/project.pbxproj:
+        * WebProcess/WebCoreSupport/WebChromeClient.cpp:
+        (WebKit::WebChromeClient::handleTelephoneNumberClick):
+        (WebKit::WebChromeClient::handleSelectionServiceClick):
+        (WebKit::WebChromeClient::hasRelevantSelectionServices):
+        Implement services-related ChromeClient callbacks.
+        Clicks are forwarded to WebPageMac where they do what they used to;
+        hasRelevantSelectionServices is implemented as it was when it lived
+        inside ServicesOverlayController.
+
+        * WebProcess/WebCoreSupport/WebChromeClient.h:
+        * WebProcess/WebCoreSupport/WebEditorClient.cpp:
+        (WebKit::WebEditorClient::selectedTelephoneNumberRangesChanged): Deleted.
+        (WebKit::WebEditorClient::selectionRectsDidChange): Deleted.
+        * WebProcess/WebCoreSupport/WebEditorClient.h:
+        Remove WebEditorClient overrides for now-removed functions.
+
+        * WebProcess/WebPage/WebPage.cpp:
+        (WebKit::WebPage::WebPage):
+        (WebKit::WebPage::updatePreferences):
+        Forward serviceControlsEnabled setting to WebCore.
+
+        (WebKit::WebPage::servicesOverlayController): Deleted.
+        * WebProcess/WebPage/WebPage.h:
+        (WebKit::WebPage::serviceControlsEnabled): Deleted.
+
</ins><span class="cx"> 2014-10-09  Andy Estes  &lt;aestes@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         [iOS] Crash in CFURLDownloadClient.didFail if the download has a null resumeData
</span></span></pre></div>
<a id="trunkSourceWebKit2PlatformLoggingh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/Platform/Logging.h (174523 => 174524)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/Platform/Logging.h        2014-10-09 20:51:55 UTC (rev 174523)
+++ trunk/Source/WebKit2/Platform/Logging.h        2014-10-09 20:53:02 UTC (rev 174524)
</span><span class="lines">@@ -51,7 +51,6 @@
</span><span class="cx">     M(TextInput) \
</span><span class="cx">     M(View) \
</span><span class="cx">     M(IDB) \
</span><del>-    M(Services) \
</del><span class="cx"> 
</span><span class="cx"> #define DECLARE_LOG_CHANNEL(name) \
</span><span class="cx">     extern WTFLogChannel JOIN_LOG_CHANNEL_WITH_PREFIX(LOG_CHANNEL_PREFIX, name);
</span></span></pre></div>
<a id="trunkSourceWebKit2WebKit2xcodeprojprojectpbxproj"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/WebKit2.xcodeproj/project.pbxproj (174523 => 174524)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/WebKit2.xcodeproj/project.pbxproj        2014-10-09 20:51:55 UTC (rev 174523)
+++ trunk/Source/WebKit2/WebKit2.xcodeproj/project.pbxproj        2014-10-09 20:53:02 UTC (rev 174524)
</span><span class="lines">@@ -931,7 +931,6 @@
</span><span class="cx">                 518E8F0B16B2093700E91429 /* DownloadManager.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 518E8F0216B2093700E91429 /* DownloadManager.cpp */; };
</span><span class="cx">                 518E8F0C16B2093700E91429 /* DownloadManager.h in Headers */ = {isa = PBXBuildFile; fileRef = 518E8F0316B2093700E91429 /* DownloadManager.h */; };
</span><span class="cx">                 518E8F0D16B2093700E91429 /* DownloadMac.mm in Sources */ = {isa = PBXBuildFile; fileRef = 518E8F0516B2093700E91429 /* DownloadMac.mm */; };
</span><del>-                5192D5761961FD0300CD19AA /* ServicesOverlayController.mm in Sources */ = {isa = PBXBuildFile; fileRef = 5192D5751961FD0300CD19AA /* ServicesOverlayController.mm */; };
</del><span class="cx">                 51933DEF1965EB31008AC3EA /* MenuUtilities.h in Headers */ = {isa = PBXBuildFile; fileRef = 51933DEB1965EB24008AC3EA /* MenuUtilities.h */; };
</span><span class="cx">                 51933DF01965EB31008AC3EA /* MenuUtilities.mm in Sources */ = {isa = PBXBuildFile; fileRef = 51933DEC1965EB24008AC3EA /* MenuUtilities.mm */; };
</span><span class="cx">                 51A4D5A916CAC4FF000E615E /* StatisticsRequest.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 51A4D5A816CAC4FF000E615E /* StatisticsRequest.cpp */; };
</span><span class="lines">@@ -2949,8 +2948,6 @@
</span><span class="cx">                 518E8F0216B2093700E91429 /* DownloadManager.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = DownloadManager.cpp; path = Downloads/DownloadManager.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 518E8F0316B2093700E91429 /* DownloadManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DownloadManager.h; path = Downloads/DownloadManager.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 518E8F0516B2093700E91429 /* DownloadMac.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = DownloadMac.mm; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><del>-                5192D5711961FA2F00CD19AA /* ServicesOverlayController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ServicesOverlayController.h; sourceTree = &quot;&lt;group&gt;&quot;; };
-                5192D5751961FD0300CD19AA /* ServicesOverlayController.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = ServicesOverlayController.mm; sourceTree = &quot;&lt;group&gt;&quot;; };
</del><span class="cx">                 51933DEB1965EB24008AC3EA /* MenuUtilities.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MenuUtilities.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 51933DEC1965EB24008AC3EA /* MenuUtilities.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = MenuUtilities.mm; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 51A4D5A816CAC4FF000E615E /* StatisticsRequest.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = StatisticsRequest.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="lines">@@ -5699,7 +5696,6 @@
</span><span class="cx">                                 7CF47FF917275C57008ACB91 /* PageBanner.h */,
</span><span class="cx">                                 2D5C9D0319C81D8F00B3C5C1 /* WebPageOverlay.cpp */,
</span><span class="cx">                                 2D5C9D0419C81D8F00B3C5C1 /* WebPageOverlay.h */,
</span><del>-                                5192D5711961FA2F00CD19AA /* ServicesOverlayController.h */,
</del><span class="cx">                                 2D819B99186275B3001F03D1 /* ViewGestureGeometryCollector.cpp */,
</span><span class="cx">                                 2D819B9A186275B3001F03D1 /* ViewGestureGeometryCollector.h */,
</span><span class="cx">                                 2D819B9B186275B3001F03D1 /* ViewGestureGeometryCollector.messages.in */,
</span><span class="lines">@@ -6468,7 +6464,6 @@
</span><span class="cx">                                 1AB16AE7164B3A8800290D62 /* RemoteLayerTreeContext.mm */,
</span><span class="cx">                                 1AB16ADC1648598400290D62 /* RemoteLayerTreeDrawingArea.h */,
</span><span class="cx">                                 1AB16ADB1648598400290D62 /* RemoteLayerTreeDrawingArea.mm */,
</span><del>-                                5192D5751961FD0300CD19AA /* ServicesOverlayController.mm */,
</del><span class="cx">                                 1AAF263714687C39004A1E8A /* TiledCoreAnimationDrawingArea.h */,
</span><span class="cx">                                 1AAF263614687C39004A1E8A /* TiledCoreAnimationDrawingArea.mm */,
</span><span class="cx">                                 1C8E2DAD1278C5B200BC7BD0 /* WebInspectorUIMac.mm */,
</span><span class="lines">@@ -8729,7 +8724,6 @@
</span><span class="cx">                                 512F589612A8838800629530 /* AuthenticationChallengeProxy.cpp in Sources */,
</span><span class="cx">                                 1AE00D4C182D6EB000087DD7 /* WKBrowsingContextHandle.mm in Sources */,
</span><span class="cx">                                 512F589812A8838800629530 /* AuthenticationDecisionListener.cpp in Sources */,
</span><del>-                                5192D5761961FD0300CD19AA /* ServicesOverlayController.mm in Sources */,
</del><span class="cx">                                 518E8EF816B2091C00E91429 /* AuthenticationManager.cpp in Sources */,
</span><span class="cx">                                 518E8EFB16B2091C00E91429 /* AuthenticationManager.mac.mm in Sources */,
</span><span class="cx">                                 512F58A212A883AD00629530 /* AuthenticationManagerMessageReceiver.cpp in Sources */,
</span></span></pre></div>
<a id="trunkSourceWebKit2WebProcessWebCoreSupportWebChromeClientcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/WebProcess/WebCoreSupport/WebChromeClient.cpp (174523 => 174524)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/WebProcess/WebCoreSupport/WebChromeClient.cpp        2014-10-09 20:51:55 UTC (rev 174523)
+++ trunk/Source/WebKit2/WebProcess/WebCoreSupport/WebChromeClient.cpp        2014-10-09 20:53:02 UTC (rev 174524)
</span><span class="lines">@@ -1074,5 +1074,24 @@
</span><span class="cx"> }
</span><span class="cx"> #endif
</span><span class="cx"> 
</span><ins>+#if ENABLE(TELEPHONE_NUMBER_DETECTION) &amp;&amp; PLATFORM(MAC)
+void WebChromeClient::handleTelephoneNumberClick(const String&amp; number, const WebCore::IntPoint&amp; point)
+{
+    m_page-&gt;handleTelephoneNumberClick(number, point);
+}
+#endif
</ins><span class="cx"> 
</span><ins>+#if ENABLE(SERVICE_CONTROLS)
+void WebChromeClient::handleSelectionServiceClick(WebCore::FrameSelection&amp; selection, const Vector&lt;String&gt;&amp; telephoneNumbers, const WebCore::IntPoint&amp; point)
+{
+    m_page-&gt;handleSelectionServiceClick(selection, telephoneNumbers, point);
+}
+
+bool WebChromeClient::hasRelevantSelectionServices(bool isTextOnly) const
+{
+    return (isTextOnly &amp;&amp; WebProcess::shared().hasSelectionServices()) || WebProcess::shared().hasRichContentServices();
+}
+
+#endif
+
</ins><span class="cx"> } // namespace WebKit
</span></span></pre></div>
<a id="trunkSourceWebKit2WebProcessWebCoreSupportWebChromeClienth"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/WebProcess/WebCoreSupport/WebChromeClient.h (174523 => 174524)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/WebProcess/WebCoreSupport/WebChromeClient.h        2014-10-09 20:51:55 UTC (rev 174523)
+++ trunk/Source/WebKit2/WebProcess/WebCoreSupport/WebChromeClient.h        2014-10-09 20:53:02 UTC (rev 174524)
</span><span class="lines">@@ -305,6 +305,14 @@
</span><span class="cx">     virtual bool unwrapCryptoKey(const Vector&lt;uint8_t&gt;&amp;, Vector&lt;uint8_t&gt;&amp;) const override;
</span><span class="cx"> #endif
</span><span class="cx"> 
</span><ins>+#if ENABLE(TELEPHONE_NUMBER_DETECTION) &amp;&amp; PLATFORM(MAC)
+    virtual void handleTelephoneNumberClick(const String&amp; number, const WebCore::IntPoint&amp;) override;
+#endif
+#if ENABLE(SERVICE_CONTROLS)
+    virtual void handleSelectionServiceClick(WebCore::FrameSelection&amp;, const Vector&lt;String&gt;&amp; telephoneNumbers, const WebCore::IntPoint&amp;) override;
+    virtual bool hasRelevantSelectionServices(bool isTextOnly) const override;
+#endif
+
</ins><span class="cx">     String m_cachedToolTip;
</span><span class="cx">     mutable RefPtr&lt;WebFrame&gt; m_cachedFrameSetLargestFrame;
</span><span class="cx">     mutable bool m_cachedMainFrameHasHorizontalScrollbar;
</span></span></pre></div>
<a id="trunkSourceWebKit2WebProcessWebCoreSupportWebEditorClientcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/WebProcess/WebCoreSupport/WebEditorClient.cpp (174523 => 174524)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/WebProcess/WebCoreSupport/WebEditorClient.cpp        2014-10-09 20:51:55 UTC (rev 174523)
+++ trunk/Source/WebKit2/WebProcess/WebCoreSupport/WebEditorClient.cpp        2014-10-09 20:53:02 UTC (rev 174524)
</span><span class="lines">@@ -27,7 +27,6 @@
</span><span class="cx"> #include &quot;WebEditorClient.h&quot;
</span><span class="cx"> 
</span><span class="cx"> #include &quot;EditorState.h&quot;
</span><del>-#include &quot;ServicesOverlayController.h&quot;
</del><span class="cx"> #include &quot;WebCoreArgumentCoders.h&quot;
</span><span class="cx"> #include &quot;WebFrame.h&quot;
</span><span class="cx"> #include &quot;WebPage.h&quot;
</span><span class="lines">@@ -531,20 +530,4 @@
</span><span class="cx"> #endif
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-#if ENABLE(SERVICE_CONTROLS) || ENABLE(TELEPHONE_NUMBER_DETECTION)
-void WebEditorClient::selectedTelephoneNumberRangesChanged()
-{
-#if PLATFORM(MAC)
-    m_page-&gt;servicesOverlayController().selectedTelephoneNumberRangesChanged();
-#endif
-}
-void WebEditorClient::selectionRectsDidChange(const Vector&lt;LayoutRect&gt;&amp; rects, const Vector&lt;GapRects&gt;&amp; gapRects, bool isTextOnly)
-{
-#if PLATFORM(MAC)
-    if (m_page-&gt;serviceControlsEnabled())
-        m_page-&gt;servicesOverlayController().selectionRectsDidChange(rects, gapRects, isTextOnly);
-#endif
-}
-#endif // ENABLE(SERVICE_CONTROLS) &amp;&amp; ENABLE(TELEPHONE_NUMBER_DETECTION)
-
</del><span class="cx"> } // namespace WebKit
</span></span></pre></div>
<a id="trunkSourceWebKit2WebProcessWebCoreSupportWebEditorClienth"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/WebProcess/WebCoreSupport/WebEditorClient.h (174523 => 174524)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/WebProcess/WebCoreSupport/WebEditorClient.h        2014-10-09 20:51:55 UTC (rev 174523)
+++ trunk/Source/WebKit2/WebProcess/WebCoreSupport/WebEditorClient.h        2014-10-09 20:53:02 UTC (rev 174524)
</span><span class="lines">@@ -168,11 +168,6 @@
</span><span class="cx"> 
</span><span class="cx">     virtual bool supportsGlobalSelection() override;
</span><span class="cx"> 
</span><del>-#if ENABLE(TELEPHONE_NUMBER_DETECTION) || ENABLE(SERVICE_CONTROLS)
-    virtual void selectedTelephoneNumberRangesChanged() override;
-    virtual void selectionRectsDidChange(const Vector&lt;WebCore::LayoutRect&gt;&amp;, const Vector&lt;WebCore::GapRects&gt;&amp;, bool isTextOnly) override;
-#endif
-
</del><span class="cx">     WebPage* m_page;
</span><span class="cx"> };
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceWebKit2WebProcessWebPageServicesOverlayControllerh"></a>
<div class="delfile"><h4>Deleted: trunk/Source/WebKit2/WebProcess/WebPage/ServicesOverlayController.h (174523 => 174524)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/WebProcess/WebPage/ServicesOverlayController.h        2014-10-09 20:51:55 UTC (rev 174523)
+++ trunk/Source/WebKit2/WebProcess/WebPage/ServicesOverlayController.h        2014-10-09 20:53:02 UTC (rev 174524)
</span><span class="lines">@@ -1,167 +0,0 @@
</span><del>-/*
- * Copyright (C) 2014 Apple Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
- * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
- * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
- * THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef ServicesOverlayController_h
-#define ServicesOverlayController_h
-
-#if ENABLE(SERVICE_CONTROLS) || ENABLE(TELEPHONE_NUMBER_DETECTION)
-
-#include &quot;WebFrame.h&quot;
-#include &lt;WebCore/GraphicsLayerClient.h&gt;
-#include &lt;WebCore/PageOverlay.h&gt;
-#include &lt;WebCore/Range.h&gt;
-#include &lt;WebCore/Timer.h&gt;
-#include &lt;wtf/RefCounted.h&gt;
-
-typedef void* DDHighlightRef;
-
-namespace WebCore {
-class LayoutRect;
-struct GapRects;
-}
-
-namespace WebKit {
-
-class WebPage;
-
-class ServicesOverlayController : private WebCore::PageOverlay::Client {
-public:
-    ServicesOverlayController(WebPage&amp;);
-    ~ServicesOverlayController();
-
-    void selectedTelephoneNumberRangesChanged();
-    void selectionRectsDidChange(const Vector&lt;WebCore::LayoutRect&gt;&amp;, const Vector&lt;WebCore::GapRects&gt;&amp;, bool isTextOnly);
-
-private:
-    class Highlight : public RefCounted&lt;Highlight&gt;, private WebCore::GraphicsLayerClient {
-        WTF_MAKE_NONCOPYABLE(Highlight);
-    public:
-        static PassRefPtr&lt;Highlight&gt; createForSelection(ServicesOverlayController&amp;, RetainPtr&lt;DDHighlightRef&gt;, PassRefPtr&lt;WebCore::Range&gt;);
-        static PassRefPtr&lt;Highlight&gt; createForTelephoneNumber(ServicesOverlayController&amp;, RetainPtr&lt;DDHighlightRef&gt;, PassRefPtr&lt;WebCore::Range&gt;);
-        ~Highlight();
-
-        void invalidate();
-
-        DDHighlightRef ddHighlight() const { return m_ddHighlight.get(); }
-        WebCore::Range* range() const { return m_range.get(); }
-        WebCore::GraphicsLayer* layer() const { return m_graphicsLayer.get(); }
-
-        enum class Type {
-            TelephoneNumber,
-            Selection
-        };
-        Type type() const { return m_type; }
-
-        void fadeIn();
-        void fadeOut();
-
-        void setDDHighlight(DDHighlightRef);
-
-    private:
-        explicit Highlight(ServicesOverlayController&amp;, Type, RetainPtr&lt;DDHighlightRef&gt;, PassRefPtr&lt;WebCore::Range&gt;);
-
-        // GraphicsLayerClient
-        virtual void notifyFlushRequired(const WebCore::GraphicsLayer*) override;
-        virtual void paintContents(const WebCore::GraphicsLayer*, WebCore::GraphicsContext&amp;, WebCore::GraphicsLayerPaintingPhase, const WebCore::FloatRect&amp; inClip) override;
-        virtual float deviceScaleFactor() const override;
-
-        void didFinishFadeOutAnimation();
-
-        RetainPtr&lt;DDHighlightRef&gt; m_ddHighlight;
-        RefPtr&lt;WebCore::Range&gt; m_range;
-        std::unique_ptr&lt;WebCore::GraphicsLayer&gt; m_graphicsLayer;
-        Type m_type;
-        ServicesOverlayController* m_controller;
-    };
-
-    // PageOverlay::Client
-    virtual void pageOverlayDestroyed(WebCore::PageOverlay&amp;) override;
-    virtual void willMoveToPage(WebCore::PageOverlay&amp;, WebCore::Page*) override;
-    virtual void didMoveToPage(WebCore::PageOverlay&amp;, WebCore::Page*) override;
-    virtual void drawRect(WebCore::PageOverlay&amp;, WebCore::GraphicsContext&amp;, const WebCore::IntRect&amp; dirtyRect) override;
-    virtual bool mouseEvent(WebCore::PageOverlay&amp;, const WebCore::PlatformMouseEvent&amp;) override;
-    virtual void didScrollFrame(WebCore::PageOverlay&amp;, WebCore::Frame&amp;) override;
-
-    void createOverlayIfNeeded();
-    void handleClick(const WebCore::IntPoint&amp;, Highlight&amp;);
-
-    void drawHighlight(Highlight&amp;, WebCore::GraphicsContext&amp;);
-
-    void replaceHighlightsOfTypePreservingEquivalentHighlights(HashSet&lt;RefPtr&lt;Highlight&gt;&gt;&amp;, Highlight::Type);
-    void removeAllPotentialHighlightsOfType(Highlight::Type);
-    void buildPhoneNumberHighlights();
-    void buildSelectionHighlight();
-    void didRebuildPotentialHighlights();
-
-    void determineActiveHighlight(bool&amp; mouseIsOverButton);
-    void clearActiveHighlight();
-    Highlight* activeHighlight() const { return m_activeHighlight.get(); }
-
-    Highlight* findTelephoneNumberHighlightContainingSelectionHighlight(Highlight&amp;);
-
-    bool hasRelevantSelectionServices();
-
-    bool mouseIsOverHighlight(Highlight&amp;, bool&amp; mouseIsOverButton) const;
-    std::chrono::milliseconds remainingTimeUntilHighlightShouldBeShown(Highlight*) const;
-    void determineActiveHighlightTimerFired(WebCore::Timer&lt;ServicesOverlayController&gt;&amp;);
-
-    static bool highlightsAreEquivalent(const Highlight* a, const Highlight* b);
-
-    Vector&lt;RefPtr&lt;WebCore::Range&gt;&gt; telephoneNumberRangesForFocusedFrame();
-
-    void didCreateHighlight(Highlight*);
-    void willDestroyHighlight(Highlight*);
-    void didFinishFadingOutHighlight(Highlight*);
-
-    WebPage&amp; webPage() const { return m_webPage; }
-
-    WebPage&amp; m_webPage;
-    WebCore::PageOverlay* m_servicesOverlay;
-
-    RefPtr&lt;Highlight&gt; m_activeHighlight;
-    RefPtr&lt;Highlight&gt; m_nextActiveHighlight;
-    HashSet&lt;RefPtr&lt;Highlight&gt;&gt; m_potentialHighlights;
-    HashSet&lt;RefPtr&lt;Highlight&gt;&gt; m_animatingHighlights;
-
-    HashSet&lt;Highlight*&gt; m_highlights;
-
-    // FIXME: These should move onto Highlight.
-    Vector&lt;WebCore::LayoutRect&gt; m_currentSelectionRects;
-    bool m_isTextOnly;
-
-    std::chrono::steady_clock::time_point m_lastSelectionChangeTime;
-    std::chrono::steady_clock::time_point m_nextActiveHighlightChangeTime;
-    std::chrono::steady_clock::time_point m_lastMouseUpTime;
-
-    RefPtr&lt;Highlight&gt; m_currentMouseDownOnButtonHighlight;
-    WebCore::IntPoint m_mousePosition;
-
-    WebCore::Timer&lt;ServicesOverlayController&gt; m_determineActiveHighlightTimer;
-};
-
-} // namespace WebKit
-
-#endif // ENABLE(SERVICE_CONTROLS) &amp;&amp; ENABLE(TELEPHONE_NUMBER_DETECTION)
-#endif // ServicesOverlayController_h
</del></span></pre></div>
<a id="trunkSourceWebKit2WebProcessWebPageWebPagecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/WebProcess/WebPage/WebPage.cpp (174523 => 174524)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/WebProcess/WebPage/WebPage.cpp        2014-10-09 20:51:55 UTC (rev 174523)
+++ trunk/Source/WebKit2/WebProcess/WebPage/WebPage.cpp        2014-10-09 20:53:02 UTC (rev 174524)
</span><span class="lines">@@ -48,7 +48,6 @@
</span><span class="cx"> #include &quot;PluginProxy.h&quot;
</span><span class="cx"> #include &quot;PluginView.h&quot;
</span><span class="cx"> #include &quot;PrintInfo.h&quot;
</span><del>-#include &quot;ServicesOverlayController.h&quot;
</del><span class="cx"> #include &quot;SessionState.h&quot;
</span><span class="cx"> #include &quot;SessionStateConversion.h&quot;
</span><span class="cx"> #include &quot;SessionTracker.h&quot;
</span><span class="lines">@@ -263,9 +262,6 @@
</span><span class="cx">     , m_numberOfPrimarySnapshotDetectionAttempts(0)
</span><span class="cx">     , m_determinePrimarySnapshottedPlugInTimer(RunLoop::main(), this, &amp;WebPage::determinePrimarySnapshottedPlugInTimerFired)
</span><span class="cx"> #endif
</span><del>-#if ENABLE(SERVICE_CONTROLS)
-    , m_serviceControlsEnabled(false)
-#endif
</del><span class="cx">     , m_layerHostingMode(parameters.layerHostingMode)
</span><span class="cx"> #if PLATFORM(COCOA)
</span><span class="cx">     , m_pdfPluginEnabled(false)
</span><span class="lines">@@ -2626,10 +2622,6 @@
</span><span class="cx">     m_pdfPluginEnabled = store.getBoolValueForKey(WebPreferencesKey::pdfPluginEnabledKey());
</span><span class="cx"> #endif
</span><span class="cx"> 
</span><del>-#if ENABLE(SERVICE_CONTROLS)
-    m_serviceControlsEnabled = store.getBoolValueForKey(WebPreferencesKey::serviceControlsEnabledKey());
-#endif
-
</del><span class="cx">     // FIXME: This should be generated from macro expansion for all preferences,
</span><span class="cx">     // but we currently don't match the naming of WebCore exactly so we are
</span><span class="cx">     // handrolling the boolean and integer preferences until that is fixed.
</span><span class="lines">@@ -2845,6 +2837,10 @@
</span><span class="cx">     RuntimeEnabledFeatures::sharedFeatures().setGamepadsEnabled(store.getBoolValueForKey(WebPreferencesKey::gamepadsEnabledKey()));
</span><span class="cx"> #endif
</span><span class="cx"> 
</span><ins>+#if ENABLE(SERVICE_CONTROLS)
+    settings.setServiceControlsEnabled(store.getBoolValueForKey(WebPreferencesKey::serviceControlsEnabledKey()));
+#endif
+
</ins><span class="cx">     if (store.getBoolValueForKey(WebPreferencesKey::pageVisibilityBasedProcessSuppressionEnabledKey()))
</span><span class="cx">         m_processSuppressionDisabledByWebPreference.stop();
</span><span class="cx">     else
</span><span class="lines">@@ -4778,17 +4774,7 @@
</span><span class="cx"> #endif
</span><span class="cx">     return false;
</span><span class="cx"> }
</span><del>-    
-#if ENABLE(SERVICE_CONTROLS) || ENABLE(TELEPHONE_NUMBER_DETECTION)
-ServicesOverlayController&amp; WebPage::servicesOverlayController()
-{
-    if (!m_servicesOverlayController)
-        m_servicesOverlayController = std::make_unique&lt;ServicesOverlayController&gt;(*this);
</del><span class="cx"> 
</span><del>-    return *m_servicesOverlayController;
-}
-#endif
-
</del><span class="cx"> void WebPage::didChangeScrollOffsetForFrame(Frame* frame)
</span><span class="cx"> {
</span><span class="cx">     if (!frame-&gt;isMainFrame())
</span></span></pre></div>
<a id="trunkSourceWebKit2WebProcessWebPageWebPageh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/WebProcess/WebPage/WebPage.h (174523 => 174524)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/WebProcess/WebPage/WebPage.h        2014-10-09 20:51:55 UTC (rev 174523)
+++ trunk/Source/WebKit2/WebProcess/WebPage/WebPage.h        2014-10-09 20:53:02 UTC (rev 174524)
</span><span class="lines">@@ -141,7 +141,6 @@
</span><span class="cx"> class NotificationPermissionRequestManager;
</span><span class="cx"> class PageBanner;
</span><span class="cx"> class PluginView;
</span><del>-class ServicesOverlayController;
</del><span class="cx"> class VisibleContentRectUpdateInfo;
</span><span class="cx"> class WebColorChooser;
</span><span class="cx"> class WebContextMenu;
</span><span class="lines">@@ -828,11 +827,9 @@
</span><span class="cx">     // While this is not ideal, it does not have to be applied to every platform at the moment.
</span><span class="cx">     static bool synchronousMessagesShouldSpinRunLoop();
</span><span class="cx"> 
</span><del>-#if ENABLE(SERVICE_CONTROLS) || ENABLE(TELEPHONE_NUMBER_DETECTION) 
-    ServicesOverlayController&amp; servicesOverlayController();
</del><ins>+#if ENABLE(SERVICE_CONTROLS) || ENABLE(TELEPHONE_NUMBER_DETECTION)
</ins><span class="cx">     void handleTelephoneNumberClick(const String&amp; number, const WebCore::IntPoint&amp;);
</span><span class="cx">     void handleSelectionServiceClick(WebCore::FrameSelection&amp;, const Vector&lt;String&gt;&amp; telephoneNumbers, const WebCore::IntPoint&amp;);
</span><del>-    bool serviceControlsEnabled() const { return m_serviceControlsEnabled; }
</del><span class="cx"> #endif
</span><span class="cx"> 
</span><span class="cx">     void didChangeScrollOffsetForFrame(WebCore::Frame*);
</span><span class="lines">@@ -1091,10 +1088,6 @@
</span><span class="cx">     RunLoop::Timer&lt;WebPage&gt; m_determinePrimarySnapshottedPlugInTimer;
</span><span class="cx"> #endif
</span><span class="cx"> 
</span><del>-#if ENABLE(SERVICE_CONTROLS) || ENABLE(TELEPHONE_NUMBER_DETECTION)
-    bool m_serviceControlsEnabled;
-#endif
-
</del><span class="cx">     // The layer hosting mode.
</span><span class="cx">     LayerHostingMode m_layerHostingMode;
</span><span class="cx"> 
</span><span class="lines">@@ -1269,10 +1262,6 @@
</span><span class="cx"> #if ENABLE(WEBGL)
</span><span class="cx">     WebCore::WebGLLoadPolicy m_systemWebGLPolicy;
</span><span class="cx"> #endif
</span><del>-
-#if ENABLE(SERVICE_CONTROLS) || ENABLE(TELEPHONE_NUMBER_DETECTION)
-    std::unique_ptr&lt;ServicesOverlayController&gt; m_servicesOverlayController;
-#endif
</del><span class="cx"> };
</span><span class="cx"> 
</span><span class="cx"> } // namespace WebKit
</span></span></pre></div>
<a id="trunkSourceWebKit2WebProcessWebPagemacServicesOverlayControllermm"></a>
<div class="delfile"><h4>Deleted: trunk/Source/WebKit2/WebProcess/WebPage/mac/ServicesOverlayController.mm (174523 => 174524)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/WebProcess/WebPage/mac/ServicesOverlayController.mm        2014-10-09 20:51:55 UTC (rev 174523)
+++ trunk/Source/WebKit2/WebProcess/WebPage/mac/ServicesOverlayController.mm        2014-10-09 20:53:02 UTC (rev 174524)
</span><span class="lines">@@ -1,823 +0,0 @@
</span><del>-/*
- * Copyright (C) 2014 Apple Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
- * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
- * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
- * THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#import &quot;config.h&quot;
-#import &quot;ServicesOverlayController.h&quot;
-
-#if ENABLE(SERVICE_CONTROLS) || ENABLE(TELEPHONE_NUMBER_DETECTION) &amp;&amp; PLATFORM(MAC)
-
-#import &quot;Logging.h&quot;
-#import &quot;WebPage.h&quot;
-#import &quot;WebProcess.h&quot;
-#import &lt;QuartzCore/QuartzCore.h&gt;
-#import &lt;WebCore/Document.h&gt;
-#import &lt;WebCore/EventHandler.h&gt;
-#import &lt;WebCore/FloatQuad.h&gt;
-#import &lt;WebCore/FocusController.h&gt;
-#import &lt;WebCore/FrameView.h&gt;
-#import &lt;WebCore/GapRects.h&gt;
-#import &lt;WebCore/GraphicsContext.h&gt;
-#import &lt;WebCore/GraphicsLayer.h&gt;
-#import &lt;WebCore/GraphicsLayerCA.h&gt;
-#import &lt;WebCore/MainFrame.h&gt;
-#import &lt;WebCore/PageOverlayController.h&gt;
-#import &lt;WebCore/PlatformCAAnimationMac.h&gt;
-#import &lt;WebCore/SoftLinking.h&gt;
-
-#if __has_include(&lt;DataDetectors/DDHighlightDrawing.h&gt;)
-#import &lt;DataDetectors/DDHighlightDrawing.h&gt;
-#else
-typedef void* DDHighlightRef;
-#endif
-
-#if __has_include(&lt;DataDetectors/DDHighlightDrawing_Private.h&gt;)
-#import &lt;DataDetectors/DDHighlightDrawing_Private.h&gt;
-#endif
-
-const float highlightFadeAnimationDuration = 0.3;
-
-typedef NSUInteger DDHighlightStyle;
-static const DDHighlightStyle DDHighlightNoOutlineWithArrow = (1 &lt;&lt; 16);
-static const DDHighlightStyle DDHighlightOutlineWithArrow = (1 &lt;&lt; 16) | 1;
-
-SOFT_LINK_PRIVATE_FRAMEWORK_OPTIONAL(DataDetectors)
-SOFT_LINK(DataDetectors, DDHighlightCreateWithRectsInVisibleRectWithStyleAndDirection, DDHighlightRef, (CFAllocatorRef allocator, CGRect* rects, CFIndex count, CGRect globalVisibleRect, DDHighlightStyle style, Boolean withArrow, NSWritingDirection writingDirection, Boolean endsWithEOL, Boolean flipped), (allocator, rects, count, globalVisibleRect, style, withArrow, writingDirection, endsWithEOL, flipped))
-SOFT_LINK(DataDetectors, DDHighlightGetLayerWithContext, CGLayerRef, (DDHighlightRef highlight, CGContextRef context), (highlight, context))
-SOFT_LINK(DataDetectors, DDHighlightGetBoundingRect, CGRect, (DDHighlightRef highlight), (highlight))
-SOFT_LINK(DataDetectors, DDHighlightPointIsOnHighlight, Boolean, (DDHighlightRef highlight, CGPoint point, Boolean* onButton), (highlight, point, onButton))
-
-using namespace WebCore;
-
-namespace WebKit {
-
-PassRefPtr&lt;ServicesOverlayController::Highlight&gt; ServicesOverlayController::Highlight::createForSelection(ServicesOverlayController&amp; controller, RetainPtr&lt;DDHighlightRef&gt; ddHighlight, PassRefPtr&lt;Range&gt; range)
-{
-    return adoptRef(new Highlight(controller, Type::Selection, ddHighlight, range));
-}
-
-PassRefPtr&lt;ServicesOverlayController::Highlight&gt; ServicesOverlayController::Highlight::createForTelephoneNumber(ServicesOverlayController&amp; controller, RetainPtr&lt;DDHighlightRef&gt; ddHighlight, PassRefPtr&lt;Range&gt; range)
-{
-    return adoptRef(new Highlight(controller, Type::TelephoneNumber, ddHighlight, range));
-}
-
-ServicesOverlayController::Highlight::Highlight(ServicesOverlayController&amp; controller, Type type, RetainPtr&lt;DDHighlightRef&gt; ddHighlight, PassRefPtr&lt;WebCore::Range&gt; range)
-    : m_range(range)
-    , m_type(type)
-    , m_controller(&amp;controller)
-{
-    ASSERT(ddHighlight);
-    ASSERT(m_range);
-
-    DrawingArea* drawingArea = controller.webPage().drawingArea();
-    m_graphicsLayer = GraphicsLayer::create(drawingArea ? drawingArea-&gt;graphicsLayerFactory() : nullptr, *this);
-    m_graphicsLayer-&gt;setDrawsContent(true);
-
-    setDDHighlight(ddHighlight.get());
-
-    // Set directly on the PlatformCALayer so that when we leave the 'from' value implicit
-    // in our animations, we get the right initial value regardless of flush timing.
-    toGraphicsLayerCA(layer())-&gt;platformCALayer()-&gt;setOpacity(0);
-
-    controller.didCreateHighlight(this);
-}
-
-ServicesOverlayController::Highlight::~Highlight()
-{
-    if (m_controller)
-        m_controller-&gt;willDestroyHighlight(this);
-}
-
-void ServicesOverlayController::Highlight::setDDHighlight(DDHighlightRef highlight)
-{
-    if (!m_controller)
-        return;
-
-    m_ddHighlight = highlight;
-
-    if (!m_ddHighlight)
-        return;
-
-    CGRect highlightBoundingRect = DDHighlightGetBoundingRect(m_ddHighlight.get());
-    m_graphicsLayer-&gt;setPosition(FloatPoint(highlightBoundingRect.origin));
-    m_graphicsLayer-&gt;setSize(FloatSize(highlightBoundingRect.size));
-
-    m_graphicsLayer-&gt;setNeedsDisplay();
-}
-
-void ServicesOverlayController::Highlight::invalidate()
-{
-    layer()-&gt;removeFromParent();
-    m_controller = nullptr;
-}
-
-void ServicesOverlayController::Highlight::notifyFlushRequired(const GraphicsLayer*)
-{
-    if (!m_controller)
-        return;
-
-    if (DrawingArea* drawingArea = m_controller-&gt;webPage().drawingArea())
-        drawingArea-&gt;scheduleCompositingLayerFlush();
-}
-
-void ServicesOverlayController::Highlight::paintContents(const GraphicsLayer*, GraphicsContext&amp; graphicsContext, GraphicsLayerPaintingPhase, const FloatRect&amp; inClip)
-{
-    CGContextRef cgContext = graphicsContext.platformContext();
-
-    CGLayerRef highlightLayer = DDHighlightGetLayerWithContext(ddHighlight(), cgContext);
-    CGRect highlightBoundingRect = DDHighlightGetBoundingRect(ddHighlight());
-    highlightBoundingRect.origin = CGPointZero;
-
-    CGContextDrawLayerInRect(cgContext, highlightBoundingRect, highlightLayer);
-}
-
-float ServicesOverlayController::Highlight::deviceScaleFactor() const
-{
-    if (!m_controller)
-        return 1;
-
-    return m_controller-&gt;webPage().deviceScaleFactor();
-}
-
-void ServicesOverlayController::Highlight::fadeIn()
-{
-    RetainPtr&lt;CABasicAnimation&gt; animation = [CABasicAnimation animationWithKeyPath:@&quot;opacity&quot;];
-    [animation setDuration:highlightFadeAnimationDuration];
-    [animation setFillMode:kCAFillModeForwards];
-    [animation setRemovedOnCompletion:false];
-    [animation setToValue:@1];
-
-    RefPtr&lt;PlatformCAAnimation&gt; platformAnimation = PlatformCAAnimationMac::create(animation.get());
-    toGraphicsLayerCA(layer())-&gt;platformCALayer()-&gt;addAnimationForKey(&quot;FadeHighlightIn&quot;, platformAnimation.get());
-}
-
-void ServicesOverlayController::Highlight::fadeOut()
-{
-    RetainPtr&lt;CABasicAnimation&gt; animation = [CABasicAnimation animationWithKeyPath:@&quot;opacity&quot;];
-    [animation setDuration:highlightFadeAnimationDuration];
-    [animation setFillMode:kCAFillModeForwards];
-    [animation setRemovedOnCompletion:false];
-    [animation setToValue:@0];
-
-    RefPtr&lt;Highlight&gt; retainedSelf = this;
-    [CATransaction begin];
-    [CATransaction setCompletionBlock:[retainedSelf] () {
-        retainedSelf-&gt;didFinishFadeOutAnimation();
-    }];
-
-    RefPtr&lt;PlatformCAAnimation&gt; platformAnimation = PlatformCAAnimationMac::create(animation.get());
-    toGraphicsLayerCA(layer())-&gt;platformCALayer()-&gt;addAnimationForKey(&quot;FadeHighlightOut&quot;, platformAnimation.get());
-    [CATransaction commit];
-}
-
-void ServicesOverlayController::Highlight::didFinishFadeOutAnimation()
-{
-    if (!m_controller)
-        return;
-
-    if (m_controller-&gt;activeHighlight() == this)
-        return;
-
-    layer()-&gt;removeFromParent();
-}
-
-static IntRect textQuadsToBoundingRectForRange(Range&amp; range)
-{
-    Vector&lt;FloatQuad&gt; textQuads;
-    range.textQuads(textQuads);
-    FloatRect boundingRect;
-    for (auto&amp; quad : textQuads)
-        boundingRect.unite(quad.boundingBox());
-    return enclosingIntRect(boundingRect);
-}
-
-ServicesOverlayController::ServicesOverlayController(WebPage&amp; webPage)
-    : m_webPage(webPage)
-    , m_servicesOverlay(nullptr)
-    , m_isTextOnly(false)
-    , m_determineActiveHighlightTimer(this, &amp;ServicesOverlayController::determineActiveHighlightTimerFired)
-{
-}
-
-ServicesOverlayController::~ServicesOverlayController()
-{
-    for (auto&amp; highlight : m_highlights)
-        highlight-&gt;invalidate();
-}
-
-void ServicesOverlayController::pageOverlayDestroyed(PageOverlay&amp;)
-{
-    // Before the overlay is destroyed, it should have moved out of the WebPage,
-    // at which point we already cleared our back pointer.
-    ASSERT(!m_servicesOverlay);
-}
-
-void ServicesOverlayController::willMoveToPage(PageOverlay&amp;, Page* page)
-{
-    if (page)
-        return;
-
-    ASSERT(m_servicesOverlay);
-    m_servicesOverlay = nullptr;
-}
-
-void ServicesOverlayController::didMoveToPage(PageOverlay&amp;, Page*)
-{
-}
-
-static const uint8_t AlignmentNone = 0;
-static const uint8_t AlignmentLeft = 1 &lt;&lt; 0;
-static const uint8_t AlignmentRight = 1 &lt;&lt; 1;
-
-static void expandForGap(Vector&lt;LayoutRect&gt;&amp; rects, uint8_t* alignments, const GapRects&amp; gap)
-{
-    if (!gap.left().isEmpty()) {
-        LayoutUnit leftEdge = gap.left().x();
-        for (unsigned i = 0; i &lt; rects.size(); ++i) {
-            if (alignments[i] &amp; AlignmentLeft)
-                rects[i].shiftXEdgeTo(leftEdge);
-        }
-    }
-
-    if (!gap.right().isEmpty()) {
-        LayoutUnit rightEdge = gap.right().maxX();
-        for (unsigned i = 0; i &lt; rects.size(); ++i) {
-            if (alignments[i] &amp; AlignmentRight)
-                rects[i].shiftMaxXEdgeTo(rightEdge);
-        }
-    }
-}
-
-static inline void stitchRects(Vector&lt;LayoutRect&gt;&amp; rects)
-{
-    if (rects.size() &lt;= 1)
-        return;
-    
-    Vector&lt;LayoutRect&gt; newRects;
-    
-    // FIXME: Need to support vertical layout.
-    // First stitch together all the rects on the first line of the selection.
-    size_t indexFromStart = 0;
-    LayoutUnit firstTop = rects[indexFromStart].y();
-    LayoutRect&amp; currentRect = rects[indexFromStart];
-    while (indexFromStart &lt; rects.size() &amp;&amp; rects[indexFromStart].y() == firstTop)
-        currentRect.unite(rects[indexFromStart++]);
-    
-    newRects.append(currentRect);
-    if (indexFromStart == rects.size()) {
-        // All the rects are on one line. There is nothing else to do.
-        rects.swap(newRects);
-        return;
-    }
-    
-    // Next stitch together all the rects on the last line of the selection.
-    size_t indexFromEnd = rects.size() - 1;
-    LayoutUnit lastTop = rects[indexFromEnd].y();
-    LayoutRect lastRect = rects[indexFromEnd];
-    while (indexFromEnd &gt;= indexFromStart &amp;&amp; rects[indexFromEnd].y() == lastTop)
-        lastRect.unite(rects[indexFromEnd--]);
-    
-    // indexFromStart is the index of the first rectangle on the second line.
-    // indexFromEnd is the index of the last rectangle on the second to the last line.
-    // if they are equal, there is one additional rectangle for the line in the middle.
-    if (indexFromEnd == indexFromStart)
-        newRects.append(rects[indexFromStart]);
-    
-    if (indexFromEnd &lt;= indexFromStart) {
-        // There are no more rects to stitch. Just append the last line.
-        newRects.append(lastRect);
-        rects.swap(newRects);
-        return;
-    }
-    
-    // Stitch together all the rects after the first line until the second to the last included.
-    currentRect = rects[indexFromStart];
-    while (indexFromStart != indexFromEnd)
-        currentRect.unite(rects[++indexFromStart]);
-    
-    newRects.append(currentRect);
-    newRects.append(lastRect);
-
-    rects.swap(newRects);
-}
-
-static void compactRectsWithGapRects(Vector&lt;LayoutRect&gt;&amp; rects, const Vector&lt;GapRects&gt;&amp; gapRects)
-{
-    stitchRects(rects);
-    
-    // FIXME: The following alignments are correct for LTR text.
-    // We should also account for RTL.
-    uint8_t alignments[3];
-    if (rects.size() == 1) {
-        alignments[0] = AlignmentLeft | AlignmentRight;
-        alignments[1] = AlignmentNone;
-        alignments[2] = AlignmentNone;
-    } else if (rects.size() == 2) {
-        alignments[0] = AlignmentRight;
-        alignments[1] = AlignmentLeft;
-        alignments[2] = AlignmentNone;
-    } else {
-        alignments[0] = AlignmentRight;
-        alignments[1] = AlignmentLeft | AlignmentRight;
-        alignments[2] = AlignmentLeft;
-    }
-
-    // Account for each GapRects by extending the edge of certain LayoutRects to meet the gap.
-    for (auto&amp; gap : gapRects)
-        expandForGap(rects, alignments, gap);
-
-    // If we have 3 rects we might need one final GapRects to align the edges.
-    if (rects.size() == 3) {
-        LayoutRect left;
-        LayoutRect right;
-        for (unsigned i = 0; i &lt; 3; ++i) {
-            if (alignments[i] &amp; AlignmentLeft) {
-                if (left.isEmpty())
-                    left = rects[i];
-                else if (rects[i].x() &lt; left.x())
-                    left = rects[i];
-            }
-            if (alignments[i] &amp; AlignmentRight) {
-                if (right.isEmpty())
-                    right = rects[i];
-                else if ((rects[i].x() + rects[i].width()) &gt; (right.x() + right.width()))
-                    right = rects[i];
-            }
-        }
-
-        if (!left.isEmpty() || !right.isEmpty()) {
-            GapRects gap;
-            gap.uniteLeft(left);
-            gap.uniteRight(right);
-            expandForGap(rects, alignments, gap);
-        }
-    }
-}
-
-void ServicesOverlayController::selectionRectsDidChange(const Vector&lt;LayoutRect&gt;&amp; rects, const Vector&lt;GapRects&gt;&amp; gapRects, bool isTextOnly)
-{
-#if PLATFORM(MAC) &amp;&amp; __MAC_OS_X_VERSION_MIN_REQUIRED &gt; 1090
-    m_currentSelectionRects = rects;
-    m_isTextOnly = isTextOnly;
-
-    m_lastSelectionChangeTime = std::chrono::steady_clock::now();
-
-    compactRectsWithGapRects(m_currentSelectionRects, gapRects);
-
-    // DataDetectors needs these reversed in order to place the arrow in the right location.
-    m_currentSelectionRects.reverse();
-
-    LOG(Services, &quot;ServicesOverlayController - Selection rects changed - Now have %lu\n&quot;, rects.size());
-
-    buildSelectionHighlight();
-#else
-    UNUSED_PARAM(rects);
-    UNUSED_PARAM(gapRects);
-    UNUSED_PARAM(isTextOnly);
-#endif
-}
-
-void ServicesOverlayController::selectedTelephoneNumberRangesChanged()
-{
-#if PLATFORM(MAC) &amp;&amp; __MAC_OS_X_VERSION_MIN_REQUIRED &gt; 1090
-    LOG(Services, &quot;ServicesOverlayController - Telephone number ranges changed\n&quot;);
-    buildPhoneNumberHighlights();
-#endif
-}
-
-bool ServicesOverlayController::mouseIsOverHighlight(Highlight&amp; highlight, bool&amp; mouseIsOverButton) const
-{
-    Boolean onButton;
-    bool hovered = DDHighlightPointIsOnHighlight(highlight.ddHighlight(), (CGPoint)m_mousePosition, &amp;onButton);
-    mouseIsOverButton = onButton;
-    return hovered;
-}
-
-std::chrono::milliseconds ServicesOverlayController::remainingTimeUntilHighlightShouldBeShown(Highlight* highlight) const
-{
-    if (!highlight)
-        return std::chrono::milliseconds::zero();
-
-    auto minimumTimeUntilHighlightShouldBeShown = 200_ms;
-    if (m_webPage.corePage()-&gt;focusController().focusedOrMainFrame().selection().selection().isContentEditable())
-        minimumTimeUntilHighlightShouldBeShown = 1000_ms;
-
-    bool mousePressed = false;
-    if (Frame* mainFrame = m_webPage.mainFrame())
-        mousePressed = mainFrame-&gt;eventHandler().mousePressed();
-
-    // Highlight hysteresis is only for selection services, because telephone number highlights are already much more stable
-    // by virtue of being expanded to include the entire telephone number. However, we will still avoid highlighting
-    // telephone numbers while the mouse is down.
-    if (highlight-&gt;type() == Highlight::Type::TelephoneNumber)
-        return mousePressed ? minimumTimeUntilHighlightShouldBeShown : 0_ms;
-
-    auto now = std::chrono::steady_clock::now();
-    auto timeSinceLastSelectionChange = now - m_lastSelectionChangeTime;
-    auto timeSinceHighlightBecameActive = now - m_nextActiveHighlightChangeTime;
-    auto timeSinceLastMouseUp = mousePressed ? 0_ms : now - m_lastMouseUpTime;
-
-    auto remainingDelay = minimumTimeUntilHighlightShouldBeShown - std::min(std::min(timeSinceLastSelectionChange, timeSinceHighlightBecameActive), timeSinceLastMouseUp);
-    return std::chrono::duration_cast&lt;std::chrono::milliseconds&gt;(remainingDelay);
-}
-
-void ServicesOverlayController::determineActiveHighlightTimerFired(Timer&lt;ServicesOverlayController&gt;&amp;)
-{
-    bool mouseIsOverButton;
-    determineActiveHighlight(mouseIsOverButton);
-}
-
-void ServicesOverlayController::drawRect(PageOverlay&amp; overlay, GraphicsContext&amp; graphicsContext, const IntRect&amp; dirtyRect)
-{
-}
-
-void ServicesOverlayController::clearActiveHighlight()
-{
-    if (!m_activeHighlight)
-        return;
-
-    if (m_currentMouseDownOnButtonHighlight == m_activeHighlight)
-        m_currentMouseDownOnButtonHighlight = nullptr;
-    m_activeHighlight = nullptr;
-}
-
-void ServicesOverlayController::removeAllPotentialHighlightsOfType(Highlight::Type type)
-{
-    Vector&lt;RefPtr&lt;Highlight&gt;&gt; highlightsToRemove;
-    for (auto&amp; highlight : m_potentialHighlights) {
-        if (highlight-&gt;type() == type)
-            highlightsToRemove.append(highlight);
-    }
-
-    while (!highlightsToRemove.isEmpty())
-        m_potentialHighlights.remove(highlightsToRemove.takeLast());
-}
-
-void ServicesOverlayController::buildPhoneNumberHighlights()
-{
-    if (!DataDetectorsLibrary())
-        return;
-
-    HashSet&lt;RefPtr&lt;Highlight&gt;&gt; newPotentialHighlights;
-
-    Frame* mainFrame = m_webPage.mainFrame();
-    FrameView&amp; mainFrameView = *mainFrame-&gt;view();
-
-    for (Frame* frame = mainFrame; frame; frame = frame-&gt;tree().traverseNext()) {
-        auto&amp; ranges = frame-&gt;editor().detectedTelephoneNumberRanges();
-        for (auto&amp; range : ranges) {
-            // FIXME: This will choke if the range wraps around the edge of the view.
-            // What should we do in that case?
-            IntRect rect = textQuadsToBoundingRectForRange(*range);
-
-            // Convert to the main document's coordinate space.
-            // FIXME: It's a little crazy to call contentsToWindow and then windowToContents in order to get the right coordinate space.
-            // We should consider adding conversion functions to ScrollView for contentsToDocument(). Right now, contentsToRootView() is
-            // not equivalent to what we need when you have a topContentInset or a header banner.
-            FrameView* viewForRange = range-&gt;ownerDocument().view();
-            if (!viewForRange)
-                continue;
-            rect.setLocation(mainFrameView.windowToContents(viewForRange-&gt;contentsToWindow(rect.location())));
-
-            CGRect cgRect = rect;
-            RetainPtr&lt;DDHighlightRef&gt; ddHighlight = adoptCF(DDHighlightCreateWithRectsInVisibleRectWithStyleAndDirection(nullptr, &amp;cgRect, 1, mainFrameView.visibleContentRect(), DDHighlightOutlineWithArrow, YES, NSWritingDirectionNatural, NO, YES));
-
-            newPotentialHighlights.add(Highlight::createForTelephoneNumber(*this, ddHighlight, range));
-        }
-    }
-
-    replaceHighlightsOfTypePreservingEquivalentHighlights(newPotentialHighlights, Highlight::Type::TelephoneNumber);
-
-    didRebuildPotentialHighlights();
-}
-
-void ServicesOverlayController::buildSelectionHighlight()
-{
-    if (!DataDetectorsLibrary())
-        return;
-
-    HashSet&lt;RefPtr&lt;Highlight&gt;&gt; newPotentialHighlights;
-
-    Vector&lt;CGRect&gt; cgRects;
-    cgRects.reserveCapacity(m_currentSelectionRects.size());
-
-    RefPtr&lt;Range&gt; selectionRange = m_webPage.corePage()-&gt;selection().firstRange();
-    if (selectionRange) {
-        Frame* mainFrame = m_webPage.mainFrame();
-        FrameView&amp; mainFrameView = *mainFrame-&gt;view();
-        FrameView* viewForRange = selectionRange-&gt;ownerDocument().view();
-
-        for (auto&amp; rect : m_currentSelectionRects) {
-            IntRect currentRect = snappedIntRect(rect);
-            currentRect.setLocation(mainFrameView.windowToContents(viewForRange-&gt;contentsToWindow(currentRect.location())));
-            cgRects.append((CGRect)currentRect);
-        }
-
-        if (!cgRects.isEmpty()) {
-            CGRect visibleRect = m_webPage.corePage()-&gt;mainFrame().view()-&gt;visibleContentRect();
-            RetainPtr&lt;DDHighlightRef&gt; ddHighlight = adoptCF(DDHighlightCreateWithRectsInVisibleRectWithStyleAndDirection(nullptr, cgRects.begin(), cgRects.size(), visibleRect, DDHighlightNoOutlineWithArrow, YES, NSWritingDirectionNatural, NO, YES));
-            
-            newPotentialHighlights.add(Highlight::createForSelection(*this, ddHighlight, selectionRange));
-        }
-    }
-
-    replaceHighlightsOfTypePreservingEquivalentHighlights(newPotentialHighlights, Highlight::Type::Selection);
-
-    didRebuildPotentialHighlights();
-}
-
-void ServicesOverlayController::replaceHighlightsOfTypePreservingEquivalentHighlights(HashSet&lt;RefPtr&lt;Highlight&gt;&gt;&amp; newPotentialHighlights, Highlight::Type type)
-{
-    // If any old Highlights are equivalent (by Range) to a new Highlight, reuse the old
-    // one so that any metadata is retained.
-    HashSet&lt;RefPtr&lt;Highlight&gt;&gt; reusedPotentialHighlights;
-
-    for (auto&amp; oldHighlight : m_potentialHighlights) {
-        if (oldHighlight-&gt;type() != type)
-            continue;
-
-        for (auto&amp; newHighlight : newPotentialHighlights) {
-            if (highlightsAreEquivalent(oldHighlight.get(), newHighlight.get())) {
-                oldHighlight-&gt;setDDHighlight(newHighlight-&gt;ddHighlight());
-
-                reusedPotentialHighlights.add(oldHighlight);
-                newPotentialHighlights.remove(newHighlight);
-
-                break;
-            }
-        }
-    }
-
-    removeAllPotentialHighlightsOfType(type);
-
-    m_potentialHighlights.add(newPotentialHighlights.begin(), newPotentialHighlights.end());
-    m_potentialHighlights.add(reusedPotentialHighlights.begin(), reusedPotentialHighlights.end());
-}
-
-bool ServicesOverlayController::hasRelevantSelectionServices()
-{
-    return (m_isTextOnly &amp;&amp; WebProcess::shared().hasSelectionServices()) || WebProcess::shared().hasRichContentServices();
-}
-
-void ServicesOverlayController::didRebuildPotentialHighlights()
-{
-    if (m_potentialHighlights.isEmpty()) {
-        if (m_servicesOverlay)
-            m_webPage.mainFrame()-&gt;pageOverlayController().uninstallPageOverlay(m_servicesOverlay, PageOverlay::FadeMode::DoNotFade);
-        return;
-    }
-
-    if (telephoneNumberRangesForFocusedFrame().isEmpty() &amp;&amp; !hasRelevantSelectionServices())
-        return;
-
-    createOverlayIfNeeded();
-
-    bool mouseIsOverButton;
-    determineActiveHighlight(mouseIsOverButton);
-}
-
-void ServicesOverlayController::createOverlayIfNeeded()
-{
-    if (m_servicesOverlay)
-        return;
-
-    RefPtr&lt;PageOverlay&gt; overlay = PageOverlay::create(*this, PageOverlay::OverlayType::Document);
-    m_servicesOverlay = overlay.get();
-    m_webPage.mainFrame()-&gt;pageOverlayController().installPageOverlay(overlay.release(), PageOverlay::FadeMode::DoNotFade);
-}
-
-Vector&lt;RefPtr&lt;Range&gt;&gt; ServicesOverlayController::telephoneNumberRangesForFocusedFrame()
-{
-    Page* page = m_webPage.corePage();
-    if (!page)
-        return Vector&lt;RefPtr&lt;Range&gt;&gt;();
-
-    return page-&gt;focusController().focusedOrMainFrame().editor().detectedTelephoneNumberRanges();
-}
-
-bool ServicesOverlayController::highlightsAreEquivalent(const Highlight* a, const Highlight* b)
-{
-    if (a == b)
-        return true;
-
-    if (!a || !b)
-        return false;
-
-    if (a-&gt;type() == b-&gt;type() &amp;&amp; areRangesEqual(a-&gt;range(), b-&gt;range()))
-        return true;
-
-    return false;
-}
-
-ServicesOverlayController::Highlight* ServicesOverlayController::findTelephoneNumberHighlightContainingSelectionHighlight(Highlight&amp; selectionHighlight)
-{
-    if (selectionHighlight.type() != Highlight::Type::Selection)
-        return nullptr;
-
-    const VisibleSelection&amp; selection = m_webPage.corePage()-&gt;selection();
-    if (!selection.isRange())
-        return nullptr;
-
-    RefPtr&lt;Range&gt; activeSelectionRange = selection.toNormalizedRange();
-    if (!activeSelectionRange)
-        return nullptr;
-
-    for (auto&amp; highlight : m_potentialHighlights) {
-        if (highlight-&gt;type() != Highlight::Type::TelephoneNumber)
-            continue;
-
-        if (highlight-&gt;range()-&gt;contains(*activeSelectionRange))
-            return highlight.get();
-    }
-
-    return nullptr;
-}
-
-void ServicesOverlayController::determineActiveHighlight(bool&amp; mouseIsOverActiveHighlightButton)
-{
-    mouseIsOverActiveHighlightButton = false;
-
-    RefPtr&lt;Highlight&gt; newActiveHighlight;
-
-    for (auto&amp; highlight : m_potentialHighlights) {
-        if (highlight-&gt;type() == Highlight::Type::Selection) {
-            // If we've already found a new active highlight, and it's
-            // a telephone number highlight, prefer that over this selection highlight.
-            if (newActiveHighlight &amp;&amp; newActiveHighlight-&gt;type() == Highlight::Type::TelephoneNumber)
-                continue;
-
-            // If this highlight has no compatible services, it can't be active.
-            if (!hasRelevantSelectionServices())
-                continue;
-        }
-
-        // If this highlight isn't hovered, it can't be active.
-        bool mouseIsOverButton;
-        if (!mouseIsOverHighlight(*highlight, mouseIsOverButton))
-            continue;
-
-        newActiveHighlight = highlight;
-        mouseIsOverActiveHighlightButton = mouseIsOverButton;
-    }
-
-    // If our new active highlight is a selection highlight that is completely contained
-    // by one of the phone number highlights, we'll make the phone number highlight active even if it's not hovered.
-    if (newActiveHighlight &amp;&amp; newActiveHighlight-&gt;type() == Highlight::Type::Selection) {
-        if (Highlight* containedTelephoneNumberHighlight = findTelephoneNumberHighlightContainingSelectionHighlight(*newActiveHighlight)) {
-            newActiveHighlight = containedTelephoneNumberHighlight;
-
-            // We will always initially choose the telephone number highlight over the selection highlight if the
-            // mouse is over the telephone number highlight's button, so we know that it's not hovered if we got here.
-            mouseIsOverActiveHighlightButton = false;
-        }
-    }
-
-    if (!this-&gt;highlightsAreEquivalent(m_activeHighlight.get(), newActiveHighlight.get())) {
-        // When transitioning to a new highlight, we might end up in determineActiveHighlight multiple times
-        // before the new highlight actually becomes active. Keep track of the last next-but-not-yet-active
-        // highlight, and only reset the active highlight hysteresis when that changes.
-        if (m_nextActiveHighlight != newActiveHighlight) {
-            m_nextActiveHighlight = newActiveHighlight;
-            m_nextActiveHighlightChangeTime = std::chrono::steady_clock::now();
-        }
-
-        m_currentMouseDownOnButtonHighlight = nullptr;
-
-        if (m_activeHighlight) {
-            m_activeHighlight-&gt;fadeOut();
-            m_activeHighlight = nullptr;
-        }
-
-        auto remainingTimeUntilHighlightShouldBeShown = this-&gt;remainingTimeUntilHighlightShouldBeShown(newActiveHighlight.get());
-        if (remainingTimeUntilHighlightShouldBeShown &gt; std::chrono::steady_clock::duration::zero()) {
-            m_determineActiveHighlightTimer.startOneShot(remainingTimeUntilHighlightShouldBeShown);
-            return;
-        }
-
-        m_activeHighlight = m_nextActiveHighlight.release();
-
-        if (m_activeHighlight) {
-            m_servicesOverlay-&gt;layer().addChild(m_activeHighlight-&gt;layer());
-            m_activeHighlight-&gt;fadeIn();
-        }
-    }
-}
-
-bool ServicesOverlayController::mouseEvent(PageOverlay&amp;, const PlatformMouseEvent&amp; event)
-{
-    m_mousePosition = m_webPage.corePage()-&gt;mainFrame().view()-&gt;rootViewToContents(event.position());
-
-    bool mouseIsOverActiveHighlightButton = false;
-    determineActiveHighlight(mouseIsOverActiveHighlightButton);
-
-    // Cancel the potential click if any button other than the left button changes state, and ignore the event.
-    if (event.button() != MouseButton::LeftButton) {
-        m_currentMouseDownOnButtonHighlight = nullptr;
-        return false;
-    }
-
-    // If the mouse lifted while still over the highlight button that it went down on, then that is a click.
-    if (event.type() == PlatformEvent::MouseReleased) {
-        RefPtr&lt;Highlight&gt; mouseDownHighlight = m_currentMouseDownOnButtonHighlight;
-        m_currentMouseDownOnButtonHighlight = nullptr;
-
-        m_lastMouseUpTime = std::chrono::steady_clock::now();
-
-        if (mouseIsOverActiveHighlightButton &amp;&amp; mouseDownHighlight) {
-            handleClick(m_mousePosition, *mouseDownHighlight);
-            return true;
-        }
-        
-        return false;
-    }
-
-    // If the mouse moved outside of the button tracking a potential click, stop tracking the click.
-    if (event.type() == PlatformEvent::MouseMoved) {
-        if (m_currentMouseDownOnButtonHighlight &amp;&amp; mouseIsOverActiveHighlightButton)
-            return true;
-
-        m_currentMouseDownOnButtonHighlight = nullptr;
-        return false;
-    }
-
-    // If the mouse went down over the active highlight's button, track this as a potential click.
-    if (event.type() == PlatformEvent::MousePressed) {
-        if (m_activeHighlight &amp;&amp; mouseIsOverActiveHighlightButton) {
-            m_currentMouseDownOnButtonHighlight = m_activeHighlight;
-            return true;
-        }
-
-        return false;
-    }
-
-    return false;
-}
-
-void ServicesOverlayController::didScrollFrame(PageOverlay&amp;, Frame&amp; frame)
-{
-    if (frame.isMainFrame())
-        return;
-
-    buildPhoneNumberHighlights();
-    buildSelectionHighlight();
-
-    bool mouseIsOverActiveHighlightButton;
-    determineActiveHighlight(mouseIsOverActiveHighlightButton);
-}
-
-void ServicesOverlayController::handleClick(const IntPoint&amp; clickPoint, Highlight&amp; highlight)
-{
-    FrameView* frameView = m_webPage.mainFrameView();
-    if (!frameView)
-        return;
-
-    IntPoint windowPoint = frameView-&gt;contentsToWindow(clickPoint);
-
-    if (highlight.type() == Highlight::Type::Selection) {
-        auto telephoneNumberRanges = telephoneNumberRangesForFocusedFrame();
-        Vector&lt;String&gt; selectedTelephoneNumbers;
-        selectedTelephoneNumbers.reserveCapacity(telephoneNumberRanges.size());
-        for (auto&amp; range : telephoneNumberRanges)
-            selectedTelephoneNumbers.append(range-&gt;text());
-
-        m_webPage.handleSelectionServiceClick(m_webPage.corePage()-&gt;focusController().focusedOrMainFrame().selection(), selectedTelephoneNumbers, windowPoint);
-    } else if (highlight.type() == Highlight::Type::TelephoneNumber)
-        m_webPage.handleTelephoneNumberClick(highlight.range()-&gt;text(), windowPoint);
-}
-
-void ServicesOverlayController::didCreateHighlight(Highlight* highlight)
-{
-    ASSERT(!m_highlights.contains(highlight));
-    m_highlights.add(highlight);
-}
-
-void ServicesOverlayController::willDestroyHighlight(Highlight* highlight)
-{
-    ASSERT(m_highlights.contains(highlight));
-    m_highlights.remove(highlight);
-}
-
-} // namespace WebKit
-
-#endif // #if ENABLE(SERVICE_CONTROLS) || ENABLE(TELEPHONE_NUMBER_DETECTION) &amp;&amp; PLATFORM(MAC)
</del></span></pre>
</div>
</div>

</body>
</html>