e377aaa575d73cbc6bd515c91e492dcfec2b8de1
[WebKit-https.git] / Source / WebKit2 / UIProcess / mac / WebPageProxyMac.mm
1 /*
2  * Copyright (C) 2010, 2011 Apple Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
14  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
15  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
17  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
18  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
19  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
20  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
21  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
22  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
23  * THE POSSIBILITY OF SUCH DAMAGE.
24  */
25
26 #import "config.h"
27 #import "WebPageProxy.h"
28
29 #import "AttributedString.h"
30 #import "DataReference.h"
31 #import "DictionaryPopupInfo.h"
32 #import "NativeWebKeyboardEvent.h"
33 #import "PageClient.h"
34 #import "PageClientImpl.h"
35 #import "TextChecker.h"
36 #import "TextInputState.h"
37 #import "WebPageMessages.h"
38 #import "WebProcessProxy.h"
39 #import <wtf/text/StringConcatenate.h>
40
41 @interface NSApplication (Details)
42 - (void)speakString:(NSString *)string;
43 @end
44
45 using namespace WebCore;
46
47 namespace WebKit {
48
49 #if defined(__ppc__) || defined(__ppc64__)
50 #define PROCESSOR "PPC"
51 #elif defined(__i386__) || defined(__x86_64__)
52 #define PROCESSOR "Intel"
53 #else
54 #error Unknown architecture
55 #endif
56
57 static inline int callGestalt(OSType selector)
58 {
59     SInt32 value = 0;
60     Gestalt(selector, &value);
61     return value;
62 }
63
64 // Uses underscores instead of dots because if "4." ever appears in a user agent string, old DHTML libraries treat it as Netscape 4.
65 static String macOSXVersionString()
66 {
67     // Can't use -[NSProcessInfo operatingSystemVersionString] because it has too much stuff we don't want.
68     int major = callGestalt(gestaltSystemVersionMajor);
69     ASSERT(major);
70
71     int minor = callGestalt(gestaltSystemVersionMinor);
72     int bugFix = callGestalt(gestaltSystemVersionBugFix);
73     if (bugFix)
74         return String::format("%d_%d_%d", major, minor, bugFix);
75     if (minor)
76         return String::format("%d_%d", major, minor);
77     return String::format("%d", major);
78 }
79
80 static String userVisibleWebKitVersionString()
81 {
82     // If the version is 4 digits long or longer, then the first digit represents
83     // the version of the OS. Our user agent string should not include this first digit,
84     // so strip it off and report the rest as the version. <rdar://problem/4997547>
85     NSString *fullVersion = [[NSBundle bundleForClass:NSClassFromString(@"WKView")] objectForInfoDictionaryKey:(NSString *)kCFBundleVersionKey];
86     NSRange nonDigitRange = [fullVersion rangeOfCharacterFromSet:[[NSCharacterSet decimalDigitCharacterSet] invertedSet]];
87     if (nonDigitRange.location == NSNotFound && [fullVersion length] >= 4)
88         return [fullVersion substringFromIndex:1];
89     if (nonDigitRange.location != NSNotFound && nonDigitRange.location >= 4)
90         return [fullVersion substringFromIndex:1];
91     return fullVersion;
92 }
93
94 String WebPageProxy::standardUserAgent(const String& applicationNameForUserAgent)
95 {
96     DEFINE_STATIC_LOCAL(String, osVersion, (macOSXVersionString()));
97     DEFINE_STATIC_LOCAL(String, webKitVersion, (userVisibleWebKitVersionString()));
98
99     if (applicationNameForUserAgent.isEmpty())
100         return makeString("Mozilla/5.0 (Macintosh; " PROCESSOR " Mac OS X ", osVersion, ") AppleWebKit/", webKitVersion, " (KHTML, like Gecko)");
101     return makeString("Mozilla/5.0 (Macintosh; " PROCESSOR " Mac OS X ", osVersion, ") AppleWebKit/", webKitVersion, " (KHTML, like Gecko) ", applicationNameForUserAgent);
102 }
103
104 void WebPageProxy::getIsSpeaking(bool& isSpeaking)
105 {
106     isSpeaking = [NSApp isSpeaking];
107 }
108
109 void WebPageProxy::speak(const String& string)
110 {
111     [NSApp speakString:nsStringFromWebCoreString(string)];
112 }
113
114 void WebPageProxy::stopSpeaking()
115 {
116     [NSApp stopSpeaking:nil];
117 }
118
119 void WebPageProxy::searchWithSpotlight(const String& string)
120 {
121     [[NSWorkspace sharedWorkspace] showSearchResultsForQueryString:nsStringFromWebCoreString(string)];
122 }
123
124 CGContextRef WebPageProxy::containingWindowGraphicsContext()
125 {
126     return m_pageClient->containingWindowGraphicsContext();
127 }
128
129 void WebPageProxy::updateWindowIsVisible(bool windowIsVisible)
130 {
131     if (!isValid())
132         return;
133     process()->send(Messages::WebPage::SetWindowIsVisible(windowIsVisible), m_pageID);
134 }
135
136 void WebPageProxy::windowAndViewFramesChanged(const IntRect& windowFrameInScreenCoordinates, const IntRect& viewFrameInWindowCoordinates, const IntPoint& accessibilityViewCoordinates)
137 {
138     if (!isValid())
139         return;
140
141     process()->send(Messages::WebPage::WindowAndViewFramesChanged(windowFrameInScreenCoordinates, viewFrameInWindowCoordinates, accessibilityViewCoordinates), m_pageID);
142 }
143
144 void WebPageProxy::setComposition(const String& text, Vector<CompositionUnderline> underlines, uint64_t selectionStart, uint64_t selectionEnd, uint64_t replacementRangeStart, uint64_t replacementRangeEnd, TextInputState& newState)
145 {
146     process()->sendSync(Messages::WebPage::SetComposition(text, underlines, selectionStart, selectionEnd, replacementRangeStart, replacementRangeEnd), Messages::WebPage::SetComposition::Reply(newState), m_pageID);
147 }
148
149 void WebPageProxy::confirmComposition(TextInputState& newState)
150 {
151     process()->sendSync(Messages::WebPage::ConfirmComposition(), Messages::WebPage::ConfirmComposition::Reply(newState), m_pageID);
152 }
153
154 bool WebPageProxy::insertText(const String& text, uint64_t replacementRangeStart, uint64_t replacementRangeEnd, TextInputState& newState)
155 {
156     bool handled;
157     process()->sendSync(Messages::WebPage::InsertText(text, replacementRangeStart, replacementRangeEnd), Messages::WebPage::InsertText::Reply(handled, newState), m_pageID);
158     return handled;
159 }
160
161 void WebPageProxy::getMarkedRange(uint64_t& location, uint64_t& length)
162 {
163     process()->sendSync(Messages::WebPage::GetMarkedRange(), Messages::WebPage::GetMarkedRange::Reply(location, length), m_pageID);
164 }
165
166 void WebPageProxy::getSelectedRange(uint64_t& location, uint64_t& length)
167 {
168     process()->sendSync(Messages::WebPage::GetSelectedRange(), Messages::WebPage::GetSelectedRange::Reply(location, length), m_pageID);
169 }
170
171 void WebPageProxy::getAttributedSubstringFromRange(uint64_t location, uint64_t length, AttributedString& result)
172 {
173     process()->sendSync(Messages::WebPage::GetAttributedSubstringFromRange(location, length), Messages::WebPage::GetAttributedSubstringFromRange::Reply(result), m_pageID);
174 }
175
176 uint64_t WebPageProxy::characterIndexForPoint(const IntPoint point)
177 {
178     uint64_t result;
179     process()->sendSync(Messages::WebPage::CharacterIndexForPoint(point), Messages::WebPage::CharacterIndexForPoint::Reply(result), m_pageID);
180     return result;
181 }
182
183 WebCore::IntRect WebPageProxy::firstRectForCharacterRange(uint64_t location, uint64_t length)
184 {
185     IntRect resultRect;
186     process()->sendSync(Messages::WebPage::FirstRectForCharacterRange(location, length), Messages::WebPage::FirstRectForCharacterRange::Reply(resultRect), m_pageID);
187     return resultRect;
188 }
189
190 bool WebPageProxy::executeKeypressCommands(const Vector<WebCore::KeypressCommand>& commands, TextInputState& newState)
191 {
192     bool result;
193     process()->sendSync(Messages::WebPage::ExecuteKeypressCommands(commands), Messages::WebPage::ExecuteKeypressCommands::Reply(result, newState), m_pageID);
194     return result;
195 }
196
197 bool WebPageProxy::writeSelectionToPasteboard(const String& pasteboardName, const Vector<String>& pasteboardTypes)
198 {
199     bool result;
200     const double MessageTimeout = 20;
201     process()->sendSync(Messages::WebPage::WriteSelectionToPasteboard(pasteboardName, pasteboardTypes), Messages::WebPage::WriteSelectionToPasteboard::Reply(result), m_pageID, MessageTimeout);
202     return result;
203 }
204
205 bool WebPageProxy::readSelectionFromPasteboard(const String& pasteboardName)
206 {
207     bool result;
208     const double MessageTimeout = 20;
209     process()->sendSync(Messages::WebPage::ReadSelectionFromPasteboard(pasteboardName), Messages::WebPage::ReadSelectionFromPasteboard::Reply(result), m_pageID, MessageTimeout);
210     return result;
211 }
212
213 void WebPageProxy::setDragImage(const WebCore::IntPoint& clientPosition, const ShareableBitmap::Handle& dragImageHandle, bool isLinkDrag)
214 {
215     RefPtr<ShareableBitmap> dragImage = ShareableBitmap::create(dragImageHandle);
216     if (!dragImage)
217         return;
218     
219     m_pageClient->setDragImage(clientPosition, dragImage.release(), isLinkDrag);
220 }
221
222 void WebPageProxy::performDictionaryLookupAtLocation(const WebCore::FloatPoint& point)
223 {
224     if (!isValid())
225         return;
226
227     process()->send(Messages::WebPage::PerformDictionaryLookupAtLocation(point), m_pageID); 
228 }
229
230 void WebPageProxy::interpretQueuedKeyEvent(const TextInputState& state, bool& handled, Vector<WebCore::KeypressCommand>& commands)
231 {
232     handled = m_pageClient->interpretKeyEvent(m_keyEventQueue.first(), state, commands);
233 }
234
235 // Complex text input support for plug-ins.
236 void WebPageProxy::sendComplexTextInputToPlugin(uint64_t pluginComplexTextInputIdentifier, const String& textInput)
237 {
238     if (!isValid())
239         return;
240     
241     process()->send(Messages::WebPage::SendComplexTextInputToPlugin(pluginComplexTextInputIdentifier, textInput), m_pageID);
242 }
243
244 void WebPageProxy::uppercaseWord()
245 {
246     process()->send(Messages::WebPage::UppercaseWord(), m_pageID);
247 }
248
249 void WebPageProxy::lowercaseWord()
250 {
251     process()->send(Messages::WebPage::LowercaseWord(), m_pageID);
252 }
253
254 void WebPageProxy::capitalizeWord()
255 {
256     process()->send(Messages::WebPage::CapitalizeWord(), m_pageID);
257 }
258
259 void WebPageProxy::setSmartInsertDeleteEnabled(bool isSmartInsertDeleteEnabled)
260
261     if (m_isSmartInsertDeleteEnabled == isSmartInsertDeleteEnabled)
262         return;
263
264     TextChecker::setSmartInsertDeleteEnabled(isSmartInsertDeleteEnabled);
265     m_isSmartInsertDeleteEnabled = isSmartInsertDeleteEnabled;
266     process()->send(Messages::WebPage::SetSmartInsertDeleteEnabled(isSmartInsertDeleteEnabled), m_pageID);
267 }
268
269 void WebPageProxy::didPerformDictionaryLookup(const String& text, const DictionaryPopupInfo& dictionaryPopupInfo)
270 {
271     m_pageClient->didPerformDictionaryLookup(text, m_viewScaleFactor, dictionaryPopupInfo);
272 }
273     
274 void WebPageProxy::registerWebProcessAccessibilityToken(const CoreIPC::DataReference& data)
275 {
276     m_pageClient->accessibilityWebProcessTokenReceived(data);
277 }    
278     
279 void WebPageProxy::registerUIProcessAccessibilityTokens(const CoreIPC::DataReference& elementToken, const CoreIPC::DataReference& windowToken)
280 {
281     if (!isValid())
282         return;
283
284     process()->send(Messages::WebPage::RegisterUIProcessAccessibilityTokens(elementToken, windowToken), m_pageID);
285 }
286
287 void WebPageProxy::setComplexTextInputEnabled(uint64_t pluginComplexTextInputIdentifier, bool complexTextInputEnabled)
288 {
289     m_pageClient->setComplexTextInputEnabled(pluginComplexTextInputIdentifier, complexTextInputEnabled);
290 }
291
292 void WebPageProxy::executeSavedCommandBySelector(const String& selector, bool& handled)
293 {
294     handled = m_pageClient->executeSavedCommandBySelector(selector);
295 }
296
297 bool WebPageProxy::shouldDelayWindowOrderingForEvent(const WebKit::WebMouseEvent& event)
298 {
299     bool result = false;
300     const double messageTimeout = 3;
301     process()->sendSync(Messages::WebPage::ShouldDelayWindowOrderingEvent(event), Messages::WebPage::ShouldDelayWindowOrderingEvent::Reply(result), m_pageID, messageTimeout);
302     return result;
303 }
304
305 bool WebPageProxy::acceptsFirstMouse(int eventNumber, const WebKit::WebMouseEvent& event)
306 {
307     bool result = false;
308     const double messageTimeout = 3;
309     process()->sendSync(Messages::WebPage::AcceptsFirstMouse(eventNumber, event), Messages::WebPage::AcceptsFirstMouse::Reply(result), m_pageID, messageTimeout);
310     return result;
311 }
312
313 } // namespace WebKit