Home | History | Annotate | Download | only in mac
      1 /*
      2  * Copyright (C) 2006, 2010, 2011 Apple Computer, Inc.  All rights reserved.
      3  * Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies)
      4  *
      5  * Redistribution and use in source and binary forms, with or without
      6  * modification, are permitted provided that the following conditions
      7  * are met:
      8  *
      9  * 1.  Redistributions of source code must retain the above copyright
     10  *     notice, this list of conditions and the following disclaimer.
     11  * 2.  Redistributions in binary form must reproduce the above copyright
     12  *     notice, this list of conditions and the following disclaimer in the
     13  *     documentation and/or other materials provided with the distribution.
     14  * 3.  Neither the name of Apple Computer, Inc. ("Apple") nor the names of
     15  *     its contributors may be used to endorse or promote products derived
     16  *     from this software without specific prior written permission.
     17  *
     18  * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
     19  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
     20  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
     21  * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
     22  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
     23  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
     24  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
     25  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     26  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
     27  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     28  */
     29 
     30 #import "config.h"
     31 #import "WebEditorClient.h"
     32 
     33 #import "WebCoreArgumentCoders.h"
     34 #import "WebPage.h"
     35 #import "WebFrame.h"
     36 #import "WebPageProxyMessages.h"
     37 #import "WebProcess.h"
     38 #import <WebCore/ArchiveResource.h>
     39 #import <WebCore/DocumentFragment.h>
     40 #import <WebCore/DOMDocumentFragmentInternal.h>
     41 #import <WebCore/DOMDocumentInternal.h>
     42 #import <WebCore/FocusController.h>
     43 #import <WebCore/Frame.h>
     44 #import <WebCore/KeyboardEvent.h>
     45 #import <WebCore/NotImplemented.h>
     46 #import <WebCore/Page.h>
     47 #import <WebKit/WebResource.h>
     48 #import <WebKit/WebNSURLExtras.h>
     49 
     50 using namespace WebCore;
     51 
     52 @interface NSAttributedString (WebNSAttributedStringDetails)
     53 - (DOMDocumentFragment*)_documentFromRange:(NSRange)range document:(DOMDocument*)document documentAttributes:(NSDictionary *)dict subresources:(NSArray **)subresources;
     54 @end
     55 
     56 @interface WebResource (WebResourceInternal)
     57 - (WebCore::ArchiveResource*)_coreResource;
     58 @end
     59 
     60 namespace WebKit {
     61 
     62 void WebEditorClient::handleKeyboardEvent(KeyboardEvent* event)
     63 {
     64     if (m_page->handleEditingKeyboardEvent(event, false))
     65         event->setDefaultHandled();
     66 }
     67 
     68 void WebEditorClient::handleInputMethodKeydown(KeyboardEvent* event)
     69 {
     70     if (m_page->handleEditingKeyboardEvent(event, true))
     71         event->setDefaultHandled();
     72 }
     73 
     74 NSString *WebEditorClient::userVisibleString(NSURL *url)
     75 {
     76     return [url _web_userVisibleString];
     77 }
     78 
     79 NSURL *WebEditorClient::canonicalizeURL(NSURL *url)
     80 {
     81     return [url _webkit_canonicalize];
     82 }
     83 
     84 NSURL *WebEditorClient::canonicalizeURLString(NSString *URLString)
     85 {
     86     NSURL *URL = nil;
     87     if ([URLString _webkit_looksLikeAbsoluteURL])
     88         URL = [[NSURL _web_URLWithUserTypedString:URLString] _webkit_canonicalize];
     89     return URL;
     90 }
     91 
     92 static NSArray *createExcludedElementsForAttributedStringConversion()
     93 {
     94     NSArray *elements = [[NSArray alloc] initWithObjects:
     95         // Omit style since we want style to be inline so the fragment can be easily inserted.
     96         @"style",
     97         // Omit xml so the result is not XHTML.
     98         @"xml",
     99         // Omit tags that will get stripped when converted to a fragment anyway.
    100         @"doctype", @"html", @"head", @"body",
    101         // Omit deprecated tags.
    102         @"applet", @"basefont", @"center", @"dir", @"font", @"isindex", @"menu", @"s", @"strike", @"u",
    103         // Omit object so no file attachments are part of the fragment.
    104         @"object", nil];
    105     CFRetain(elements);
    106     return elements;
    107 }
    108 
    109 DocumentFragment* WebEditorClient::documentFragmentFromAttributedString(NSAttributedString *string, Vector<RefPtr<ArchiveResource> >& resources)
    110 {
    111     static NSArray *excludedElements = createExcludedElementsForAttributedStringConversion();
    112 
    113     NSDictionary *dictionary = [[NSDictionary alloc] initWithObjectsAndKeys: excludedElements,
    114         NSExcludedElementsDocumentAttribute, nil, @"WebResourceHandler", nil];
    115 
    116     NSArray *subResources;
    117     DOMDocumentFragment* fragment = [string _documentFromRange:NSMakeRange(0, [string length])
    118                                                       document:kit(m_page->mainFrame()->coreFrame()->document())
    119                                             documentAttributes:dictionary
    120                                                   subresources:&subResources];
    121     for (WebResource* resource in subResources)
    122         resources.append([resource _coreResource]);
    123 
    124     [dictionary release];
    125     return core(fragment);
    126 }
    127 
    128 void WebEditorClient::setInsertionPasteboard(NSPasteboard *)
    129 {
    130     // This is used only by Mail, no need to implement it now.
    131     notImplemented();
    132 }
    133 
    134 #ifdef BUILDING_ON_TIGER
    135 NSArray *WebEditorClient::pasteboardTypesForSelection(Frame*)
    136 {
    137     notImplemented();
    138     return nil;
    139 }
    140 #endif
    141 
    142 static void changeWordCase(WebPage* page, SEL selector)
    143 {
    144     Frame* frame = page->corePage()->focusController()->focusedOrMainFrame();
    145     if (!frame->editor()->canEdit())
    146         return;
    147 
    148     frame->editor()->command("selectWord").execute();
    149 
    150     NSString *selectedString = frame->displayStringModifiedByEncoding(frame->editor()->selectedText());
    151     page->replaceSelectionWithText(frame, [selectedString performSelector:selector]);
    152 }
    153 
    154 void WebEditorClient::uppercaseWord()
    155 {
    156     changeWordCase(m_page, @selector(uppercaseString));
    157 }
    158 
    159 void WebEditorClient::lowercaseWord()
    160 {
    161     changeWordCase(m_page, @selector(lowercaseString));
    162 }
    163 
    164 void WebEditorClient::capitalizeWord()
    165 {
    166     changeWordCase(m_page, @selector(capitalizedString));
    167 }
    168 
    169 void WebEditorClient::showSubstitutionsPanel(bool)
    170 {
    171     notImplemented();
    172 }
    173 
    174 bool WebEditorClient::substitutionsPanelIsShowing()
    175 {
    176     bool isShowing;
    177     m_page->sendSync(Messages::WebPageProxy::SubstitutionsPanelIsShowing(), Messages::WebPageProxy::SubstitutionsPanelIsShowing::Reply(isShowing));
    178     return isShowing;
    179 }
    180 
    181 void WebEditorClient::toggleSmartInsertDelete()
    182 {
    183     // This is handled in the UI process.
    184     ASSERT_NOT_REACHED();
    185 }
    186 
    187 bool WebEditorClient::isAutomaticQuoteSubstitutionEnabled()
    188 {
    189     return WebProcess::shared().textCheckerState().isAutomaticQuoteSubstitutionEnabled;
    190 }
    191 
    192 void WebEditorClient::toggleAutomaticQuoteSubstitution()
    193 {
    194     // This is handled in the UI process.
    195     ASSERT_NOT_REACHED();
    196 }
    197 
    198 bool WebEditorClient::isAutomaticLinkDetectionEnabled()
    199 {
    200     return WebProcess::shared().textCheckerState().isAutomaticLinkDetectionEnabled;
    201 }
    202 
    203 void WebEditorClient::toggleAutomaticLinkDetection()
    204 {
    205     // This is handled in the UI process.
    206     ASSERT_NOT_REACHED();
    207 }
    208 
    209 bool WebEditorClient::isAutomaticDashSubstitutionEnabled()
    210 {
    211     return WebProcess::shared().textCheckerState().isAutomaticDashSubstitutionEnabled;
    212 }
    213 
    214 void WebEditorClient::toggleAutomaticDashSubstitution()
    215 {
    216     // This is handled in the UI process.
    217     ASSERT_NOT_REACHED();
    218 }
    219 
    220 bool WebEditorClient::isAutomaticTextReplacementEnabled()
    221 {
    222     return WebProcess::shared().textCheckerState().isAutomaticTextReplacementEnabled;
    223 }
    224 
    225 void WebEditorClient::toggleAutomaticTextReplacement()
    226 {
    227     // This is handled in the UI process.
    228     ASSERT_NOT_REACHED();
    229 }
    230 
    231 bool WebEditorClient::isAutomaticSpellingCorrectionEnabled()
    232 {
    233     return WebProcess::shared().textCheckerState().isAutomaticSpellingCorrectionEnabled;
    234 }
    235 
    236 void WebEditorClient::toggleAutomaticSpellingCorrection()
    237 {
    238     notImplemented();
    239 }
    240 
    241 void WebEditorClient::checkTextOfParagraph(const UChar* text, int length, WebCore::TextCheckingTypeMask checkingTypes, Vector<TextCheckingResult>& results)
    242 {
    243     // FIXME: It would be nice if we wouldn't have to copy the text here.
    244     m_page->sendSync(Messages::WebPageProxy::CheckTextOfParagraph(String(text, length), checkingTypes), Messages::WebPageProxy::CheckTextOfParagraph::Reply(results));
    245 }
    246 
    247 #if !defined(BUILDING_ON_SNOW_LEOPARD)
    248 void WebEditorClient::showCorrectionPanel(WebCore::CorrectionPanelInfo::PanelType type, const WebCore::FloatRect& boundingBoxOfReplacedString, const String& replacedString, const String& replacementString, const Vector<String>& alternativeReplacementStrings)
    249 {
    250     m_page->send(Messages::WebPageProxy::ShowCorrectionPanel(type, boundingBoxOfReplacedString, replacedString, replacementString, alternativeReplacementStrings));
    251 }
    252 
    253 void WebEditorClient::dismissCorrectionPanel(WebCore::ReasonForDismissingCorrectionPanel reason)
    254 {
    255     m_page->send(Messages::WebPageProxy::DismissCorrectionPanel(reason));
    256 }
    257 
    258 String WebEditorClient::dismissCorrectionPanelSoon(WebCore::ReasonForDismissingCorrectionPanel reason)
    259 {
    260     String result;
    261     m_page->sendSync(Messages::WebPageProxy::DismissCorrectionPanelSoon(reason), Messages::WebPageProxy::DismissCorrectionPanelSoon::Reply(result));
    262     return result;
    263 }
    264 
    265 void WebEditorClient::recordAutocorrectionResponse(EditorClient::AutocorrectionResponseType responseType, const String& replacedString, const String& replacementString)
    266 {
    267     m_page->send(Messages::WebPageProxy::RecordAutocorrectionResponse(responseType, replacedString, replacementString));
    268 }
    269 #endif
    270 
    271 } // namespace WebKit
    272