initial import
[vuplus_webkit] / Source / WebKit2 / WebProcess / WebCoreSupport / mac / WebEditorClientMac.mm
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
135 static void changeWordCase(WebPage* page, SEL selector)
136 {
137     Frame* frame = page->corePage()->focusController()->focusedOrMainFrame();
138     if (!frame->editor()->canEdit())
139         return;
140
141     frame->editor()->command("selectWord").execute();
142
143     NSString *selectedString = frame->displayStringModifiedByEncoding(frame->editor()->selectedText());
144     page->replaceSelectionWithText(frame, [selectedString performSelector:selector]);
145 }
146
147 void WebEditorClient::uppercaseWord()
148 {
149     changeWordCase(m_page, @selector(uppercaseString));
150 }
151
152 void WebEditorClient::lowercaseWord()
153 {
154     changeWordCase(m_page, @selector(lowercaseString));
155 }
156
157 void WebEditorClient::capitalizeWord()
158 {
159     changeWordCase(m_page, @selector(capitalizedString));
160 }
161
162 void WebEditorClient::showSubstitutionsPanel(bool)
163 {
164     notImplemented();
165 }
166
167 bool WebEditorClient::substitutionsPanelIsShowing()
168 {
169     bool isShowing;
170     m_page->sendSync(Messages::WebPageProxy::SubstitutionsPanelIsShowing(), Messages::WebPageProxy::SubstitutionsPanelIsShowing::Reply(isShowing));
171     return isShowing;
172 }
173
174 void WebEditorClient::toggleSmartInsertDelete()
175 {
176     // This is handled in the UI process.
177     ASSERT_NOT_REACHED();
178 }
179
180 bool WebEditorClient::isAutomaticQuoteSubstitutionEnabled()
181 {
182     return WebProcess::shared().textCheckerState().isAutomaticQuoteSubstitutionEnabled;
183 }
184
185 void WebEditorClient::toggleAutomaticQuoteSubstitution()
186 {
187     // This is handled in the UI process.
188     ASSERT_NOT_REACHED();
189 }
190
191 bool WebEditorClient::isAutomaticLinkDetectionEnabled()
192 {
193     return WebProcess::shared().textCheckerState().isAutomaticLinkDetectionEnabled;
194 }
195
196 void WebEditorClient::toggleAutomaticLinkDetection()
197 {
198     // This is handled in the UI process.
199     ASSERT_NOT_REACHED();
200 }
201
202 bool WebEditorClient::isAutomaticDashSubstitutionEnabled()
203 {
204     return WebProcess::shared().textCheckerState().isAutomaticDashSubstitutionEnabled;
205 }
206
207 void WebEditorClient::toggleAutomaticDashSubstitution()
208 {
209     // This is handled in the UI process.
210     ASSERT_NOT_REACHED();
211 }
212
213 bool WebEditorClient::isAutomaticTextReplacementEnabled()
214 {
215     return WebProcess::shared().textCheckerState().isAutomaticTextReplacementEnabled;
216 }
217
218 void WebEditorClient::toggleAutomaticTextReplacement()
219 {
220     // This is handled in the UI process.
221     ASSERT_NOT_REACHED();
222 }
223
224 bool WebEditorClient::isAutomaticSpellingCorrectionEnabled()
225 {
226     return WebProcess::shared().textCheckerState().isAutomaticSpellingCorrectionEnabled;
227 }
228
229 void WebEditorClient::toggleAutomaticSpellingCorrection()
230 {
231     notImplemented();
232 }
233
234 void WebEditorClient::checkTextOfParagraph(const UChar* text, int length, WebCore::TextCheckingTypeMask checkingTypes, Vector<TextCheckingResult>& results)
235 {
236     // FIXME: It would be nice if we wouldn't have to copy the text here.
237     m_page->sendSync(Messages::WebPageProxy::CheckTextOfParagraph(String(text, length), checkingTypes), Messages::WebPageProxy::CheckTextOfParagraph::Reply(results));
238 }
239
240 #if !defined(BUILDING_ON_SNOW_LEOPARD)
241 void WebEditorClient::showCorrectionPanel(WebCore::CorrectionPanelInfo::PanelType type, const WebCore::FloatRect& boundingBoxOfReplacedString, const String& replacedString, const String& replacementString, const Vector<String>& alternativeReplacementStrings)
242 {
243     m_page->send(Messages::WebPageProxy::ShowCorrectionPanel(type, boundingBoxOfReplacedString, replacedString, replacementString, alternativeReplacementStrings));
244 }
245
246 void WebEditorClient::dismissCorrectionPanel(WebCore::ReasonForDismissingCorrectionPanel reason)
247 {
248     m_page->send(Messages::WebPageProxy::DismissCorrectionPanel(reason));
249 }
250
251 String WebEditorClient::dismissCorrectionPanelSoon(WebCore::ReasonForDismissingCorrectionPanel reason)
252 {
253     String result;
254     m_page->sendSync(Messages::WebPageProxy::DismissCorrectionPanelSoon(reason), Messages::WebPageProxy::DismissCorrectionPanelSoon::Reply(result));
255     return result;
256 }
257
258 void WebEditorClient::recordAutocorrectionResponse(EditorClient::AutocorrectionResponseType responseType, const String& replacedString, const String& replacementString)
259 {
260     m_page->send(Messages::WebPageProxy::RecordAutocorrectionResponse(responseType, replacedString, replacementString));
261 }
262 #endif
263
264 } // namespace WebKit