[chromium] move most of the remaining mocks to TestRunner library
[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 "Task.h"
36 #include "TestNavigationController.h"
37 #include "TestShell.h"
38 #include "WebCachedURLRequest.h"
39 #include "WebConsoleMessage.h"
40 #include "WebContextMenuData.h"
41 #include "WebDOMMessageEvent.h"
42 #include "WebDataSource.h"
43 #include "WebDocument.h"
44 #include "WebElement.h"
45 #include "WebFrame.h"
46 #include "WebHistoryItem.h"
47 #include "WebKit.h"
48 #include "WebNode.h"
49 #include "WebPluginParams.h"
50 #include "WebPopupMenu.h"
51 #include "WebPopupType.h"
52 #include "WebPrintParams.h"
53 #include "WebRange.h"
54 #include "WebScreenInfo.h"
55 #include "WebSerializedScriptValue.h"
56 #include "WebStorageNamespace.h"
57 #include "WebView.h"
58 #include "WebWindowFeatures.h"
59 #include "webkit/support/test_media_stream_client.h"
60 #include "webkit/support/webkit_support.h"
61 #include <cctype>
62 #include <clocale>
63 #include <public/WebCString.h>
64 #include <public/WebCompositorOutputSurface.h>
65 #include <public/WebCompositorSupport.h>
66 #include <public/WebDragData.h>
67 #include <public/WebRect.h>
68 #include <public/WebSize.h>
69 #include <public/WebThread.h>
70 #include <public/WebURLRequest.h>
71 #include <public/WebURLResponse.h>
72
73 #include <wtf/Assertions.h>
74 #include <wtf/OwnArrayPtr.h>
75 #include <wtf/PassOwnPtr.h>
76 #include <wtf/Vector.h>
77
78 using namespace WebCore;
79 using namespace WebKit;
80 using namespace WebTestRunner;
81 using namespace std;
82
83 static const int screenWidth = 1920;
84 static const int screenHeight = 1080;
85 static const int screenUnavailableBorder = 8;
86
87 static int nextPageID = 1;
88
89 // WebViewClient -------------------------------------------------------------
90
91 WebView* WebViewHost::createView(WebFrame* creator, const WebURLRequest&, const WebWindowFeatures&, const WebString&, WebNavigationPolicy)
92 {
93     creator->consumeUserGesture();
94     return m_shell->createNewWindow(WebURL())->webView();
95 }
96
97 WebWidget* WebViewHost::createPopupMenu(WebPopupType type)
98 {
99     switch (type) {
100     case WebKit::WebPopupTypeNone:
101     case WebKit::WebPopupTypePage:
102     case WebKit::WebPopupTypeHelperPlugin:
103         break;
104     case WebKit::WebPopupTypeSelect:
105     case WebKit::WebPopupTypeSuggestion:
106         m_popupmenus.append(WebPopupMenu::create(0));
107         return m_popupmenus.last();
108     }
109     return 0;
110 }
111
112 WebWidget* WebViewHost::createPopupMenu(const WebPopupMenuInfo&)
113 {
114     // Do not use this method. It's been replaced by createExternalPopupMenu.
115     ASSERT_NOT_REACHED();
116     return 0;
117 }
118
119 WebStorageNamespace* WebViewHost::createSessionStorageNamespace(unsigned quota)
120 {
121     return webkit_support::CreateSessionStorageNamespace(quota);
122 }
123
124 WebCompositorOutputSurface* WebViewHost::createOutputSurface()
125 {
126     if (!webView())
127         return 0;
128
129     if (m_shell->softwareCompositingEnabled())
130         return WebKit::Platform::current()->compositorSupport()->createOutputSurfaceForSoftware();
131
132     WebGraphicsContext3D* context = webkit_support::CreateGraphicsContext3D(WebGraphicsContext3D::Attributes(), webView());
133     return WebKit::Platform::current()->compositorSupport()->createOutputSurfaceFor3D(context);
134 }
135
136 void WebViewHost::didAddMessageToConsole(const WebConsoleMessage& message, const WebString& sourceName, unsigned sourceLine)
137 {
138 }
139
140 void WebViewHost::didStartLoading()
141 {
142 }
143
144 void WebViewHost::didStopLoading()
145 {
146 }
147
148 bool WebViewHost::shouldBeginEditing(const WebRange& range)
149 {
150     return true;
151 }
152
153 bool WebViewHost::shouldEndEditing(const WebRange& range)
154 {
155     return true;
156 }
157
158 bool WebViewHost::shouldInsertNode(const WebNode& node, const WebRange& range, WebEditingAction action)
159 {
160     return true;
161 }
162
163 bool WebViewHost::shouldInsertText(const WebString& text, const WebRange& range, WebEditingAction action)
164 {
165     return true;
166 }
167
168 bool WebViewHost::shouldChangeSelectedRange(
169     const WebRange& fromRange, const WebRange& toRange, WebTextAffinity affinity, bool stillSelecting)
170 {
171     return true;
172 }
173
174 bool WebViewHost::shouldDeleteRange(const WebRange& range)
175 {
176     return true;
177 }
178
179 bool WebViewHost::shouldApplyStyle(const WebString& style, const WebRange& range)
180 {
181     return true;
182 }
183
184 bool WebViewHost::isSmartInsertDeleteEnabled()
185 {
186     return true;
187 }
188
189 bool WebViewHost::isSelectTrailingWhitespaceEnabled()
190 {
191 #if OS(WINDOWS)
192     return true;
193 #else
194     return false;
195 #endif
196 }
197
198 bool WebViewHost::handleCurrentKeyboardEvent()
199 {
200     if (m_editCommandName.empty())
201         return false;
202     WebFrame* frame = webView()->focusedFrame();
203     if (!frame)
204         return false;
205
206     return frame->executeCommand(WebString::fromUTF8(m_editCommandName), WebString::fromUTF8(m_editCommandValue));
207 }
208
209 // WebKit::WebPrerendererClient
210
211 void WebViewHost::willAddPrerender(WebKit::WebPrerender*)
212 {
213 }
214
215
216 void WebViewHost::runModalAlertDialog(WebFrame*, const WebString& message)
217 {
218 }
219
220 bool WebViewHost::runModalConfirmDialog(WebFrame*, const WebString& message)
221 {
222     return true;
223 }
224
225 bool WebViewHost::runModalPromptDialog(WebFrame* frame, const WebString& message,
226                                        const WebString& defaultValue, WebString*)
227 {
228     return true;
229 }
230
231 void WebViewHost::showContextMenu(WebFrame*, const WebContextMenuData& contextMenuData)
232 {
233 }
234
235 void WebViewHost::didUpdateLayout()
236 {
237 #if OS(MAC_OS_X)
238     static bool queryingPreferredSize = false;
239     if (queryingPreferredSize)
240         return;
241
242     queryingPreferredSize = true;
243     // Query preferred width to emulate the same functionality in Chromium:
244     // see RenderView::CheckPreferredSize (src/content/renderer/render_view.cc)
245     // and TabContentsViewMac::RenderViewCreated (src/chrome/browser/tab_contents/tab_contents_view_mac.mm)
246     webView()->mainFrame()->contentsPreferredWidth();
247     webView()->mainFrame()->documentElementScrollHeight();
248     queryingPreferredSize = false;
249 #endif
250 }
251
252 void WebViewHost::navigateBackForwardSoon(int offset)
253 {
254     navigationController()->goToOffset(offset);
255 }
256
257 int WebViewHost::historyBackListCount()
258 {
259     return navigationController()->lastCommittedEntryIndex();
260 }
261
262 int WebViewHost::historyForwardListCount()
263 {
264     int currentIndex =navigationController()->lastCommittedEntryIndex();
265     return navigationController()->entryCount() - currentIndex - 1;
266 }
267
268 // WebWidgetClient -----------------------------------------------------------
269
270 void WebViewHost::didAutoResize(const WebSize& newSize)
271 {
272     // Purposely don't include the virtualWindowBorder in this case so that
273     // window.inner[Width|Height] is the same as window.outer[Width|Height]
274     setWindowRect(WebRect(0, 0, newSize.width, newSize.height));
275 }
276
277 void WebViewHost::initializeLayerTreeView(WebLayerTreeViewClient* client, const WebLayer& rootLayer, const WebLayerTreeView::Settings& settings)
278 {
279     m_layerTreeView = adoptPtr(Platform::current()->compositorSupport()->createLayerTreeView(client, rootLayer, settings));
280     if (m_layerTreeView)
281         m_layerTreeView->setSurfaceReady();
282 }
283
284 WebLayerTreeView* WebViewHost::layerTreeView()
285 {
286     return m_layerTreeView.get();
287 }
288
289 void WebViewHost::scheduleAnimation()
290 {
291     if (webView()->settings()->scrollAnimatorEnabled())
292         webView()->animate(0.0);
293 }
294
295 void WebViewHost::didFocus()
296 {
297     m_shell->setFocus(webWidget(), true);
298 }
299
300 void WebViewHost::didBlur()
301 {
302     m_shell->setFocus(webWidget(), false);
303 }
304
305 WebScreenInfo WebViewHost::screenInfo()
306 {
307     // We don't need to set actual values.
308     WebScreenInfo info;
309     info.depth = 24;
310     info.depthPerComponent = 8;
311     info.isMonochrome = false;
312     info.rect = WebRect(0, 0, screenWidth, screenHeight);
313     // Use values different from info.rect for testing.
314     info.availableRect = WebRect(screenUnavailableBorder, screenUnavailableBorder,
315                                  screenWidth - screenUnavailableBorder * 2,
316                                  screenHeight - screenUnavailableBorder * 2);
317     return info;
318 }
319
320 void WebViewHost::show(WebNavigationPolicy)
321 {
322     m_hasWindow = true;
323 }
324
325
326
327 void WebViewHost::closeWidget()
328 {
329     m_hasWindow = false;
330     m_shell->closeWindow(this);
331     // No more code here, we should be deleted at this point.
332 }
333
334 void WebViewHost::closeWidgetSoon()
335 {
336     postDelayedTask(new HostMethodTask(this, &WebViewHost::closeWidget), 0);
337 }
338
339 void WebViewHost::didChangeCursor(const WebCursorInfo& cursorInfo)
340 {
341     if (!hasWindow())
342         return;
343     m_currentCursor = cursorInfo;
344 }
345
346 WebRect WebViewHost::windowRect()
347 {
348     return m_windowRect;
349 }
350
351 void WebViewHost::setWindowRect(const WebRect& rect)
352 {
353     m_windowRect = rect;
354     const int border2 = TestShell::virtualWindowBorder * 2;
355     if (m_windowRect.width <= border2)
356         m_windowRect.width = 1 + border2;
357     if (m_windowRect.height <= border2)
358         m_windowRect.height = 1 + border2;
359     int width = m_windowRect.width - border2;
360     int height = m_windowRect.height - border2;
361     webWidget()->resize(WebSize(width, height));
362 }
363
364 WebRect WebViewHost::rootWindowRect()
365 {
366     return windowRect();
367 }
368
369 WebRect WebViewHost::windowResizerRect()
370 {
371     // Not necessary.
372     return WebRect();
373 }
374
375 void WebViewHost::runModal()
376 {
377     if (m_shell->isDisplayingModalDialog()) {
378         // DumpRenderTree doesn't support real modal dialogs, so a test shouldn't try to start two modal dialogs at the same time.
379         ASSERT_NOT_REACHED();
380         return;
381     }
382     // This WebViewHost might get deleted before RunMessageLoop() returns, so keep a copy of the m_shell member variable around.
383     ASSERT(m_shell->webViewHost() != this);
384     TestShell* shell = m_shell;
385     shell->setIsDisplayingModalDialog(true);
386     bool oldState = webkit_support::MessageLoopNestableTasksAllowed();
387     webkit_support::MessageLoopSetNestableTasksAllowed(true);
388     m_inModalLoop = true;
389     webkit_support::RunMessageLoop();
390     webkit_support::MessageLoopSetNestableTasksAllowed(oldState);
391     shell->setIsDisplayingModalDialog(false);
392 }
393
394 bool WebViewHost::enterFullScreen()
395 {
396     postDelayedTask(new HostMethodTask(this, &WebViewHost::enterFullScreenNow), 0);
397     return true;
398 }
399
400 void WebViewHost::exitFullScreen()
401 {
402     postDelayedTask(new HostMethodTask(this, &WebViewHost::exitFullScreenNow), 0);
403 }
404
405 // WebFrameClient ------------------------------------------------------------
406
407 WebPlugin* WebViewHost::createPlugin(WebFrame* frame, const WebPluginParams& params)
408 {
409     return webkit_support::CreateWebPlugin(frame, params);
410 }
411
412 WebMediaPlayer* WebViewHost::createMediaPlayer(WebFrame* frame, const WebURL& url, WebMediaPlayerClient* client)
413 {
414 #if ENABLE(MEDIA_STREAM)
415     return webkit_support::CreateMediaPlayer(frame, url, client, testMediaStreamClient());
416 #else
417     return webkit_support::CreateMediaPlayer(frame, url, client);
418 #endif
419 }
420
421 WebApplicationCacheHost* WebViewHost::createApplicationCacheHost(WebFrame* frame, WebApplicationCacheHostClient* client)
422 {
423     return webkit_support::CreateApplicationCacheHost(frame, client);
424 }
425
426 void WebViewHost::loadURLExternally(WebFrame* frame, const WebURLRequest& request, WebNavigationPolicy policy)
427 {
428     loadURLExternally(frame, request, policy, WebString());
429 }
430
431 void WebViewHost::loadURLExternally(WebFrame*, const WebURLRequest& request, WebNavigationPolicy policy, const WebString& downloadName)
432 {
433     ASSERT(policy !=  WebKit::WebNavigationPolicyCurrentTab);
434     WebViewHost* another = m_shell->createNewWindow(request.url());
435     if (another)
436         another->show(policy);
437 }
438
439 WebNavigationPolicy WebViewHost::decidePolicyForNavigation(
440     WebFrame*, const WebURLRequest&,
441     WebNavigationType, const WebNode&,
442     WebNavigationPolicy defaultPolicy, bool)
443 {
444     return defaultPolicy;
445 }
446
447 bool WebViewHost::canHandleRequest(WebFrame*, const WebURLRequest& request)
448 {
449     return true;
450 }
451
452 WebURLError WebViewHost::cancelledError(WebFrame*, const WebURLRequest& request)
453 {
454     return webkit_support::CreateCancelledError(request);
455 }
456
457 void WebViewHost::unableToImplementPolicyWithError(WebFrame* frame, const WebURLError& error)
458 {
459 }
460
461 void WebViewHost::didCreateDataSource(WebFrame*, WebDataSource* ds)
462 {
463     ds->setExtraData(m_pendingExtraData.leakPtr());
464 }
465
466 void WebViewHost::didCommitProvisionalLoad(WebFrame* frame, bool isNewNavigation)
467 {
468     updateForCommittedLoad(frame, isNewNavigation);
469 }
470
471 void WebViewHost::didClearWindowObject(WebFrame* frame)
472 {
473     m_shell->bindJSObjectsToWindow(frame);
474 }
475
476 void WebViewHost::didReceiveTitle(WebFrame* frame, const WebString& title, WebTextDirection direction)
477 {
478     setPageTitle(title);
479 }
480
481 void WebViewHost::didNavigateWithinPage(WebFrame* frame, bool isNewNavigation)
482 {
483     frame->dataSource()->setExtraData(m_pendingExtraData.leakPtr());
484
485     updateForCommittedLoad(frame, isNewNavigation);
486 }
487
488 void WebViewHost::willSendRequest(WebFrame* frame, unsigned, WebURLRequest& request, const WebURLResponse&)
489 {
490     if (request.url().isEmpty())
491         return;
492
493     request.setExtraData(webkit_support::CreateWebURLRequestExtraData(frame->document().referrerPolicy()));
494 }
495
496 void WebViewHost::openFileSystem(WebFrame* frame, WebFileSystem::Type type, long long size, bool create, WebFileSystemCallbacks* callbacks)
497 {
498     webkit_support::OpenFileSystem(frame, type, size, create, callbacks);
499 }
500
501 void WebViewHost::deleteFileSystem(WebKit::WebFrame* frame, WebKit::WebFileSystem::Type type, WebKit::WebFileSystemCallbacks* callbacks)
502 {
503     webkit_support::DeleteFileSystem(frame, type, callbacks);
504 }
505
506 bool WebViewHost::willCheckAndDispatchMessageEvent(WebFrame* sourceFrame, WebFrame* targetFrame, WebSecurityOrigin target, WebDOMMessageEvent event)
507 {
508     return false;
509 }
510
511 // WebTestDelegate ------------------------------------------------------------
512
513 void WebViewHost::setEditCommand(const string& name, const string& value)
514 {
515     m_editCommandName = name;
516     m_editCommandValue = value;
517 }
518
519 void WebViewHost::clearEditCommand()
520 {
521     m_editCommandName.clear();
522     m_editCommandValue.clear();
523 }
524
525 void WebViewHost::setGamepadData(const WebGamepads& pads)
526 {
527     webkit_support::SetGamepadData(pads);
528 }
529
530 void WebViewHost::printMessage(const std::string& message)
531 {
532     printf("%s", message.c_str());
533 }
534
535 void WebViewHost::postTask(WebTask* task)
536 {
537     ::postTask(task);
538 }
539
540 void WebViewHost::postDelayedTask(WebTask* task, long long ms)
541 {
542     ::postDelayedTask(task, ms);
543 }
544
545 WebString WebViewHost::registerIsolatedFileSystem(const WebVector<WebString>& absoluteFilenames)
546 {
547     return webkit_support::RegisterIsolatedFileSystem(absoluteFilenames);
548 }
549
550 long long WebViewHost::getCurrentTimeInMillisecond()
551 {
552     return webkit_support::GetCurrentTimeInMillisecond();
553 }
554
555 WebKit::WebString WebViewHost::getAbsoluteWebStringFromUTF8Path(const std::string& path)
556 {
557     return webkit_support::GetAbsoluteWebStringFromUTF8Path(path);
558 }
559
560 WebURL WebViewHost::localFileToDataURL(const WebKit::WebURL& url)
561 {
562     return webkit_support::LocalFileToDataURL(url);
563 }
564
565 WebURL WebViewHost::rewriteLayoutTestsURL(const std::string& url)
566 {
567     return webkit_support::RewriteLayoutTestsURL(url);
568 }
569
570 WebPreferences* WebViewHost::preferences()
571 {
572     return m_shell->preferences();
573 }
574
575 void WebViewHost::applyPreferences()
576 {
577     m_shell->applyPreferences();
578 }
579
580 std::string WebViewHost::makeURLErrorDescription(const WebKit::WebURLError& error)
581 {
582     return webkit_support::MakeURLErrorDescription(error);
583 }
584
585 void WebViewHost::showDevTools()
586 {
587     m_shell->showDevTools();
588 }
589
590 void WebViewHost::closeDevTools()
591 {
592     m_shell->closeDevTools();
593 }
594
595 void WebViewHost::evaluateInWebInspector(long callID, const std::string& script)
596 {
597     m_shell->drtDevToolsAgent()->evaluateInWebInspector(callID, script);
598 }
599
600 void WebViewHost::clearAllDatabases()
601 {
602     webkit_support::ClearAllDatabases();
603 }
604
605 void WebViewHost::setDatabaseQuota(int quota)
606 {
607     webkit_support::SetDatabaseQuota(quota);
608 }
609
610 void WebViewHost::setDeviceScaleFactor(float deviceScaleFactor)
611 {
612     webView()->setDeviceScaleFactor(deviceScaleFactor);
613 }
614
615 void WebViewHost::setFocus(bool focused)
616 {
617     m_shell->setFocus(m_shell->webView(), focused);
618 }
619
620 void WebViewHost::setAcceptAllCookies(bool acceptCookies)
621 {
622     webkit_support::SetAcceptAllCookies(acceptCookies);
623 }
624
625 string WebViewHost::pathToLocalResource(const string& url)
626 {
627 #if OS(WINDOWS)
628     if (!url.find("/tmp/")) {
629         // We want a temp file.
630         const unsigned tempPrefixLength = 5;
631         size_t bufferSize = MAX_PATH;
632         OwnArrayPtr<WCHAR> tempPath = adoptArrayPtr(new WCHAR[bufferSize]);
633         DWORD tempLength = ::GetTempPathW(bufferSize, tempPath.get());
634         if (tempLength + url.length() - tempPrefixLength + 1 > bufferSize) {
635             bufferSize = tempLength + url.length() - tempPrefixLength + 1;
636             tempPath = adoptArrayPtr(new WCHAR[bufferSize]);
637             tempLength = GetTempPathW(bufferSize, tempPath.get());
638             ASSERT(tempLength < bufferSize);
639         }
640         string resultPath(WebString(tempPath.get(), tempLength).utf8());
641         resultPath.append(url.substr(tempPrefixLength));
642         return resultPath;
643     }
644 #endif
645
646     // Some layout tests use file://// which we resolve as a UNC path. Normalize
647     // them to just file:///.
648     string lowerUrl = url;
649     string result = url;
650     transform(lowerUrl.begin(), lowerUrl.end(), lowerUrl.begin(), ::tolower);
651     while (!lowerUrl.find("file:////")) {
652         result = result.substr(0, 8) + result.substr(9);
653         lowerUrl = lowerUrl.substr(0, 8) + lowerUrl.substr(9);
654     }
655     return webkit_support::RewriteLayoutTestsURL(result).spec();
656 }
657
658 void WebViewHost::setLocale(const std::string& locale)
659 {
660     setlocale(LC_ALL, locale.c_str());
661 }
662
663 void WebViewHost::testFinished()
664 {
665     m_shell->testFinished(this);
666 }
667
668 void WebViewHost::testTimedOut()
669 {
670     m_shell->testTimedOut();
671 }
672
673 bool WebViewHost::isBeingDebugged()
674 {
675     return webkit_support::BeingDebugged();
676 }
677
678 int WebViewHost::layoutTestTimeout()
679 {
680     return m_shell->layoutTestTimeout();
681 }
682
683 void WebViewHost::closeRemainingWindows()
684 {
685     m_shell->closeRemainingWindows();
686 }
687
688 int WebViewHost::navigationEntryCount()
689 {
690     return m_shell->navigationEntryCount();
691 }
692
693 void WebViewHost::goToOffset(int offset)
694 {
695     m_shell->goToOffset(offset);
696 }
697
698 void WebViewHost::reload()
699 {
700     m_shell->reload();
701 }
702
703 void WebViewHost::loadURLForFrame(const WebURL& url, const string& frameName)
704 {
705     if (!url.isValid())
706         return;
707     TestShell::resizeWindowForTest(this, url);
708     navigationController()->loadEntry(TestNavigationEntry::create(-1, url, WebString(), WebString::fromUTF8(frameName)).get());
709 }
710
711 bool WebViewHost::allowExternalPages()
712 {
713     return m_shell->allowExternalPages();
714 }
715
716 void WebViewHost::captureHistoryForWindow(size_t windowIndex, WebVector<WebHistoryItem>* history, size_t* currentEntryIndex)
717 {
718     m_shell->captureHistoryForWindow(windowIndex, history, currentEntryIndex);
719 }
720
721 // Public functions -----------------------------------------------------------
722
723 WebViewHost::WebViewHost(TestShell* shell)
724     : m_shell(shell)
725     , m_proxy(0)
726     , m_webWidget(0)
727     , m_shutdownWasInvoked(false)
728 {
729     reset();
730 }
731
732 WebViewHost::~WebViewHost()
733 {
734     ASSERT(m_shutdownWasInvoked);
735     if (m_inModalLoop)
736         webkit_support::QuitMessageLoop();
737 }
738
739 void WebViewHost::shutdown()
740 {
741     ASSERT(!m_shutdownWasInvoked);
742
743     // DevTools frontend page is supposed to be navigated only once and
744     // loading another URL in that Page is an error.
745     if (m_shell->devToolsWebView() != this) {
746         // Navigate to an empty page to fire all the destruction logic for the
747         // current page.
748         loadURLForFrame(GURL("about:blank"), string());
749     }
750
751     for (Vector<WebKit::WebWidget*>::iterator it = m_popupmenus.begin();
752          it < m_popupmenus.end(); ++it)
753         (*it)->close();
754
755     webWidget()->willCloseLayerTreeView();
756     m_layerTreeView.clear();
757     webWidget()->close();
758     m_webWidget = 0;
759     m_shutdownWasInvoked = true;
760 }
761
762 void WebViewHost::setWebWidget(WebKit::WebWidget* widget)
763 {
764     m_webWidget = widget;
765     webView()->setSpellCheckClient(proxy()->spellCheckClient());
766     webView()->setPrerendererClient(this);
767 }
768
769 WebView* WebViewHost::webView() const
770 {
771     ASSERT(m_webWidget);
772     // DRT does not support popup widgets. So m_webWidget is always a WebView.
773     return static_cast<WebView*>(m_webWidget);
774 }
775
776 WebWidget* WebViewHost::webWidget() const
777 {
778     ASSERT(m_webWidget);
779     return m_webWidget;
780 }
781
782 WebTestProxyBase* WebViewHost::proxy() const
783 {
784     ASSERT(m_proxy);
785     return m_proxy;
786 }
787
788 void WebViewHost::setProxy(WebTestProxyBase* proxy)
789 {
790     ASSERT(!m_proxy);
791     ASSERT(proxy);
792     m_proxy = proxy;
793 }
794
795 void WebViewHost::reset()
796 {
797     m_pageId = -1;
798     m_lastPageIdUpdated = -1;
799     m_hasWindow = false;
800     m_inModalLoop = false;
801
802     m_navigationController = adoptPtr(new TestNavigationController(this));
803
804     m_pendingExtraData.clear();
805     m_editCommandName.clear();
806     m_editCommandValue.clear();
807
808     m_currentCursor = WebCursorInfo();
809     m_windowRect = WebRect();
810     // m_proxy is not set when reset() is invoked from the constructor.
811     if (m_proxy)
812         proxy()->reset();
813
814     if (m_webWidget) {
815         webView()->mainFrame()->setName(WebString());
816     }
817 }
818
819 void WebViewHost::setClientWindowRect(const WebKit::WebRect& rect)
820 {
821     setWindowRect(rect);
822 }
823
824 bool WebViewHost::navigate(const TestNavigationEntry& entry, bool reload)
825 {
826     // Get the right target frame for the entry.
827     WebFrame* frame = webView()->mainFrame();
828     if (!entry.targetFrame().isEmpty())
829         frame = webView()->findFrameByName(entry.targetFrame());
830
831     // TODO(mpcomplete): should we clear the target frame, or should
832     // back/forward navigations maintain the target frame?
833
834     // A navigation resulting from loading a javascript URL should not be
835     // treated as a browser initiated event. Instead, we want it to look as if
836     // the page initiated any load resulting from JS execution.
837     if (!GURL(entry.URL()).SchemeIs("javascript"))
838         setPendingExtraData(adoptPtr(new TestShellExtraData(entry.pageID())));
839
840     // If we are reloading, then WebKit will use the state of the current page.
841     // Otherwise, we give it the state to navigate to.
842     if (reload) {
843         frame->reload(false);
844     } else if (!entry.contentState().isNull()) {
845         ASSERT(entry.pageID() != -1);
846         frame->loadHistoryItem(entry.contentState());
847     } else {
848         ASSERT(entry.pageID() == -1);
849         frame->loadRequest(WebURLRequest(entry.URL()));
850     }
851
852     // In case LoadRequest failed before DidCreateDataSource was called.
853     setPendingExtraData(nullptr);
854
855     // Restore focus to the main frame prior to loading new request.
856     // This makes sure that we don't have a focused iframe. Otherwise, that
857     // iframe would keep focus when the SetFocus called immediately after
858     // LoadRequest, thus making some tests fail (see http://b/issue?id=845337
859     // for more details).
860     webView()->setFocusedFrame(frame);
861     m_shell->setFocus(webView(), true);
862
863     return true;
864 }
865
866 // Private functions ----------------------------------------------------------
867
868 void WebViewHost::updateForCommittedLoad(WebFrame* frame, bool isNewNavigation)
869 {
870     // Code duplicated from RenderView::DidCommitLoadForFrame.
871     TestShellExtraData* extraData = static_cast<TestShellExtraData*>(frame->dataSource()->extraData());
872     const WebURL& url = frame->dataSource()->request().url();
873     bool nonBlankPageAfterReset = m_pageId == -1 && !url.isEmpty() && strcmp(url.spec().data(), "about:blank");
874
875     if (isNewNavigation || nonBlankPageAfterReset) {
876         // New navigation.
877         updateSessionHistory(frame);
878         m_pageId = nextPageID++;
879     } else if (extraData && extraData->pendingPageID != -1 && !extraData->requestCommitted) {
880         // This is a successful session history navigation!
881         updateSessionHistory(frame);
882         m_pageId = extraData->pendingPageID;
883     }
884
885     // Don't update session history multiple times.
886     if (extraData)
887         extraData->requestCommitted = true;
888
889     updateURL(frame);
890 }
891
892 void WebViewHost::updateURL(WebFrame* frame)
893 {
894     WebDataSource* ds = frame->dataSource();
895     ASSERT(ds);
896     const WebURLRequest& request = ds->request();
897     RefPtr<TestNavigationEntry> entry(TestNavigationEntry::create());
898
899     // The referrer will be empty on https->http transitions. It
900     // would be nice if we could get the real referrer from somewhere.
901     entry->setPageID(m_pageId);
902     if (ds->hasUnreachableURL())
903         entry->setURL(ds->unreachableURL());
904     else
905         entry->setURL(request.url());
906
907     const WebHistoryItem& historyItem = frame->currentHistoryItem();
908     if (!historyItem.isNull())
909         entry->setContentState(historyItem);
910
911     navigationController()->didNavigateToEntry(entry.get());
912     m_lastPageIdUpdated = max(m_lastPageIdUpdated, m_pageId);
913 }
914
915 void WebViewHost::updateSessionHistory(WebFrame* frame)
916 {
917     // If we have a valid page ID at this point, then it corresponds to the page
918     // we are navigating away from. Otherwise, this is the first navigation, so
919     // there is no past session history to record.
920     if (m_pageId == -1)
921         return;
922
923     TestNavigationEntry* entry = navigationController()->entryWithPageID(m_pageId);
924     if (!entry)
925         return;
926
927     const WebHistoryItem& historyItem = webView()->mainFrame()->previousHistoryItem();
928     if (historyItem.isNull())
929         return;
930
931     entry->setContentState(historyItem);
932 }
933
934 void WebViewHost::printFrameDescription(WebFrame* webframe)
935 {
936     string name8 = webframe->uniqueName().utf8();
937     if (webframe == webView()->mainFrame()) {
938         if (!name8.length()) {
939             fputs("main frame", stdout);
940             return;
941         }
942         printf("main frame \"%s\"", name8.c_str());
943         return;
944     }
945     if (!name8.length()) {
946         fputs("frame (anonymous)", stdout);
947         return;
948     }
949     printf("frame \"%s\"", name8.c_str());
950 }
951
952 void WebViewHost::setPendingExtraData(PassOwnPtr<TestShellExtraData> extraData)
953 {
954     m_pendingExtraData = extraData;
955 }
956
957 void WebViewHost::setPageTitle(const WebString&)
958 {
959     // Nothing to do in layout test.
960 }
961
962 void WebViewHost::enterFullScreenNow()
963 {
964     webView()->willEnterFullScreen();
965     webView()->didEnterFullScreen();
966 }
967
968 void WebViewHost::exitFullScreenNow()
969 {
970     webView()->willExitFullScreen();
971     webView()->didExitFullScreen();
972 }
973
974 #if ENABLE(MEDIA_STREAM)
975 webkit_support::TestMediaStreamClient* WebViewHost::testMediaStreamClient()
976 {
977     if (!m_testMediaStreamClient.get())
978         m_testMediaStreamClient = adoptPtr(new webkit_support::TestMediaStreamClient());
979     return m_testMediaStreamClient.get();
980 }
981 #endif