// Copyright (c) 2012 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #include "content/public/test/render_view_fake_resources_test.h" #include #include "base/command_line.h" #include "base/process.h" #include "base/run_loop.h" #include "base/shared_memory.h" #include "base/time/time.h" #include "content/common/resource_messages.h" #include "content/common/view_messages.h" #include "content/public/common/resource_response.h" #include "content/public/renderer/history_item_serialization.h" #include "content/renderer/render_thread_impl.h" #include "content/renderer/render_view_impl.h" #include "content/renderer/renderer_webkitplatformsupport_impl.h" #include "content/test/mock_render_process.h" #include "net/base/net_errors.h" #include "net/base/upload_data.h" #include "net/http/http_response_headers.h" #include "net/url_request/url_request_status.h" #include "third_party/WebKit/public/platform/WebString.h" #include "third_party/WebKit/public/platform/WebURLRequest.h" #include "third_party/WebKit/public/web/WebFrame.h" #include "third_party/WebKit/public/web/WebHistoryItem.h" #include "third_party/WebKit/public/web/WebView.h" #include "ui/base/ui_base_switches.h" #include "url/gurl.h" #include "webkit/common/dom_storage/dom_storage_types.h" #include "webkit/glue/webkit_glue.h" namespace content { const int32 RenderViewFakeResourcesTest::kViewId = 5; RenderViewFakeResourcesTest::RenderViewFakeResourcesTest() {} RenderViewFakeResourcesTest::~RenderViewFakeResourcesTest() {} bool RenderViewFakeResourcesTest::OnMessageReceived( const IPC::Message& message) { IPC_BEGIN_MESSAGE_MAP(RenderViewFakeResourcesTest, message) IPC_MESSAGE_HANDLER(ViewHostMsg_RenderViewReady, OnRenderViewReady) IPC_MESSAGE_HANDLER(ViewHostMsg_DidStopLoading, OnDidStopLoading) IPC_MESSAGE_HANDLER(ResourceHostMsg_RequestResource, OnRequestResource) IPC_END_MESSAGE_MAP() return true; } bool RenderViewFakeResourcesTest::Visit(RenderView* render_view) { view_ = render_view; return false; } void RenderViewFakeResourcesTest::SetUp() { // Set up the renderer. This code is largely adapted from // render_view_test.cc and renderer_main.cc. Note that we use a // MockRenderProcess (because we don't need to use IPC for painting), // but we use a real RenderThread so that we can use the ResourceDispatcher // to fetch network resources. These are then served canned content // in OnRequestResource(). SetRendererClientForTesting(&content_renderer_client_); // Generate a unique channel id so that multiple instances of the test can // run in parallel. std::string channel_id = IPC::Channel::GenerateVerifiedChannelID( std::string()); channel_.reset(new IPC::Channel(channel_id, IPC::Channel::MODE_SERVER, this)); ASSERT_TRUE(channel_->Connect()); CommandLine& command_line = *CommandLine::ForCurrentProcess(); command_line.AppendSwitchASCII(switches::kLang, "en-us"); webkit_glue::SetJavaScriptFlags("--expose-gc"); mock_process_.reset(new MockRenderProcess); sandbox_was_enabled_ = RendererWebKitPlatformSupportImpl::SetSandboxEnabledForTesting(false); render_thread_ = new RenderThreadImpl(channel_id); // Tell the renderer to create a view, then wait until it's ready. // We can't call View::Create() directly here or else we won't get // RenderProcess's lazy initialization of WebKit. view_ = NULL; ViewMsg_New_Params params; params.view_id = kViewId; params.opener_route_id = MSG_ROUTING_NONE; params.session_storage_namespace_id = dom_storage::kInvalidSessionStorageNamespaceId; ASSERT_TRUE(channel_->Send(new ViewMsg_New(params))); message_loop_.Run(); } void RenderViewFakeResourcesTest::TearDown() { // Try very hard to collect garbage before shutting down. GetMainFrame()->collectGarbage(); GetMainFrame()->collectGarbage(); ASSERT_TRUE(channel_->Send(new ViewMsg_Close(kViewId))); do { base::RunLoop().RunUntilIdle(); view_ = NULL; RenderView::ForEach(this); } while (view_); mock_process_.reset(); RendererWebKitPlatformSupportImpl::SetSandboxEnabledForTesting( sandbox_was_enabled_); } RenderView* RenderViewFakeResourcesTest::view() { return view_; } WebKit::WebFrame* RenderViewFakeResourcesTest::GetMainFrame() { return view_->GetWebView()->mainFrame(); } void RenderViewFakeResourcesTest::LoadURL(const std::string& url) { GURL g_url(url); GetMainFrame()->loadRequest(WebKit::WebURLRequest(g_url)); message_loop_.Run(); } void RenderViewFakeResourcesTest::LoadURLWithPost(const std::string& url) { GURL g_url(url); WebKit::WebURLRequest request(g_url); request.setHTTPMethod(WebKit::WebString::fromUTF8("POST")); GetMainFrame()->loadRequest(request); message_loop_.Run(); } void RenderViewFakeResourcesTest::GoBack() { GoToOffset(-1, GetMainFrame()->previousHistoryItem()); } void RenderViewFakeResourcesTest::GoForward( const WebKit::WebHistoryItem& history_item) { GoToOffset(1, history_item); } void RenderViewFakeResourcesTest::OnDidStopLoading() { message_loop_.Quit(); } void RenderViewFakeResourcesTest::OnRequestResource( const IPC::Message& message, int request_id, const ResourceHostMsg_Request& request_data) { std::string headers, body; std::map::const_iterator it = responses_.find(request_data.url.spec()); if (it == responses_.end()) { headers = "HTTP/1.1 404 Not Found\0Content-Type:text/html\0\0"; body = "content not found"; } else { headers = "HTTP/1.1 200 OK\0Content-Type:text/html\0\0"; body = it->second; } ResourceResponseHead response_head; response_head.headers = new net::HttpResponseHeaders(headers); response_head.mime_type = "text/html"; ASSERT_TRUE(channel_->Send(new ResourceMsg_ReceivedResponse( message.routing_id(), request_id, response_head))); base::SharedMemory shared_memory; ASSERT_TRUE(shared_memory.CreateAndMapAnonymous(body.size())); memcpy(shared_memory.memory(), body.data(), body.size()); base::SharedMemoryHandle handle; ASSERT_TRUE(shared_memory.GiveToProcess(base::Process::Current().handle(), &handle)); ASSERT_TRUE(channel_->Send(new ResourceMsg_SetDataBuffer( message.routing_id(), request_id, handle, body.size(), 0))); ASSERT_TRUE(channel_->Send(new ResourceMsg_DataReceived( message.routing_id(), request_id, 0, body.size(), body.size()))); ASSERT_TRUE(channel_->Send(new ResourceMsg_RequestComplete( message.routing_id(), request_id, net::OK, false, std::string(), base::TimeTicks()))); } void RenderViewFakeResourcesTest::OnRenderViewReady() { // Grab a pointer to the new view using RenderViewVisitor. ASSERT_TRUE(!view_); RenderView::ForEach(this); ASSERT_TRUE(view_); message_loop_.Quit(); } void RenderViewFakeResourcesTest::GoToOffset( int offset, const WebKit::WebHistoryItem& history_item) { RenderViewImpl* impl = static_cast(view_); ViewMsg_Navigate_Params params; params.page_id = impl->GetPageId() + offset; params.pending_history_list_offset = impl->history_list_offset() + offset; params.current_history_list_offset = impl->history_list_offset(); params.current_history_list_length = (impl->historyBackListCount() + impl->historyForwardListCount() + 1); params.url = GURL(history_item.urlString()); params.transition = PAGE_TRANSITION_FORWARD_BACK; params.page_state = HistoryItemToPageState(history_item); params.navigation_type = ViewMsg_Navigate_Type::NORMAL; params.request_time = base::Time::Now(); channel_->Send(new ViewMsg_Navigate(impl->routing_id(), params)); message_loop_.Run(); } } // namespace content