Home | History | Annotate | Download | only in mac
      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 "EditorState.h"
     33 #import "NativeWebKeyboardEvent.h"
     34 #import "PageClient.h"
     35 #import "PageClientImpl.h"
     36 #import "TextChecker.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)
    145 {
    146     process()->sendSync(Messages::WebPage::SetComposition(text, underlines, selectionStart, selectionEnd, replacementRangeStart, replacementRangeEnd), Messages::WebPage::SetComposition::Reply(m_editorState), m_pageID);
    147 }
    148 
    149 void WebPageProxy::confirmComposition()
    150 {
    151     process()->sendSync(Messages::WebPage::ConfirmComposition(), Messages::WebPage::ConfirmComposition::Reply(m_editorState), m_pageID);
    152 }
    153 
    154 bool WebPageProxy::insertText(const String& text, uint64_t replacementRangeStart, uint64_t replacementRangeEnd)
    155 {
    156     bool handled;
    157     process()->sendSync(Messages::WebPage::InsertText(text, replacementRangeStart, replacementRangeEnd), Messages::WebPage::InsertText::Reply(handled, m_editorState), 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)
    191 {
    192     bool result;
    193     process()->sendSync(Messages::WebPage::ExecuteKeypressCommands(commands), Messages::WebPage::ExecuteKeypressCommands::Reply(result, m_editorState), 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 EditorState& state, bool& handled, Vector<WebCore::KeypressCommand>& commands)
    231 {
    232     m_editorState = state;
    233     handled = m_pageClient->interpretKeyEvent(m_keyEventQueue.first(), commands);
    234 }
    235 
    236 // Complex text input support for plug-ins.
    237 void WebPageProxy::sendComplexTextInputToPlugin(uint64_t pluginComplexTextInputIdentifier, const String& textInput)
    238 {
    239     if (!isValid())
    240         return;
    241 
    242     process()->send(Messages::WebPage::SendComplexTextInputToPlugin(pluginComplexTextInputIdentifier, textInput), m_pageID);
    243 }
    244 
    245 void WebPageProxy::uppercaseWord()
    246 {
    247     process()->send(Messages::WebPage::UppercaseWord(), m_pageID);
    248 }
    249 
    250 void WebPageProxy::lowercaseWord()
    251 {
    252     process()->send(Messages::WebPage::LowercaseWord(), m_pageID);
    253 }
    254 
    255 void WebPageProxy::capitalizeWord()
    256 {
    257     process()->send(Messages::WebPage::CapitalizeWord(), m_pageID);
    258 }
    259 
    260 void WebPageProxy::setSmartInsertDeleteEnabled(bool isSmartInsertDeleteEnabled)
    261 {
    262     if (m_isSmartInsertDeleteEnabled == isSmartInsertDeleteEnabled)
    263         return;
    264 
    265     TextChecker::setSmartInsertDeleteEnabled(isSmartInsertDeleteEnabled);
    266     m_isSmartInsertDeleteEnabled = isSmartInsertDeleteEnabled;
    267     process()->send(Messages::WebPage::SetSmartInsertDeleteEnabled(isSmartInsertDeleteEnabled), m_pageID);
    268 }
    269 
    270 void WebPageProxy::didPerformDictionaryLookup(const String& text, const DictionaryPopupInfo& dictionaryPopupInfo)
    271 {
    272     m_pageClient->didPerformDictionaryLookup(text, m_viewScaleFactor, dictionaryPopupInfo);
    273 }
    274 
    275 void WebPageProxy::registerWebProcessAccessibilityToken(const CoreIPC::DataReference& data)
    276 {
    277     m_pageClient->accessibilityWebProcessTokenReceived(data);
    278 }
    279 
    280 void WebPageProxy::registerUIProcessAccessibilityTokens(const CoreIPC::DataReference& elementToken, const CoreIPC::DataReference& windowToken)
    281 {
    282     if (!isValid())
    283         return;
    284 
    285     process()->send(Messages::WebPage::RegisterUIProcessAccessibilityTokens(elementToken, windowToken), m_pageID);
    286 }
    287 
    288 void WebPageProxy::setComplexTextInputEnabled(uint64_t pluginComplexTextInputIdentifier, bool complexTextInputEnabled)
    289 {
    290     m_pageClient->setComplexTextInputEnabled(pluginComplexTextInputIdentifier, complexTextInputEnabled);
    291 }
    292 
    293 void WebPageProxy::executeSavedCommandBySelector(const String& selector, bool& handled)
    294 {
    295     handled = m_pageClient->executeSavedCommandBySelector(selector);
    296 }
    297 
    298 bool WebPageProxy::shouldDelayWindowOrderingForEvent(const WebKit::WebMouseEvent& event)
    299 {
    300     bool result = false;
    301     const double messageTimeout = 3;
    302     process()->sendSync(Messages::WebPage::ShouldDelayWindowOrderingEvent(event), Messages::WebPage::ShouldDelayWindowOrderingEvent::Reply(result), m_pageID, messageTimeout);
    303     return result;
    304 }
    305 
    306 bool WebPageProxy::acceptsFirstMouse(int eventNumber, const WebKit::WebMouseEvent& event)
    307 {
    308     bool result = false;
    309     const double messageTimeout = 3;
    310     process()->sendSync(Messages::WebPage::AcceptsFirstMouse(eventNumber, event), Messages::WebPage::AcceptsFirstMouse::Reply(result), m_pageID, messageTimeout);
    311     return result;
    312 }
    313 
    314 } // namespace WebKit
    315