1/* 2 * Copyright (C) 2006, 2010, 2011 Apple 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 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#if PLATFORM(MAC) 34 35#import "WebCoreArgumentCoders.h" 36#import "WebPage.h" 37#import "WebFrame.h" 38#import "WebPageProxyMessages.h" 39#import "WebProcess.h" 40#import <WebCore/ArchiveResource.h> 41#import <WebCore/DocumentFragment.h> 42#import <WebCore/DOMDocumentFragmentInternal.h> 43#import <WebCore/DOMDocumentInternal.h> 44#import <WebCore/FocusController.h> 45#import <WebCore/Frame.h> 46#import <WebCore/KeyboardEvent.h> 47#import <WebCore/NotImplemented.h> 48#import <WebCore/Page.h> 49#import <WebCore/WebCoreNSURLExtras.h> 50 51using namespace WebCore; 52 53@interface NSAttributedString (WebNSAttributedStringDetails) 54- (DOMDocumentFragment*)_documentFromRange:(NSRange)range document:(DOMDocument*)document documentAttributes:(NSDictionary *)dict subresources:(NSArray **)subresources; 55@end 56 57@interface NSObject (WebResourceInternal) 58- (WebCore::ArchiveResource*)_coreResource; 59@end 60 61namespace WebKit { 62 63void WebEditorClient::handleKeyboardEvent(KeyboardEvent* event) 64{ 65 if (m_page->handleEditingKeyboardEvent(event)) 66 event->setDefaultHandled(); 67} 68 69void WebEditorClient::handleInputMethodKeydown(KeyboardEvent* event) 70{ 71 if (event->handledByInputMethod()) 72 event->setDefaultHandled(); 73} 74 75NSString *WebEditorClient::userVisibleString(NSURL *url) 76{ 77 return WebCore::userVisibleString(url); 78} 79 80NSURL *WebEditorClient::canonicalizeURL(NSURL *url) 81{ 82 return URLByCanonicalizingURL(url); 83} 84 85NSURL *WebEditorClient::canonicalizeURLString(NSString *URLString) 86{ 87 NSURL *URL = nil; 88 if (looksLikeAbsoluteURL(URLString)) 89 URL = URLByCanonicalizingURL(URLWithUserTypedString(URLString, nil)); 90 return URL; 91} 92 93static NSArray *createExcludedElementsForAttributedStringConversion() 94{ 95 NSArray *elements = [[NSArray alloc] initWithObjects: 96 // Omit style since we want style to be inline so the fragment can be easily inserted. 97 @"style", 98 // Omit xml so the result is not XHTML. 99 @"xml", 100 // Omit tags that will get stripped when converted to a fragment anyway. 101 @"doctype", @"html", @"head", @"body", 102 // Omit deprecated tags. 103 @"applet", @"basefont", @"center", @"dir", @"font", @"isindex", @"menu", @"s", @"strike", @"u", 104 // Omit object so no file attachments are part of the fragment. 105 @"object", nil]; 106 CFRetain(elements); 107 return elements; 108} 109 110DocumentFragment* WebEditorClient::documentFragmentFromAttributedString(NSAttributedString *string, Vector<RefPtr<ArchiveResource>>& resources) 111{ 112 static NSArray *excludedElements = createExcludedElementsForAttributedStringConversion(); 113 114 NSDictionary *dictionary = [NSDictionary dictionaryWithObject:excludedElements forKey:NSExcludedElementsDocumentAttribute]; 115 116 NSArray *subResources; 117 Document* document = m_page->mainFrame()->document(); 118 119 // FIXME: Isntead of calling this WebKit1 method, the code should be factored out and moved into WebCore. 120 DOMDocumentFragment* fragment = [string _documentFromRange:NSMakeRange(0, [string length]) 121 document:kit(document) 122 documentAttributes:dictionary 123 subresources:&subResources]; 124 for (id resource in subResources) 125 resources.append([resource _coreResource]); 126 127 return core(fragment); 128} 129 130void WebEditorClient::setInsertionPasteboard(const String&) 131{ 132 // This is used only by Mail, no need to implement it now. 133 notImplemented(); 134} 135 136 137static void changeWordCase(WebPage* page, SEL selector) 138{ 139 Frame& frame = page->corePage()->focusController().focusedOrMainFrame(); 140 if (!frame.editor().canEdit()) 141 return; 142 143 frame.editor().command("selectWord").execute(); 144 145 NSString *selectedString = frame.displayStringModifiedByEncoding(frame.editor().selectedText()); 146 page->replaceSelectionWithText(&frame, [selectedString performSelector:selector]); 147} 148 149#if USE(APPKIT) 150void WebEditorClient::uppercaseWord() 151{ 152 changeWordCase(m_page, @selector(uppercaseString)); 153} 154 155void WebEditorClient::lowercaseWord() 156{ 157 changeWordCase(m_page, @selector(lowercaseString)); 158} 159 160void WebEditorClient::capitalizeWord() 161{ 162 changeWordCase(m_page, @selector(capitalizedString)); 163} 164#endif 165 166#if USE(AUTOMATIC_TEXT_REPLACEMENT) 167void WebEditorClient::showSubstitutionsPanel(bool) 168{ 169 notImplemented(); 170} 171 172bool WebEditorClient::substitutionsPanelIsShowing() 173{ 174 bool isShowing; 175 m_page->sendSync(Messages::WebPageProxy::SubstitutionsPanelIsShowing(), Messages::WebPageProxy::SubstitutionsPanelIsShowing::Reply(isShowing)); 176 return isShowing; 177} 178 179void WebEditorClient::toggleSmartInsertDelete() 180{ 181 // This is handled in the UI process. 182 ASSERT_NOT_REACHED(); 183} 184 185bool WebEditorClient::isAutomaticQuoteSubstitutionEnabled() 186{ 187 return WebProcess::shared().textCheckerState().isAutomaticQuoteSubstitutionEnabled; 188} 189 190void WebEditorClient::toggleAutomaticQuoteSubstitution() 191{ 192 // This is handled in the UI process. 193 ASSERT_NOT_REACHED(); 194} 195 196bool WebEditorClient::isAutomaticLinkDetectionEnabled() 197{ 198 return WebProcess::shared().textCheckerState().isAutomaticLinkDetectionEnabled; 199} 200 201void WebEditorClient::toggleAutomaticLinkDetection() 202{ 203 // This is handled in the UI process. 204 ASSERT_NOT_REACHED(); 205} 206 207bool WebEditorClient::isAutomaticDashSubstitutionEnabled() 208{ 209 return WebProcess::shared().textCheckerState().isAutomaticDashSubstitutionEnabled; 210} 211 212void WebEditorClient::toggleAutomaticDashSubstitution() 213{ 214 // This is handled in the UI process. 215 ASSERT_NOT_REACHED(); 216} 217 218bool WebEditorClient::isAutomaticTextReplacementEnabled() 219{ 220 return WebProcess::shared().textCheckerState().isAutomaticTextReplacementEnabled; 221} 222 223void WebEditorClient::toggleAutomaticTextReplacement() 224{ 225 // This is handled in the UI process. 226 ASSERT_NOT_REACHED(); 227} 228 229bool WebEditorClient::isAutomaticSpellingCorrectionEnabled() 230{ 231 return WebProcess::shared().textCheckerState().isAutomaticSpellingCorrectionEnabled; 232} 233 234void WebEditorClient::toggleAutomaticSpellingCorrection() 235{ 236 notImplemented(); 237} 238#endif // USE(AUTOMATIC_TEXT_REPLACEMENT) 239 240} // namespace WebKit 241 242#endif // PLATFORM(MAC) 243