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