2 * Copyright (C) 2010, 2011 Apple Inc. All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
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.
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.
29 #import "AttributedString.h"
30 #import "DataReference.h"
31 #import "EditorState.h"
32 #import "PluginView.h"
33 #import "WKAccessibilityWebPageObject.h"
34 #import "WebCoreArgumentCoders.h"
36 #import "WebEventConversion.h"
38 #import "WebPageProxyMessages.h"
39 #import "WebProcess.h"
40 #import <WebCore/AXObjectCache.h>
41 #import <WebCore/FocusController.h>
42 #import <WebCore/Frame.h>
43 #import <WebCore/FrameView.h>
44 #import <WebCore/HitTestResult.h>
45 #import <WebCore/HTMLConverter.h>
46 #import <WebCore/KeyboardEvent.h>
47 #import <WebCore/Page.h>
48 #import <WebCore/PlatformKeyboardEvent.h>
49 #import <WebCore/ResourceHandle.h>
50 #import <WebCore/RenderObject.h>
51 #import <WebCore/RenderStyle.h>
52 #import <WebCore/ScrollView.h>
53 #import <WebCore/TextIterator.h>
54 #import <WebCore/WindowsKeyboardCodes.h>
55 #import <WebCore/visible_units.h>
56 #import <WebKitSystemInterface.h>
58 using namespace WebCore;
62 static PassRefPtr<Range> convertToRange(Frame*, NSRange);
64 void WebPage::platformInitialize()
67 m_page->addSchedulePair(SchedulePair::create([[NSRunLoop currentRunLoop] getCFRunLoop], kCFRunLoopCommonModes));
69 m_page->addSchedulePair(SchedulePair::create([NSRunLoop currentRunLoop], kCFRunLoopCommonModes));
72 WKAccessibilityWebPageObject* mockAccessibilityElement = [[[WKAccessibilityWebPageObject alloc] init] autorelease];
74 // Get the pid for the starting process.
75 pid_t pid = WebProcess::shared().presenterApplicationPid();
76 WKAXInitializeElementWithPresenterPid(mockAccessibilityElement, pid);
77 [mockAccessibilityElement setWebPage:this];
79 // send data back over
80 NSData* remoteToken = (NSData *)WKAXRemoteTokenForElement(mockAccessibilityElement);
81 CoreIPC::DataReference dataToken = CoreIPC::DataReference(reinterpret_cast<const uint8_t*>([remoteToken bytes]), [remoteToken length]);
82 send(Messages::WebPageProxy::RegisterWebProcessAccessibilityToken(dataToken));
83 m_mockAccessibilityElement = mockAccessibilityElement;
86 void WebPage::platformPreferencesDidChange(const WebPreferencesStore&)
90 typedef HashMap<String, String> SelectorNameMap;
92 // Map selectors into Editor command names.
93 // This is not needed for any selectors that have the same name as the Editor command.
94 static const SelectorNameMap* createSelectorExceptionMap()
96 SelectorNameMap* map = new HashMap<String, String>;
98 map->add("insertNewlineIgnoringFieldEditor:", "InsertNewline");
99 map->add("insertParagraphSeparator:", "InsertNewline");
100 map->add("insertTabIgnoringFieldEditor:", "InsertTab");
101 map->add("pageDown:", "MovePageDown");
102 map->add("pageDownAndModifySelection:", "MovePageDownAndModifySelection");
103 map->add("pageUp:", "MovePageUp");
104 map->add("pageUpAndModifySelection:", "MovePageUpAndModifySelection");
109 static String commandNameForSelectorName(const String& selectorName)
111 // Check the exception map first.
112 static const SelectorNameMap* exceptionMap = createSelectorExceptionMap();
113 SelectorNameMap::const_iterator it = exceptionMap->find(selectorName);
114 if (it != exceptionMap->end())
117 // Remove the trailing colon.
118 // No need to capitalize the command name since Editor command names are not case sensitive.
119 size_t selectorNameLength = selectorName.length();
120 if (selectorNameLength < 2 || selectorName[selectorNameLength - 1] != ':')
122 return selectorName.left(selectorNameLength - 1);
125 static Frame* frameForEvent(KeyboardEvent* event)
127 Node* node = event->target()->toNode();
129 Frame* frame = node->document()->frame();
134 bool WebPage::executeKeypressCommandsInternal(const Vector<WebCore::KeypressCommand>& commands, KeyboardEvent* event)
136 Frame* frame = frameForEvent(event);
137 ASSERT(frame->page() == corePage());
139 bool eventWasHandled = false;
140 for (size_t i = 0; i < commands.size(); ++i) {
141 if (commands[i].commandName == "insertText:") {
142 ASSERT(!frame->editor()->hasComposition());
144 if (!frame->editor()->canEdit())
147 // An insertText: might be handled by other responders in the chain if we don't handle it.
148 // One example is space bar that results in scrolling down the page.
149 eventWasHandled |= frame->editor()->insertText(commands[i].text, event);
151 Editor::Command command = frame->editor()->command(commandNameForSelectorName(commands[i].commandName));
152 if (command.isSupported()) {
153 bool commandExecutedByEditor = command.execute(event);
154 eventWasHandled |= commandExecutedByEditor;
155 if (!commandExecutedByEditor) {
156 bool performedNonEditingBehavior = event->keyEvent()->type() == PlatformKeyboardEvent::RawKeyDown && performNonEditingBehaviorForSelector(commands[i].commandName);
157 eventWasHandled |= performedNonEditingBehavior;
160 bool commandWasHandledByUIProcess = false;
161 WebProcess::shared().connection()->sendSync(Messages::WebPageProxy::ExecuteSavedCommandBySelector(commands[i].commandName),
162 Messages::WebPageProxy::ExecuteSavedCommandBySelector::Reply(commandWasHandledByUIProcess), m_pageID);
163 eventWasHandled |= commandWasHandledByUIProcess;
167 return eventWasHandled;
170 bool WebPage::handleEditingKeyboardEvent(KeyboardEvent* event, bool saveCommands)
172 ASSERT(!saveCommands || event->keypressCommands().isEmpty()); // Save commands once for each event.
174 Frame* frame = frameForEvent(event);
176 const PlatformKeyboardEvent* platformEvent = event->keyEvent();
179 Vector<KeypressCommand>& commands = event->keypressCommands();
181 if ([platformEvent->macEvent() type] == NSFlagsChanged)
184 bool eventWasHandled = false;
187 KeyboardEvent* oldEvent = m_keyboardEventBeingInterpreted;
188 m_keyboardEventBeingInterpreted = event;
189 bool sendResult = WebProcess::shared().connection()->sendSync(Messages::WebPageProxy::InterpretQueuedKeyEvent(editorState()),
190 Messages::WebPageProxy::InterpretQueuedKeyEvent::Reply(eventWasHandled, commands), m_pageID);
191 m_keyboardEventBeingInterpreted = oldEvent;
195 // An input method may make several actions per keypress. For example, pressing Return with Korean IM both confirms it and sends a newline.
196 // IM-like actions are handled immediately (so the return value from UI process is true), but there are saved commands that
197 // should be handled like normal text input after DOM event dispatch.
198 if (!event->keypressCommands().isEmpty())
201 // Are there commands that could just cause text insertion if executed via Editor?
202 // WebKit doesn't have enough information about mode to decide how they should be treated, so we leave it upon WebCore
203 // to either handle them immediately (e.g. Tab that changes focus) or let a keypress event be generated
204 // (e.g. Tab that inserts a Tab character, or Enter).
205 bool haveTextInsertionCommands = false;
206 for (size_t i = 0; i < commands.size(); ++i) {
207 if (frame->editor()->command(commandNameForSelectorName(commands[i].commandName)).isTextInsertion())
208 haveTextInsertionCommands = true;
210 // If there are no text insertion commands, default keydown handler is the right time to execute the commands.
211 // Keypress (Char event) handler is the latest opportunity to execute.
212 if (!haveTextInsertionCommands || platformEvent->type() == PlatformKeyboardEvent::Char) {
213 eventWasHandled = executeKeypressCommandsInternal(event->keypressCommands(), event);
214 event->keypressCommands().clear();
217 return eventWasHandled;
220 void WebPage::sendComplexTextInputToPlugin(uint64_t pluginComplexTextInputIdentifier, const String& textInput)
222 for (HashSet<PluginView*>::const_iterator it = m_pluginViews.begin(), end = m_pluginViews.end(); it != end; ++it) {
223 if ((*it)->sendComplexTextInput(pluginComplexTextInputIdentifier, textInput))
228 void WebPage::setComposition(const String& text, Vector<CompositionUnderline> underlines, uint64_t selectionStart, uint64_t selectionEnd, uint64_t replacementRangeStart, uint64_t replacementRangeEnd, EditorState& newState)
230 Frame* frame = m_page->focusController()->focusedOrMainFrame();
232 if (frame->selection()->isContentEditable()) {
233 RefPtr<Range> replacementRange;
234 if (replacementRangeStart != NSNotFound) {
235 replacementRange = convertToRange(frame, NSMakeRange(replacementRangeStart, replacementRangeEnd - replacementRangeStart));
236 frame->selection()->setSelection(VisibleSelection(replacementRange.get(), SEL_DEFAULT_AFFINITY));
239 frame->editor()->setComposition(text, underlines, selectionStart, selectionEnd);
242 newState = editorState();
245 void WebPage::confirmComposition(EditorState& newState)
247 Frame* frame = m_page->focusController()->focusedOrMainFrame();
249 frame->editor()->confirmComposition();
251 newState = editorState();
254 void WebPage::cancelComposition(EditorState& newState)
256 Frame* frame = m_page->focusController()->focusedOrMainFrame();
258 frame->editor()->cancelComposition();
260 newState = editorState();
263 void WebPage::insertText(const String& text, uint64_t replacementRangeStart, uint64_t replacementRangeEnd, bool& handled, EditorState& newState)
265 Frame* frame = m_page->focusController()->focusedOrMainFrame();
267 RefPtr<Range> replacementRange;
268 if (replacementRangeStart != NSNotFound) {
269 replacementRange = convertToRange(frame, NSMakeRange(replacementRangeStart, replacementRangeEnd - replacementRangeStart));
270 frame->selection()->setSelection(VisibleSelection(replacementRange.get(), SEL_DEFAULT_AFFINITY));
273 if (!frame->editor()->hasComposition()) {
274 // An insertText: might be handled by other responders in the chain if we don't handle it.
275 // One example is space bar that results in scrolling down the page.
276 handled = frame->editor()->insertText(text, m_keyboardEventBeingInterpreted);
279 frame->editor()->confirmComposition(text);
282 newState = editorState();
285 void WebPage::getMarkedRange(uint64_t& location, uint64_t& length)
287 location = NSNotFound;
289 Frame* frame = m_page->focusController()->focusedOrMainFrame();
293 RefPtr<Range> range = frame->editor()->compositionRange();
296 if (range && TextIterator::getLocationAndLengthFromRange(frame->selection()->rootEditableElementOrDocumentElement(), range.get(), locationSize, lengthSize)) {
297 location = static_cast<uint64_t>(locationSize);
298 length = static_cast<uint64_t>(lengthSize);
302 void WebPage::getSelectedRange(uint64_t& location, uint64_t& length)
304 location = NSNotFound;
306 Frame* frame = m_page->focusController()->focusedOrMainFrame();
312 RefPtr<Range> range = frame->selection()->toNormalizedRange();
313 if (range && TextIterator::getLocationAndLengthFromRange(frame->selection()->rootEditableElementOrDocumentElement(), range.get(), locationSize, lengthSize)) {
314 location = static_cast<uint64_t>(locationSize);
315 length = static_cast<uint64_t>(lengthSize);
319 void WebPage::getAttributedSubstringFromRange(uint64_t location, uint64_t length, AttributedString& result)
321 NSRange nsRange = NSMakeRange(location, length - location);
323 Frame* frame = m_page->focusController()->focusedOrMainFrame();
327 if (frame->selection()->isNone() || !frame->selection()->isContentEditable() || frame->selection()->isInPasswordField())
330 RefPtr<Range> range = convertToRange(frame, nsRange);
334 result.string = [WebHTMLConverter editingAttributedStringFromRange:range.get()];
335 NSAttributedString* attributedString = result.string.get();
337 // [WebHTMLConverter editingAttributedStringFromRange:] insists on inserting a trailing
338 // whitespace at the end of the string which breaks the ATOK input method. <rdar://problem/5400551>
339 // To work around this we truncate the resultant string to the correct length.
340 if ([attributedString length] > nsRange.length) {
341 ASSERT([attributedString length] == nsRange.length + 1);
342 ASSERT([[attributedString string] characterAtIndex:nsRange.length] == '\n' || [[attributedString string] characterAtIndex:nsRange.length] == ' ');
343 result.string = [attributedString attributedSubstringFromRange:NSMakeRange(0, nsRange.length)];
347 void WebPage::characterIndexForPoint(IntPoint point, uint64_t& index)
350 Frame* frame = m_page->mainFrame();
354 HitTestResult result = frame->eventHandler()->hitTestResultAtPoint(point, false);
355 frame = result.innerNonSharedNode() ? result.innerNonSharedNode()->document()->frame() : m_page->focusController()->focusedOrMainFrame();
357 RefPtr<Range> range = frame->rangeForPoint(result.point());
363 if (TextIterator::getLocationAndLengthFromRange(frame->selection()->rootEditableElementOrDocumentElement(), range.get(), location, length))
364 index = static_cast<uint64_t>(location);
367 PassRefPtr<Range> convertToRange(Frame* frame, NSRange nsrange)
369 if (nsrange.location > INT_MAX)
371 if (nsrange.length > INT_MAX || nsrange.location + nsrange.length > INT_MAX)
372 nsrange.length = INT_MAX - nsrange.location;
374 // our critical assumption is that we are only called by input methods that
375 // concentrate on a given area containing the selection
376 // We have to do this because of text fields and textareas. The DOM for those is not
377 // directly in the document DOM, so serialization is problematic. Our solution is
378 // to use the root editable element of the selection start as the positional base.
379 // That fits with AppKit's idea of an input context.
380 return TextIterator::rangeFromLocationAndLength(frame->selection()->rootEditableElementOrDocumentElement(), nsrange.location, nsrange.length);
383 void WebPage::firstRectForCharacterRange(uint64_t location, uint64_t length, WebCore::IntRect& resultRect)
385 Frame* frame = m_page->focusController()->focusedOrMainFrame();
386 resultRect.setLocation(IntPoint(0, 0));
387 resultRect.setSize(IntSize(0, 0));
389 RefPtr<Range> range = convertToRange(frame, NSMakeRange(location, length));
393 ASSERT(range->startContainer());
394 ASSERT(range->endContainer());
396 IntRect rect = frame->editor()->firstRectForRange(range.get());
397 resultRect = frame->view()->contentsToWindow(rect);
400 void WebPage::executeKeypressCommands(const Vector<WebCore::KeypressCommand>& commands, bool& handled, EditorState& newState)
402 handled = executeKeypressCommandsInternal(commands, m_keyboardEventBeingInterpreted);
403 newState = editorState();
406 static bool isPositionInRange(const VisiblePosition& position, Range* range)
408 RefPtr<Range> positionRange = makeRange(position, position);
410 ExceptionCode ec = 0;
411 range->compareBoundaryPoints(Range::START_TO_START, positionRange.get(), ec);
415 if (!range->isPointInRange(positionRange->startContainer(), positionRange->startOffset(), ec))
423 static bool shouldUseSelection(const VisiblePosition& position, const VisibleSelection& selection)
425 if (!selection.isRange())
428 RefPtr<Range> selectedRange = selection.toNormalizedRange();
432 return isPositionInRange(position, selectedRange.get());
435 void WebPage::performDictionaryLookupAtLocation(const FloatPoint& floatPoint)
437 Frame* frame = m_page->mainFrame();
441 // Find the frame the point is over.
442 IntPoint point = roundedIntPoint(floatPoint);
443 HitTestResult result = frame->eventHandler()->hitTestResultAtPoint(point, false);
444 frame = result.innerNonSharedNode() ? result.innerNonSharedNode()->document()->frame() : m_page->focusController()->focusedOrMainFrame();
446 IntPoint translatedPoint = frame->view()->windowToContents(point);
448 // Don't do anything if there is no character at the point.
449 if (!frame->rangeForPoint(translatedPoint))
452 VisiblePosition position = frame->visiblePositionForPoint(translatedPoint);
453 VisibleSelection selection = m_page->focusController()->focusedOrMainFrame()->selection()->selection();
454 if (shouldUseSelection(position, selection)) {
455 performDictionaryLookupForSelection(DictionaryPopupInfo::HotKey, frame, selection);
459 NSDictionary *options = nil;
461 #if !defined(BUILDING_ON_SNOW_LEOPARD)
462 // As context, we are going to use the surrounding paragraph of text.
463 VisiblePosition paragraphStart = startOfParagraph(position);
464 VisiblePosition paragraphEnd = endOfParagraph(position);
466 NSRange rangeToPass = NSMakeRange(TextIterator::rangeLength(makeRange(paragraphStart, position).get()), 0);
468 RefPtr<Range> fullCharacterRange = makeRange(paragraphStart, paragraphEnd);
469 String fullPlainTextString = plainText(fullCharacterRange.get());
471 NSRange extractedRange = WKExtractWordDefinitionTokenRangeFromContextualString(fullPlainTextString, rangeToPass, &options);
473 RefPtr<Range> finalRange = TextIterator::subrange(fullCharacterRange.get(), extractedRange.location, extractedRange.length);
477 RefPtr<Range> finalRange = makeRange(startOfWord(position), endOfWord(position));
482 performDictionaryLookupForRange(DictionaryPopupInfo::HotKey, frame, finalRange.get(), options);
485 void WebPage::performDictionaryLookupForSelection(DictionaryPopupInfo::Type type, Frame* frame, const VisibleSelection& selection)
487 RefPtr<Range> selectedRange = selection.toNormalizedRange();
491 NSDictionary *options = nil;
493 #if !defined(BUILDING_ON_SNOW_LEOPARD)
494 VisiblePosition selectionStart = selection.visibleStart();
495 VisiblePosition selectionEnd = selection.visibleEnd();
497 // As context, we are going to use the surrounding paragraphs of text.
498 VisiblePosition paragraphStart = startOfParagraph(selectionStart);
499 VisiblePosition paragraphEnd = endOfParagraph(selectionEnd);
501 int lengthToSelectionStart = TextIterator::rangeLength(makeRange(paragraphStart, selectionStart).get());
502 int lengthToSelectionEnd = TextIterator::rangeLength(makeRange(paragraphStart, selectionEnd).get());
503 NSRange rangeToPass = NSMakeRange(lengthToSelectionStart, lengthToSelectionEnd - lengthToSelectionStart);
505 String fullPlainTextString = plainText(makeRange(paragraphStart, paragraphEnd).get());
507 // Since we already have the range we want, we just need to grab the returned options.
508 WKExtractWordDefinitionTokenRangeFromContextualString(fullPlainTextString, rangeToPass, &options);
511 performDictionaryLookupForRange(type, frame, selectedRange.get(), options);
514 void WebPage::performDictionaryLookupForRange(DictionaryPopupInfo::Type type, Frame* frame, Range* range, NSDictionary *options)
516 String rangeText = range->text();
517 if (rangeText.stripWhiteSpace().isEmpty())
520 RenderObject* renderer = range->startContainer()->renderer();
521 RenderStyle* style = renderer->style();
522 NSFont *font = style->font().primaryFont()->getNSFont();
524 // We won't be able to get an NSFont in the case that a Web Font is being used, so use
525 // the default system font at the same size instead.
527 font = [NSFont systemFontOfSize:style->font().primaryFont()->platformData().size()];
529 CFDictionaryRef fontDescriptorAttributes = (CFDictionaryRef)[[font fontDescriptor] fontAttributes];
530 if (!fontDescriptorAttributes)
533 Vector<FloatQuad> quads;
534 range->textQuads(quads);
538 IntRect rangeRect = frame->view()->contentsToWindow(quads[0].enclosingBoundingBox());
540 DictionaryPopupInfo dictionaryPopupInfo;
541 dictionaryPopupInfo.type = type;
542 dictionaryPopupInfo.origin = FloatPoint(rangeRect.x(), rangeRect.y());
543 dictionaryPopupInfo.fontInfo.fontAttributeDictionary = fontDescriptorAttributes;
544 #if !defined(BUILDING_ON_SNOW_LEOPARD)
545 dictionaryPopupInfo.options = (CFDictionaryRef)options;
548 send(Messages::WebPageProxy::DidPerformDictionaryLookup(rangeText, dictionaryPopupInfo));
551 bool WebPage::performNonEditingBehaviorForSelector(const String& selector)
553 // FIXME: All these selectors have corresponding Editor commands, but the commands only work in editable content.
554 // Should such non-editing behaviors be implemented in Editor or EventHandler::defaultArrowEventHandler() perhaps?
555 if (selector == "moveUp:")
556 scroll(m_page.get(), ScrollUp, ScrollByLine);
557 else if (selector == "moveToBeginningOfParagraph:")
558 scroll(m_page.get(), ScrollUp, ScrollByPage);
559 else if (selector == "moveToBeginningOfDocument:") {
560 scroll(m_page.get(), ScrollUp, ScrollByDocument);
561 scroll(m_page.get(), ScrollLeft, ScrollByDocument);
562 } else if (selector == "moveDown:")
563 scroll(m_page.get(), ScrollDown, ScrollByLine);
564 else if (selector == "moveToEndOfParagraph:")
565 scroll(m_page.get(), ScrollDown, ScrollByPage);
566 else if (selector == "moveToEndOfDocument:") {
567 scroll(m_page.get(), ScrollDown, ScrollByDocument);
568 scroll(m_page.get(), ScrollLeft, ScrollByDocument);
569 } else if (selector == "moveLeft:")
570 scroll(m_page.get(), ScrollLeft, ScrollByLine);
571 else if (selector == "moveWordLeft:")
572 scroll(m_page.get(), ScrollLeft, ScrollByPage);
573 else if (selector == "moveToLeftEndOfLine:")
575 else if (selector == "moveRight:")
576 scroll(m_page.get(), ScrollRight, ScrollByLine);
577 else if (selector == "moveWordRight:")
578 scroll(m_page.get(), ScrollRight, ScrollByPage);
579 else if (selector == "moveToRightEndOfLine:")
587 bool WebPage::performDefaultBehaviorForKeyEvent(const WebKeyboardEvent&)
592 void WebPage::registerUIProcessAccessibilityTokens(const CoreIPC::DataReference& elementToken, const CoreIPC::DataReference& windowToken)
594 NSData* elementTokenData = [NSData dataWithBytes:elementToken.data() length:elementToken.size()];
595 NSData* windowTokenData = [NSData dataWithBytes:windowToken.data() length:windowToken.size()];
596 id remoteElement = WKAXRemoteElementForToken(elementTokenData);
597 id remoteWindow = WKAXRemoteElementForToken(windowTokenData);
598 WKAXSetWindowForRemoteElement(remoteWindow, remoteElement);
600 [accessibilityRemoteObject() setRemoteParent:remoteElement];
603 void WebPage::writeSelectionToPasteboard(const String& pasteboardName, const Vector<String>& pasteboardTypes, bool& result)
605 Frame* frame = m_page->focusController()->focusedOrMainFrame();
606 if (!frame || frame->selection()->isNone()) {
610 frame->editor()->writeSelectionToPasteboard(pasteboardName, pasteboardTypes);
614 void WebPage::readSelectionFromPasteboard(const String& pasteboardName, bool& result)
616 Frame* frame = m_page->focusController()->focusedOrMainFrame();
617 if (!frame || frame->selection()->isNone()) {
621 frame->editor()->readSelectionFromPasteboard(pasteboardName);
625 WKAccessibilityWebPageObject* WebPage::accessibilityRemoteObject()
627 return m_mockAccessibilityElement.get();
630 bool WebPage::platformHasLocalDataForURL(const WebCore::KURL& url)
632 NSMutableURLRequest* request = [[NSMutableURLRequest alloc] initWithURL:url];
633 [request setValue:(NSString*)userAgent() forHTTPHeaderField:@"User-Agent"];
634 NSCachedURLResponse *cachedResponse;
635 #if USE(CFURLSTORAGESESSIONS)
636 if (CFURLStorageSessionRef storageSession = ResourceHandle::currentStorageSession())
637 cachedResponse = WKCachedResponseForRequest(storageSession, request);
640 cachedResponse = [[NSURLCache sharedURLCache] cachedResponseForRequest:request];
643 return cachedResponse;
646 static NSCachedURLResponse *cachedResponseForURL(WebPage* webPage, const KURL& url)
648 RetainPtr<NSMutableURLRequest> request(AdoptNS, [[NSMutableURLRequest alloc] initWithURL:url]);
649 [request.get() setValue:(NSString *)webPage->userAgent() forHTTPHeaderField:@"User-Agent"];
651 #if USE(CFURLSTORAGESESSIONS)
652 if (CFURLStorageSessionRef storageSession = ResourceHandle::currentStorageSession())
653 return WKCachedResponseForRequest(storageSession, request.get());
656 return [[NSURLCache sharedURLCache] cachedResponseForRequest:request.get()];
659 String WebPage::cachedSuggestedFilenameForURL(const KURL& url)
661 return [[cachedResponseForURL(this, url) response] suggestedFilename];
664 String WebPage::cachedResponseMIMETypeForURL(const KURL& url)
666 return [[cachedResponseForURL(this, url) response] MIMEType];
669 PassRefPtr<SharedBuffer> WebPage::cachedResponseDataForURL(const KURL& url)
671 return SharedBuffer::wrapNSData([cachedResponseForURL(this, url) data]);
674 bool WebPage::platformCanHandleRequest(const WebCore::ResourceRequest& request)
676 if ([NSURLConnection canHandleRequest:request.nsURLRequest()])
679 // FIXME: Return true if this scheme is any one WebKit2 knows how to handle.
680 return request.url().protocolIs("applewebdata");
683 void WebPage::shouldDelayWindowOrderingEvent(const WebKit::WebMouseEvent& event, bool& result)
686 Frame* frame = m_page->focusController()->focusedOrMainFrame();
690 HitTestResult hitResult = frame->eventHandler()->hitTestResultAtPoint(event.position(), true);
691 if (hitResult.isSelected())
692 result = frame->eventHandler()->eventMayStartDrag(platform(event));
695 void WebPage::acceptsFirstMouse(int eventNumber, const WebKit::WebMouseEvent& event, bool& result)
698 Frame* frame = m_page->focusController()->focusedOrMainFrame();
702 HitTestResult hitResult = frame->eventHandler()->hitTestResultAtPoint(event.position(), true);
703 frame->eventHandler()->setActivationEventNumber(eventNumber);
704 if (hitResult.isSelected())
705 result = frame->eventHandler()->eventMayStartDrag(platform(event));
707 result = !!hitResult.scrollbar();
710 } // namespace WebKit