[chromium] Remove dead transitional code from WebViewImpl
[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 "DRTDevToolsAgent.h"
35 #include "DRTTestRunner.h"
36 #include "MockWebSpeechInputController.h"
37 #include "MockWebSpeechRecognizer.h"
38 #include "Task.h"
39 #include "TestNavigationController.h"
40 #include "TestShell.h"
41 #include "WebCachedURLRequest.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 "WebElement.h"
49 #include "WebEventSender.h"
50 #include "WebFrame.h"
51 #include "WebGeolocationClientMock.h"
52 #include "WebHistoryItem.h"
53 #include "WebKit.h"
54 #include "WebNode.h"
55 #include "WebPluginParams.h"
56 #include "WebPopupMenu.h"
57 #include "WebPopupType.h"
58 #include "WebPrintParams.h"
59 #include "WebRange.h"
60 #include "WebScreenInfo.h"
61 #include "WebSerializedScriptValue.h"
62 #include "WebStorageNamespace.h"
63 #include "WebTestPlugin.h"
64 #include "WebUserMediaClientMock.h"
65 #include "WebView.h"
66 #include "WebWindowFeatures.h"
67 #include "skia/ext/platform_canvas.h"
68 #include "webkit/support/test_media_stream_client.h"
69 #include "webkit/support/webkit_support.h"
70 #include <cctype>
71 #include <clocale>
72 #include <public/WebCString.h>
73 #include <public/WebCompositorOutputSurface.h>
74 #include <public/WebCompositorSupport.h>
75 #include <public/WebDragData.h>
76 #include <public/WebRect.h>
77 #include <public/WebSize.h>
78 #include <public/WebThread.h>
79 #include <public/WebURLRequest.h>
80 #include <public/WebURLResponse.h>
81
82 #include <wtf/Assertions.h>
83 #include <wtf/OwnArrayPtr.h>
84 #include <wtf/PassOwnPtr.h>
85 #include <wtf/Vector.h>
86
87 using namespace WebCore;
88 using namespace WebKit;
89 using namespace WebTestRunner;
90 using namespace std;
91
92 static const int screenWidth = 1920;
93 static const int screenHeight = 1080;
94 static const int screenUnavailableBorder = 8;
95
96 // WebNavigationType debugging strings taken from PolicyDelegate.mm.
97 static const char* linkClickedString = "link clicked";
98 static const char* formSubmittedString = "form submitted";
99 static const char* backForwardString = "back/forward";
100 static const char* reloadString = "reload";
101 static const char* formResubmittedString = "form resubmitted";
102 static const char* otherString = "other";
103 static const char* illegalString = "illegal value";
104
105 static int nextPageID = 1;
106
107 // Get a debugging string from a WebNavigationType.
108 static const char* webNavigationTypeToString(WebNavigationType type)
109 {
110     switch (type) {
111     case WebKit::WebNavigationTypeLinkClicked:
112         return linkClickedString;
113     case WebKit::WebNavigationTypeFormSubmitted:
114         return formSubmittedString;
115     case WebKit::WebNavigationTypeBackForward:
116         return backForwardString;
117     case WebKit::WebNavigationTypeReload:
118         return reloadString;
119     case WebKit::WebNavigationTypeFormResubmitted:
120         return formResubmittedString;
121     case WebKit::WebNavigationTypeOther:
122         return otherString;
123     }
124     return illegalString;
125 }
126
127 static string URLDescription(const GURL& url)
128 {
129     if (url.SchemeIs("file"))
130         return url.ExtractFileName();
131     return url.possibly_invalid_spec();
132 }
133
134 static void printNodeDescription(const WebNode& node, int exception)
135 {
136     if (exception) {
137         fputs("ERROR", stdout);
138         return;
139     }
140     if (node.isNull()) {
141         fputs("(null)", stdout);
142         return;
143     }
144     fputs(node.nodeName().utf8().data(), stdout);
145     const WebNode& parent = node.parentNode();
146     if (!parent.isNull()) {
147         fputs(" > ", stdout);
148         printNodeDescription(parent, 0);
149     }
150 }
151
152 // WebViewClient -------------------------------------------------------------
153
154 WebView* WebViewHost::createView(WebFrame* creator, const WebURLRequest&, const WebWindowFeatures&, const WebString&, WebNavigationPolicy)
155 {
156     if (!testRunner()->canOpenWindows())
157         return 0;
158     creator->consumeUserGesture();
159     return m_shell->createNewWindow(WebURL())->webView();
160 }
161
162 WebWidget* WebViewHost::createPopupMenu(WebPopupType type)
163 {
164     switch (type) {
165     case WebKit::WebPopupTypeNone:
166     case WebKit::WebPopupTypePage:
167     case WebKit::WebPopupTypeHelperPlugin:
168         break;
169     case WebKit::WebPopupTypeSelect:
170     case WebKit::WebPopupTypeSuggestion:
171         m_popupmenus.append(WebPopupMenu::create(0));
172         return m_popupmenus.last();
173     }
174     return 0;
175 }
176
177 WebWidget* WebViewHost::createPopupMenu(const WebPopupMenuInfo&)
178 {
179     // Do not use this method. It's been replaced by createExternalPopupMenu.
180     ASSERT_NOT_REACHED();
181     return 0;
182 }
183
184 WebStorageNamespace* WebViewHost::createSessionStorageNamespace(unsigned quota)
185 {
186     return webkit_support::CreateSessionStorageNamespace(quota);
187 }
188
189 WebCompositorOutputSurface* WebViewHost::createOutputSurface()
190 {
191     if (!webView())
192         return 0;
193
194     if (m_shell->softwareCompositingEnabled())
195         return WebKit::Platform::current()->compositorSupport()->createOutputSurfaceForSoftware();
196
197     WebGraphicsContext3D* context = webkit_support::CreateGraphicsContext3D(WebGraphicsContext3D::Attributes(), webView());
198     return WebKit::Platform::current()->compositorSupport()->createOutputSurfaceFor3D(context);
199 }
200
201 void WebViewHost::didAddMessageToConsole(const WebConsoleMessage& message, const WebString& sourceName, unsigned sourceLine)
202 {
203 }
204
205 void WebViewHost::didStartLoading()
206 {
207     m_shell->setIsLoading(true);
208 }
209
210 void WebViewHost::didStopLoading()
211 {
212     m_shell->setIsLoading(false);
213 }
214
215 bool WebViewHost::shouldBeginEditing(const WebRange& range)
216 {
217     return true;
218 }
219
220 bool WebViewHost::shouldEndEditing(const WebRange& range)
221 {
222     return true;
223 }
224
225 bool WebViewHost::shouldInsertNode(const WebNode& node, const WebRange& range, WebEditingAction action)
226 {
227     return true;
228 }
229
230 bool WebViewHost::shouldInsertText(const WebString& text, const WebRange& range, WebEditingAction action)
231 {
232     return true;
233 }
234
235 bool WebViewHost::shouldChangeSelectedRange(
236     const WebRange& fromRange, const WebRange& toRange, WebTextAffinity affinity, bool stillSelecting)
237 {
238     return true;
239 }
240
241 bool WebViewHost::shouldDeleteRange(const WebRange& range)
242 {
243     return true;
244 }
245
246 bool WebViewHost::shouldApplyStyle(const WebString& style, const WebRange& range)
247 {
248     return true;
249 }
250
251 bool WebViewHost::isSmartInsertDeleteEnabled()
252 {
253     return m_smartInsertDeleteEnabled;
254 }
255
256 bool WebViewHost::isSelectTrailingWhitespaceEnabled()
257 {
258     return m_selectTrailingWhitespaceEnabled;
259 }
260
261 bool WebViewHost::handleCurrentKeyboardEvent()
262 {
263     if (m_editCommandName.empty())
264         return false;
265     WebFrame* frame = webView()->focusedFrame();
266     if (!frame)
267         return false;
268
269     return frame->executeCommand(WebString::fromUTF8(m_editCommandName), WebString::fromUTF8(m_editCommandValue));
270 }
271
272 // WebKit::WebPrerendererClient
273
274 void WebViewHost::willAddPrerender(WebKit::WebPrerender*)
275 {
276 }
277
278
279 void WebViewHost::runModalAlertDialog(WebFrame*, const WebString& message)
280 {
281 }
282
283 bool WebViewHost::runModalConfirmDialog(WebFrame*, const WebString& message)
284 {
285     return true;
286 }
287
288 bool WebViewHost::runModalPromptDialog(WebFrame* frame, const WebString& message,
289                                        const WebString& defaultValue, WebString*)
290 {
291     return true;
292 }
293
294 bool WebViewHost::runModalBeforeUnloadDialog(WebFrame*, const WebString& message)
295 {
296     return !testRunner()->shouldStayOnPageAfterHandlingBeforeUnload();
297 }
298
299 void WebViewHost::showContextMenu(WebFrame*, const WebContextMenuData& contextMenuData)
300 {
301     m_lastContextMenuData = adoptPtr(new WebContextMenuData(contextMenuData));
302 }
303
304 void WebViewHost::didUpdateLayout()
305 {
306 #if OS(MAC_OS_X)
307     static bool queryingPreferredSize = false;
308     if (queryingPreferredSize)
309         return;
310
311     queryingPreferredSize = true;
312     // Query preferred width to emulate the same functionality in Chromium:
313     // see RenderView::CheckPreferredSize (src/content/renderer/render_view.cc)
314     // and TabContentsViewMac::RenderViewCreated (src/chrome/browser/tab_contents/tab_contents_view_mac.mm)
315     webView()->mainFrame()->contentsPreferredWidth();
316     webView()->mainFrame()->documentElementScrollHeight();
317     queryingPreferredSize = false;
318 #endif
319 }
320
321 void WebViewHost::navigateBackForwardSoon(int offset)
322 {
323     navigationController()->goToOffset(offset);
324 }
325
326 int WebViewHost::historyBackListCount()
327 {
328     return navigationController()->lastCommittedEntryIndex();
329 }
330
331 int WebViewHost::historyForwardListCount()
332 {
333     int currentIndex =navigationController()->lastCommittedEntryIndex();
334     return navigationController()->entryCount() - currentIndex - 1;
335 }
336
337 #if ENABLE(NOTIFICATIONS)
338 WebNotificationPresenter* WebViewHost::notificationPresenter()
339 {
340     return m_shell->notificationPresenter();
341 }
342 #endif
343
344 WebKit::WebGeolocationClient* WebViewHost::geolocationClient()
345 {
346     return geolocationClientMock();
347 }
348
349 WebKit::WebGeolocationClientMock* WebViewHost::geolocationClientMock()
350 {
351     if (!m_geolocationClientMock)
352         m_geolocationClientMock = adoptPtr(WebGeolocationClientMock::create());
353     return m_geolocationClientMock.get();
354 }
355
356 #if ENABLE(INPUT_SPEECH)
357 WebSpeechInputController* WebViewHost::speechInputController(WebKit::WebSpeechInputListener* listener)
358 {
359     if (!m_speechInputControllerMock)
360         m_speechInputControllerMock = MockWebSpeechInputController::create(listener);
361     return m_speechInputControllerMock.get();
362 }
363 #endif
364
365 #if ENABLE(SCRIPTED_SPEECH)
366 WebSpeechRecognizer* WebViewHost::speechRecognizer()
367 {
368     if (!m_mockSpeechRecognizer)
369         m_mockSpeechRecognizer = MockWebSpeechRecognizer::create();
370     return m_mockSpeechRecognizer.get();
371 }
372 #endif
373
374 WebDeviceOrientationClientMock* WebViewHost::deviceOrientationClientMock()
375 {
376     if (!m_deviceOrientationClientMock.get())
377         m_deviceOrientationClientMock = adoptPtr(WebDeviceOrientationClientMock::create());
378     return m_deviceOrientationClientMock.get();
379 }
380
381 WebDeviceOrientationClient* WebViewHost::deviceOrientationClient()
382 {
383     return deviceOrientationClientMock();
384 }
385
386 #if ENABLE(MEDIA_STREAM)
387 WebUserMediaClient* WebViewHost::userMediaClient()
388 {
389     return userMediaClientMock();
390 }
391
392 WebUserMediaClientMock* WebViewHost::userMediaClientMock()
393 {
394     if (!m_userMediaClientMock.get())
395         m_userMediaClientMock = WebUserMediaClientMock::create();
396     return m_userMediaClientMock.get();
397 }
398 #endif
399
400 // WebWidgetClient -----------------------------------------------------------
401
402 void WebViewHost::didAutoResize(const WebSize& newSize)
403 {
404     // Purposely don't include the virtualWindowBorder in this case so that
405     // window.inner[Width|Height] is the same as window.outer[Width|Height]
406     setWindowRect(WebRect(0, 0, newSize.width, newSize.height));
407 }
408
409 void WebViewHost::initializeLayerTreeView(WebLayerTreeViewClient* client, const WebLayer& rootLayer, const WebLayerTreeView::Settings& settings)
410 {
411     m_layerTreeView = adoptPtr(Platform::current()->compositorSupport()->createLayerTreeView(client, rootLayer, settings));
412     if (m_layerTreeView)
413         m_layerTreeView->setSurfaceReady();
414 }
415
416 WebLayerTreeView* WebViewHost::layerTreeView()
417 {
418     return m_layerTreeView.get();
419 }
420
421 void WebViewHost::scheduleAnimation()
422 {
423     if (webView()->settings()->scrollAnimatorEnabled())
424         webView()->animate(0.0);
425 }
426
427 void WebViewHost::didFocus()
428 {
429     m_shell->setFocus(webWidget(), true);
430 }
431
432 void WebViewHost::didBlur()
433 {
434     m_shell->setFocus(webWidget(), false);
435 }
436
437 WebScreenInfo WebViewHost::screenInfo()
438 {
439     // We don't need to set actual values.
440     WebScreenInfo info;
441     info.depth = 24;
442     info.depthPerComponent = 8;
443     info.isMonochrome = false;
444     info.rect = WebRect(0, 0, screenWidth, screenHeight);
445     // Use values different from info.rect for testing.
446     info.availableRect = WebRect(screenUnavailableBorder, screenUnavailableBorder,
447                                  screenWidth - screenUnavailableBorder * 2,
448                                  screenHeight - screenUnavailableBorder * 2);
449     return info;
450 }
451
452 #if ENABLE(POINTER_LOCK)
453 bool WebViewHost::requestPointerLock()
454 {
455     switch (m_pointerLockPlannedResult) {
456     case PointerLockWillSucceed:
457         postDelayedTask(new HostMethodTask(this, &WebViewHost::didAcquirePointerLock), 0);
458         return true;
459     case PointerLockWillRespondAsync:
460         ASSERT(!m_pointerLocked);
461         return true;
462     case PointerLockWillFailSync:
463         ASSERT(!m_pointerLocked);
464         return false;
465     default:
466         ASSERT_NOT_REACHED();
467         return false;
468     }
469 }
470
471 void WebViewHost::requestPointerUnlock()
472 {
473     postDelayedTask(new HostMethodTask(this, &WebViewHost::didLosePointerLock), 0);
474 }
475
476 bool WebViewHost::isPointerLocked()
477 {
478     return m_pointerLocked;
479 }
480
481 void WebViewHost::didAcquirePointerLock()
482 {
483     m_pointerLocked = true;
484     webWidget()->didAcquirePointerLock();
485
486     // Reset planned result to default.
487     m_pointerLockPlannedResult = PointerLockWillSucceed;
488 }
489
490 void WebViewHost::didNotAcquirePointerLock()
491 {
492     ASSERT(!m_pointerLocked);
493     m_pointerLocked = false;
494     webWidget()->didNotAcquirePointerLock();
495
496     // Reset planned result to default.
497     m_pointerLockPlannedResult = PointerLockWillSucceed;
498 }
499
500 void WebViewHost::didLosePointerLock()
501 {
502     bool wasLocked = m_pointerLocked;
503     m_pointerLocked = false;
504     if (wasLocked)
505         webWidget()->didLosePointerLock();
506 }
507 #endif
508
509 void WebViewHost::show(WebNavigationPolicy)
510 {
511     m_hasWindow = true;
512 }
513
514
515
516 void WebViewHost::closeWidget()
517 {
518     m_hasWindow = false;
519     m_shell->closeWindow(this);
520     // No more code here, we should be deleted at this point.
521 }
522
523 void WebViewHost::closeWidgetSoon()
524 {
525     postDelayedTask(new HostMethodTask(this, &WebViewHost::closeWidget), 0);
526 }
527
528 void WebViewHost::didChangeCursor(const WebCursorInfo& cursorInfo)
529 {
530     if (!hasWindow())
531         return;
532     m_currentCursor = cursorInfo;
533 }
534
535 WebRect WebViewHost::windowRect()
536 {
537     return m_windowRect;
538 }
539
540 void WebViewHost::setWindowRect(const WebRect& rect)
541 {
542     m_windowRect = rect;
543     const int border2 = TestShell::virtualWindowBorder * 2;
544     if (m_windowRect.width <= border2)
545         m_windowRect.width = 1 + border2;
546     if (m_windowRect.height <= border2)
547         m_windowRect.height = 1 + border2;
548     int width = m_windowRect.width - border2;
549     int height = m_windowRect.height - border2;
550     discardBackingStore();
551     webWidget()->resize(WebSize(width, height));
552 }
553
554 WebRect WebViewHost::rootWindowRect()
555 {
556     return windowRect();
557 }
558
559 WebRect WebViewHost::windowResizerRect()
560 {
561     // Not necessary.
562     return WebRect();
563 }
564
565 void WebViewHost::runModal()
566 {
567     if (m_shell->isDisplayingModalDialog()) {
568         // DumpRenderTree doesn't support real modal dialogs, so a test shouldn't try to start two modal dialogs at the same time.
569         ASSERT_NOT_REACHED();
570         return;
571     }
572     // This WebViewHost might get deleted before RunMessageLoop() returns, so keep a copy of the m_shell member variable around.
573     ASSERT(m_shell->webViewHost() != this);
574     TestShell* shell = m_shell;
575     shell->setIsDisplayingModalDialog(true);
576     bool oldState = webkit_support::MessageLoopNestableTasksAllowed();
577     webkit_support::MessageLoopSetNestableTasksAllowed(true);
578     m_inModalLoop = true;
579     webkit_support::RunMessageLoop();
580     webkit_support::MessageLoopSetNestableTasksAllowed(oldState);
581     shell->setIsDisplayingModalDialog(false);
582 }
583
584 bool WebViewHost::enterFullScreen()
585 {
586     postDelayedTask(new HostMethodTask(this, &WebViewHost::enterFullScreenNow), 0);
587     return true;
588 }
589
590 void WebViewHost::exitFullScreen()
591 {
592     postDelayedTask(new HostMethodTask(this, &WebViewHost::exitFullScreenNow), 0);
593 }
594
595 // WebFrameClient ------------------------------------------------------------
596
597 WebPlugin* WebViewHost::createPlugin(WebFrame* frame, const WebPluginParams& params)
598 {
599     if (params.mimeType == WebTestPlugin::mimeType())
600         return WebTestPlugin::create(frame, params, this);
601
602     return webkit_support::CreateWebPlugin(frame, params);
603 }
604
605 WebMediaPlayer* WebViewHost::createMediaPlayer(WebFrame* frame, const WebURL& url, WebMediaPlayerClient* client)
606 {
607 #if ENABLE(MEDIA_STREAM)
608     return webkit_support::CreateMediaPlayer(frame, url, client, testMediaStreamClient());
609 #else
610     return webkit_support::CreateMediaPlayer(frame, url, client);
611 #endif
612 }
613
614 WebApplicationCacheHost* WebViewHost::createApplicationCacheHost(WebFrame* frame, WebApplicationCacheHostClient* client)
615 {
616     return webkit_support::CreateApplicationCacheHost(frame, client);
617 }
618
619 void WebViewHost::loadURLExternally(WebFrame* frame, const WebURLRequest& request, WebNavigationPolicy policy)
620 {
621     loadURLExternally(frame, request, policy, WebString());
622 }
623
624 void WebViewHost::loadURLExternally(WebFrame*, const WebURLRequest& request, WebNavigationPolicy policy, const WebString& downloadName)
625 {
626     ASSERT(policy !=  WebKit::WebNavigationPolicyCurrentTab);
627     WebViewHost* another = m_shell->createNewWindow(request.url());
628     if (another)
629         another->show(policy);
630 }
631
632 WebNavigationPolicy WebViewHost::decidePolicyForNavigation(
633     WebFrame*, const WebURLRequest& request,
634     WebNavigationType type, const WebNode& originatingNode,
635     WebNavigationPolicy defaultPolicy, bool isRedirect)
636 {
637     WebNavigationPolicy result;
638     if (!m_policyDelegateEnabled)
639         return defaultPolicy;
640
641     printf("Policy delegate: attempt to load %s with navigation type '%s'",
642            URLDescription(request.url()).c_str(), webNavigationTypeToString(type));
643     if (!originatingNode.isNull()) {
644         fputs(" originating from ", stdout);
645         printNodeDescription(originatingNode, 0);
646     }
647     fputs("\n", stdout);
648     if (m_policyDelegateIsPermissive)
649         result = WebKit::WebNavigationPolicyCurrentTab;
650     else
651         result = WebKit::WebNavigationPolicyIgnore;
652
653     if (m_policyDelegateShouldNotifyDone)
654         testRunner()->policyDelegateDone();
655     return result;
656 }
657
658 bool WebViewHost::canHandleRequest(WebFrame*, const WebURLRequest& request)
659 {
660     GURL url = request.url();
661     // Just reject the scheme used in
662     // LayoutTests/http/tests/misc/redirect-to-external-url.html
663     return !url.SchemeIs("spaceballs");
664 }
665
666 WebURLError WebViewHost::cannotHandleRequestError(WebFrame*, const WebURLRequest& request)
667 {
668     WebURLError error;
669     // A WebKit layout test expects the following values.
670     // unableToImplementPolicyWithError() below prints them.
671     error.domain = WebString::fromUTF8("WebKitErrorDomain");
672     error.reason = 101;
673     error.unreachableURL = request.url();
674     return error;
675 }
676
677 WebURLError WebViewHost::cancelledError(WebFrame*, const WebURLRequest& request)
678 {
679     return webkit_support::CreateCancelledError(request);
680 }
681
682 void WebViewHost::unableToImplementPolicyWithError(WebFrame* frame, const WebURLError& error)
683 {
684 }
685
686 void WebViewHost::didCreateDataSource(WebFrame*, WebDataSource* ds)
687 {
688     ds->setExtraData(m_pendingExtraData.leakPtr());
689     if (!testRunner()->deferMainResourceDataLoad())
690         ds->setDeferMainResourceDataLoad(false);
691 }
692
693 void WebViewHost::didStartProvisionalLoad(WebFrame* frame)
694 {
695     if (!m_topLoadingFrame)
696         m_topLoadingFrame = frame;
697
698     updateAddressBar(frame->view());
699 }
700
701 void WebViewHost::didReceiveServerRedirectForProvisionalLoad(WebFrame* frame)
702 {
703     updateAddressBar(frame->view());
704 }
705
706 void WebViewHost::didFailProvisionalLoad(WebFrame* frame, const WebURLError& error)
707 {
708     locationChangeDone(frame);
709
710     // Don't display an error page if we're running layout tests, because
711     // DumpRenderTree doesn't.
712 }
713
714 void WebViewHost::didCommitProvisionalLoad(WebFrame* frame, bool isNewNavigation)
715 {
716     updateForCommittedLoad(frame, isNewNavigation);
717 }
718
719 void WebViewHost::didClearWindowObject(WebFrame* frame)
720 {
721     m_shell->bindJSObjectsToWindow(frame);
722 }
723
724 void WebViewHost::didReceiveTitle(WebFrame* frame, const WebString& title, WebTextDirection direction)
725 {
726     setPageTitle(title);
727 }
728
729 void WebViewHost::didFailLoad(WebFrame* frame, const WebURLError& error)
730 {
731     locationChangeDone(frame);
732 }
733
734 void WebViewHost::didFinishLoad(WebFrame* frame)
735 {
736     updateAddressBar(frame->view());
737     locationChangeDone(frame);
738 }
739
740 void WebViewHost::didNavigateWithinPage(WebFrame* frame, bool isNewNavigation)
741 {
742     frame->dataSource()->setExtraData(m_pendingExtraData.leakPtr());
743
744     updateForCommittedLoad(frame, isNewNavigation);
745 }
746
747 static void blockRequest(WebURLRequest& request)
748 {
749     request.setURL(WebURL());
750 }
751
752 static bool isLocalhost(const string& host)
753 {
754     return host == "127.0.0.1" || host == "localhost";
755 }
756
757 static bool hostIsUsedBySomeTestsToGenerateError(const string& host)
758 {
759     return host == "255.255.255.255";
760 }
761
762 void WebViewHost::willSendRequest(WebFrame* frame, unsigned identifier, WebURLRequest& request, const WebURLResponse& redirectResponse)
763 {
764     if (request.url().isEmpty())
765         return;
766
767     // Need to use GURL for host() and SchemeIs()
768     GURL url = request.url();
769     string requestURL = url.possibly_invalid_spec();
770
771     GURL mainDocumentURL = request.firstPartyForCookies();
772
773     request.setExtraData(webkit_support::CreateWebURLRequestExtraData(frame->document().referrerPolicy()));
774
775     string host = url.host();
776     if (!host.empty() && (url.SchemeIs("http") || url.SchemeIs("https"))) {
777         if (!isLocalhost(host) && !hostIsUsedBySomeTestsToGenerateError(host)
778             && ((!mainDocumentURL.SchemeIs("http") && !mainDocumentURL.SchemeIs("https")) || isLocalhost(mainDocumentURL.host()))
779             && !m_shell->allowExternalPages()) {
780             printf("Blocked access to external URL %s\n", requestURL.c_str());
781             blockRequest(request);
782             return;
783         }
784     }
785
786     // Set the new substituted URL.
787     request.setURL(webkit_support::RewriteLayoutTestsURL(request.url().spec()));
788 }
789
790 void WebViewHost::openFileSystem(WebFrame* frame, WebFileSystem::Type type, long long size, bool create, WebFileSystemCallbacks* callbacks)
791 {
792     webkit_support::OpenFileSystem(frame, type, size, create, callbacks);
793 }
794
795 void WebViewHost::deleteFileSystem(WebKit::WebFrame* frame, WebKit::WebFileSystem::Type type, WebKit::WebFileSystemCallbacks* callbacks)
796 {
797     webkit_support::DeleteFileSystem(frame, type, callbacks);
798 }
799
800 bool WebViewHost::willCheckAndDispatchMessageEvent(WebFrame* sourceFrame, WebFrame* targetFrame, WebSecurityOrigin target, WebDOMMessageEvent event)
801 {
802     if (m_shell->testRunner()->shouldInterceptPostMessage()) {
803         fputs("intercepted postMessage\n", stdout);
804         return true;
805     }
806
807     return false;
808 }
809
810 // WebTestDelegate ------------------------------------------------------------
811
812 WebContextMenuData* WebViewHost::lastContextMenuData() const
813 {
814     return m_lastContextMenuData.get();
815 }
816
817 void WebViewHost::clearContextMenuData()
818 {
819     m_lastContextMenuData.clear();
820 }
821
822 void WebViewHost::setEditCommand(const string& name, const string& value)
823 {
824     m_editCommandName = name;
825     m_editCommandValue = value;
826 }
827
828 void WebViewHost::clearEditCommand()
829 {
830     m_editCommandName.clear();
831     m_editCommandValue.clear();
832 }
833
834 void WebViewHost::setGamepadData(const WebGamepads& pads)
835 {
836     webkit_support::SetGamepadData(pads);
837 }
838
839 void WebViewHost::printMessage(const std::string& message)
840 {
841     printf("%s", message.c_str());
842 }
843
844 void WebViewHost::postTask(WebTask* task)
845 {
846     ::postTask(task);
847 }
848
849 void WebViewHost::postDelayedTask(WebTask* task, long long ms)
850 {
851     ::postDelayedTask(task, ms);
852 }
853
854 WebString WebViewHost::registerIsolatedFileSystem(const WebVector<WebString>& absoluteFilenames)
855 {
856     return webkit_support::RegisterIsolatedFileSystem(absoluteFilenames);
857 }
858
859 long long WebViewHost::getCurrentTimeInMillisecond()
860 {
861     return webkit_support::GetCurrentTimeInMillisecond();
862 }
863
864 WebKit::WebString WebViewHost::getAbsoluteWebStringFromUTF8Path(const std::string& path)
865 {
866     return webkit_support::GetAbsoluteWebStringFromUTF8Path(path);
867 }
868
869 WebURL WebViewHost::localFileToDataURL(const WebKit::WebURL& url)
870 {
871     return webkit_support::LocalFileToDataURL(url);
872 }
873
874 WebURL WebViewHost::rewriteLayoutTestsURL(const std::string& url)
875 {
876     return webkit_support::RewriteLayoutTestsURL(url);
877 }
878
879 WebPreferences* WebViewHost::preferences()
880 {
881     return m_shell->preferences();
882 }
883
884 void WebViewHost::applyPreferences()
885 {
886     m_shell->applyPreferences();
887 }
888
889 void WebViewHost::setCurrentWebIntentRequest(const WebIntentRequest& request)
890 {
891     m_currentRequest = request;
892 }
893
894 WebIntentRequest* WebViewHost::currentWebIntentRequest()
895 {
896     return &m_currentRequest;
897 }
898
899 std::string WebViewHost::makeURLErrorDescription(const WebKit::WebURLError& error)
900 {
901     return webkit_support::MakeURLErrorDescription(error);
902 }
903
904 std::string WebViewHost::normalizeLayoutTestURL(const std::string& url)
905 {
906     return m_shell->normalizeLayoutTestURL(url);
907 }
908
909 void WebViewHost::showDevTools()
910 {
911     m_shell->showDevTools();
912 }
913
914 void WebViewHost::closeDevTools()
915 {
916     m_shell->closeDevTools();
917 }
918
919 void WebViewHost::evaluateInWebInspector(long callID, const std::string& script)
920 {
921     m_shell->drtDevToolsAgent()->evaluateInWebInspector(callID, script);
922 }
923
924 void WebViewHost::clearAllDatabases()
925 {
926     webkit_support::ClearAllDatabases();
927 }
928
929 void WebViewHost::setDatabaseQuota(int quota)
930 {
931     webkit_support::SetDatabaseQuota(quota);
932 }
933
934 void WebViewHost::setDeviceScaleFactor(float deviceScaleFactor)
935 {
936     webView()->setDeviceScaleFactor(deviceScaleFactor);
937     discardBackingStore();
938 }
939
940 void WebViewHost::setFocus(bool focused)
941 {
942     m_shell->setFocus(m_shell->webView(), focused);
943 }
944
945 void WebViewHost::setAcceptAllCookies(bool acceptCookies)
946 {
947     webkit_support::SetAcceptAllCookies(acceptCookies);
948 }
949
950 string WebViewHost::pathToLocalResource(const string& url)
951 {
952 #if OS(WINDOWS)
953     if (!url.find("/tmp/")) {
954         // We want a temp file.
955         const unsigned tempPrefixLength = 5;
956         size_t bufferSize = MAX_PATH;
957         OwnArrayPtr<WCHAR> tempPath = adoptArrayPtr(new WCHAR[bufferSize]);
958         DWORD tempLength = ::GetTempPathW(bufferSize, tempPath.get());
959         if (tempLength + url.length() - tempPrefixLength + 1 > bufferSize) {
960             bufferSize = tempLength + url.length() - tempPrefixLength + 1;
961             tempPath = adoptArrayPtr(new WCHAR[bufferSize]);
962             tempLength = GetTempPathW(bufferSize, tempPath.get());
963             ASSERT(tempLength < bufferSize);
964         }
965         string resultPath(WebString(tempPath.get(), tempLength).utf8());
966         resultPath.append(url.substr(tempPrefixLength));
967         return resultPath;
968     }
969 #endif
970
971     // Some layout tests use file://// which we resolve as a UNC path. Normalize
972     // them to just file:///.
973     string lowerUrl = url;
974     string result = url;
975     transform(lowerUrl.begin(), lowerUrl.end(), lowerUrl.begin(), ::tolower);
976     while (!lowerUrl.find("file:////")) {
977         result = result.substr(0, 8) + result.substr(9);
978         lowerUrl = lowerUrl.substr(0, 8) + lowerUrl.substr(9);
979     }
980     return webkit_support::RewriteLayoutTestsURL(result).spec();
981 }
982
983 void WebViewHost::setLocale(const std::string& locale)
984 {
985     setlocale(LC_ALL, locale.c_str());
986 }
987
988 void WebViewHost::setDeviceOrientation(WebKit::WebDeviceOrientation& orientation)
989 {
990     deviceOrientationClientMock()->setOrientation(orientation);
991 }
992
993 int WebViewHost::numberOfPendingGeolocationPermissionRequests()
994 {
995     Vector<WebViewHost*> windowList = m_shell->windowList();
996     int numberOfRequests = 0;
997     for (size_t i = 0; i < windowList.size(); i++)
998         numberOfRequests += windowList[i]->geolocationClientMock()->numberOfPendingPermissionRequests();
999     return numberOfRequests;
1000 }
1001
1002 void WebViewHost::setGeolocationPermission(bool allowed)
1003 {
1004     Vector<WebViewHost*> windowList = m_shell->windowList();
1005     for (size_t i = 0; i < windowList.size(); i++)
1006         windowList[i]->geolocationClientMock()->setPermission(allowed);
1007 }
1008
1009 void WebViewHost::setMockGeolocationPosition(double latitude, double longitude, double accuracy)
1010 {
1011     Vector<WebViewHost*> windowList = m_shell->windowList();
1012     for (size_t i = 0; i < windowList.size(); i++)
1013         windowList[i]->geolocationClientMock()->setPosition(latitude, longitude, accuracy);
1014 }
1015
1016 void WebViewHost::setMockGeolocationPositionUnavailableError(const std::string& message)
1017 {
1018     Vector<WebViewHost*> windowList = m_shell->windowList();
1019     // FIXME: Benjamin
1020     for (size_t i = 0; i < windowList.size(); i++)
1021         windowList[i]->geolocationClientMock()->setPositionUnavailableError(WebString::fromUTF8(message));
1022 }
1023
1024 #if ENABLE(NOTIFICATIONS)
1025 void WebViewHost::grantWebNotificationPermission(const std::string& origin)
1026 {
1027     m_shell->notificationPresenter()->grantPermission(WebString::fromUTF8(origin));
1028 }
1029
1030 bool WebViewHost::simulateLegacyWebNotificationClick(const std::string& notificationIdentifier)
1031 {
1032     return m_shell->notificationPresenter()->simulateClick(WebString::fromUTF8(notificationIdentifier));
1033 }
1034 #endif
1035
1036 #if ENABLE(INPUT_SPEECH)
1037 void WebViewHost::addMockSpeechInputResult(const std::string& result, double confidence, const std::string& language)
1038 {
1039     m_speechInputControllerMock->addMockRecognitionResult(WebString::fromUTF8(result), confidence, WebString::fromUTF8(language));
1040 }
1041
1042 void WebViewHost::setMockSpeechInputDumpRect(bool dumpRect)
1043 {
1044     m_speechInputControllerMock->setDumpRect(dumpRect);
1045 }
1046 #endif
1047
1048 #if ENABLE(SCRIPTED_SPEECH)
1049 void WebViewHost::addMockSpeechRecognitionResult(const std::string& transcript, double confidence)
1050 {
1051     m_mockSpeechRecognizer->addMockResult(WebString::fromUTF8(transcript), confidence);
1052 }
1053
1054 void WebViewHost::setMockSpeechRecognitionError(const std::string& error, const std::string& message)
1055 {
1056     m_mockSpeechRecognizer->setError(WebString::fromUTF8(error), WebString::fromUTF8(message));
1057 }
1058
1059 bool WebViewHost::wasMockSpeechRecognitionAborted()
1060 {
1061     return m_mockSpeechRecognizer->wasAborted();
1062 }
1063 #endif
1064
1065 void WebViewHost::display()
1066 {
1067     const WebKit::WebSize& size = webView()->size();
1068     WebRect rect(0, 0, size.width, size.height);
1069     proxy()->setPaintRect(rect);
1070     paintInvalidatedRegion();
1071     displayRepaintMask();
1072 }
1073
1074 void WebViewHost::displayInvalidatedRegion()
1075 {
1076     paintInvalidatedRegion();
1077     displayRepaintMask();
1078 }
1079
1080 // Public functions -----------------------------------------------------------
1081
1082 WebViewHost::WebViewHost(TestShell* shell)
1083     : m_shell(shell)
1084     , m_proxy(0)
1085     , m_webWidget(0)
1086     , m_shutdownWasInvoked(false)
1087 {
1088     reset();
1089 }
1090
1091 WebViewHost::~WebViewHost()
1092 {
1093     ASSERT(m_shutdownWasInvoked);
1094     if (m_inModalLoop)
1095         webkit_support::QuitMessageLoop();
1096 }
1097
1098 void WebViewHost::shutdown()
1099 {
1100     ASSERT(!m_shutdownWasInvoked);
1101
1102     // DevTools frontend page is supposed to be navigated only once and
1103     // loading another URL in that Page is an error.
1104     if (m_shell->devToolsWebView() != this) {
1105         // Navigate to an empty page to fire all the destruction logic for the
1106         // current page.
1107         loadURLForFrame(GURL("about:blank"), WebString());
1108     }
1109
1110     for (Vector<WebKit::WebWidget*>::iterator it = m_popupmenus.begin();
1111          it < m_popupmenus.end(); ++it)
1112         (*it)->close();
1113
1114     m_layerTreeView.clear();
1115     webWidget()->close();
1116     m_webWidget = 0;
1117     m_shutdownWasInvoked = true;
1118 }
1119
1120 void WebViewHost::setWebWidget(WebKit::WebWidget* widget)
1121 {
1122     m_webWidget = widget;
1123     webView()->setSpellCheckClient(proxy()->spellCheckClient());
1124     webView()->setPrerendererClient(this);
1125 }
1126
1127 WebView* WebViewHost::webView() const
1128 {
1129     ASSERT(m_webWidget);
1130     // DRT does not support popup widgets. So m_webWidget is always a WebView.
1131     return static_cast<WebView*>(m_webWidget);
1132 }
1133
1134 WebWidget* WebViewHost::webWidget() const
1135 {
1136     ASSERT(m_webWidget);
1137     return m_webWidget;
1138 }
1139
1140 WebTestProxyBase* WebViewHost::proxy() const
1141 {
1142     ASSERT(m_proxy);
1143     return m_proxy;
1144 }
1145
1146 void WebViewHost::setProxy(WebTestProxyBase* proxy)
1147 {
1148     ASSERT(!m_proxy);
1149     ASSERT(proxy);
1150     m_proxy = proxy;
1151 }
1152
1153 void WebViewHost::reset()
1154 {
1155     m_policyDelegateEnabled = false;
1156     m_policyDelegateIsPermissive = false;
1157     m_policyDelegateShouldNotifyDone = false;
1158     m_topLoadingFrame = 0;
1159     m_pageId = -1;
1160     m_lastPageIdUpdated = -1;
1161     m_hasWindow = false;
1162     m_inModalLoop = false;
1163     m_smartInsertDeleteEnabled = true;
1164 #if OS(WINDOWS)
1165     m_selectTrailingWhitespaceEnabled = true;
1166 #else
1167     m_selectTrailingWhitespaceEnabled = false;
1168 #endif
1169     m_isPainting = false;
1170     m_canvas.clear();
1171 #if ENABLE(POINTER_LOCK)
1172     m_pointerLocked = false;
1173     m_pointerLockPlannedResult = PointerLockWillSucceed;
1174 #endif
1175
1176     m_navigationController = adoptPtr(new TestNavigationController(this));
1177
1178     m_pendingExtraData.clear();
1179     m_editCommandName.clear();
1180     m_editCommandValue.clear();
1181
1182     if (m_geolocationClientMock.get())
1183         m_geolocationClientMock->resetMock();
1184
1185 #if ENABLE(INPUT_SPEECH)
1186     if (m_speechInputControllerMock.get())
1187         m_speechInputControllerMock->clearResults();
1188 #endif
1189
1190     m_currentCursor = WebCursorInfo();
1191     m_windowRect = WebRect();
1192     // m_proxy is not set when reset() is invoked from the constructor.
1193     if (m_proxy)
1194         proxy()->reset();
1195
1196     if (m_webWidget) {
1197         webView()->mainFrame()->setName(WebString());
1198         webView()->settings()->setMinimumTimerInterval(webkit_support::GetForegroundTabTimerInterval());
1199     }
1200 }
1201
1202 void WebViewHost::setSelectTrailingWhitespaceEnabled(bool enabled)
1203 {
1204     m_selectTrailingWhitespaceEnabled = enabled;
1205     // In upstream WebKit, smart insert/delete is mutually exclusive with select
1206     // trailing whitespace, however, we allow both because Chromium on Windows
1207     // allows both.
1208 }
1209
1210 void WebViewHost::setSmartInsertDeleteEnabled(bool enabled)
1211 {
1212     m_smartInsertDeleteEnabled = enabled;
1213     // In upstream WebKit, smart insert/delete is mutually exclusive with select
1214     // trailing whitespace, however, we allow both because Chromium on Windows
1215     // allows both.
1216 }
1217
1218 void WebViewHost::setClientWindowRect(const WebKit::WebRect& rect)
1219 {
1220     setWindowRect(rect);
1221 }
1222
1223 void WebViewHost::setCustomPolicyDelegate(bool isCustom, bool isPermissive)
1224 {
1225     m_policyDelegateEnabled = isCustom;
1226     m_policyDelegateIsPermissive = isPermissive;
1227 }
1228
1229 void WebViewHost::waitForPolicyDelegate()
1230 {
1231     m_policyDelegateEnabled = true;
1232     m_policyDelegateShouldNotifyDone = true;
1233 }
1234
1235 void WebViewHost::loadURLForFrame(const WebURL& url, const WebString& frameName)
1236 {
1237     if (!url.isValid())
1238         return;
1239     TestShell::resizeWindowForTest(this, url);
1240     navigationController()->loadEntry(TestNavigationEntry::create(-1, url, WebString(), frameName).get());
1241 }
1242
1243 bool WebViewHost::navigate(const TestNavigationEntry& entry, bool reload)
1244 {
1245     // Get the right target frame for the entry.
1246     WebFrame* frame = webView()->mainFrame();
1247     if (!entry.targetFrame().isEmpty())
1248         frame = webView()->findFrameByName(entry.targetFrame());
1249
1250     // TODO(mpcomplete): should we clear the target frame, or should
1251     // back/forward navigations maintain the target frame?
1252
1253     // A navigation resulting from loading a javascript URL should not be
1254     // treated as a browser initiated event. Instead, we want it to look as if
1255     // the page initiated any load resulting from JS execution.
1256     if (!GURL(entry.URL()).SchemeIs("javascript"))
1257         setPendingExtraData(adoptPtr(new TestShellExtraData(entry.pageID())));
1258
1259     // If we are reloading, then WebKit will use the state of the current page.
1260     // Otherwise, we give it the state to navigate to.
1261     if (reload) {
1262         frame->reload(false);
1263     } else if (!entry.contentState().isNull()) {
1264         ASSERT(entry.pageID() != -1);
1265         frame->loadHistoryItem(entry.contentState());
1266     } else {
1267         ASSERT(entry.pageID() == -1);
1268         frame->loadRequest(WebURLRequest(entry.URL()));
1269     }
1270
1271     // In case LoadRequest failed before DidCreateDataSource was called.
1272     setPendingExtraData(nullptr);
1273
1274     // Restore focus to the main frame prior to loading new request.
1275     // This makes sure that we don't have a focused iframe. Otherwise, that
1276     // iframe would keep focus when the SetFocus called immediately after
1277     // LoadRequest, thus making some tests fail (see http://b/issue?id=845337
1278     // for more details).
1279     webView()->setFocusedFrame(frame);
1280     m_shell->setFocus(webView(), true);
1281
1282     return true;
1283 }
1284
1285 // Private functions ----------------------------------------------------------
1286
1287 DRTTestRunner* WebViewHost::testRunner() const
1288 {
1289     return m_shell->testRunner();
1290 }
1291
1292 void WebViewHost::updateAddressBar(WebView* webView)
1293 {
1294     WebFrame* mainFrame = webView->mainFrame();
1295     WebDataSource* dataSource = mainFrame->dataSource();
1296     if (!dataSource)
1297         dataSource = mainFrame->provisionalDataSource();
1298     if (!dataSource)
1299         return;
1300
1301     setAddressBarURL(dataSource->request().url());
1302 }
1303
1304 void WebViewHost::locationChangeDone(WebFrame* frame)
1305 {
1306     if (frame != m_topLoadingFrame)
1307         return;
1308     m_topLoadingFrame = 0;
1309     testRunner()->locationChangeDone();
1310 }
1311
1312 void WebViewHost::updateForCommittedLoad(WebFrame* frame, bool isNewNavigation)
1313 {
1314     // Code duplicated from RenderView::DidCommitLoadForFrame.
1315     TestShellExtraData* extraData = static_cast<TestShellExtraData*>(frame->dataSource()->extraData());
1316     const WebURL& url = frame->dataSource()->request().url();
1317     bool nonBlankPageAfterReset = m_pageId == -1 && !url.isEmpty() && strcmp(url.spec().data(), "about:blank");
1318
1319     if (isNewNavigation || nonBlankPageAfterReset) {
1320         // New navigation.
1321         updateSessionHistory(frame);
1322         m_pageId = nextPageID++;
1323     } else if (extraData && extraData->pendingPageID != -1 && !extraData->requestCommitted) {
1324         // This is a successful session history navigation!
1325         updateSessionHistory(frame);
1326         m_pageId = extraData->pendingPageID;
1327     }
1328
1329     // Don't update session history multiple times.
1330     if (extraData)
1331         extraData->requestCommitted = true;
1332
1333     updateURL(frame);
1334 }
1335
1336 void WebViewHost::updateURL(WebFrame* frame)
1337 {
1338     WebDataSource* ds = frame->dataSource();
1339     ASSERT(ds);
1340     const WebURLRequest& request = ds->request();
1341     RefPtr<TestNavigationEntry> entry(TestNavigationEntry::create());
1342
1343     // The referrer will be empty on https->http transitions. It
1344     // would be nice if we could get the real referrer from somewhere.
1345     entry->setPageID(m_pageId);
1346     if (ds->hasUnreachableURL())
1347         entry->setURL(ds->unreachableURL());
1348     else
1349         entry->setURL(request.url());
1350
1351     const WebHistoryItem& historyItem = frame->currentHistoryItem();
1352     if (!historyItem.isNull())
1353         entry->setContentState(historyItem);
1354
1355     navigationController()->didNavigateToEntry(entry.get());
1356     updateAddressBar(frame->view());
1357     m_lastPageIdUpdated = max(m_lastPageIdUpdated, m_pageId);
1358 }
1359
1360 void WebViewHost::updateSessionHistory(WebFrame* frame)
1361 {
1362     // If we have a valid page ID at this point, then it corresponds to the page
1363     // we are navigating away from. Otherwise, this is the first navigation, so
1364     // there is no past session history to record.
1365     if (m_pageId == -1)
1366         return;
1367
1368     TestNavigationEntry* entry = navigationController()->entryWithPageID(m_pageId);
1369     if (!entry)
1370         return;
1371
1372     const WebHistoryItem& historyItem = webView()->mainFrame()->previousHistoryItem();
1373     if (historyItem.isNull())
1374         return;
1375
1376     entry->setContentState(historyItem);
1377 }
1378
1379 void WebViewHost::printFrameDescription(WebFrame* webframe)
1380 {
1381     string name8 = webframe->uniqueName().utf8();
1382     if (webframe == webView()->mainFrame()) {
1383         if (!name8.length()) {
1384             fputs("main frame", stdout);
1385             return;
1386         }
1387         printf("main frame \"%s\"", name8.c_str());
1388         return;
1389     }
1390     if (!name8.length()) {
1391         fputs("frame (anonymous)", stdout);
1392         return;
1393     }
1394     printf("frame \"%s\"", name8.c_str());
1395 }
1396
1397 void WebViewHost::setPendingExtraData(PassOwnPtr<TestShellExtraData> extraData)
1398 {
1399     m_pendingExtraData = extraData;
1400 }
1401
1402 void WebViewHost::setPageTitle(const WebString&)
1403 {
1404     // Nothing to do in layout test.
1405 }
1406
1407 void WebViewHost::setAddressBarURL(const WebURL&)
1408 {
1409     // Nothing to do in layout test.
1410 }
1411
1412 void WebViewHost::enterFullScreenNow()
1413 {
1414     webView()->willEnterFullScreen();
1415     webView()->didEnterFullScreen();
1416 }
1417
1418 void WebViewHost::exitFullScreenNow()
1419 {
1420     webView()->willExitFullScreen();
1421     webView()->didExitFullScreen();
1422 }
1423
1424 #if ENABLE(MEDIA_STREAM)
1425 webkit_support::TestMediaStreamClient* WebViewHost::testMediaStreamClient()
1426 {
1427     if (!m_testMediaStreamClient.get())
1428         m_testMediaStreamClient = adoptPtr(new webkit_support::TestMediaStreamClient());
1429     return m_testMediaStreamClient.get();
1430 }
1431 #endif
1432
1433 // Painting functions ---------------------------------------------------------
1434
1435 void WebViewHost::paintRect(const WebRect& rect)
1436 {
1437     ASSERT(!m_isPainting);
1438     ASSERT(canvas());
1439     m_isPainting = true;
1440     float deviceScaleFactor = webView()->deviceScaleFactor();
1441     int scaledX = static_cast<int>(static_cast<float>(rect.x) * deviceScaleFactor);
1442     int scaledY = static_cast<int>(static_cast<float>(rect.y) * deviceScaleFactor);
1443     int scaledWidth = static_cast<int>(ceil(static_cast<float>(rect.width) * deviceScaleFactor));
1444     int scaledHeight = static_cast<int>(ceil(static_cast<float>(rect.height) * deviceScaleFactor));
1445     WebRect deviceRect(scaledX, scaledY, scaledWidth, scaledHeight);
1446     webWidget()->paint(canvas(), deviceRect);
1447     m_isPainting = false;
1448 }
1449
1450 void WebViewHost::paintInvalidatedRegion()
1451 {
1452 #if ENABLE(REQUEST_ANIMATION_FRAME)
1453     webWidget()->animate(0.0);
1454 #endif
1455     webWidget()->layout();
1456     WebSize widgetSize = webWidget()->size();
1457     WebRect clientRect(0, 0, widgetSize.width, widgetSize.height);
1458
1459     // Paint the canvas if necessary. Allow painting to generate extra rects
1460     // for the first two calls. This is necessary because some WebCore rendering
1461     // objects update their layout only when painted.
1462     // Store the total area painted in total_paint. Then tell the gdk window
1463     // to update that area after we're done painting it.
1464     for (int i = 0; i < 3; ++i) {
1465         // rect = intersect(proxy()->paintRect() , clientRect)
1466         WebRect damageRect = proxy()->paintRect();
1467         int left = max(damageRect.x, clientRect.x);
1468         int top = max(damageRect.y, clientRect.y);
1469         int right = min(damageRect.x + damageRect.width, clientRect.x + clientRect.width);
1470         int bottom = min(damageRect.y + damageRect.height, clientRect.y + clientRect.height);
1471         WebRect rect;
1472         if (left < right && top < bottom)
1473             rect = WebRect(left, top, right - left, bottom - top);
1474
1475         proxy()->setPaintRect(WebRect());
1476         if (rect.isEmpty())
1477             continue;
1478         paintRect(rect);
1479     }
1480     ASSERT(proxy()->paintRect().isEmpty());
1481 }
1482
1483 void WebViewHost::paintPagesWithBoundaries()
1484 {
1485     ASSERT(!m_isPainting);
1486     ASSERT(canvas());
1487     m_isPainting = true;
1488
1489     WebSize pageSizeInPixels = webWidget()->size();
1490     WebFrame* webFrame = webView()->mainFrame();
1491
1492     int pageCount = webFrame->printBegin(pageSizeInPixels);
1493     int totalHeight = pageCount * (pageSizeInPixels.height + 1) - 1;
1494
1495     SkCanvas* testCanvas = skia::TryCreateBitmapCanvas(pageSizeInPixels.width, totalHeight, true);
1496     if (testCanvas) {
1497         discardBackingStore();
1498         m_canvas = adoptPtr(testCanvas);
1499     } else {
1500         webFrame->printEnd();
1501         return;
1502     }
1503
1504     webFrame->printPagesWithBoundaries(canvas(), pageSizeInPixels);
1505     webFrame->printEnd();
1506
1507     m_isPainting = false;
1508 }
1509
1510 SkCanvas* WebViewHost::canvas()
1511 {
1512     if (m_canvas)
1513         return m_canvas.get();
1514     WebSize widgetSize = webWidget()->size();
1515     float deviceScaleFactor = webView()->deviceScaleFactor();
1516     int scaledWidth = static_cast<int>(ceil(static_cast<float>(widgetSize.width) * deviceScaleFactor));
1517     int scaledHeight = static_cast<int>(ceil(static_cast<float>(widgetSize.height) * deviceScaleFactor));
1518     resetScrollRect();
1519     m_canvas = adoptPtr(skia::CreateBitmapCanvas(scaledWidth, scaledHeight, true));
1520     return m_canvas.get();
1521 }
1522
1523 void WebViewHost::resetScrollRect()
1524 {
1525 }
1526
1527 void WebViewHost::discardBackingStore()
1528 {
1529     m_canvas.clear();
1530 }
1531
1532 // Paints the entire canvas a semi-transparent black (grayish). This is used
1533 // by the layout tests in fast/repaint. The alpha value matches upstream.
1534 void WebViewHost::displayRepaintMask()
1535 {
1536     canvas()->drawARGB(167, 0, 0, 0);
1537 }
1538
1539 // Simulate a print by going into print mode and then exit straight away.
1540 void WebViewHost::printPage(WebKit::WebFrame* frame)
1541 {
1542     WebSize pageSizeInPixels = webWidget()->size();
1543     WebPrintParams printParams(pageSizeInPixels);
1544     frame->printBegin(printParams);
1545     frame->printEnd();
1546 }