| Index: content/renderer/resource_fetcher_browsertest.cc | 
| =================================================================== | 
| --- content/renderer/resource_fetcher_browsertest.cc	(revision 195423) | 
| +++ content/renderer/resource_fetcher_browsertest.cc	(working copy) | 
| @@ -6,14 +6,18 @@ | 
|  | 
| #include "base/bind.h" | 
| #include "base/bind_helpers.h" | 
| +#include "base/command_line.h" | 
| #include "base/message_loop.h" | 
| #include "base/timer.h" | 
| +#include "content/public/common/content_switches.h" | 
| +#include "content/public/renderer/render_view.h" | 
| +#include "content/public/test/test_utils.h" | 
| +#include "content/shell/shell.h" | 
| +#include "content/test/content_browser_test.h" | 
| +#include "content/test/content_browser_test_utils.h" | 
| #include "third_party/WebKit/Source/Platform/chromium/public/WebURLResponse.h" | 
| #include "third_party/WebKit/Source/WebKit/chromium/public/WebFrame.h" | 
| #include "third_party/WebKit/Source/WebKit/chromium/public/WebView.h" | 
| -#include "webkit/glue/unittest_test_server.h" | 
| -#include "webkit/tools/test_shell/simple_resource_loader_bridge.h" | 
| -#include "webkit/tools/test_shell/test_shell_test.h" | 
|  | 
| using WebKit::WebFrame; | 
| using WebKit::WebURLRequest; | 
| @@ -21,13 +25,8 @@ | 
| using webkit_glue::ResourceFetcher; | 
| using webkit_glue::ResourceFetcherWithTimeout; | 
|  | 
| -namespace { | 
| +namespace content { | 
|  | 
| -class ResourceFetcherTests : public TestShellTest { | 
| - protected: | 
| -  UnittestTestServer test_server_; | 
| -}; | 
| - | 
| static const int kMaxWaitTimeMs = 5000; | 
|  | 
| class FetcherDelegate { | 
| @@ -54,7 +53,8 @@ | 
| data_ = data; | 
| completed_ = true; | 
| timer_.Stop(); | 
| -    MessageLoop::current()->Quit(); | 
| +    if (!timed_out_) | 
| +      quit_task_.Run(); | 
| } | 
|  | 
| bool completed() const { return completed_; } | 
| @@ -63,12 +63,11 @@ | 
| std::string data() const { return data_; } | 
| const WebURLResponse& response() const { return response_; } | 
|  | 
| -  // Wait for the request to complete or timeout.  We use a loop here b/c the | 
| -  // testing infrastructure (test_shell) can generate spurious calls to the | 
| -  // MessageLoop's Quit method. | 
| +  // Wait for the request to complete or timeout. | 
| void WaitForResponse() { | 
| -    while (!completed() && !timed_out()) | 
| -      MessageLoop::current()->Run(); | 
| +    scoped_refptr<MessageLoopRunner> runner = new MessageLoopRunner; | 
| +    quit_task_ = runner->QuitClosure(); | 
| +    runner->Run(); | 
| } | 
|  | 
| void StartTimer() { | 
| @@ -82,7 +81,8 @@ | 
| ASSERT_FALSE(completed_); | 
|  | 
| timed_out_ = true; | 
| -    MessageLoop::current()->Quit(); | 
| +    if (!completed_) | 
| +      quit_task_.Run(); | 
| FAIL() << "fetch timed out"; | 
| } | 
|  | 
| @@ -94,124 +94,193 @@ | 
| bool timed_out_; | 
| WebURLResponse response_; | 
| std::string data_; | 
| +  base::Closure quit_task_; | 
| }; | 
|  | 
| FetcherDelegate* FetcherDelegate::instance_ = NULL; | 
|  | 
| -// Test a fetch from the test server. | 
| -// Flaky, http://crbug.com/51622. | 
| -TEST_F(ResourceFetcherTests, DISABLED_ResourceFetcherDownload) { | 
| -  ASSERT_TRUE(test_server_.Start()); | 
| +class EvilFetcherDelegate : public FetcherDelegate { | 
| + public: | 
| +  virtual ~EvilFetcherDelegate() {} | 
|  | 
| -  WebFrame* frame = test_shell_->webView()->mainFrame(); | 
| +  void SetFetcher(ResourceFetcher* fetcher) { | 
| +    fetcher_.reset(fetcher); | 
| +  } | 
|  | 
| -  GURL url(test_server_.GetURL("files/test_shell/index.html")); | 
| -  scoped_ptr<FetcherDelegate> delegate(new FetcherDelegate); | 
| -  scoped_ptr<ResourceFetcher> fetcher(new ResourceFetcher( | 
| -      url, frame, WebURLRequest::TargetIsMainFrame, delegate->NewCallback())); | 
| +  virtual void OnURLFetchComplete(const WebURLResponse& response, | 
| +                                  const std::string& data) OVERRIDE { | 
| +    // Destroy the ResourceFetcher here.  We are testing that upon returning | 
| +    // to the ResourceFetcher that it does not crash. | 
| +    fetcher_.reset(); | 
| +    FetcherDelegate::OnURLFetchComplete(response, data); | 
| +  } | 
|  | 
| -  delegate->WaitForResponse(); | 
| + private: | 
| +  scoped_ptr<ResourceFetcher> fetcher_; | 
| +}; | 
|  | 
| -  ASSERT_TRUE(delegate->completed()); | 
| -  EXPECT_EQ(delegate->response().httpStatusCode(), 200); | 
| -  std::string text = delegate->data(); | 
| -  EXPECT_TRUE(text.find("What is this page?") != std::string::npos); | 
| +class ResourceFetcherTests : public ContentBrowserTest { | 
| + public: | 
| +  virtual void SetUpCommandLine(CommandLine* command_line) { | 
| +    command_line->AppendSwitch(switches::kSingleProcess); | 
| +  } | 
|  | 
| -  // Test 404 response. | 
| -  url = test_server_.GetURL("files/thisfiledoesntexist.html"); | 
| -  delegate.reset(new FetcherDelegate); | 
| -  fetcher.reset(new ResourceFetcher(url, frame, | 
| -                                    WebURLRequest::TargetIsMainFrame, | 
| -                                    delegate->NewCallback())); | 
| +  RenderView* GetRenderView() { | 
| +    // We could have the test on the UI thread get the WebContent's routing ID, | 
| +    // but we know this will be the first RV so skip that and just hardcode it. | 
| +    return RenderView::FromRoutingID(1); | 
| +  } | 
|  | 
| -  delegate->WaitForResponse(); | 
| +  void ResourceFetcherDownloadOnRenderer(const GURL& url) { | 
| +    WebFrame* frame = GetRenderView()->GetWebView()->mainFrame(); | 
|  | 
| -  ASSERT_TRUE(delegate->completed()); | 
| -  EXPECT_EQ(delegate->response().httpStatusCode(), 404); | 
| -  EXPECT_TRUE(delegate->data().find("Not Found.") != std::string::npos); | 
| -} | 
| +    scoped_ptr<FetcherDelegate> delegate(new FetcherDelegate); | 
| +    scoped_ptr<ResourceFetcher> fetcher(new ResourceFetcher( | 
| +        url, frame, WebURLRequest::TargetIsMainFrame, delegate->NewCallback())); | 
|  | 
| -// Flaky, http://crbug.com/51622. | 
| -TEST_F(ResourceFetcherTests, DISABLED_ResourceFetcherDidFail) { | 
| -  ASSERT_TRUE(test_server_.Start()); | 
| +    delegate->WaitForResponse(); | 
|  | 
| -  WebFrame* frame = test_shell_->webView()->mainFrame(); | 
| +    ASSERT_TRUE(delegate->completed()); | 
| +    EXPECT_EQ(delegate->response().httpStatusCode(), 200); | 
| +    std::string text = delegate->data(); | 
| +    EXPECT_TRUE(text.find("Basic html test.") != std::string::npos); | 
| +  } | 
|  | 
| -  // Try to fetch a page on a site that doesn't exist. | 
| -  GURL url("http://localhost:1339/doesnotexist"); | 
| -  scoped_ptr<FetcherDelegate> delegate(new FetcherDelegate); | 
| -  scoped_ptr<ResourceFetcher> fetcher(new ResourceFetcher( | 
| -      url, frame, WebURLRequest::TargetIsMainFrame, delegate->NewCallback())); | 
| +  void ResourceFetcher404OnRenderer(const GURL& url) { | 
| +    WebFrame* frame = GetRenderView()->GetWebView()->mainFrame(); | 
|  | 
| -  delegate->WaitForResponse(); | 
| +    scoped_ptr<FetcherDelegate> delegate(new FetcherDelegate); | 
| +    scoped_ptr<ResourceFetcher> fetcher(new ResourceFetcher( | 
| +        url, frame, WebURLRequest::TargetIsMainFrame, delegate->NewCallback())); | 
|  | 
| -  // When we fail, we still call the Delegate callback but we pass in empty | 
| -  // values. | 
| -  EXPECT_TRUE(delegate->completed()); | 
| -  EXPECT_TRUE(delegate->response().isNull()); | 
| -  EXPECT_EQ(delegate->data(), std::string()); | 
| -  EXPECT_FALSE(delegate->timed_out()); | 
| -} | 
| +    delegate->WaitForResponse(); | 
|  | 
| -TEST_F(ResourceFetcherTests, ResourceFetcherTimeout) { | 
| -  ASSERT_TRUE(test_server_.Start()); | 
| +    ASSERT_TRUE(delegate->completed()); | 
| +    EXPECT_EQ(delegate->response().httpStatusCode(), 404); | 
| +    EXPECT_TRUE(delegate->data().find("Not Found.") != std::string::npos); | 
| +  } | 
|  | 
| -  WebFrame* frame = test_shell_->webView()->mainFrame(); | 
| +  void ResourceFetcherDidFailOnRenderer() { | 
| +    WebFrame* frame = GetRenderView()->GetWebView()->mainFrame(); | 
|  | 
| -  // Grab a page that takes at least 1 sec to respond, but set the fetcher to | 
| -  // timeout in 0 sec. | 
| -  GURL url(test_server_.GetURL("slow?1")); | 
| -  scoped_ptr<FetcherDelegate> delegate(new FetcherDelegate); | 
| -  scoped_ptr<ResourceFetcher> fetcher(new ResourceFetcherWithTimeout( | 
| -      url, frame, WebURLRequest::TargetIsMainFrame, | 
| -      0, delegate->NewCallback())); | 
| +    // Try to fetch a page on a site that doesn't exist. | 
| +    GURL url("http://localhost:1339/doesnotexist"); | 
| +    scoped_ptr<FetcherDelegate> delegate(new FetcherDelegate); | 
| +    scoped_ptr<ResourceFetcher> fetcher(new ResourceFetcher( | 
| +        url, frame, WebURLRequest::TargetIsMainFrame, delegate->NewCallback())); | 
|  | 
| -  delegate->WaitForResponse(); | 
| +    delegate->WaitForResponse(); | 
|  | 
| -  // When we timeout, we still call the Delegate callback but we pass in empty | 
| -  // values. | 
| -  EXPECT_TRUE(delegate->completed()); | 
| -  EXPECT_TRUE(delegate->response().isNull()); | 
| -  EXPECT_EQ(delegate->data(), std::string()); | 
| -  EXPECT_FALSE(delegate->timed_out()); | 
| -} | 
| +    // When we fail, we still call the Delegate callback but we pass in empty | 
| +    // values. | 
| +    EXPECT_TRUE(delegate->completed()); | 
| +    EXPECT_TRUE(delegate->response().isNull()); | 
| +    EXPECT_EQ(delegate->data(), std::string()); | 
| +    EXPECT_FALSE(delegate->timed_out()); | 
| +  } | 
|  | 
| -class EvilFetcherDelegate : public FetcherDelegate { | 
| - public: | 
| -  virtual ~EvilFetcherDelegate() {} | 
| +  void ResourceFetcherTimeoutOnRenderer(const GURL& url) { | 
| +    WebFrame* frame = GetRenderView()->GetWebView()->mainFrame(); | 
|  | 
| -  void SetFetcher(ResourceFetcher* fetcher) { | 
| -    fetcher_.reset(fetcher); | 
| +    scoped_ptr<FetcherDelegate> delegate(new FetcherDelegate); | 
| +    scoped_ptr<ResourceFetcher> fetcher(new ResourceFetcherWithTimeout( | 
| +        url, frame, WebURLRequest::TargetIsMainFrame, | 
| +        0, delegate->NewCallback())); | 
| + | 
| +    delegate->WaitForResponse(); | 
| + | 
| +    // When we timeout, we still call the Delegate callback but we pass in empty | 
| +    // values. | 
| +    EXPECT_TRUE(delegate->completed()); | 
| +    EXPECT_TRUE(delegate->response().isNull()); | 
| +    EXPECT_EQ(delegate->data(), std::string()); | 
| +    EXPECT_FALSE(delegate->timed_out()); | 
| } | 
|  | 
| -  virtual void OnURLFetchComplete(const WebURLResponse& response, | 
| -                                  const std::string& data) OVERRIDE { | 
| -    // Destroy the ResourceFetcher here.  We are testing that upon returning | 
| -    // to the ResourceFetcher that it does not crash. | 
| -    fetcher_.reset(); | 
| -    FetcherDelegate::OnURLFetchComplete(response, data); | 
| +  void ResourceFetcherDeletedInCallbackOnRenderer(const GURL& url) { | 
| +    WebFrame* frame = GetRenderView()->GetWebView()->mainFrame(); | 
| + | 
| +    scoped_ptr<EvilFetcherDelegate> delegate(new EvilFetcherDelegate); | 
| +    scoped_ptr<ResourceFetcher> fetcher(new ResourceFetcherWithTimeout( | 
| +        url, frame, WebURLRequest::TargetIsMainFrame, | 
| +        0, delegate->NewCallback())); | 
| +    delegate->SetFetcher(fetcher.release()); | 
| + | 
| +    delegate->WaitForResponse(); | 
| +    EXPECT_FALSE(delegate->timed_out()); | 
| } | 
| - | 
| - private: | 
| -  scoped_ptr<ResourceFetcher> fetcher_; | 
| }; | 
|  | 
| -TEST_F(ResourceFetcherTests, ResourceFetcherDeletedInCallback) { | 
| -  ASSERT_TRUE(test_server_.Start()); | 
| +// These tests randomly crash on the Mac trybots with no callstacks. They never | 
| +// failed locally across hundreds of runs in both debug and release. | 
| +#if !defined(OS_MACOSX) | 
|  | 
| -  WebFrame* frame = test_shell_->webView()->mainFrame(); | 
| +// Test a fetch from the test server. | 
| +// If this flakes, use http://crbug.com/51622. | 
| +IN_PROC_BROWSER_TEST_F(ResourceFetcherTests, ResourceFetcherDownload) { | 
| +  // Need to spin up the renderer. | 
| +  NavigateToURL(shell(), GURL("about:blank")); | 
|  | 
| +  ASSERT_TRUE(test_server()->Start()); | 
| +  GURL url(test_server()->GetURL("files/simple_page.html")); | 
| + | 
| +  PostTaskToInProcessRendererAndWait( | 
| +        base::Bind(&ResourceFetcherTests::ResourceFetcherDownloadOnRenderer, | 
| +                   base::Unretained(this), url)); | 
| +} | 
| + | 
| +IN_PROC_BROWSER_TEST_F(ResourceFetcherTests, ResourceFetcher404) { | 
| +  // Need to spin up the renderer. | 
| +  NavigateToURL(shell(), GURL("about:blank")); | 
| + | 
| +  // Test 404 response. | 
| +  ASSERT_TRUE(test_server()->Start()); | 
| +  GURL url = test_server()->GetURL("files/thisfiledoesntexist.html"); | 
| + | 
| +  PostTaskToInProcessRendererAndWait( | 
| +        base::Bind(&ResourceFetcherTests::ResourceFetcher404OnRenderer, | 
| +                   base::Unretained(this), url)); | 
| +} | 
| + | 
| +// If this flakes, use http://crbug.com/51622. | 
| +IN_PROC_BROWSER_TEST_F(ResourceFetcherTests, ResourceFetcherDidFail) { | 
| +  // Need to spin up the renderer. | 
| +  NavigateToURL(shell(), GURL("about:blank")); | 
| + | 
| +  PostTaskToInProcessRendererAndWait( | 
| +        base::Bind(&ResourceFetcherTests::ResourceFetcherDidFailOnRenderer, | 
| +                   base::Unretained(this))); | 
| +} | 
| + | 
| +IN_PROC_BROWSER_TEST_F(ResourceFetcherTests, ResourceFetcherTimeout) { | 
| +  // Need to spin up the renderer. | 
| +  NavigateToURL(shell(), GURL("about:blank")); | 
| + | 
| // Grab a page that takes at least 1 sec to respond, but set the fetcher to | 
| // timeout in 0 sec. | 
| -  GURL url(test_server_.GetURL("slow?1")); | 
| -  scoped_ptr<EvilFetcherDelegate> delegate(new EvilFetcherDelegate); | 
| -  scoped_ptr<ResourceFetcher> fetcher(new ResourceFetcherWithTimeout( | 
| -      url, frame, WebURLRequest::TargetIsMainFrame, | 
| -      0, delegate->NewCallback())); | 
| -  delegate->SetFetcher(fetcher.release()); | 
| +  ASSERT_TRUE(test_server()->Start()); | 
| +  GURL url(test_server()->GetURL("slow?1")); | 
|  | 
| -  delegate->WaitForResponse(); | 
| -  EXPECT_FALSE(delegate->timed_out()); | 
| +  PostTaskToInProcessRendererAndWait( | 
| +        base::Bind(&ResourceFetcherTests::ResourceFetcherTimeoutOnRenderer, | 
| +                   base::Unretained(this), url)); | 
| } | 
|  | 
| -}  // namespace | 
| +IN_PROC_BROWSER_TEST_F(ResourceFetcherTests, ResourceFetcherDeletedInCallback) { | 
| +  // Need to spin up the renderer. | 
| +  NavigateToURL(shell(), GURL("about:blank")); | 
| + | 
| +  // Grab a page that takes at least 1 sec to respond, but set the fetcher to | 
| +  // timeout in 0 sec. | 
| +  ASSERT_TRUE(test_server()->Start()); | 
| +  GURL url(test_server()->GetURL("slow?1")); | 
| + | 
| +  PostTaskToInProcessRendererAndWait( | 
| +        base::Bind( | 
| +            &ResourceFetcherTests::ResourceFetcherDeletedInCallbackOnRenderer, | 
| +            base::Unretained(this), url)); | 
| +} | 
| + | 
| +#endif  // OS_MACOSX | 
| + | 
| +}  // namespace content | 
|  |