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