• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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
50using 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
60namespace WebKit {
61
62void WebEditorClient::handleKeyboardEvent(KeyboardEvent* event)
63{
64    if (m_page->handleEditingKeyboardEvent(event, false))
65        event->setDefaultHandled();
66}
67
68void WebEditorClient::handleInputMethodKeydown(KeyboardEvent* event)
69{
70    if (m_page->handleEditingKeyboardEvent(event, true))
71        event->setDefaultHandled();
72}
73
74NSString *WebEditorClient::userVisibleString(NSURL *url)
75{
76    return [url _web_userVisibleString];
77}
78
79NSURL *WebEditorClient::canonicalizeURL(NSURL *url)
80{
81    return [url _webkit_canonicalize];
82}
83
84NSURL *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
92static 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
109DocumentFragment* 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
128void 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
135NSArray *WebEditorClient::pasteboardTypesForSelection(Frame*)
136{
137    notImplemented();
138    return nil;
139}
140#endif
141
142static 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
154void WebEditorClient::uppercaseWord()
155{
156    changeWordCase(m_page, @selector(uppercaseString));
157}
158
159void WebEditorClient::lowercaseWord()
160{
161    changeWordCase(m_page, @selector(lowercaseString));
162}
163
164void WebEditorClient::capitalizeWord()
165{
166    changeWordCase(m_page, @selector(capitalizedString));
167}
168
169void WebEditorClient::showSubstitutionsPanel(bool)
170{
171    notImplemented();
172}
173
174bool WebEditorClient::substitutionsPanelIsShowing()
175{
176    bool isShowing;
177    m_page->sendSync(Messages::WebPageProxy::SubstitutionsPanelIsShowing(), Messages::WebPageProxy::SubstitutionsPanelIsShowing::Reply(isShowing));
178    return isShowing;
179}
180
181void WebEditorClient::toggleSmartInsertDelete()
182{
183    // This is handled in the UI process.
184    ASSERT_NOT_REACHED();
185}
186
187bool WebEditorClient::isAutomaticQuoteSubstitutionEnabled()
188{
189    return WebProcess::shared().textCheckerState().isAutomaticQuoteSubstitutionEnabled;
190}
191
192void WebEditorClient::toggleAutomaticQuoteSubstitution()
193{
194    // This is handled in the UI process.
195    ASSERT_NOT_REACHED();
196}
197
198bool WebEditorClient::isAutomaticLinkDetectionEnabled()
199{
200    return WebProcess::shared().textCheckerState().isAutomaticLinkDetectionEnabled;
201}
202
203void WebEditorClient::toggleAutomaticLinkDetection()
204{
205    // This is handled in the UI process.
206    ASSERT_NOT_REACHED();
207}
208
209bool WebEditorClient::isAutomaticDashSubstitutionEnabled()
210{
211    return WebProcess::shared().textCheckerState().isAutomaticDashSubstitutionEnabled;
212}
213
214void WebEditorClient::toggleAutomaticDashSubstitution()
215{
216    // This is handled in the UI process.
217    ASSERT_NOT_REACHED();
218}
219
220bool WebEditorClient::isAutomaticTextReplacementEnabled()
221{
222    return WebProcess::shared().textCheckerState().isAutomaticTextReplacementEnabled;
223}
224
225void WebEditorClient::toggleAutomaticTextReplacement()
226{
227    // This is handled in the UI process.
228    ASSERT_NOT_REACHED();
229}
230
231bool WebEditorClient::isAutomaticSpellingCorrectionEnabled()
232{
233    return WebProcess::shared().textCheckerState().isAutomaticSpellingCorrectionEnabled;
234}
235
236void WebEditorClient::toggleAutomaticSpellingCorrection()
237{
238    notImplemented();
239}
240
241void 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)
248void 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
253void WebEditorClient::dismissCorrectionPanel(WebCore::ReasonForDismissingCorrectionPanel reason)
254{
255    m_page->send(Messages::WebPageProxy::DismissCorrectionPanel(reason));
256}
257
258String 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
265void 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