blob: 9c542a406b4aa16867124cc1e7ffbb47f992b056 [file] [log] [blame]
/*
* Copyright (C) 2010, 2011, 2012 Google Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Google Inc. nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "config.h"
#include "WebViewHost.h"
#include "DRTDevToolsAgent.h"
#include "Task.h"
#include "TestNavigationController.h"
#include "TestShell.h"
#include "WebCachedURLRequest.h"
#include "WebConsoleMessage.h"
#include "WebContextMenuData.h"
#include "WebDOMMessageEvent.h"
#include "WebDataSource.h"
#include "WebDocument.h"
#include "WebElement.h"
#include "WebFrame.h"
#include "WebHistoryItem.h"
#include "WebKit.h"
#include "WebNode.h"
#include "WebPluginParams.h"
#include "WebPopupMenu.h"
#include "WebPopupType.h"
#include "WebPrintParams.h"
#include "WebRange.h"
#include "WebScreenInfo.h"
#include "WebSerializedScriptValue.h"
#include "WebUserGestureIndicator.h"
#include "WebView.h"
#include "WebWindowFeatures.h"
#include "webkit/support/test_media_stream_client.h"
#include "webkit/support/webkit_support.h"
#include <cctype>
#include <clocale>
#include <public/WebCString.h>
#include <public/WebCompositorOutputSurface.h>
#include <public/WebCompositorSupport.h>
#include <public/WebDragData.h>
#include <public/WebRect.h>
#include <public/WebSize.h>
#include <public/WebStorageNamespace.h>
#include <public/WebThread.h>
#include <public/WebURLRequest.h>
#include <public/WebURLResponse.h>
#include <wtf/Assertions.h>
#include <wtf/OwnArrayPtr.h>
#include <wtf/PassOwnPtr.h>
#include <wtf/Vector.h>
using namespace WebCore;
using namespace WebKit;
using namespace WebTestRunner;
using namespace std;
static const int screenWidth = 1920;
static const int screenHeight = 1080;
static const int screenUnavailableBorder = 8;
static int nextPageID = 1;
// WebViewClient -------------------------------------------------------------
WebView* WebViewHost::createView(WebFrame* creator, const WebURLRequest&, const WebWindowFeatures&, const WebString&, WebNavigationPolicy)
{
WebUserGestureIndicator::consumeUserGesture();
return m_shell->createNewWindow(WebURL())->webView();
}
WebWidget* WebViewHost::createPopupMenu(WebPopupType type)
{
switch (type) {
case WebKit::WebPopupTypeNone:
case WebKit::WebPopupTypePage:
case WebKit::WebPopupTypeHelperPlugin:
break;
case WebKit::WebPopupTypeSelect:
case WebKit::WebPopupTypeSuggestion:
m_popupmenus.append(WebPopupMenu::create(0));
return m_popupmenus.last();
}
return 0;
}
WebWidget* WebViewHost::createPopupMenu(const WebPopupMenuInfo&)
{
// Do not use this method. It's been replaced by createExternalPopupMenu.
ASSERT_NOT_REACHED();
return 0;
}
WebStorageNamespace* WebViewHost::createSessionStorageNamespace(unsigned quota)
{
return webkit_support::CreateSessionStorageNamespace(quota);
}
void WebViewHost::didAddMessageToConsole(const WebConsoleMessage& message, const WebString& sourceName, unsigned sourceLine)
{
}
void WebViewHost::didStartLoading()
{
}
void WebViewHost::didStopLoading()
{
}
bool WebViewHost::shouldBeginEditing(const WebRange& range)
{
return true;
}
bool WebViewHost::shouldEndEditing(const WebRange& range)
{
return true;
}
bool WebViewHost::shouldInsertNode(const WebNode& node, const WebRange& range, WebEditingAction action)
{
return true;
}
bool WebViewHost::shouldInsertText(const WebString& text, const WebRange& range, WebEditingAction action)
{
return true;
}
bool WebViewHost::shouldChangeSelectedRange(
const WebRange& fromRange, const WebRange& toRange, WebTextAffinity affinity, bool stillSelecting)
{
return true;
}
bool WebViewHost::shouldDeleteRange(const WebRange& range)
{
return true;
}
bool WebViewHost::shouldApplyStyle(const WebString& style, const WebRange& range)
{
return true;
}
bool WebViewHost::handleCurrentKeyboardEvent()
{
if (m_editCommandName.empty())
return false;
WebFrame* frame = webView()->focusedFrame();
if (!frame)
return false;
return frame->executeCommand(WebString::fromUTF8(m_editCommandName), WebString::fromUTF8(m_editCommandValue));
}
// WebKit::WebPrerendererClient
void WebViewHost::willAddPrerender(WebKit::WebPrerender*)
{
}
void WebViewHost::runModalAlertDialog(WebFrame*, const WebString& message)
{
}
bool WebViewHost::runModalConfirmDialog(WebFrame*, const WebString& message)
{
return true;
}
bool WebViewHost::runModalPromptDialog(WebFrame* frame, const WebString& message,
const WebString& defaultValue, WebString*)
{
return true;
}
void WebViewHost::showContextMenu(WebFrame*, const WebContextMenuData& contextMenuData)
{
}
void WebViewHost::didUpdateLayout()
{
#if OS(MAC_OS_X)
static bool queryingPreferredSize = false;
if (queryingPreferredSize)
return;
queryingPreferredSize = true;
// Query preferred width to emulate the same functionality in Chromium:
// see RenderView::CheckPreferredSize (src/content/renderer/render_view.cc)
// and TabContentsViewMac::RenderViewCreated (src/chrome/browser/tab_contents/tab_contents_view_mac.mm)
webView()->mainFrame()->contentsPreferredWidth();
webView()->mainFrame()->documentElementScrollHeight();
queryingPreferredSize = false;
#endif
}
void WebViewHost::navigateBackForwardSoon(int offset)
{
navigationController()->goToOffset(offset);
}
int WebViewHost::historyBackListCount()
{
return navigationController()->lastCommittedEntryIndex();
}
int WebViewHost::historyForwardListCount()
{
int currentIndex =navigationController()->lastCommittedEntryIndex();
return navigationController()->entryCount() - currentIndex - 1;
}
// WebWidgetClient -----------------------------------------------------------
void WebViewHost::didAutoResize(const WebSize& newSize)
{
// Purposely don't include the virtualWindowBorder in this case so that
// window.inner[Width|Height] is the same as window.outer[Width|Height]
setWindowRect(WebRect(0, 0, newSize.width, newSize.height));
}
class WebViewHostDRTLayerTreeViewClient : public webkit_support::DRTLayerTreeViewClient {
public:
explicit WebViewHostDRTLayerTreeViewClient(WebViewHost* host)
: m_host(host) { }
virtual ~WebViewHostDRTLayerTreeViewClient() { }
virtual void Layout() { m_host->webView()->layout(); }
virtual void ScheduleComposite() { m_host->proxy()->scheduleComposite(); }
private:
WebViewHost* m_host;
};
void WebViewHost::initializeLayerTreeView()
{
m_layerTreeViewClient = adoptPtr(new WebViewHostDRTLayerTreeViewClient(this));
if (m_shell->softwareCompositingEnabled()) {
m_layerTreeView = adoptPtr(webkit_support::CreateLayerTreeView(
webkit_support::SOFTWARE_CONTEXT,
m_layerTreeViewClient.get(),
m_shell->webCompositorThread()));
} else {
m_layerTreeView = adoptPtr(webkit_support::CreateLayerTreeView(
webkit_support::MESA_CONTEXT,
m_layerTreeViewClient.get(),
m_shell->webCompositorThread()));
}
ASSERT(m_layerTreeView);
updateViewportSize();
m_layerTreeView->setSurfaceReady();
}
WebLayerTreeView* WebViewHost::layerTreeView()
{
return m_layerTreeView.get();
}
void WebViewHost::scheduleAnimation()
{
if (webView()->settings()->scrollAnimatorEnabled())
webView()->animate(0.0);
}
void WebViewHost::didFocus()
{
}
void WebViewHost::didBlur()
{
}
WebScreenInfo WebViewHost::screenInfo()
{
// We don't need to set actual values.
WebScreenInfo info;
info.depth = 24;
info.depthPerComponent = 8;
info.isMonochrome = false;
info.rect = WebRect(0, 0, screenWidth, screenHeight);
// Use values different from info.rect for testing.
info.availableRect = WebRect(screenUnavailableBorder, screenUnavailableBorder,
screenWidth - screenUnavailableBorder * 2,
screenHeight - screenUnavailableBorder * 2);
return info;
}
void WebViewHost::show(WebNavigationPolicy)
{
m_hasWindow = true;
}
void WebViewHost::closeWidget()
{
m_hasWindow = false;
m_shell->closeWindow(this);
// No more code here, we should be deleted at this point.
}
void WebViewHost::closeWidgetSoon()
{
postDelayedTask(new HostMethodTask(this, &WebViewHost::closeWidget), 0);
}
void WebViewHost::didChangeCursor(const WebCursorInfo& cursorInfo)
{
if (!hasWindow())
return;
m_currentCursor = cursorInfo;
}
WebRect WebViewHost::windowRect()
{
return m_windowRect;
}
void WebViewHost::setWindowRect(const WebRect& rect)
{
m_windowRect = rect;
const int border2 = TestShell::virtualWindowBorder * 2;
if (m_windowRect.width <= border2)
m_windowRect.width = 1 + border2;
if (m_windowRect.height <= border2)
m_windowRect.height = 1 + border2;
int width = m_windowRect.width - border2;
int height = m_windowRect.height - border2;
webWidget()->resize(WebSize(width, height));
updateViewportSize();
}
WebRect WebViewHost::rootWindowRect()
{
return windowRect();
}
WebRect WebViewHost::windowResizerRect()
{
// Not necessary.
return WebRect();
}
void WebViewHost::runModal()
{
if (m_shell->isDisplayingModalDialog()) {
// DumpRenderTree doesn't support real modal dialogs, so a test shouldn't try to start two modal dialogs at the same time.
ASSERT_NOT_REACHED();
return;
}
// This WebViewHost might get deleted before RunMessageLoop() returns, so keep a copy of the m_shell member variable around.
ASSERT(m_shell->webViewHost() != this);
TestShell* shell = m_shell;
shell->setIsDisplayingModalDialog(true);
bool oldState = webkit_support::MessageLoopNestableTasksAllowed();
webkit_support::MessageLoopSetNestableTasksAllowed(true);
m_inModalLoop = true;
webkit_support::RunMessageLoop();
webkit_support::MessageLoopSetNestableTasksAllowed(oldState);
shell->setIsDisplayingModalDialog(false);
}
bool WebViewHost::enterFullScreen()
{
postDelayedTask(new HostMethodTask(this, &WebViewHost::enterFullScreenNow), 0);
return true;
}
void WebViewHost::exitFullScreen()
{
postDelayedTask(new HostMethodTask(this, &WebViewHost::exitFullScreenNow), 0);
}
// WebFrameClient ------------------------------------------------------------
WebPlugin* WebViewHost::createPlugin(WebFrame* frame, const WebPluginParams& params)
{
return webkit_support::CreateWebPlugin(frame, params);
}
WebMediaPlayer* WebViewHost::createMediaPlayer(WebFrame* frame, const WebURL& url, WebMediaPlayerClient* client)
{
#if ENABLE(MEDIA_STREAM)
return webkit_support::CreateMediaPlayer(frame, url, client, testMediaStreamClient());
#else
return webkit_support::CreateMediaPlayer(frame, url, client);
#endif
}
WebApplicationCacheHost* WebViewHost::createApplicationCacheHost(WebFrame* frame, WebApplicationCacheHostClient* client)
{
return webkit_support::CreateApplicationCacheHost(frame, client);
}
void WebViewHost::loadURLExternally(WebFrame* frame, const WebURLRequest& request, WebNavigationPolicy policy)
{
loadURLExternally(frame, request, policy, WebString());
}
void WebViewHost::loadURLExternally(WebFrame*, const WebURLRequest& request, WebNavigationPolicy policy, const WebString& downloadName)
{
ASSERT(policy != WebKit::WebNavigationPolicyCurrentTab);
WebViewHost* another = m_shell->createNewWindow(request.url());
if (another)
another->show(policy);
}
WebNavigationPolicy WebViewHost::decidePolicyForNavigation(
WebFrame*, const WebURLRequest&,
WebNavigationType, const WebNode&,
WebNavigationPolicy defaultPolicy, bool)
{
return defaultPolicy;
}
bool WebViewHost::canHandleRequest(WebFrame*, const WebURLRequest& request)
{
return true;
}
WebURLError WebViewHost::cancelledError(WebFrame*, const WebURLRequest& request)
{
return webkit_support::CreateCancelledError(request);
}
void WebViewHost::unableToImplementPolicyWithError(WebFrame* frame, const WebURLError& error)
{
}
void WebViewHost::didCreateDataSource(WebFrame*, WebDataSource* ds)
{
ds->setExtraData(m_pendingExtraData.leakPtr());
}
void WebViewHost::didCommitProvisionalLoad(WebFrame* frame, bool isNewNavigation)
{
updateForCommittedLoad(frame, isNewNavigation);
}
void WebViewHost::didClearWindowObject(WebFrame* frame)
{
m_shell->bindJSObjectsToWindow(frame);
}
void WebViewHost::didReceiveTitle(WebFrame* frame, const WebString& title, WebTextDirection direction)
{
setPageTitle(title);
}
void WebViewHost::didChangeIcon(WebFrame* , WebIconURL::Type)
{
}
void WebViewHost::didNavigateWithinPage(WebFrame* frame, bool isNewNavigation)
{
frame->dataSource()->setExtraData(m_pendingExtraData.leakPtr());
updateForCommittedLoad(frame, isNewNavigation);
}
void WebViewHost::willSendRequest(WebFrame* frame, unsigned, WebURLRequest& request, const WebURLResponse&)
{
if (request.url().isEmpty())
return;
request.setExtraData(webkit_support::CreateWebURLRequestExtraData(frame->document().referrerPolicy()));
}
void WebViewHost::openFileSystem(WebFrame* frame, WebFileSystemType type, long long size, bool create, WebFileSystemCallbacks* callbacks)
{
webkit_support::OpenFileSystem(frame, type, size, create, callbacks);
}
void WebViewHost::deleteFileSystem(WebKit::WebFrame* frame, WebKit::WebFileSystemType type, WebKit::WebFileSystemCallbacks* callbacks)
{
webkit_support::DeleteFileSystem(frame, type, callbacks);
}
bool WebViewHost::willCheckAndDispatchMessageEvent(WebFrame* sourceFrame, WebFrame* targetFrame, WebSecurityOrigin target, WebDOMMessageEvent event)
{
return false;
}
// WebTestDelegate ------------------------------------------------------------
void WebViewHost::setEditCommand(const string& name, const string& value)
{
m_editCommandName = name;
m_editCommandValue = value;
}
void WebViewHost::clearEditCommand()
{
m_editCommandName.clear();
m_editCommandValue.clear();
}
void WebViewHost::setGamepadData(const WebGamepads& pads)
{
webkit_support::SetGamepadData(pads);
}
void WebViewHost::printMessage(const std::string& message)
{
printf("%s", message.c_str());
}
void WebViewHost::postTask(WebTask* task)
{
::postTask(task);
}
void WebViewHost::postDelayedTask(WebTask* task, long long ms)
{
::postDelayedTask(task, ms);
}
WebString WebViewHost::registerIsolatedFileSystem(const WebVector<WebString>& absoluteFilenames)
{
return webkit_support::RegisterIsolatedFileSystem(absoluteFilenames);
}
long long WebViewHost::getCurrentTimeInMillisecond()
{
return webkit_support::GetCurrentTimeInMillisecond();
}
WebKit::WebString WebViewHost::getAbsoluteWebStringFromUTF8Path(const std::string& path)
{
return webkit_support::GetAbsoluteWebStringFromUTF8Path(path);
}
WebURL WebViewHost::localFileToDataURL(const WebKit::WebURL& url)
{
return webkit_support::LocalFileToDataURL(url);
}
WebURL WebViewHost::rewriteLayoutTestsURL(const std::string& url)
{
return webkit_support::RewriteLayoutTestsURL(url);
}
WebPreferences* WebViewHost::preferences()
{
return m_shell->preferences();
}
void WebViewHost::applyPreferences()
{
m_shell->applyPreferences();
}
std::string WebViewHost::makeURLErrorDescription(const WebKit::WebURLError& error)
{
return webkit_support::MakeURLErrorDescription(error);
}
void WebViewHost::showDevTools()
{
m_shell->showDevTools();
}
void WebViewHost::closeDevTools()
{
m_shell->closeDevTools();
}
void WebViewHost::evaluateInWebInspector(long callID, const std::string& script)
{
m_shell->drtDevToolsAgent()->evaluateInWebInspector(callID, script);
}
void WebViewHost::clearAllDatabases()
{
webkit_support::ClearAllDatabases();
}
void WebViewHost::setDatabaseQuota(int quota)
{
webkit_support::SetDatabaseQuota(quota);
}
void WebViewHost::setDeviceScaleFactor(float deviceScaleFactor)
{
webView()->setDeviceScaleFactor(deviceScaleFactor);
updateViewportSize();
}
void WebViewHost::setFocus(WebTestProxyBase* proxy, bool focused)
{
for (size_t i = 0; i < m_shell->windowList().size(); ++i) {
if (m_shell->windowList()[i]->proxy() == proxy)
m_shell->setFocus(m_shell->windowList()[i]->webWidget(), focused);
}
}
void WebViewHost::setAcceptAllCookies(bool acceptCookies)
{
webkit_support::SetAcceptAllCookies(acceptCookies);
}
string WebViewHost::pathToLocalResource(const string& url)
{
#if OS(WINDOWS)
if (!url.find("/tmp/")) {
// We want a temp file.
const unsigned tempPrefixLength = 5;
size_t bufferSize = MAX_PATH;
OwnArrayPtr<WCHAR> tempPath = adoptArrayPtr(new WCHAR[bufferSize]);
DWORD tempLength = ::GetTempPathW(bufferSize, tempPath.get());
if (tempLength + url.length() - tempPrefixLength + 1 > bufferSize) {
bufferSize = tempLength + url.length() - tempPrefixLength + 1;
tempPath = adoptArrayPtr(new WCHAR[bufferSize]);
tempLength = GetTempPathW(bufferSize, tempPath.get());
ASSERT(tempLength < bufferSize);
}
string resultPath(WebString(tempPath.get(), tempLength).utf8());
resultPath.append(url.substr(tempPrefixLength));
return resultPath;
}
#endif
// Some layout tests use file://// which we resolve as a UNC path. Normalize
// them to just file:///.
string lowerUrl = url;
string result = url;
transform(lowerUrl.begin(), lowerUrl.end(), lowerUrl.begin(), ::tolower);
while (!lowerUrl.find("file:////")) {
result = result.substr(0, 8) + result.substr(9);
lowerUrl = lowerUrl.substr(0, 8) + lowerUrl.substr(9);
}
return webkit_support::RewriteLayoutTestsURL(result).spec();
}
void WebViewHost::setLocale(const std::string& locale)
{
setlocale(LC_ALL, locale.c_str());
}
void WebViewHost::testFinished()
{
m_shell->testFinished(this);
}
void WebViewHost::testTimedOut()
{
m_shell->testTimedOut();
}
bool WebViewHost::isBeingDebugged()
{
return webkit_support::BeingDebugged();
}
int WebViewHost::layoutTestTimeout()
{
return m_shell->layoutTestTimeout();
}
void WebViewHost::closeRemainingWindows()
{
m_shell->closeRemainingWindows();
}
int WebViewHost::navigationEntryCount()
{
return m_shell->navigationEntryCount();
}
void WebViewHost::goToOffset(int offset)
{
m_shell->goToOffset(offset);
}
void WebViewHost::reload()
{
m_shell->reload();
}
void WebViewHost::loadURLForFrame(const WebURL& url, const string& frameName)
{
if (!url.isValid())
return;
TestShell::resizeWindowForTest(this, url);
navigationController()->loadEntry(TestNavigationEntry::create(-1, url, WebString(), WebString::fromUTF8(frameName)).get());
}
bool WebViewHost::allowExternalPages()
{
return m_shell->allowExternalPages();
}
void WebViewHost::captureHistoryForWindow(WebTestProxyBase* proxy, WebVector<WebHistoryItem>* history, size_t* currentEntryIndex)
{
for (size_t i = 0; i < m_shell->windowList().size(); ++i) {
if (m_shell->windowList()[i]->proxy() == proxy)
m_shell->captureHistoryForWindow(i, history, currentEntryIndex);
}
}
// Public functions -----------------------------------------------------------
WebViewHost::WebViewHost(TestShell* shell)
: m_shell(shell)
, m_proxy(0)
, m_webWidget(0)
, m_shutdownWasInvoked(false)
{
reset();
}
WebViewHost::~WebViewHost()
{
ASSERT(m_shutdownWasInvoked);
if (m_inModalLoop)
webkit_support::QuitMessageLoop();
}
void WebViewHost::shutdown()
{
ASSERT(!m_shutdownWasInvoked);
// DevTools frontend page is supposed to be navigated only once and
// loading another URL in that Page is an error.
if (m_shell->devToolsWebView() != this) {
// Navigate to an empty page to fire all the destruction logic for the
// current page.
loadURLForFrame(GURL("about:blank"), string());
}
for (Vector<WebKit::WebWidget*>::iterator it = m_popupmenus.begin();
it < m_popupmenus.end(); ++it)
(*it)->close();
webWidget()->willCloseLayerTreeView();
m_layerTreeView.clear();
webWidget()->close();
m_webWidget = 0;
m_shutdownWasInvoked = true;
}
void WebViewHost::setWebWidget(WebKit::WebWidget* widget)
{
m_webWidget = widget;
webView()->setSpellCheckClient(proxy()->spellCheckClient());
webView()->setPrerendererClient(this);
}
WebView* WebViewHost::webView() const
{
ASSERT(m_webWidget);
// DRT does not support popup widgets. So m_webWidget is always a WebView.
return static_cast<WebView*>(m_webWidget);
}
WebWidget* WebViewHost::webWidget() const
{
ASSERT(m_webWidget);
return m_webWidget;
}
WebTestProxyBase* WebViewHost::proxy() const
{
ASSERT(m_proxy);
return m_proxy;
}
void WebViewHost::setProxy(WebTestProxyBase* proxy)
{
ASSERT(!m_proxy);
ASSERT(proxy);
m_proxy = proxy;
}
void WebViewHost::reset()
{
m_pageId = -1;
m_lastPageIdUpdated = -1;
m_hasWindow = false;
m_inModalLoop = false;
m_navigationController = adoptPtr(new TestNavigationController(this));
m_pendingExtraData.clear();
m_editCommandName.clear();
m_editCommandValue.clear();
m_currentCursor = WebCursorInfo();
m_windowRect = WebRect();
// m_proxy is not set when reset() is invoked from the constructor.
if (m_proxy)
proxy()->reset();
if (m_webWidget) {
webView()->mainFrame()->setName(WebString());
}
}
void WebViewHost::setClientWindowRect(const WebKit::WebRect& rect)
{
setWindowRect(rect);
}
bool WebViewHost::navigate(const TestNavigationEntry& entry, bool reload)
{
// Get the right target frame for the entry.
WebFrame* frame = webView()->mainFrame();
if (!entry.targetFrame().isEmpty())
frame = webView()->findFrameByName(entry.targetFrame());
// TODO(mpcomplete): should we clear the target frame, or should
// back/forward navigations maintain the target frame?
// A navigation resulting from loading a javascript URL should not be
// treated as a browser initiated event. Instead, we want it to look as if
// the page initiated any load resulting from JS execution.
if (!GURL(entry.URL()).SchemeIs("javascript"))
setPendingExtraData(adoptPtr(new TestShellExtraData(entry.pageID())));
// If we are reloading, then WebKit will use the state of the current page.
// Otherwise, we give it the state to navigate to.
if (reload) {
frame->reload(false);
} else if (!entry.contentState().isNull()) {
ASSERT(entry.pageID() != -1);
frame->loadHistoryItem(entry.contentState());
} else {
ASSERT(entry.pageID() == -1);
frame->loadRequest(WebURLRequest(entry.URL()));
}
// In case LoadRequest failed before DidCreateDataSource was called.
setPendingExtraData(nullptr);
// Restore focus to the main frame prior to loading new request.
// This makes sure that we don't have a focused iframe. Otherwise, that
// iframe would keep focus when the SetFocus called immediately after
// LoadRequest, thus making some tests fail (see http://b/issue?id=845337
// for more details).
webView()->setFocusedFrame(frame);
m_shell->setFocus(webView(), true);
return true;
}
// Private functions ----------------------------------------------------------
void WebViewHost::updateForCommittedLoad(WebFrame* frame, bool isNewNavigation)
{
// Code duplicated from RenderView::DidCommitLoadForFrame.
TestShellExtraData* extraData = static_cast<TestShellExtraData*>(frame->dataSource()->extraData());
const WebURL& url = frame->dataSource()->request().url();
bool nonBlankPageAfterReset = m_pageId == -1 && !url.isEmpty() && strcmp(url.spec().data(), "about:blank");
if (isNewNavigation || nonBlankPageAfterReset) {
// New navigation.
updateSessionHistory(frame);
m_pageId = nextPageID++;
} else if (extraData && extraData->pendingPageID != -1 && !extraData->requestCommitted) {
// This is a successful session history navigation!
updateSessionHistory(frame);
m_pageId = extraData->pendingPageID;
}
// Don't update session history multiple times.
if (extraData)
extraData->requestCommitted = true;
updateURL(frame);
}
void WebViewHost::updateURL(WebFrame* frame)
{
WebDataSource* ds = frame->dataSource();
ASSERT(ds);
const WebURLRequest& request = ds->request();
RefPtr<TestNavigationEntry> entry(TestNavigationEntry::create());
// The referrer will be empty on https->http transitions. It
// would be nice if we could get the real referrer from somewhere.
entry->setPageID(m_pageId);
if (ds->hasUnreachableURL())
entry->setURL(ds->unreachableURL());
else
entry->setURL(request.url());
const WebHistoryItem& historyItem = frame->currentHistoryItem();
if (!historyItem.isNull())
entry->setContentState(historyItem);
navigationController()->didNavigateToEntry(entry.get());
m_lastPageIdUpdated = max(m_lastPageIdUpdated, m_pageId);
}
void WebViewHost::updateSessionHistory(WebFrame* frame)
{
// If we have a valid page ID at this point, then it corresponds to the page
// we are navigating away from. Otherwise, this is the first navigation, so
// there is no past session history to record.
if (m_pageId == -1)
return;
TestNavigationEntry* entry = navigationController()->entryWithPageID(m_pageId);
if (!entry)
return;
const WebHistoryItem& historyItem = webView()->mainFrame()->previousHistoryItem();
if (historyItem.isNull())
return;
entry->setContentState(historyItem);
}
void WebViewHost::updateViewportSize()
{
if (!m_layerTreeView)
return;
WebSize deviceViewportSize(webWidget()->size().width * webView()->deviceScaleFactor(),
webWidget()->size().height * webView()->deviceScaleFactor());
m_layerTreeView->setViewportSize(webWidget()->size(), deviceViewportSize);
}
void WebViewHost::printFrameDescription(WebFrame* webframe)
{
string name8 = webframe->uniqueName().utf8();
if (webframe == webView()->mainFrame()) {
if (!name8.length()) {
fputs("main frame", stdout);
return;
}
printf("main frame \"%s\"", name8.c_str());
return;
}
if (!name8.length()) {
fputs("frame (anonymous)", stdout);
return;
}
printf("frame \"%s\"", name8.c_str());
}
void WebViewHost::setPendingExtraData(PassOwnPtr<TestShellExtraData> extraData)
{
m_pendingExtraData = extraData;
}
void WebViewHost::setPageTitle(const WebString&)
{
// Nothing to do in layout test.
}
void WebViewHost::enterFullScreenNow()
{
webView()->willEnterFullScreen();
webView()->didEnterFullScreen();
}
void WebViewHost::exitFullScreenNow()
{
webView()->willExitFullScreen();
webView()->didExitFullScreen();
}
#if ENABLE(MEDIA_STREAM)
webkit_support::TestMediaStreamClient* WebViewHost::testMediaStreamClient()
{
if (!m_testMediaStreamClient.get())
m_testMediaStreamClient = adoptPtr(new webkit_support::TestMediaStreamClient());
return m_testMediaStreamClient.get();
}
#endif