[chromium] move EventSender into TestRunner.a
[WebKit-https.git] / Tools / DumpRenderTree / chromium / WebViewHost.cpp
1 /*
2  * Copyright (C) 2010, 2011, 2012 Google 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 are
6  * met:
7  *
8  *     * Redistributions of source code must retain the above copyright
9  * notice, this list of conditions and the following disclaimer.
10  *     * Redistributions in binary form must reproduce the above
11  * copyright notice, this list of conditions and the following disclaimer
12  * in the documentation and/or other materials provided with the
13  * distribution.
14  *     * Neither the name of Google Inc. nor the names of its
15  * contributors may be used to endorse or promote products derived from
16  * this software without specific prior written permission.
17  *
18  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29  */
30
31 #include "config.h"
32 #include "WebViewHost.h"
33
34 #include "EventSender.h"
35 #include "LayoutTestController.h"
36 #include "MockGrammarCheck.h"
37 #include "MockWebSpeechInputController.h"
38 #include "MockWebSpeechRecognizer.h"
39 #include "TestNavigationController.h"
40 #include "TestShell.h"
41 #include "TestWebPlugin.h"
42 #include "platform/WebCString.h"
43 #include "WebConsoleMessage.h"
44 #include "WebContextMenuData.h"
45 #include "WebDOMMessageEvent.h"
46 #include "WebDataSource.h"
47 #include "WebDeviceOrientationClientMock.h"
48 #include "WebDocument.h"
49 #include "platform/WebDragData.h"
50 #include "WebElement.h"
51 #include "WebFrame.h"
52 #include "WebGeolocationClientMock.h"
53 #include "WebHistoryItem.h"
54 #include "WebIntent.h"
55 #include "WebIntentServiceInfo.h"
56 #include "WebKit.h"
57 #include "WebNode.h"
58 #include "WebPluginParams.h"
59 #include "WebPopupMenu.h"
60 #include "WebPopupType.h"
61 #include "WebPrintParams.h"
62 #include "WebRange.h"
63 #include "platform/WebRect.h"
64 #include "WebScreenInfo.h"
65 #include "platform/WebSerializedScriptValue.h"
66 #include "platform/WebSize.h"
67 #include "WebStorageNamespace.h"
68 #include "WebTextCheckingCompletion.h"
69 #include "WebTextCheckingResult.h"
70 #include "WebUserMediaClientMock.h"
71 #include "platform/WebThread.h"
72 #include "platform/WebURLRequest.h"
73 #include "platform/WebURLResponse.h"
74 #include "WebView.h"
75 #include "WebWindowFeatures.h"
76 #include "skia/ext/platform_canvas.h"
77 #include "webkit/support/test_media_stream_client.h"
78 #include "webkit/support/webkit_support.h"
79
80 #include <wtf/Assertions.h>
81 #include <wtf/PassOwnPtr.h>
82 #include <wtf/Vector.h>
83
84 using namespace WebCore;
85 using namespace WebKit;
86 using namespace std;
87
88 static const int screenWidth = 1920;
89 static const int screenHeight = 1080;
90 static const int screenUnavailableBorder = 8;
91
92 // WebNavigationType debugging strings taken from PolicyDelegate.mm.
93 static const char* linkClickedString = "link clicked";
94 static const char* formSubmittedString = "form submitted";
95 static const char* backForwardString = "back/forward";
96 static const char* reloadString = "reload";
97 static const char* formResubmittedString = "form resubmitted";
98 static const char* otherString = "other";
99 static const char* illegalString = "illegal value";
100
101 static int nextPageID = 1;
102
103 // Used to write a platform neutral file:/// URL by only taking the filename
104 // (e.g., converts "file:///tmp/foo.txt" to just "foo.txt").
105 static string urlSuitableForTestResult(const string& url)
106 {
107     if (url.empty() || string::npos == url.find("file://"))
108         return url;
109
110     size_t pos = url.rfind('/');
111     if (pos == string::npos) {
112 #if OS(WINDOWS)
113         pos = url.rfind('\\');
114         if (pos == string::npos)
115             pos = 0;
116 #else
117         pos = 0;
118 #endif
119     }
120     string filename = url.substr(pos + 1);
121     if (filename.empty())
122         return "file:"; // A WebKit test has this in its expected output.
123     return filename;
124 }
125
126 // Used to write a platform neutral file:/// URL by taking the
127 // filename and its directory. (e.g., converts
128 // "file:///tmp/foo/bar.txt" to just "bar.txt").
129 static string descriptionSuitableForTestResult(const string& url)
130 {
131     if (url.empty() || string::npos == url.find("file://"))
132         return url;
133
134     size_t pos = url.rfind('/');
135     if (pos == string::npos || !pos)
136         return "ERROR:" + url;
137     pos = url.rfind('/', pos - 1);
138     if (pos == string::npos)
139         return "ERROR:" + url;
140
141     return url.substr(pos + 1);
142 }
143
144 // Adds a file called "DRTFakeFile" to dragData (CF_HDROP). Use to fake
145 // dragging a file.
146 static void addDRTFakeFileToDataObject(WebDragData* dragData)
147 {
148     WebDragData::Item item;
149     item.storageType = WebDragData::Item::StorageTypeFilename;
150     item.filenameData = WebString::fromUTF8("DRTFakeFile");
151     dragData->addItem(item);
152 }
153
154 // Get a debugging string from a WebNavigationType.
155 static const char* webNavigationTypeToString(WebNavigationType type)
156 {
157     switch (type) {
158     case WebKit::WebNavigationTypeLinkClicked:
159         return linkClickedString;
160     case WebKit::WebNavigationTypeFormSubmitted:
161         return formSubmittedString;
162     case WebKit::WebNavigationTypeBackForward:
163         return backForwardString;
164     case WebKit::WebNavigationTypeReload:
165         return reloadString;
166     case WebKit::WebNavigationTypeFormResubmitted:
167         return formResubmittedString;
168     case WebKit::WebNavigationTypeOther:
169         return otherString;
170     }
171     return illegalString;
172 }
173
174 static string URLDescription(const GURL& url)
175 {
176     if (url.SchemeIs("file"))
177         return url.ExtractFileName();
178     return url.possibly_invalid_spec();
179 }
180
181 static void printResponseDescription(const WebURLResponse& response)
182 {
183     if (response.isNull()) {
184         fputs("(null)", stdout);
185         return;
186     }
187     string url = response.url().spec();
188     printf("<NSURLResponse %s, http status code %d>",
189            descriptionSuitableForTestResult(url).c_str(),
190            response.httpStatusCode());
191 }
192
193 static void printNodeDescription(const WebNode& node, int exception)
194 {
195     if (exception) {
196         fputs("ERROR", stdout);
197         return;
198     }
199     if (node.isNull()) {
200         fputs("(null)", stdout);
201         return;
202     }
203     fputs(node.nodeName().utf8().data(), stdout);
204     const WebNode& parent = node.parentNode();
205     if (!parent.isNull()) {
206         fputs(" > ", stdout);
207         printNodeDescription(parent, 0);
208     }
209 }
210
211 static void printRangeDescription(const WebRange& range)
212 {
213     if (range.isNull()) {
214         fputs("(null)", stdout);
215         return;
216     }
217     printf("range from %d of ", range.startOffset());
218     int exception = 0;
219     WebNode startNode = range.startContainer(exception);
220     printNodeDescription(startNode, exception);
221     printf(" to %d of ", range.endOffset());
222     WebNode endNode = range.endContainer(exception);
223     printNodeDescription(endNode, exception);
224 }
225
226 static string editingActionDescription(WebEditingAction action)
227 {
228     switch (action) {
229     case WebKit::WebEditingActionTyped:
230         return "WebViewInsertActionTyped";
231     case WebKit::WebEditingActionPasted:
232         return "WebViewInsertActionPasted";
233     case WebKit::WebEditingActionDropped:
234         return "WebViewInsertActionDropped";
235     }
236     return "(UNKNOWN ACTION)";
237 }
238
239 static string textAffinityDescription(WebTextAffinity affinity)
240 {
241     switch (affinity) {
242     case WebKit::WebTextAffinityUpstream:
243         return "NSSelectionAffinityUpstream";
244     case WebKit::WebTextAffinityDownstream:
245         return "NSSelectionAffinityDownstream";
246     }
247     return "(UNKNOWN AFFINITY)";
248 }
249
250 // WebViewClient -------------------------------------------------------------
251
252 WebView* WebViewHost::createView(WebFrame*, const WebURLRequest& request, const WebWindowFeatures&, const WebString&, WebNavigationPolicy)
253 {
254     if (!layoutTestController()->canOpenWindows())
255         return 0;
256     if (layoutTestController()->shouldDumpCreateView())
257         fprintf(stdout, "createView(%s)\n", URLDescription(request.url()).c_str());
258     return m_shell->createNewWindow(WebURL())->webView();
259 }
260
261 WebWidget* WebViewHost::createPopupMenu(WebPopupType type)
262 {
263     switch (type) {
264     case WebKit::WebPopupTypeNone:
265     case WebKit::WebPopupTypePage:
266     case WebKit::WebPopupTypeHelperPlugin:
267         break;
268     case WebKit::WebPopupTypeSelect:
269     case WebKit::WebPopupTypeSuggestion:
270         m_popupmenus.append(WebPopupMenu::create(0));
271         return m_popupmenus.last();
272     }
273     return 0;
274 }
275
276 WebWidget* WebViewHost::createPopupMenu(const WebPopupMenuInfo&)
277 {
278     // Do not use this method. It's been replaced by createExternalPopupMenu.
279     ASSERT_NOT_REACHED();
280     return 0;
281 }
282
283 WebStorageNamespace* WebViewHost::createSessionStorageNamespace(unsigned quota)
284 {
285     return webkit_support::CreateSessionStorageNamespace(quota);
286 }
287
288 WebKit::WebGraphicsContext3D* WebViewHost::createGraphicsContext3D(const WebKit::WebGraphicsContext3D::Attributes& attributes)
289 {
290     if (!webView())
291         return 0;
292     return webkit_support::CreateGraphicsContext3D(attributes, webView());
293 }
294
295 void WebViewHost::didAddMessageToConsole(const WebConsoleMessage& message, const WebString& sourceName, unsigned sourceLine)
296 {
297     // This matches win DumpRenderTree's UIDelegate.cpp.
298     if (!m_logConsoleOutput)
299         return;
300     string newMessage;
301     if (!message.text.isEmpty()) {
302         newMessage = message.text.utf8();
303         size_t fileProtocol = newMessage.find("file://");
304         if (fileProtocol != string::npos) {
305             newMessage = newMessage.substr(0, fileProtocol)
306                 + urlSuitableForTestResult(newMessage.substr(fileProtocol));
307         }
308     }
309     printf("CONSOLE MESSAGE: ");
310     if (sourceLine)
311         printf("line %d: ", sourceLine);
312     printf("%s\n", newMessage.data());
313 }
314
315 void WebViewHost::didStartLoading()
316 {
317     m_shell->setIsLoading(true);
318 }
319
320 void WebViewHost::didStopLoading()
321 {
322     if (layoutTestController()->shouldDumpProgressFinishedCallback())
323         fputs("postProgressFinishedNotification\n", stdout);
324     m_shell->setIsLoading(false);
325 }
326
327 // The output from these methods in layout test mode should match that
328 // expected by the layout tests. See EditingDelegate.m in DumpRenderTree.
329
330 bool WebViewHost::shouldBeginEditing(const WebRange& range)
331 {
332     if (layoutTestController()->shouldDumpEditingCallbacks()) {
333         fputs("EDITING DELEGATE: shouldBeginEditingInDOMRange:", stdout);
334         printRangeDescription(range);
335         fputs("\n", stdout);
336     }
337     return layoutTestController()->acceptsEditing();
338 }
339
340 bool WebViewHost::shouldEndEditing(const WebRange& range)
341 {
342     if (layoutTestController()->shouldDumpEditingCallbacks()) {
343         fputs("EDITING DELEGATE: shouldEndEditingInDOMRange:", stdout);
344         printRangeDescription(range);
345         fputs("\n", stdout);
346     }
347     return layoutTestController()->acceptsEditing();
348 }
349
350 bool WebViewHost::shouldInsertNode(const WebNode& node, const WebRange& range, WebEditingAction action)
351 {
352     if (layoutTestController()->shouldDumpEditingCallbacks()) {
353         fputs("EDITING DELEGATE: shouldInsertNode:", stdout);
354         printNodeDescription(node, 0);
355         fputs(" replacingDOMRange:", stdout);
356         printRangeDescription(range);
357         printf(" givenAction:%s\n", editingActionDescription(action).c_str());
358     }
359     return layoutTestController()->acceptsEditing();
360 }
361
362 bool WebViewHost::shouldInsertText(const WebString& text, const WebRange& range, WebEditingAction action)
363 {
364     if (layoutTestController()->shouldDumpEditingCallbacks()) {
365         printf("EDITING DELEGATE: shouldInsertText:%s replacingDOMRange:", text.utf8().data());
366         printRangeDescription(range);
367         printf(" givenAction:%s\n", editingActionDescription(action).c_str());
368     }
369     return layoutTestController()->acceptsEditing();
370 }
371
372 bool WebViewHost::shouldChangeSelectedRange(
373     const WebRange& fromRange, const WebRange& toRange, WebTextAffinity affinity, bool stillSelecting)
374 {
375     if (layoutTestController()->shouldDumpEditingCallbacks()) {
376         fputs("EDITING DELEGATE: shouldChangeSelectedDOMRange:", stdout);
377         printRangeDescription(fromRange);
378         fputs(" toDOMRange:", stdout);
379         printRangeDescription(toRange);
380         printf(" affinity:%s stillSelecting:%s\n",
381                textAffinityDescription(affinity).c_str(),
382                (stillSelecting ? "TRUE" : "FALSE"));
383     }
384     return layoutTestController()->acceptsEditing();
385 }
386
387 bool WebViewHost::shouldDeleteRange(const WebRange& range)
388 {
389     if (layoutTestController()->shouldDumpEditingCallbacks()) {
390         fputs("EDITING DELEGATE: shouldDeleteDOMRange:", stdout);
391         printRangeDescription(range);
392         fputs("\n", stdout);
393     }
394     return layoutTestController()->acceptsEditing();
395 }
396
397 bool WebViewHost::shouldApplyStyle(const WebString& style, const WebRange& range)
398 {
399     if (layoutTestController()->shouldDumpEditingCallbacks()) {
400         printf("EDITING DELEGATE: shouldApplyStyle:%s toElementsInDOMRange:", style.utf8().data());
401         printRangeDescription(range);
402         fputs("\n", stdout);
403     }
404     return layoutTestController()->acceptsEditing();
405 }
406
407 bool WebViewHost::isSmartInsertDeleteEnabled()
408 {
409     return m_smartInsertDeleteEnabled;
410 }
411
412 bool WebViewHost::isSelectTrailingWhitespaceEnabled()
413 {
414     return m_selectTrailingWhitespaceEnabled;
415 }
416
417 void WebViewHost::didBeginEditing()
418 {
419     if (!layoutTestController()->shouldDumpEditingCallbacks())
420         return;
421     fputs("EDITING DELEGATE: webViewDidBeginEditing:WebViewDidBeginEditingNotification\n", stdout);
422 }
423
424 void WebViewHost::didChangeSelection(bool isEmptySelection)
425 {
426     if (layoutTestController()->shouldDumpEditingCallbacks())
427         fputs("EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification\n", stdout);
428     // No need to update clipboard with the selected text in DRT.
429 }
430
431 void WebViewHost::didChangeContents()
432 {
433     if (!layoutTestController()->shouldDumpEditingCallbacks())
434         return;
435     fputs("EDITING DELEGATE: webViewDidChange:WebViewDidChangeNotification\n", stdout);
436 }
437
438 void WebViewHost::didEndEditing()
439 {
440     if (!layoutTestController()->shouldDumpEditingCallbacks())
441         return;
442     fputs("EDITING DELEGATE: webViewDidEndEditing:WebViewDidEndEditingNotification\n", stdout);
443 }
444
445 bool WebViewHost::handleCurrentKeyboardEvent()
446 {
447     if (m_editCommandName.empty())
448         return false;
449     WebFrame* frame = webView()->focusedFrame();
450     if (!frame)
451         return false;
452
453     return frame->executeCommand(WebString::fromUTF8(m_editCommandName), WebString::fromUTF8(m_editCommandValue));
454 }
455
456 // WebKit::WebPrerendererClient
457
458 void WebViewHost::willAddPrerender(WebKit::WebPrerender*)
459 {
460 }
461
462
463 // WebKit::WebSpellCheckClient
464
465 void WebViewHost::spellCheck(const WebString& text, int& misspelledOffset, int& misspelledLength, WebVector<WebString>* optionalSuggestions)
466 {
467     // Check the spelling of the given text.
468     m_spellcheck.spellCheckWord(text, &misspelledOffset, &misspelledLength);
469 }
470
471 void WebViewHost::checkTextOfParagraph(const WebString& text, WebTextCheckingTypeMask mask, WebVector<WebTextCheckingResult>* webResults)
472 {
473     Vector<WebTextCheckingResult> results;
474     if (mask & WebTextCheckingTypeSpelling) {
475         size_t offset = 0;
476         size_t length = text.length();
477         const WebUChar* data = text.data();
478         while (offset < length) {
479             int misspelledPosition = 0;
480             int misspelledLength = 0;
481             m_spellcheck.spellCheckWord(WebString(&data[offset], length - offset), &misspelledPosition, &misspelledLength);
482             if (!misspelledLength)
483                 break;
484             WebTextCheckingResult result;
485             result.type = WebTextCheckingTypeSpelling;
486             result.location = offset + misspelledPosition;
487             result.length = misspelledLength;
488             results.append(result);
489             offset += misspelledPosition + misspelledLength;
490         }
491     }
492     if (mask & WebTextCheckingTypeGrammar)
493         MockGrammarCheck::checkGrammarOfString(text, &results);
494     webResults->assign(results);
495 }
496
497 void WebViewHost::requestCheckingOfText(const WebString& text, WebTextCheckingCompletion* completion)
498 {
499     if (text.isEmpty()) {
500         if (completion)
501             completion->didCancelCheckingText();
502         return;
503     }
504
505     m_lastRequestedTextCheckingCompletion = completion;
506     m_lastRequestedTextCheckString = text;
507     postDelayedTask(new HostMethodTask(this, &WebViewHost::finishLastTextCheck), 0);
508 }
509
510 void WebViewHost::finishLastTextCheck()
511 {
512     Vector<WebTextCheckingResult> results;
513     int offset = 0;
514     String text(m_lastRequestedTextCheckString.data(), m_lastRequestedTextCheckString.length());
515     while (text.length()) {
516         int misspelledPosition = 0;
517         int misspelledLength = 0;
518         m_spellcheck.spellCheckWord(WebString(text.characters(), text.length()), &misspelledPosition, &misspelledLength);
519         if (!misspelledLength)
520             break;
521         Vector<WebString> suggestions;
522         m_spellcheck.fillSuggestionList(WebString(text.characters() + misspelledPosition, misspelledLength), &suggestions);
523         results.append(WebTextCheckingResult(WebTextCheckingTypeSpelling, offset + misspelledPosition, misspelledLength,
524                                              suggestions.isEmpty() ? WebString() : suggestions[0]));
525         text = text.substring(misspelledPosition + misspelledLength);
526         offset += misspelledPosition + misspelledLength;
527     }
528     MockGrammarCheck::checkGrammarOfString(m_lastRequestedTextCheckString, &results);
529     m_lastRequestedTextCheckingCompletion->didFinishCheckingText(results);
530     m_lastRequestedTextCheckingCompletion = 0;
531 }
532
533
534 WebString WebViewHost::autoCorrectWord(const WebString&)
535 {
536     // Returns an empty string as Mac WebKit ('WebKitSupport/WebEditorClient.mm')
537     // does. (If this function returns a non-empty string, WebKit replaces the
538     // given misspelled string with the result one. This process executes some
539     // editor commands and causes layout-test failures.)
540     return WebString();
541 }
542
543 void WebViewHost::runModalAlertDialog(WebFrame*, const WebString& message)
544 {
545     printf("ALERT: %s\n", message.utf8().data());
546 }
547
548 bool WebViewHost::runModalConfirmDialog(WebFrame*, const WebString& message)
549 {
550     printf("CONFIRM: %s\n", message.utf8().data());
551     return true;
552 }
553
554 bool WebViewHost::runModalPromptDialog(WebFrame* frame, const WebString& message,
555                                        const WebString& defaultValue, WebString*)
556 {
557     printf("PROMPT: %s, default text: %s\n", message.utf8().data(), defaultValue.utf8().data());
558     return true;
559 }
560
561 bool WebViewHost::runModalBeforeUnloadDialog(WebFrame*, const WebString& message)
562 {
563     printf("CONFIRM NAVIGATION: %s\n", message.utf8().data());
564     return !layoutTestController()->shouldStayOnPageAfterHandlingBeforeUnload();
565 }
566
567 void WebViewHost::showContextMenu(WebFrame*, const WebContextMenuData& contextMenuData)
568 {
569     m_lastContextMenuData = adoptPtr(new WebContextMenuData(contextMenuData));
570 }
571
572 void WebViewHost::clearContextMenuData()
573 {
574     m_lastContextMenuData.clear();
575 }
576
577 WebContextMenuData* WebViewHost::lastContextMenuData() const
578 {
579     return m_lastContextMenuData.get();
580 }
581
582 void WebViewHost::setStatusText(const WebString& text)
583 {
584     if (!layoutTestController()->shouldDumpStatusCallbacks())
585         return;
586     // When running tests, write to stdout.
587     printf("UI DELEGATE STATUS CALLBACK: setStatusText:%s\n", text.utf8().data());
588 }
589
590 void WebViewHost::startDragging(WebFrame*, const WebDragData& data, WebDragOperationsMask mask, const WebImage&, const WebPoint&)
591 {
592     WebDragData mutableDragData = data;
593     if (layoutTestController()->shouldAddFileToPasteboard()) {
594         // Add a file called DRTFakeFile to the drag&drop clipboard.
595         addDRTFakeFileToDataObject(&mutableDragData);
596     }
597
598     // When running a test, we need to fake a drag drop operation otherwise
599     // Windows waits for real mouse events to know when the drag is over.
600     m_shell->eventSender()->doDragDrop(mutableDragData, mask);
601 }
602
603 void WebViewHost::didUpdateLayout()
604 {
605 #if OS(MAC_OS_X)
606     static bool queryingPreferredSize = false;
607     if (queryingPreferredSize)
608         return;
609
610     queryingPreferredSize = true;
611     // Query preferred width to emulate the same functionality in Chromium:
612     // see RenderView::CheckPreferredSize (src/content/renderer/render_view.cc)
613     // and TabContentsViewMac::RenderViewCreated (src/chrome/browser/tab_contents/tab_contents_view_mac.mm)
614     webView()->mainFrame()->contentsPreferredWidth();
615     webView()->mainFrame()->documentElementScrollHeight();
616     queryingPreferredSize = false;
617 #endif
618 }
619
620 void WebViewHost::navigateBackForwardSoon(int offset)
621 {
622     navigationController()->goToOffset(offset);
623 }
624
625 int WebViewHost::historyBackListCount()
626 {
627     return navigationController()->lastCommittedEntryIndex();
628 }
629
630 int WebViewHost::historyForwardListCount()
631 {
632     int currentIndex =navigationController()->lastCommittedEntryIndex();
633     return navigationController()->entryCount() - currentIndex - 1;
634 }
635
636 void WebViewHost::postAccessibilityNotification(const WebAccessibilityObject& obj, WebAccessibilityNotification notification)
637 {
638     if (notification == WebAccessibilityNotificationFocusedUIElementChanged)
639         m_shell->accessibilityController()->setFocusedElement(obj);
640
641     const char* notificationName;
642     switch (notification) {
643     case WebAccessibilityNotificationActiveDescendantChanged:
644         notificationName = "ActiveDescendantChanged";
645         break;
646     case WebAccessibilityNotificationAutocorrectionOccured:
647         notificationName = "AutocorrectionOccured";
648         break;
649     case WebAccessibilityNotificationCheckedStateChanged:
650         notificationName = "CheckedStateChanged";
651         break;
652     case WebAccessibilityNotificationChildrenChanged:
653         notificationName = "ChildrenChanged";
654         break;
655     case WebAccessibilityNotificationFocusedUIElementChanged:
656         notificationName = "FocusedUIElementChanged";
657         break;
658     case WebAccessibilityNotificationLayoutComplete:
659         notificationName = "LayoutComplete";
660         break;
661     case WebAccessibilityNotificationLoadComplete:
662         notificationName = "LoadComplete";
663         break;
664     case WebAccessibilityNotificationSelectedChildrenChanged:
665         notificationName = "SelectedChildrenChanged";
666         break;
667     case WebAccessibilityNotificationSelectedTextChanged:
668         notificationName = "SelectedTextChanged";
669         break;
670     case WebAccessibilityNotificationValueChanged:
671         notificationName = "ValueChanged";
672         break;
673     case WebAccessibilityNotificationScrolledToAnchor:
674         notificationName = "ScrolledToAnchor";
675         break;
676     case WebAccessibilityNotificationLiveRegionChanged:
677         notificationName = "LiveRegionChanged";
678         break;
679     case WebAccessibilityNotificationMenuListItemSelected:
680         notificationName = "MenuListItemSelected";
681         break;
682     case WebAccessibilityNotificationMenuListValueChanged:
683         notificationName = "MenuListValueChanged";
684         break;
685     case WebAccessibilityNotificationRowCountChanged:
686         notificationName = "RowCountChanged";
687         break;
688     case WebAccessibilityNotificationRowCollapsed:
689         notificationName = "RowCollapsed";
690         break;
691     case WebAccessibilityNotificationRowExpanded:
692         notificationName = "RowExpanded";
693         break;
694     case WebAccessibilityNotificationInvalidStatusChanged:
695         notificationName = "InvalidStatusChanged";
696         break;
697     default:
698         notificationName = "UnknownNotification";
699         break;
700     }
701
702     m_shell->accessibilityController()->notificationReceived(obj, notificationName);
703
704     if (m_shell->accessibilityController()->shouldLogAccessibilityEvents()) {
705         printf("AccessibilityNotification - %s", notificationName);
706
707         WebKit::WebNode node = obj.node();
708         if (!node.isNull() && node.isElementNode()) {
709             WebKit::WebElement element = node.to<WebKit::WebElement>();
710             if (element.hasAttribute("id"))
711                 printf(" - id:%s", element.getAttribute("id").utf8().data());
712         }
713
714         printf("\n");
715     }
716 }
717
718 #if ENABLE(NOTIFICATIONS)
719 WebNotificationPresenter* WebViewHost::notificationPresenter()
720 {
721     return m_shell->notificationPresenter();
722 }
723 #endif
724
725 WebKit::WebGeolocationClient* WebViewHost::geolocationClient()
726 {
727     return geolocationClientMock();
728 }
729
730 WebKit::WebGeolocationClientMock* WebViewHost::geolocationClientMock()
731 {
732     if (!m_geolocationClientMock)
733         m_geolocationClientMock = adoptPtr(WebGeolocationClientMock::create());
734     return m_geolocationClientMock.get();
735 }
736
737 #if ENABLE(INPUT_SPEECH)
738 WebSpeechInputController* WebViewHost::speechInputController(WebKit::WebSpeechInputListener* listener)
739 {
740     if (!m_speechInputControllerMock)
741         m_speechInputControllerMock = MockWebSpeechInputController::create(listener);
742     return m_speechInputControllerMock.get();
743 }
744 #endif
745
746 #if ENABLE(SCRIPTED_SPEECH)
747 WebSpeechRecognizer* WebViewHost::speechRecognizer()
748 {
749     if (!m_mockSpeechRecognizer)
750         m_mockSpeechRecognizer = MockWebSpeechRecognizer::create();
751     return m_mockSpeechRecognizer.get();
752 }
753 #endif
754
755 WebDeviceOrientationClientMock* WebViewHost::deviceOrientationClientMock()
756 {
757     if (!m_deviceOrientationClientMock.get())
758         m_deviceOrientationClientMock = adoptPtr(WebDeviceOrientationClientMock::create());
759     return m_deviceOrientationClientMock.get();
760 }
761
762 MockSpellCheck* WebViewHost::mockSpellCheck()
763 {
764     return &m_spellcheck;
765 }
766
767 void WebViewHost::fillSpellingSuggestionList(const WebKit::WebString& word, Vector<WebKit::WebString>* suggestions)
768 {
769     mockSpellCheck()->fillSuggestionList(word, suggestions);
770 }
771
772 WebDeviceOrientationClient* WebViewHost::deviceOrientationClient()
773 {
774     return deviceOrientationClientMock();
775 }
776
777 #if ENABLE(MEDIA_STREAM)
778 WebUserMediaClient* WebViewHost::userMediaClient()
779 {
780     return userMediaClientMock();
781 }
782
783 WebUserMediaClientMock* WebViewHost::userMediaClientMock()
784 {
785     if (!m_userMediaClientMock.get())
786         m_userMediaClientMock = WebUserMediaClientMock::create();
787     return m_userMediaClientMock.get();
788 }
789 #endif
790
791 // WebWidgetClient -----------------------------------------------------------
792
793 void WebViewHost::didInvalidateRect(const WebRect& rect)
794 {
795     updatePaintRect(rect);
796 }
797
798 void WebViewHost::didScrollRect(int, int, const WebRect& clipRect)
799 {
800     // This is used for optimizing painting when the renderer is scrolled. We're
801     // currently not doing any optimizations so just invalidate the region.
802     didInvalidateRect(clipRect);
803 }
804
805 void WebViewHost::didAutoResize(const WebSize& newSize)
806 {
807     // Purposely don't include the virtualWindowBorder in this case so that
808     // window.inner[Width|Height] is the same as window.outer[Width|Height]
809     setWindowRect(WebRect(0, 0, newSize.width, newSize.height));
810 }
811
812 void WebViewHost::scheduleComposite()
813 {
814     WebSize widgetSize = webWidget()->size();
815     WebRect clientRect(0, 0, widgetSize.width, widgetSize.height);
816     didInvalidateRect(clientRect);
817 }
818
819 #if ENABLE(REQUEST_ANIMATION_FRAME)
820 void WebViewHost::serviceAnimation()
821 {
822     if (webView()->settings()->scrollAnimatorEnabled())
823         webView()->animate(0.0);
824     scheduleComposite();
825 }
826
827 void WebViewHost::scheduleAnimation()
828 {
829     postDelayedTask(new HostMethodTask(this, &WebViewHost::serviceAnimation), 0);
830 }
831 #endif
832
833 void WebViewHost::didFocus()
834 {
835     m_shell->setFocus(webWidget(), true);
836 }
837
838 void WebViewHost::didBlur()
839 {
840     m_shell->setFocus(webWidget(), false);
841 }
842
843 WebScreenInfo WebViewHost::screenInfo()
844 {
845     // We don't need to set actual values.
846     WebScreenInfo info;
847     info.depth = 24;
848     info.depthPerComponent = 8;
849     info.isMonochrome = false;
850     info.rect = WebRect(0, 0, screenWidth, screenHeight);
851     // Use values different from info.rect for testing.
852     info.availableRect = WebRect(screenUnavailableBorder, screenUnavailableBorder,
853                                  screenWidth - screenUnavailableBorder * 2,
854                                  screenHeight - screenUnavailableBorder * 2);
855     return info;
856 }
857
858 #if ENABLE(POINTER_LOCK)
859 bool WebViewHost::requestPointerLock()
860 {
861     switch (m_pointerLockPlannedResult) {
862     case PointerLockWillSucceed:
863         postDelayedTask(new HostMethodTask(this, &WebViewHost::didAcquirePointerLock), 0);
864         return true;
865     case PointerLockWillFailAsync:
866         ASSERT(!m_pointerLocked);
867         postDelayedTask(new HostMethodTask(this, &WebViewHost::didNotAcquirePointerLock), 0);
868         return true;
869     case PointerLockWillFailSync:
870         ASSERT(!m_pointerLocked);
871         return false;
872     default:
873         ASSERT_NOT_REACHED();
874         return false;
875     }
876 }
877
878 void WebViewHost::requestPointerUnlock()
879 {
880     postDelayedTask(new HostMethodTask(this, &WebViewHost::didLosePointerLock), 0);
881 }
882
883 bool WebViewHost::isPointerLocked()
884 {
885     return m_pointerLocked;
886 }
887
888 void WebViewHost::didAcquirePointerLock()
889 {
890     m_pointerLocked = true;
891     webWidget()->didAcquirePointerLock();
892 }
893
894 void WebViewHost::didNotAcquirePointerLock()
895 {
896     ASSERT(!m_pointerLocked);
897     m_pointerLocked = false;
898     webWidget()->didNotAcquirePointerLock();
899 }
900
901 void WebViewHost::didLosePointerLock()
902 {
903     bool wasLocked = m_pointerLocked;
904     m_pointerLocked = false;
905     if (wasLocked)
906         webWidget()->didLosePointerLock();
907 }
908 #endif
909
910 void WebViewHost::show(WebNavigationPolicy)
911 {
912     m_hasWindow = true;
913     WebSize size = webWidget()->size();
914     updatePaintRect(WebRect(0, 0, size.width, size.height));
915 }
916
917
918
919 void WebViewHost::closeWidget()
920 {
921     m_hasWindow = false;
922     m_shell->closeWindow(this);
923     // No more code here, we should be deleted at this point.
924 }
925
926 void WebViewHost::closeWidgetSoon()
927 {
928     postDelayedTask(new HostMethodTask(this, &WebViewHost::closeWidget), 0);
929 }
930
931 void WebViewHost::didChangeCursor(const WebCursorInfo& cursorInfo)
932 {
933     if (!hasWindow())
934         return;
935     m_currentCursor = cursorInfo;
936 }
937
938 WebRect WebViewHost::windowRect()
939 {
940     return m_windowRect;
941 }
942
943 void WebViewHost::setWindowRect(const WebRect& rect)
944 {
945     m_windowRect = rect;
946     const int border2 = TestShell::virtualWindowBorder * 2;
947     if (m_windowRect.width <= border2)
948         m_windowRect.width = 1 + border2;
949     if (m_windowRect.height <= border2)
950         m_windowRect.height = 1 + border2;
951     int width = m_windowRect.width - border2;
952     int height = m_windowRect.height - border2;
953     discardBackingStore();
954     webWidget()->resize(WebSize(width, height));
955     updatePaintRect(WebRect(0, 0, width, height));
956 }
957
958 WebRect WebViewHost::rootWindowRect()
959 {
960     return windowRect();
961 }
962
963 WebRect WebViewHost::windowResizerRect()
964 {
965     // Not necessary.
966     return WebRect();
967 }
968
969 void WebViewHost::runModal()
970 {
971     if (m_shell->isDisplayingModalDialog()) {
972         // DumpRenderTree doesn't support real modal dialogs, so a test shouldn't try to start two modal dialogs at the same time.
973         ASSERT_NOT_REACHED();
974         return;
975     }
976     // This WebViewHost might get deleted before RunMessageLoop() returns, so keep a copy of the m_shell member variable around.
977     ASSERT(m_shell->webViewHost() != this);
978     TestShell* shell = m_shell;
979     shell->setIsDisplayingModalDialog(true);
980     bool oldState = webkit_support::MessageLoopNestableTasksAllowed();
981     webkit_support::MessageLoopSetNestableTasksAllowed(true);
982     m_inModalLoop = true;
983     webkit_support::RunMessageLoop();
984     webkit_support::MessageLoopSetNestableTasksAllowed(oldState);
985     shell->setIsDisplayingModalDialog(false);
986 }
987
988 bool WebViewHost::enterFullScreen()
989 {
990     postDelayedTask(new HostMethodTask(this, &WebViewHost::enterFullScreenNow), 0);
991     return true;
992 }
993
994 void WebViewHost::exitFullScreen()
995 {
996     postDelayedTask(new HostMethodTask(this, &WebViewHost::exitFullScreenNow), 0);
997 }
998
999 // WebFrameClient ------------------------------------------------------------
1000
1001 WebPlugin* WebViewHost::createPlugin(WebFrame* frame, const WebPluginParams& params)
1002 {
1003     if (params.mimeType == TestWebPlugin::mimeType())
1004         return new TestWebPlugin(frame, params);
1005
1006     return webkit_support::CreateWebPlugin(frame, params);
1007 }
1008
1009 WebMediaPlayer* WebViewHost::createMediaPlayer(WebFrame* frame, WebMediaPlayerClient* client)
1010 {
1011 #if ENABLE(MEDIA_STREAM)
1012     return webkit_support::CreateMediaPlayer(frame, client, testMediaStreamClient());
1013 #else
1014     return webkit_support::CreateMediaPlayer(frame, client);
1015 #endif
1016 }
1017
1018 WebApplicationCacheHost* WebViewHost::createApplicationCacheHost(WebFrame* frame, WebApplicationCacheHostClient* client)
1019 {
1020     return webkit_support::CreateApplicationCacheHost(frame, client);
1021 }
1022
1023 void WebViewHost::loadURLExternally(WebFrame* frame, const WebURLRequest& request, WebNavigationPolicy policy)
1024 {
1025     loadURLExternally(frame, request, policy, WebString());
1026 }
1027
1028 void WebViewHost::loadURLExternally(WebFrame*, const WebURLRequest& request, WebNavigationPolicy policy, const WebString& downloadName)
1029 {
1030     ASSERT(policy !=  WebKit::WebNavigationPolicyCurrentTab);
1031     WebViewHost* another = m_shell->createNewWindow(request.url());
1032     if (another)
1033         another->show(policy);
1034 }
1035
1036 WebNavigationPolicy WebViewHost::decidePolicyForNavigation(
1037     WebFrame*, const WebURLRequest& request,
1038     WebNavigationType type, const WebNode& originatingNode,
1039     WebNavigationPolicy defaultPolicy, bool isRedirect)
1040 {
1041     WebNavigationPolicy result;
1042     if (!m_policyDelegateEnabled)
1043         return defaultPolicy;
1044
1045     printf("Policy delegate: attempt to load %s with navigation type '%s'",
1046            URLDescription(request.url()).c_str(), webNavigationTypeToString(type));
1047     if (!originatingNode.isNull()) {
1048         fputs(" originating from ", stdout);
1049         printNodeDescription(originatingNode, 0);
1050     }
1051     fputs("\n", stdout);
1052     if (m_policyDelegateIsPermissive)
1053         result = WebKit::WebNavigationPolicyCurrentTab;
1054     else
1055         result = WebKit::WebNavigationPolicyIgnore;
1056
1057     if (m_policyDelegateShouldNotifyDone)
1058         layoutTestController()->policyDelegateDone();
1059     return result;
1060 }
1061
1062 bool WebViewHost::canHandleRequest(WebFrame*, const WebURLRequest& request)
1063 {
1064     GURL url = request.url();
1065     // Just reject the scheme used in
1066     // LayoutTests/http/tests/misc/redirect-to-external-url.html
1067     return !url.SchemeIs("spaceballs");
1068 }
1069
1070 WebURLError WebViewHost::cannotHandleRequestError(WebFrame*, const WebURLRequest& request)
1071 {
1072     WebURLError error;
1073     // A WebKit layout test expects the following values.
1074     // unableToImplementPolicyWithError() below prints them.
1075     error.domain = WebString::fromUTF8("WebKitErrorDomain");
1076     error.reason = 101;
1077     error.unreachableURL = request.url();
1078     return error;
1079 }
1080
1081 WebURLError WebViewHost::cancelledError(WebFrame*, const WebURLRequest& request)
1082 {
1083     return webkit_support::CreateCancelledError(request);
1084 }
1085
1086 void WebViewHost::unableToImplementPolicyWithError(WebFrame* frame, const WebURLError& error)
1087 {
1088     printf("Policy delegate: unable to implement policy with error domain '%s', "
1089            "error code %d, in frame '%s'\n",
1090            error.domain.utf8().data(), error.reason, frame->name().utf8().data());
1091 }
1092
1093 void WebViewHost::willPerformClientRedirect(WebFrame* frame, const WebURL& from, const WebURL& to,
1094                                             double interval, double fire_time)
1095 {
1096     if (m_shell->shouldDumpFrameLoadCallbacks()) {
1097         printFrameDescription(frame);
1098         printf(" - willPerformClientRedirectToURL: %s \n", to.spec().data());
1099     }
1100
1101     if (m_shell->shouldDumpUserGestureInFrameLoadCallbacks())
1102         printFrameUserGestureStatus(frame, " - in willPerformClientRedirect\n");
1103 }
1104
1105 void WebViewHost::didCancelClientRedirect(WebFrame* frame)
1106 {
1107     if (!m_shell->shouldDumpFrameLoadCallbacks())
1108         return;
1109     printFrameDescription(frame);
1110     fputs(" - didCancelClientRedirectForFrame\n", stdout);
1111 }
1112
1113 void WebViewHost::didCreateDataSource(WebFrame*, WebDataSource* ds)
1114 {
1115     ds->setExtraData(m_pendingExtraData.leakPtr());
1116     if (!layoutTestController()->deferMainResourceDataLoad())
1117         ds->setDeferMainResourceDataLoad(false);
1118 }
1119
1120 void WebViewHost::didStartProvisionalLoad(WebFrame* frame)
1121 {
1122     if (m_shell->shouldDumpFrameLoadCallbacks()) {
1123         printFrameDescription(frame);
1124         fputs(" - didStartProvisionalLoadForFrame\n", stdout);
1125     }
1126
1127     if (m_shell->shouldDumpUserGestureInFrameLoadCallbacks())
1128         printFrameUserGestureStatus(frame, " - in didStartProvisionalLoadForFrame\n");
1129
1130     if (!m_topLoadingFrame)
1131         m_topLoadingFrame = frame;
1132
1133     if (layoutTestController()->stopProvisionalFrameLoads()) {
1134         printFrameDescription(frame);
1135         fputs(" - stopping load in didStartProvisionalLoadForFrame callback\n", stdout);
1136         frame->stopLoading();
1137     }
1138     updateAddressBar(frame->view());
1139 }
1140
1141 void WebViewHost::didReceiveServerRedirectForProvisionalLoad(WebFrame* frame)
1142 {
1143     if (m_shell->shouldDumpFrameLoadCallbacks()) {
1144         printFrameDescription(frame);
1145         fputs(" - didReceiveServerRedirectForProvisionalLoadForFrame\n", stdout);
1146     }
1147     updateAddressBar(frame->view());
1148 }
1149
1150 void WebViewHost::didFailProvisionalLoad(WebFrame* frame, const WebURLError& error)
1151 {
1152     if (m_shell->shouldDumpFrameLoadCallbacks()) {
1153         printFrameDescription(frame);
1154         fputs(" - didFailProvisionalLoadWithError\n", stdout);
1155     }
1156
1157     locationChangeDone(frame);
1158
1159     // Don't display an error page if we're running layout tests, because
1160     // DumpRenderTree doesn't.
1161 }
1162
1163 void WebViewHost::didCommitProvisionalLoad(WebFrame* frame, bool isNewNavigation)
1164 {
1165     if (m_shell->shouldDumpFrameLoadCallbacks()) {
1166         printFrameDescription(frame);
1167         fputs(" - didCommitLoadForFrame\n", stdout);
1168     }
1169     updateForCommittedLoad(frame, isNewNavigation);
1170 }
1171
1172 void WebViewHost::didClearWindowObject(WebFrame* frame)
1173 {
1174     m_shell->bindJSObjectsToWindow(frame);
1175 }
1176
1177 void WebViewHost::didReceiveTitle(WebFrame* frame, const WebString& title, WebTextDirection direction)
1178 {
1179     WebCString title8 = title.utf8();
1180
1181     if (m_shell->shouldDumpFrameLoadCallbacks()) {
1182         printFrameDescription(frame);
1183         printf(" - didReceiveTitle: %s\n", title8.data());
1184     }
1185
1186     if (layoutTestController()->shouldDumpTitleChanges())
1187         printf("TITLE CHANGED: %s\n", title8.data());
1188
1189     setPageTitle(title);
1190     layoutTestController()->setTitleTextDirection(direction);
1191 }
1192
1193 void WebViewHost::didFinishDocumentLoad(WebFrame* frame)
1194 {
1195     if (m_shell->shouldDumpFrameLoadCallbacks()) {
1196         printFrameDescription(frame);
1197         fputs(" - didFinishDocumentLoadForFrame\n", stdout);
1198     } else {
1199         unsigned pendingUnloadEvents = frame->unloadListenerCount();
1200         if (pendingUnloadEvents) {
1201             printFrameDescription(frame);
1202             printf(" - has %u onunload handler(s)\n", pendingUnloadEvents);
1203         }
1204     }
1205 }
1206
1207 void WebViewHost::didHandleOnloadEvents(WebFrame* frame)
1208 {
1209     if (m_shell->shouldDumpFrameLoadCallbacks()) {
1210         printFrameDescription(frame);
1211         fputs(" - didHandleOnloadEventsForFrame\n", stdout);
1212     }
1213 }
1214
1215 void WebViewHost::didFailLoad(WebFrame* frame, const WebURLError& error)
1216 {
1217     if (m_shell->shouldDumpFrameLoadCallbacks()) {
1218         printFrameDescription(frame);
1219         fputs(" - didFailLoadWithError\n", stdout);
1220     }
1221     locationChangeDone(frame);
1222 }
1223
1224 void WebViewHost::didFinishLoad(WebFrame* frame)
1225 {
1226     if (m_shell->shouldDumpFrameLoadCallbacks()) {
1227         printFrameDescription(frame);
1228         fputs(" - didFinishLoadForFrame\n", stdout);
1229     }
1230     updateAddressBar(frame->view());
1231     locationChangeDone(frame);
1232 }
1233
1234 void WebViewHost::didNavigateWithinPage(WebFrame* frame, bool isNewNavigation)
1235 {
1236     frame->dataSource()->setExtraData(m_pendingExtraData.leakPtr());
1237
1238     updateForCommittedLoad(frame, isNewNavigation);
1239 }
1240
1241 void WebViewHost::didChangeLocationWithinPage(WebFrame* frame)
1242 {
1243     if (m_shell->shouldDumpFrameLoadCallbacks()) {
1244         printFrameDescription(frame);
1245         fputs(" - didChangeLocationWithinPageForFrame\n", stdout);
1246     }
1247 }
1248
1249 void WebViewHost::assignIdentifierToRequest(WebFrame*, unsigned identifier, const WebURLRequest& request)
1250 {
1251      if (!m_shell->shouldDumpResourceLoadCallbacks())
1252         return;
1253     ASSERT(!m_resourceIdentifierMap.contains(identifier));
1254     m_resourceIdentifierMap.set(identifier, descriptionSuitableForTestResult(request.url().spec()));
1255 }
1256
1257 void WebViewHost::removeIdentifierForRequest(unsigned identifier)
1258 {
1259     m_resourceIdentifierMap.remove(identifier);
1260 }
1261
1262 static void blockRequest(WebURLRequest& request)
1263 {
1264     request.setURL(WebURL());
1265 }
1266
1267 static bool isLocalhost(const string& host)
1268 {
1269     return host == "127.0.0.1" || host == "localhost";
1270 }
1271
1272 static bool hostIsUsedBySomeTestsToGenerateError(const string& host)
1273 {
1274     return host == "255.255.255.255";
1275 }
1276
1277 void WebViewHost::willSendRequest(WebFrame* frame, unsigned identifier, WebURLRequest& request, const WebURLResponse& redirectResponse)
1278 {
1279     // Need to use GURL for host() and SchemeIs()
1280     GURL url = request.url();
1281     string requestURL = url.possibly_invalid_spec();
1282
1283     GURL mainDocumentURL = request.firstPartyForCookies();
1284     if (layoutTestController()->shouldDumpResourceLoadCallbacks()) {
1285         printResourceDescription(identifier);
1286         printf(" - willSendRequest <NSURLRequest URL %s, main document URL %s,"
1287                " http method %s> redirectResponse ",
1288                descriptionSuitableForTestResult(requestURL).c_str(),
1289                URLDescription(mainDocumentURL).c_str(),
1290                request.httpMethod().utf8().data());
1291         printResponseDescription(redirectResponse);
1292         fputs("\n", stdout);
1293     }
1294
1295     request.setExtraData(webkit_support::CreateWebURLRequestExtraData(frame->document().referrerPolicy()));
1296
1297     if (!redirectResponse.isNull() && m_blocksRedirects) {
1298         fputs("Returning null for this redirect\n", stdout);
1299         blockRequest(request);
1300         return;
1301     }
1302
1303     if (m_requestReturnNull) {
1304         blockRequest(request);
1305         return;
1306     }
1307
1308     string host = url.host();
1309     if (!host.empty() && (url.SchemeIs("http") || url.SchemeIs("https"))) {
1310         if (!isLocalhost(host) && !hostIsUsedBySomeTestsToGenerateError(host)
1311             && ((!mainDocumentURL.SchemeIs("http") && !mainDocumentURL.SchemeIs("https")) || isLocalhost(mainDocumentURL.host()))
1312             && !m_shell->allowExternalPages()) {
1313             printf("Blocked access to external URL %s\n", requestURL.c_str());
1314             blockRequest(request);
1315             return;
1316         }
1317     }
1318
1319     HashSet<String>::const_iterator end = m_clearHeaders.end();
1320     for (HashSet<String>::const_iterator header = m_clearHeaders.begin(); header != end; ++header)
1321         request.clearHTTPHeaderField(WebString(header->characters(), header->length()));
1322
1323     // Set the new substituted URL.
1324     request.setURL(webkit_support::RewriteLayoutTestsURL(request.url().spec()));
1325 }
1326
1327 void WebViewHost::didReceiveResponse(WebFrame*, unsigned identifier, const WebURLResponse& response)
1328 {
1329     if (m_shell->shouldDumpResourceLoadCallbacks()) {
1330         printResourceDescription(identifier);
1331         fputs(" - didReceiveResponse ", stdout);
1332         printResponseDescription(response);
1333         fputs("\n", stdout);
1334     }
1335     if (m_shell->shouldDumpResourceResponseMIMETypes()) {
1336         GURL url = response.url();
1337         WebString mimeType = response.mimeType();
1338         printf("%s has MIME type %s\n",
1339             url.ExtractFileName().c_str(),
1340             // Simulate NSURLResponse's mapping of empty/unknown MIME types to application/octet-stream
1341             mimeType.isEmpty() ? "application/octet-stream" : mimeType.utf8().data());
1342     }
1343 }
1344
1345 void WebViewHost::didFinishResourceLoad(WebFrame*, unsigned identifier)
1346 {
1347     if (m_shell->shouldDumpResourceLoadCallbacks()) {
1348         printResourceDescription(identifier);
1349         fputs(" - didFinishLoading\n", stdout);
1350     }
1351     removeIdentifierForRequest(identifier);
1352 }
1353
1354 void WebViewHost::didFailResourceLoad(WebFrame*, unsigned identifier, const WebURLError& error)
1355 {
1356     if (m_shell->shouldDumpResourceLoadCallbacks()) {
1357         printResourceDescription(identifier);
1358         fputs(" - didFailLoadingWithError: ", stdout);
1359         fputs(webkit_support::MakeURLErrorDescription(error).c_str(), stdout);
1360         fputs("\n", stdout);
1361     }
1362     removeIdentifierForRequest(identifier);
1363 }
1364
1365 void WebViewHost::didDisplayInsecureContent(WebFrame*)
1366 {
1367     if (m_shell->shouldDumpFrameLoadCallbacks())
1368         fputs("didDisplayInsecureContent\n", stdout);
1369 }
1370
1371 void WebViewHost::didRunInsecureContent(WebFrame*, const WebSecurityOrigin& origin, const WebURL& insecureURL)
1372 {
1373     if (m_shell->shouldDumpFrameLoadCallbacks())
1374         fputs("didRunInsecureContent\n", stdout);
1375 }
1376
1377 void WebViewHost::didDetectXSS(WebFrame*, const WebURL&, bool)
1378 {
1379     if (m_shell->shouldDumpFrameLoadCallbacks())
1380         fputs("didDetectXSS\n", stdout);
1381 }
1382
1383 void WebViewHost::openFileSystem(WebFrame* frame, WebFileSystem::Type type, long long size, bool create, WebFileSystemCallbacks* callbacks)
1384 {
1385     webkit_support::OpenFileSystem(frame, type, size, create, callbacks);
1386 }
1387
1388 bool WebViewHost::willCheckAndDispatchMessageEvent(WebFrame* source, WebSecurityOrigin target, WebDOMMessageEvent event)
1389 {
1390     if (m_shell->layoutTestController()->shouldInterceptPostMessage()) {
1391         fputs("intercepted postMessage\n", stdout);
1392         return true;
1393     }
1394
1395     return false;
1396 }
1397
1398 void WebViewHost::registerIntentService(WebKit::WebFrame*, const WebKit::WebIntentServiceInfo& service)
1399 {
1400     printf("Registered Web Intent Service: action=%s type=%s title=%s url=%s disposition=%s\n",
1401            service.action().utf8().data(), service.type().utf8().data(), service.title().utf8().data(), service.url().spec().data(), service.disposition().utf8().data());
1402 }
1403
1404 void WebViewHost::dispatchIntent(WebFrame* source, const WebIntentRequest& request)
1405 {
1406     printf("Received Web Intent: action=%s type=%s\n",
1407            request.intent().action().utf8().data(),
1408            request.intent().type().utf8().data());
1409     WebMessagePortChannelArray* ports = request.intent().messagePortChannelsRelease();
1410     m_currentRequest = request;
1411     if (ports) {
1412         printf("Have %d ports\n", static_cast<int>(ports->size()));
1413         for (size_t i = 0; i < ports->size(); ++i)
1414             (*ports)[i]->destroy();
1415         delete ports;
1416     }
1417
1418     if (!request.intent().service().isEmpty())
1419         printf("Explicit intent service: %s\n", request.intent().service().spec().data());
1420
1421     WebVector<WebString> extras = request.intent().extrasNames();
1422     for (size_t i = 0; i < extras.size(); ++i) {
1423         printf("Extras[%s] = %s\n", extras[i].utf8().data(),
1424                request.intent().extrasValue(extras[i]).utf8().data());
1425     }
1426
1427     WebVector<WebURL> suggestions = request.intent().suggestions();
1428     for (size_t i = 0; i < suggestions.size(); ++i)
1429         printf("Have suggestion %s\n", suggestions[i].spec().data());
1430 }
1431
1432 void WebViewHost::deliveredIntentResult(WebFrame* frame, int id, const WebSerializedScriptValue& data)
1433 {
1434     printf("Web intent success for id %d\n", id);
1435 }
1436
1437 void WebViewHost::deliveredIntentFailure(WebFrame* frame, int id, const WebSerializedScriptValue& data)
1438 {
1439     printf("Web intent failure for id %d\n", id);
1440 }
1441
1442 // Public functions -----------------------------------------------------------
1443
1444 WebViewHost::WebViewHost(TestShell* shell)
1445     : m_shell(shell)
1446     , m_webWidget(0)
1447     , m_lastRequestedTextCheckingCompletion(0)
1448 {
1449     reset();
1450 }
1451
1452 WebViewHost::~WebViewHost()
1453 {
1454     // DevTools frontend page is supposed to be navigated only once and
1455     // loading another URL in that Page is an error.
1456     if (m_shell->devToolsWebView() != this) {
1457         // Navigate to an empty page to fire all the destruction logic for the
1458         // current page.
1459         loadURLForFrame(GURL("about:blank"), WebString());
1460     }
1461
1462     for (Vector<WebKit::WebWidget*>::iterator it = m_popupmenus.begin();
1463          it < m_popupmenus.end(); ++it)
1464         (*it)->close();
1465
1466     webWidget()->close();
1467     if (m_inModalLoop)
1468         webkit_support::QuitMessageLoop();
1469 }
1470
1471 void WebViewHost::setWebWidget(WebKit::WebWidget* widget)
1472 {
1473     m_webWidget = widget;
1474     webView()->setSpellCheckClient(this);
1475     webView()->setPrerendererClient(this);
1476     webView()->setCompositorSurfaceReady();
1477 }
1478
1479 WebView* WebViewHost::webView() const
1480 {
1481     ASSERT(m_webWidget);
1482     // DRT does not support popup widgets. So m_webWidget is always a WebView.
1483     return static_cast<WebView*>(m_webWidget);
1484 }
1485
1486 WebWidget* WebViewHost::webWidget() const
1487 {
1488     ASSERT(m_webWidget);
1489     return m_webWidget;
1490 }
1491
1492 void WebViewHost::reset()
1493 {
1494     m_policyDelegateEnabled = false;
1495     m_policyDelegateIsPermissive = false;
1496     m_policyDelegateShouldNotifyDone = false;
1497     m_topLoadingFrame = 0;
1498     m_pageId = -1;
1499     m_lastPageIdUpdated = -1;
1500     m_hasWindow = false;
1501     m_inModalLoop = false;
1502     m_smartInsertDeleteEnabled = true;
1503     m_logConsoleOutput = true;
1504 #if OS(WINDOWS)
1505     m_selectTrailingWhitespaceEnabled = true;
1506 #else
1507     m_selectTrailingWhitespaceEnabled = false;
1508 #endif
1509     m_blocksRedirects = false;
1510     m_requestReturnNull = false;
1511     m_isPainting = false;
1512     m_canvas.clear();
1513 #if ENABLE(POINTER_LOCK)
1514     m_pointerLocked = false;
1515     m_pointerLockPlannedResult = PointerLockWillSucceed;
1516 #endif
1517
1518     m_navigationController = adoptPtr(new TestNavigationController(this));
1519
1520     m_pendingExtraData.clear();
1521     m_resourceIdentifierMap.clear();
1522     m_clearHeaders.clear();
1523     m_editCommandName.clear();
1524     m_editCommandValue.clear();
1525
1526     if (m_geolocationClientMock.get())
1527         m_geolocationClientMock->resetMock();
1528
1529 #if ENABLE(INPUT_SPEECH)
1530     if (m_speechInputControllerMock.get())
1531         m_speechInputControllerMock->clearResults();
1532 #endif
1533
1534     m_currentCursor = WebCursorInfo();
1535     m_windowRect = WebRect();
1536     m_paintRect = WebRect();
1537
1538     if (m_webWidget) {
1539         webView()->mainFrame()->setName(WebString());
1540         webView()->settings()->setMinimumTimerInterval(webkit_support::GetForegroundTabTimerInterval());
1541     }
1542 }
1543
1544 void WebViewHost::setSelectTrailingWhitespaceEnabled(bool enabled)
1545 {
1546     m_selectTrailingWhitespaceEnabled = enabled;
1547     // In upstream WebKit, smart insert/delete is mutually exclusive with select
1548     // trailing whitespace, however, we allow both because Chromium on Windows
1549     // allows both.
1550 }
1551
1552 void WebViewHost::setSmartInsertDeleteEnabled(bool enabled)
1553 {
1554     m_smartInsertDeleteEnabled = enabled;
1555     // In upstream WebKit, smart insert/delete is mutually exclusive with select
1556     // trailing whitespace, however, we allow both because Chromium on Windows
1557     // allows both.
1558 }
1559
1560 void WebViewHost::setLogConsoleOutput(bool enabled)
1561 {
1562     m_logConsoleOutput = enabled;
1563 }
1564
1565 void WebViewHost::setCustomPolicyDelegate(bool isCustom, bool isPermissive)
1566 {
1567     m_policyDelegateEnabled = isCustom;
1568     m_policyDelegateIsPermissive = isPermissive;
1569 }
1570
1571 void WebViewHost::waitForPolicyDelegate()
1572 {
1573     m_policyDelegateEnabled = true;
1574     m_policyDelegateShouldNotifyDone = true;
1575 }
1576
1577 void WebViewHost::setEditCommand(const string& name, const string& value)
1578 {
1579     m_editCommandName = name;
1580     m_editCommandValue = value;
1581 }
1582
1583 void WebViewHost::clearEditCommand()
1584 {
1585     m_editCommandName.clear();
1586     m_editCommandValue.clear();
1587 }
1588
1589 void WebViewHost::loadURLForFrame(const WebURL& url, const WebString& frameName)
1590 {
1591     if (!url.isValid())
1592         return;
1593     TestShell::resizeWindowForTest(this, url);
1594     navigationController()->loadEntry(TestNavigationEntry::create(-1, url, WebString(), frameName).get());
1595 }
1596
1597 bool WebViewHost::navigate(const TestNavigationEntry& entry, bool reload)
1598 {
1599     // Get the right target frame for the entry.
1600     WebFrame* frame = webView()->mainFrame();
1601     if (!entry.targetFrame().isEmpty())
1602         frame = webView()->findFrameByName(entry.targetFrame());
1603
1604     // TODO(mpcomplete): should we clear the target frame, or should
1605     // back/forward navigations maintain the target frame?
1606
1607     // A navigation resulting from loading a javascript URL should not be
1608     // treated as a browser initiated event. Instead, we want it to look as if
1609     // the page initiated any load resulting from JS execution.
1610     if (!GURL(entry.URL()).SchemeIs("javascript"))
1611         setPendingExtraData(adoptPtr(new TestShellExtraData(entry.pageID())));
1612
1613     // If we are reloading, then WebKit will use the state of the current page.
1614     // Otherwise, we give it the state to navigate to.
1615     if (reload) {
1616         frame->reload(false);
1617     } else if (!entry.contentState().isNull()) {
1618         ASSERT(entry.pageID() != -1);
1619         frame->loadHistoryItem(entry.contentState());
1620     } else {
1621         ASSERT(entry.pageID() == -1);
1622         frame->loadRequest(WebURLRequest(entry.URL()));
1623     }
1624
1625     // In case LoadRequest failed before DidCreateDataSource was called.
1626     setPendingExtraData(nullptr);
1627
1628     // Restore focus to the main frame prior to loading new request.
1629     // This makes sure that we don't have a focused iframe. Otherwise, that
1630     // iframe would keep focus when the SetFocus called immediately after
1631     // LoadRequest, thus making some tests fail (see http://b/issue?id=845337
1632     // for more details).
1633     webView()->setFocusedFrame(frame);
1634     m_shell->setFocus(webView(), true);
1635
1636     return true;
1637 }
1638
1639 // Private functions ----------------------------------------------------------
1640
1641 LayoutTestController* WebViewHost::layoutTestController() const
1642 {
1643     return m_shell->layoutTestController();
1644 }
1645
1646 void WebViewHost::updateAddressBar(WebView* webView)
1647 {
1648     WebFrame* mainFrame = webView->mainFrame();
1649     WebDataSource* dataSource = mainFrame->dataSource();
1650     if (!dataSource)
1651         dataSource = mainFrame->provisionalDataSource();
1652     if (!dataSource)
1653         return;
1654
1655     setAddressBarURL(dataSource->request().url());
1656 }
1657
1658 void WebViewHost::locationChangeDone(WebFrame* frame)
1659 {
1660     if (frame != m_topLoadingFrame)
1661         return;
1662     m_topLoadingFrame = 0;
1663     layoutTestController()->locationChangeDone();
1664 }
1665
1666 void WebViewHost::updateForCommittedLoad(WebFrame* frame, bool isNewNavigation)
1667 {
1668     // Code duplicated from RenderView::DidCommitLoadForFrame.
1669     TestShellExtraData* extraData = static_cast<TestShellExtraData*>(frame->dataSource()->extraData());
1670
1671     if (isNewNavigation) {
1672         // New navigation.
1673         updateSessionHistory(frame);
1674         m_pageId = nextPageID++;
1675     } else if (extraData && extraData->pendingPageID != -1 && !extraData->requestCommitted) {
1676         // This is a successful session history navigation!
1677         updateSessionHistory(frame);
1678         m_pageId = extraData->pendingPageID;
1679     }
1680
1681     // Don't update session history multiple times.
1682     if (extraData)
1683         extraData->requestCommitted = true;
1684
1685     updateURL(frame);
1686 }
1687
1688 void WebViewHost::updateURL(WebFrame* frame)
1689 {
1690     WebDataSource* ds = frame->dataSource();
1691     ASSERT(ds);
1692     const WebURLRequest& request = ds->request();
1693     RefPtr<TestNavigationEntry> entry(TestNavigationEntry::create());
1694
1695     // The referrer will be empty on https->http transitions. It
1696     // would be nice if we could get the real referrer from somewhere.
1697     entry->setPageID(m_pageId);
1698     if (ds->hasUnreachableURL())
1699         entry->setURL(ds->unreachableURL());
1700     else
1701         entry->setURL(request.url());
1702
1703     const WebHistoryItem& historyItem = frame->currentHistoryItem();
1704     if (!historyItem.isNull())
1705         entry->setContentState(historyItem);
1706
1707     navigationController()->didNavigateToEntry(entry.get());
1708     updateAddressBar(frame->view());
1709     m_lastPageIdUpdated = max(m_lastPageIdUpdated, m_pageId);
1710 }
1711
1712 void WebViewHost::updateSessionHistory(WebFrame* frame)
1713 {
1714     // If we have a valid page ID at this point, then it corresponds to the page
1715     // we are navigating away from. Otherwise, this is the first navigation, so
1716     // there is no past session history to record.
1717     if (m_pageId == -1)
1718         return;
1719
1720     TestNavigationEntry* entry = navigationController()->entryWithPageID(m_pageId);
1721     if (!entry)
1722         return;
1723
1724     const WebHistoryItem& historyItem = webView()->mainFrame()->previousHistoryItem();
1725     if (historyItem.isNull())
1726         return;
1727
1728     entry->setContentState(historyItem);
1729 }
1730
1731 void WebViewHost::printFrameDescription(WebFrame* webframe)
1732 {
1733     string name8 = webframe->name().utf8();
1734     if (webframe == webView()->mainFrame()) {
1735         if (!name8.length()) {
1736             fputs("main frame", stdout);
1737             return;
1738         }
1739         printf("main frame \"%s\"", name8.c_str());
1740         return;
1741     }
1742     if (!name8.length()) {
1743         fputs("frame (anonymous)", stdout);
1744         return;
1745     }
1746     printf("frame \"%s\"", name8.c_str());
1747 }
1748
1749 void WebViewHost::printFrameUserGestureStatus(WebFrame* webframe, const char* msg)
1750 {
1751     bool isUserGesture = webframe->isProcessingUserGesture();
1752     printf("Frame with user gesture \"%s\"%s", isUserGesture ? "true" : "false", msg);
1753 }
1754
1755 void WebViewHost::printResourceDescription(unsigned identifier)
1756 {
1757     ResourceMap::iterator it = m_resourceIdentifierMap.find(identifier);
1758     printf("%s", it != m_resourceIdentifierMap.end() ? it->second.c_str() : "<unknown>");
1759 }
1760
1761 void WebViewHost::setPendingExtraData(PassOwnPtr<TestShellExtraData> extraData)
1762 {
1763     m_pendingExtraData = extraData;
1764 }
1765
1766 void WebViewHost::setGamepadData(const WebGamepads& pads)
1767 {
1768     webkit_support::SetGamepadData(pads);
1769 }
1770
1771 void WebViewHost::setPageTitle(const WebString&)
1772 {
1773     // Nothing to do in layout test.
1774 }
1775
1776 void WebViewHost::setAddressBarURL(const WebURL&)
1777 {
1778     // Nothing to do in layout test.
1779 }
1780
1781 void WebViewHost::enterFullScreenNow()
1782 {
1783     if (layoutTestController()->hasCustomFullScreenBehavior())
1784         return;
1785
1786     webView()->willEnterFullScreen();
1787     webView()->didEnterFullScreen();
1788 }
1789
1790 void WebViewHost::exitFullScreenNow()
1791 {
1792     if (layoutTestController()->hasCustomFullScreenBehavior())
1793         return;
1794
1795     webView()->willExitFullScreen();
1796     webView()->didExitFullScreen();
1797 }
1798
1799 #if ENABLE(MEDIA_STREAM)
1800 webkit_support::TestMediaStreamClient* WebViewHost::testMediaStreamClient()
1801 {
1802     if (!m_testMediaStreamClient.get())
1803         m_testMediaStreamClient = adoptPtr(new webkit_support::TestMediaStreamClient());
1804     return m_testMediaStreamClient.get();
1805 }
1806 #endif
1807
1808 // Painting functions ---------------------------------------------------------
1809
1810 void WebViewHost::updatePaintRect(const WebRect& rect)
1811 {
1812     // m_paintRect = m_paintRect U rect
1813     if (rect.isEmpty())
1814         return;
1815     if (m_paintRect.isEmpty()) {
1816         m_paintRect = rect;
1817         return;
1818     }
1819     int left = min(m_paintRect.x, rect.x);
1820     int top = min(m_paintRect.y, rect.y);
1821     int right = max(m_paintRect.x + m_paintRect.width, rect.x + rect.width);
1822     int bottom = max(m_paintRect.y + m_paintRect.height, rect.y + rect.height);
1823     m_paintRect = WebRect(left, top, right - left, bottom - top);
1824 }
1825
1826 void WebViewHost::paintRect(const WebRect& rect)
1827 {
1828     ASSERT(!m_isPainting);
1829     ASSERT(canvas());
1830     m_isPainting = true;
1831     webWidget()->paint(canvas(), rect);
1832     m_isPainting = false;
1833 }
1834
1835 void WebViewHost::paintInvalidatedRegion()
1836 {
1837 #if ENABLE(REQUEST_ANIMATION_FRAME)
1838     webWidget()->animate(0.0);
1839 #endif
1840     webWidget()->layout();
1841     WebSize widgetSize = webWidget()->size();
1842     WebRect clientRect(0, 0, widgetSize.width, widgetSize.height);
1843
1844     // Paint the canvas if necessary. Allow painting to generate extra rects
1845     // for the first two calls. This is necessary because some WebCore rendering
1846     // objects update their layout only when painted.
1847     // Store the total area painted in total_paint. Then tell the gdk window
1848     // to update that area after we're done painting it.
1849     for (int i = 0; i < 3; ++i) {
1850         // m_paintRect = intersect(m_paintRect , clientRect)
1851         int left = max(m_paintRect.x, clientRect.x);
1852         int top = max(m_paintRect.y, clientRect.y);
1853         int right = min(m_paintRect.x + m_paintRect.width, clientRect.x + clientRect.width);
1854         int bottom = min(m_paintRect.y + m_paintRect.height, clientRect.y + clientRect.height);
1855         if (left >= right || top >= bottom)
1856             m_paintRect = WebRect();
1857         else
1858             m_paintRect = WebRect(left, top, right - left, bottom - top);
1859
1860         if (m_paintRect.isEmpty())
1861             continue;
1862         WebRect rect(m_paintRect);
1863         m_paintRect = WebRect();
1864         paintRect(rect);
1865     }
1866     ASSERT(m_paintRect.isEmpty());
1867 }
1868
1869 void WebViewHost::paintPagesWithBoundaries()
1870 {
1871     ASSERT(!m_isPainting);
1872     ASSERT(canvas());
1873     m_isPainting = true;
1874
1875     WebSize pageSizeInPixels = webWidget()->size();
1876     WebFrame* webFrame = webView()->mainFrame();
1877
1878     int pageCount = webFrame->printBegin(pageSizeInPixels);
1879     int totalHeight = pageCount * (pageSizeInPixels.height + 1) - 1;
1880
1881     SkCanvas* testCanvas = skia::TryCreateBitmapCanvas(pageSizeInPixels.width, totalHeight, true);
1882     if (testCanvas) {
1883         discardBackingStore();
1884         m_canvas = adoptPtr(testCanvas);
1885     } else {
1886         webFrame->printEnd();
1887         return;
1888     }
1889
1890     webFrame->printPagesWithBoundaries(canvas(), pageSizeInPixels);
1891     webFrame->printEnd();
1892
1893     m_isPainting = false;
1894 }
1895
1896 SkCanvas* WebViewHost::canvas()
1897 {
1898     if (m_canvas)
1899         return m_canvas.get();
1900     WebSize widgetSize = webWidget()->size();
1901     resetScrollRect();
1902     m_canvas = adoptPtr(skia::CreateBitmapCanvas(widgetSize.width, widgetSize.height, true));
1903     return m_canvas.get();
1904 }
1905
1906 void WebViewHost::resetScrollRect()
1907 {
1908 }
1909
1910 void WebViewHost::discardBackingStore()
1911 {
1912     m_canvas.clear();
1913 }
1914
1915 // Paints the entire canvas a semi-transparent black (grayish). This is used
1916 // by the layout tests in fast/repaint. The alpha value matches upstream.
1917 void WebViewHost::displayRepaintMask()
1918 {
1919     canvas()->drawARGB(167, 0, 0, 0);
1920 }
1921
1922 // Simulate a print by going into print mode and then exit straight away.
1923 void WebViewHost::printPage(WebKit::WebFrame* frame)
1924 {
1925     WebSize pageSizeInPixels = webWidget()->size();
1926     WebPrintParams printParams(pageSizeInPixels);
1927     frame->printBegin(printParams);
1928     frame->printEnd();
1929 }