• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2010 Apple Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
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.
12  *
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.
24  */
25 
26 #include "config.h"
27 #include "WebPage.h"
28 
29 #include "FontSmoothingLevel.h"
30 #include "WebEvent.h"
31 #include "WebPageProxyMessages.h"
32 #include "WebPreferencesStore.h"
33 #include <WebCore/FocusController.h>
34 #include <WebCore/FontRenderingMode.h>
35 #include <WebCore/Frame.h>
36 #include <WebCore/FrameView.h>
37 #include <WebCore/HitTestRequest.h>
38 #include <WebCore/HitTestResult.h>
39 #include <WebCore/KeyboardEvent.h>
40 #include <WebCore/Page.h>
41 #include <WebCore/PlatformKeyboardEvent.h>
42 #include <WebCore/RenderLayer.h>
43 #include <WebCore/RenderView.h>
44 #include <WebCore/ResourceHandle.h>
45 #include <WebCore/Settings.h>
46 #if USE(CG)
47 #include <WebKitSystemInterface/WebKitSystemInterface.h>
48 #endif
49 #include <WinUser.h>
50 
51 #if USE(CFNETWORK)
52 #include <CFNetwork/CFURLCachePriv.h>
53 #include <CFNetwork/CFURLProtocolPriv.h>
54 #include <CFNetwork/CFURLRequestPriv.h>
55 #endif
56 
57 using namespace WebCore;
58 
59 namespace WebKit {
60 
platformInitialize()61 void WebPage::platformInitialize()
62 {
63     m_page->settings()->setFontRenderingMode(AlternateRenderingMode);
64 }
65 
platformPreferencesDidChange(const WebPreferencesStore & store)66 void WebPage::platformPreferencesDidChange(const WebPreferencesStore& store)
67 {
68     FontSmoothingLevel fontSmoothingLevel = static_cast<FontSmoothingLevel>(store.getUInt32ValueForKey(WebPreferencesKey::fontSmoothingLevelKey()));
69 
70 #if USE(CG)
71     FontSmoothingLevel adjustedLevel = fontSmoothingLevel;
72     if (adjustedLevel == FontSmoothingLevelWindows)
73         adjustedLevel = FontSmoothingLevelMedium;
74     wkSetFontSmoothingLevel(adjustedLevel);
75 #endif
76 
77     m_page->settings()->setFontRenderingMode(fontSmoothingLevel == FontSmoothingLevelWindows ? AlternateRenderingMode : NormalRenderingMode);
78 }
79 
80 static const unsigned CtrlKey = 1 << 0;
81 static const unsigned AltKey = 1 << 1;
82 static const unsigned ShiftKey = 1 << 2;
83 
84 struct KeyDownEntry {
85     unsigned virtualKey;
86     unsigned modifiers;
87     const char* name;
88 };
89 
90 struct KeyPressEntry {
91     unsigned charCode;
92     unsigned modifiers;
93     const char* name;
94 };
95 
96 static const KeyDownEntry keyDownEntries[] = {
97     { VK_LEFT,   0,                  "MoveLeft"                                    },
98     { VK_LEFT,   ShiftKey,           "MoveLeftAndModifySelection"                  },
99     { VK_LEFT,   CtrlKey,            "MoveWordLeft"                                },
100     { VK_LEFT,   CtrlKey | ShiftKey, "MoveWordLeftAndModifySelection"              },
101     { VK_RIGHT,  0,                  "MoveRight"                                   },
102     { VK_RIGHT,  ShiftKey,           "MoveRightAndModifySelection"                 },
103     { VK_RIGHT,  CtrlKey,            "MoveWordRight"                               },
104     { VK_RIGHT,  CtrlKey | ShiftKey, "MoveWordRightAndModifySelection"             },
105     { VK_UP,     0,                  "MoveUp"                                      },
106     { VK_UP,     ShiftKey,           "MoveUpAndModifySelection"                    },
107     { VK_PRIOR,  ShiftKey,           "MovePageUpAndModifySelection"                },
108     { VK_DOWN,   0,                  "MoveDown"                                    },
109     { VK_DOWN,   ShiftKey,           "MoveDownAndModifySelection"                  },
110     { VK_NEXT,   ShiftKey,           "MovePageDownAndModifySelection"              },
111     { VK_PRIOR,  0,                  "MovePageUp"                                  },
112     { VK_NEXT,   0,                  "MovePageDown"                                },
113     { VK_HOME,   0,                  "MoveToBeginningOfLine"                       },
114     { VK_HOME,   ShiftKey,           "MoveToBeginningOfLineAndModifySelection"     },
115     { VK_HOME,   CtrlKey,            "MoveToBeginningOfDocument"                   },
116     { VK_HOME,   CtrlKey | ShiftKey, "MoveToBeginningOfDocumentAndModifySelection" },
117 
118     { VK_END,    0,                  "MoveToEndOfLine"                             },
119     { VK_END,    ShiftKey,           "MoveToEndOfLineAndModifySelection"           },
120     { VK_END,    CtrlKey,            "MoveToEndOfDocument"                         },
121     { VK_END,    CtrlKey | ShiftKey, "MoveToEndOfDocumentAndModifySelection"       },
122 
123     { VK_BACK,   0,                  "DeleteBackward"                              },
124     { VK_BACK,   ShiftKey,           "DeleteBackward"                              },
125     { VK_DELETE, 0,                  "DeleteForward"                               },
126     { VK_BACK,   CtrlKey,            "DeleteWordBackward"                          },
127     { VK_DELETE, CtrlKey,            "DeleteWordForward"                           },
128 
129     { 'B',       CtrlKey,            "ToggleBold"                                  },
130     { 'I',       CtrlKey,            "ToggleItalic"                                },
131 
132     { VK_ESCAPE, 0,                  "Cancel"                                      },
133     { VK_OEM_PERIOD, CtrlKey,        "Cancel"                                      },
134     { VK_TAB,    0,                  "InsertTab"                                   },
135     { VK_TAB,    ShiftKey,           "InsertBacktab"                               },
136     { VK_RETURN, 0,                  "InsertNewline"                               },
137     { VK_RETURN, CtrlKey,            "InsertNewline"                               },
138     { VK_RETURN, AltKey,             "InsertNewline"                               },
139     { VK_RETURN, ShiftKey,           "InsertNewline"                               },
140     { VK_RETURN, AltKey | ShiftKey,  "InsertNewline"                               },
141 
142     // It's not quite clear whether clipboard shortcuts and Undo/Redo should be handled
143     // in the application or in WebKit. We chose WebKit.
144     { 'C',       CtrlKey,            "Copy"                                        },
145     { 'V',       CtrlKey,            "Paste"                                       },
146     { 'X',       CtrlKey,            "Cut"                                         },
147     { 'A',       CtrlKey,            "SelectAll"                                   },
148     { VK_INSERT, CtrlKey,            "Copy"                                        },
149     { VK_DELETE, ShiftKey,           "Cut"                                         },
150     { VK_INSERT, ShiftKey,           "Paste"                                       },
151     { 'Z',       CtrlKey,            "Undo"                                        },
152     { 'Z',       CtrlKey | ShiftKey, "Redo"                                        },
153 };
154 
155 static const KeyPressEntry keyPressEntries[] = {
156     { '\t',   0,                  "InsertTab"                                   },
157     { '\t',   ShiftKey,           "InsertBacktab"                               },
158     { '\r',   0,                  "InsertNewline"                               },
159     { '\r',   CtrlKey,            "InsertNewline"                               },
160     { '\r',   AltKey,             "InsertNewline"                               },
161     { '\r',   ShiftKey,           "InsertNewline"                               },
162     { '\r',   AltKey | ShiftKey,  "InsertNewline"                               },
163 };
164 
interpretKeyEvent(const KeyboardEvent * evt)165 const char* WebPage::interpretKeyEvent(const KeyboardEvent* evt)
166 {
167     ASSERT(evt->type() == eventNames().keydownEvent || evt->type() == eventNames().keypressEvent);
168 
169     static HashMap<int, const char*>* keyDownCommandsMap = 0;
170     static HashMap<int, const char*>* keyPressCommandsMap = 0;
171 
172     if (!keyDownCommandsMap) {
173         keyDownCommandsMap = new HashMap<int, const char*>;
174         keyPressCommandsMap = new HashMap<int, const char*>;
175 
176         for (size_t i = 0; i < WTF_ARRAY_LENGTH(keyDownEntries); ++i)
177             keyDownCommandsMap->set(keyDownEntries[i].modifiers << 16 | keyDownEntries[i].virtualKey, keyDownEntries[i].name);
178 
179         for (size_t i = 0; i < WTF_ARRAY_LENGTH(keyPressEntries); ++i)
180             keyPressCommandsMap->set(keyPressEntries[i].modifiers << 16 | keyPressEntries[i].charCode, keyPressEntries[i].name);
181     }
182 
183     unsigned modifiers = 0;
184     if (evt->shiftKey())
185         modifiers |= ShiftKey;
186     if (evt->altKey())
187         modifiers |= AltKey;
188     if (evt->ctrlKey())
189         modifiers |= CtrlKey;
190 
191     if (evt->type() == eventNames().keydownEvent) {
192         int mapKey = modifiers << 16 | evt->keyCode();
193         return mapKey ? keyDownCommandsMap->get(mapKey) : 0;
194     }
195 
196     int mapKey = modifiers << 16 | evt->charCode();
197     return mapKey ? keyPressCommandsMap->get(mapKey) : 0;
198 }
199 
performDefaultBehaviorForKeyEvent(const WebKeyboardEvent & keyboardEvent)200 bool WebPage::performDefaultBehaviorForKeyEvent(const WebKeyboardEvent& keyboardEvent)
201 {
202     if (keyboardEvent.type() != WebEvent::KeyDown && keyboardEvent.type() != WebEvent::RawKeyDown)
203         return false;
204 
205     switch (keyboardEvent.windowsVirtualKeyCode()) {
206     case VK_BACK:
207         if (keyboardEvent.isSystemKey())
208             return false;
209         if (keyboardEvent.shiftKey())
210             m_page->goForward();
211         else
212             m_page->goBack();
213         break;
214     case VK_LEFT:
215         if (keyboardEvent.isSystemKey())
216             m_page->goBack();
217         else
218             scroll(m_page.get(), ScrollLeft, ScrollByLine);
219         break;
220     case VK_RIGHT:
221         if (keyboardEvent.isSystemKey())
222             m_page->goForward();
223         else
224             scroll(m_page.get(), ScrollRight, ScrollByLine);
225         break;
226     case VK_UP:
227         if (keyboardEvent.isSystemKey())
228             return false;
229         scroll(m_page.get(), ScrollUp, ScrollByLine);
230         break;
231     case VK_DOWN:
232         if (keyboardEvent.isSystemKey())
233             return false;
234         scroll(m_page.get(), ScrollDown, ScrollByLine);
235         break;
236     case VK_HOME:
237         if (keyboardEvent.isSystemKey())
238             return false;
239         logicalScroll(m_page.get(), ScrollBlockDirectionBackward, ScrollByDocument);
240         break;
241     case VK_END:
242         if (keyboardEvent.isSystemKey())
243             return false;
244         logicalScroll(m_page.get(), ScrollBlockDirectionForward, ScrollByDocument);
245         break;
246     case VK_PRIOR:
247         if (keyboardEvent.isSystemKey())
248             return false;
249         logicalScroll(m_page.get(), ScrollBlockDirectionBackward, ScrollByPage);
250         break;
251     case VK_NEXT:
252         if (keyboardEvent.isSystemKey())
253             return false;
254         logicalScroll(m_page.get(), ScrollBlockDirectionForward, ScrollByPage);
255         break;
256     default:
257         return false;
258     }
259 
260     return true;
261 }
262 
platformHasLocalDataForURL(const WebCore::KURL & url)263 bool WebPage::platformHasLocalDataForURL(const WebCore::KURL& url)
264 {
265 #if USE(CFNETWORK)
266     RetainPtr<CFURLRef> cfURL(AdoptCF, url.createCFURL());
267     RetainPtr<CFMutableURLRequestRef> request(AdoptCF, CFURLRequestCreateMutable(0, cfURL.get(), kCFURLRequestCachePolicyReloadIgnoringCache, 60, 0));
268 
269     RetainPtr<CFStringRef> userAgent(AdoptCF, userAgent().createCFString());
270     CFURLRequestSetHTTPHeaderFieldValue(request.get(), CFSTR("User-Agent"), userAgent.get());
271 
272     RetainPtr<CFURLCacheRef> cache;
273 #if USE(CFURLSTORAGESESSIONS)
274     if (CFURLStorageSessionRef storageSession = ResourceHandle::privateBrowsingStorageSession())
275         cache.adoptCF(wkCopyURLCache(storageSession));
276     else
277 #endif
278         cache.adoptCF(CFURLCacheCopySharedURLCache());
279 
280     RetainPtr<CFCachedURLResponseRef> response(AdoptCF, CFURLCacheCopyResponseForRequest(cache.get(), request.get()));
281     return response;
282 #else
283     return false;
284 #endif
285 }
286 
cachedResponseMIMETypeForURL(const WebCore::KURL & url)287 String WebPage::cachedResponseMIMETypeForURL(const WebCore::KURL& url)
288 {
289 #if USE(CFNETWORK)
290     RetainPtr<CFURLRef> cfURL(AdoptCF, url.createCFURL());
291     RetainPtr<CFMutableURLRequestRef> request(AdoptCF, CFURLRequestCreateMutable(0, cfURL.get(), kCFURLRequestCachePolicyReloadIgnoringCache, 60, 0));
292 
293     RetainPtr<CFStringRef> userAgent(AdoptCF, userAgent().createCFString());
294     CFURLRequestSetHTTPHeaderFieldValue(request.get(), CFSTR("User-Agent"), userAgent.get());
295 
296     RetainPtr<CFURLCacheRef> cache;
297 #if USE(CFURLSTORAGESESSIONS)
298     if (CFURLStorageSessionRef storageSession = ResourceHandle::privateBrowsingStorageSession())
299         cache.adoptCF(wkCopyURLCache(storageSession));
300     else
301 #endif
302         cache.adoptCF(CFURLCacheCopySharedURLCache());
303 
304     RetainPtr<CFCachedURLResponseRef> cachedResponse(AdoptCF, CFURLCacheCopyResponseForRequest(cache.get(), request.get()));
305 
306     CFURLResponseRef response = CFCachedURLResponseGetWrappedResponse(cachedResponse.get());
307 
308     return response ? CFURLResponseGetMIMEType(response) : String();
309 #else
310     return String();
311 #endif
312 }
313 
platformCanHandleRequest(const WebCore::ResourceRequest & request)314 bool WebPage::platformCanHandleRequest(const WebCore::ResourceRequest& request)
315 {
316 #if USE(CFNETWORK)
317     return CFURLProtocolCanHandleRequest(request.cfURLRequest());
318 #else
319     return true;
320 #endif
321 }
322 
confirmComposition(const String & compositionString)323 void WebPage::confirmComposition(const String& compositionString)
324 {
325     Frame* frame = m_page->focusController()->focusedOrMainFrame();
326     if (!frame || !frame->editor()->canEdit())
327         return;
328     frame->editor()->confirmComposition(compositionString);
329 }
330 
setComposition(const String & compositionString,const Vector<WebCore::CompositionUnderline> & underlines,uint64_t cursorPosition)331 void WebPage::setComposition(const String& compositionString, const Vector<WebCore::CompositionUnderline>& underlines, uint64_t cursorPosition)
332 {
333     Frame* frame = m_page->focusController()->focusedOrMainFrame();
334     if (!frame || !frame->editor()->canEdit())
335         return;
336     frame->editor()->setComposition(compositionString, underlines, cursorPosition, 0);
337 }
338 
firstRectForCharacterInSelectedRange(const uint64_t characterPosition,WebCore::IntRect & resultRect)339 void WebPage::firstRectForCharacterInSelectedRange(const uint64_t characterPosition, WebCore::IntRect& resultRect)
340 {
341     Frame* frame = m_page->focusController()->focusedOrMainFrame();
342     IntRect rect;
343     if (RefPtr<Range> range = frame->editor()->hasComposition() ? frame->editor()->compositionRange() : frame->selection()->selection().toNormalizedRange()) {
344         ExceptionCode ec = 0;
345         RefPtr<Range> tempRange = range->cloneRange(ec);
346         tempRange->setStart(tempRange->startContainer(ec), tempRange->startOffset(ec) + characterPosition, ec);
347         rect = frame->editor()->firstRectForRange(tempRange.get());
348     }
349     resultRect = frame->view()->contentsToWindow(rect);
350 }
351 
getSelectedText(String & text)352 void WebPage::getSelectedText(String& text)
353 {
354     Frame* frame = m_page->focusController()->focusedOrMainFrame();
355     RefPtr<Range> selectedRange = frame->selection()->toNormalizedRange();
356     text = selectedRange->text();
357 }
358 
gestureWillBegin(const WebCore::IntPoint & point,bool & canBeginPanning)359 void WebPage::gestureWillBegin(const WebCore::IntPoint& point, bool& canBeginPanning)
360 {
361     m_gestureReachedScrollingLimit = false;
362 
363     bool hitScrollbar = false;
364 
365     HitTestRequest request(HitTestRequest::ReadOnly);
366     for (Frame* childFrame = m_page->mainFrame(); childFrame; childFrame = EventHandler::subframeForTargetNode(m_gestureTargetNode.get())) {
367         ScrollView* scollView = childFrame->view();
368         if (!scollView)
369             break;
370 
371         RenderView* renderView = childFrame->document()->renderView();
372         if (!renderView)
373             break;
374 
375         RenderLayer* layer = renderView->layer();
376         if (!layer)
377             break;
378 
379         HitTestResult result = scollView->windowToContents(point);
380         layer->hitTest(request, result);
381         m_gestureTargetNode = result.innerNode();
382 
383         if (!hitScrollbar)
384             hitScrollbar = result.scrollbar();
385     }
386 
387     if (hitScrollbar) {
388         canBeginPanning = false;
389         return;
390     }
391 
392     if (!m_gestureTargetNode) {
393         canBeginPanning = false;
394         return;
395     }
396 
397     for (RenderObject* renderer = m_gestureTargetNode->renderer(); renderer; renderer = renderer->parent()) {
398         if (renderer->isBox() && toRenderBox(renderer)->canBeScrolledAndHasScrollableArea()) {
399             canBeginPanning = true;
400             return;
401         }
402     }
403 
404     canBeginPanning = false;
405 }
406 
scrollbarAtTopOrBottomOfDocument(Scrollbar * scrollbar)407 static bool scrollbarAtTopOrBottomOfDocument(Scrollbar* scrollbar)
408 {
409     ASSERT_ARG(scrollbar, scrollbar);
410     return !scrollbar->currentPos() || scrollbar->currentPos() >= scrollbar->maximum();
411 }
412 
gestureDidScroll(const IntSize & size)413 void WebPage::gestureDidScroll(const IntSize& size)
414 {
415     ASSERT_ARG(size, !size.isZero());
416 
417     if (!m_gestureTargetNode || !m_gestureTargetNode->renderer() || !m_gestureTargetNode->renderer()->enclosingLayer())
418         return;
419 
420     Scrollbar* verticalScrollbar = 0;
421     if (Frame* frame = m_page->mainFrame()) {
422         if (ScrollView* view = frame->view())
423             verticalScrollbar = view->verticalScrollbar();
424     }
425 
426     m_gestureTargetNode->renderer()->enclosingLayer()->scrollByRecursively(size.width(), size.height());
427     bool gestureReachedScrollingLimit = verticalScrollbar && scrollbarAtTopOrBottomOfDocument(verticalScrollbar);
428 
429     // FIXME: We really only want to update this state if the state was updated via scrolling the main frame,
430     // not scrolling something in a main frame when the main frame had already reached its scrolling limit.
431 
432     if (gestureReachedScrollingLimit == m_gestureReachedScrollingLimit)
433         return;
434 
435     send(Messages::WebPageProxy::SetGestureReachedScrollingLimit(gestureReachedScrollingLimit));
436     m_gestureReachedScrollingLimit = gestureReachedScrollingLimit;
437 }
438 
gestureDidEnd()439 void WebPage::gestureDidEnd()
440 {
441     m_gestureTargetNode = nullptr;
442 }
443 
444 } // namespace WebKit
445