1ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// Copyright (c) 2011 The Chromium Authors. All rights reserved. 2c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Use of this source code is governed by a BSD-style license that can be 3c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// found in the LICENSE file. 4c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 5c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "webkit/glue/resource_fetcher.h" 6c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 7c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/callback.h" 83345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#include "base/message_loop.h" 972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "base/timer.h" 1072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "third_party/WebKit/Source/WebKit/chromium/public/WebFrame.h" 1172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "third_party/WebKit/Source/WebKit/chromium/public/WebURLResponse.h" 1272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "third_party/WebKit/Source/WebKit/chromium/public/WebView.h" 13c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "webkit/glue/unittest_test_server.h" 14c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "webkit/tools/test_shell/simple_resource_loader_bridge.h" 15c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "webkit/tools/test_shell/test_shell_test.h" 16c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 17c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochusing WebKit::WebFrame; 18ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenusing WebKit::WebURLRequest; 19c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochusing WebKit::WebURLResponse; 20c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochusing webkit_glue::ResourceFetcher; 21c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochusing webkit_glue::ResourceFetcherWithTimeout; 22c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 23c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochnamespace { 24c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 25c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochclass ResourceFetcherTests : public TestShellTest { 263345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick protected: 273345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick UnittestTestServer test_server_; 28c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}; 29c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 30c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstatic const int kMaxWaitTimeMs = 5000; 31c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 32c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochclass FetcherDelegate { 33c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch public: 34c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch FetcherDelegate() 3572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen : completed_(false), 3672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen timed_out_(false) { 37c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Start a repeating timer waiting for the download to complete. The 38c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // callback has to be a static function, so we hold on to our instance. 39c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch FetcherDelegate::instance_ = this; 4072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen StartTimer(); 41c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 42c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 43c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ResourceFetcher::Callback* NewCallback() { 44c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return ::NewCallback(this, &FetcherDelegate::OnURLFetchComplete); 45c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 46c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 4772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen virtual void OnURLFetchComplete(const WebURLResponse& response, 4872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen const std::string& data) { 49c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch response_ = response; 50c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch data_ = data; 51c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch completed_ = true; 5272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen timer_.Stop(); 53c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch MessageLoop::current()->Quit(); 54c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 55c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 56c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch bool completed() const { return completed_; } 5772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen bool timed_out() const { return timed_out_; } 58c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 59c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch std::string data() const { return data_; } 60c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const WebURLResponse& response() const { return response_; } 61c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 62c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Wait for the request to complete or timeout. We use a loop here b/c the 63c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // testing infrastructure (test_shell) can generate spurious calls to the 64c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // MessageLoop's Quit method. 65c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch void WaitForResponse() { 66c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch while (!completed() && !timed_out()) 67c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch MessageLoop::current()->Run(); 68c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 69c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 7072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen void StartTimer() { 7172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen timer_.Start(base::TimeDelta::FromMilliseconds(kMaxWaitTimeMs), 7272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen this, 7372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen &FetcherDelegate::TimerFired); 74c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 75c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 76c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch void TimerFired() { 77c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ASSERT_FALSE(completed_); 78c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 7972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen timed_out_ = true; 8072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen MessageLoop::current()->Quit(); 8172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen FAIL() << "fetch timed out"; 82c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 83c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 84c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch static FetcherDelegate* instance_; 85c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 86c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch private: 8772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen base::OneShotTimer<FetcherDelegate> timer_; 88c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch bool completed_; 8972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen bool timed_out_; 90c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch WebURLResponse response_; 91c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch std::string data_; 92c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}; 93c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 94c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochFetcherDelegate* FetcherDelegate::instance_ = NULL; 95c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 96c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Test a fetch from the test server. 97731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick// Flaky, http://crbug.com/51622. 98731df977c0511bca2206b5f333555b1205ff1f43Iain MerrickTEST_F(ResourceFetcherTests, FLAKY_ResourceFetcherDownload) { 993345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick ASSERT_TRUE(test_server_.Start()); 100c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 101c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch WebFrame* frame = test_shell_->webView()->mainFrame(); 102c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1033345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick GURL url(test_server_.GetURL("files/test_shell/index.html")); 104c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch scoped_ptr<FetcherDelegate> delegate(new FetcherDelegate); 105c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch scoped_ptr<ResourceFetcher> fetcher(new ResourceFetcher( 106ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen url, frame, WebURLRequest::TargetIsMainFrame, delegate->NewCallback())); 107c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 108c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch delegate->WaitForResponse(); 109c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 110c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ASSERT_TRUE(delegate->completed()); 111c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch EXPECT_EQ(delegate->response().httpStatusCode(), 200); 112c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch std::string text = delegate->data(); 113c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch EXPECT_TRUE(text.find("What is this page?") != std::string::npos); 114c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 115c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Test 404 response. 1163345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick url = test_server_.GetURL("files/thisfiledoesntexist.html"); 117c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch delegate.reset(new FetcherDelegate); 118ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen fetcher.reset(new ResourceFetcher(url, frame, 119ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen WebURLRequest::TargetIsMainFrame, 120ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen delegate->NewCallback())); 121c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 122c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch delegate->WaitForResponse(); 123c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 124c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ASSERT_TRUE(delegate->completed()); 125c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch EXPECT_EQ(delegate->response().httpStatusCode(), 404); 126c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch EXPECT_TRUE(delegate->data().find("Not Found.") != std::string::npos); 127c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 128c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 129731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick// Flaky, http://crbug.com/51622. 130731df977c0511bca2206b5f333555b1205ff1f43Iain MerrickTEST_F(ResourceFetcherTests, FLAKY_ResourceFetcherDidFail) { 1313345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick ASSERT_TRUE(test_server_.Start()); 132c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 133c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch WebFrame* frame = test_shell_->webView()->mainFrame(); 134c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 135c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Try to fetch a page on a site that doesn't exist. 136c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch GURL url("http://localhost:1339/doesnotexist"); 137c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch scoped_ptr<FetcherDelegate> delegate(new FetcherDelegate); 138c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch scoped_ptr<ResourceFetcher> fetcher(new ResourceFetcher( 139ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen url, frame, WebURLRequest::TargetIsMainFrame, delegate->NewCallback())); 140c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 141c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch delegate->WaitForResponse(); 142c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 143c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // When we fail, we still call the Delegate callback but we pass in empty 144c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // values. 145c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch EXPECT_TRUE(delegate->completed()); 146c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch EXPECT_TRUE(delegate->response().isNull()); 147c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch EXPECT_EQ(delegate->data(), std::string()); 14872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen EXPECT_FALSE(delegate->timed_out()); 149c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 150c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 151c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochTEST_F(ResourceFetcherTests, ResourceFetcherTimeout) { 1523345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick ASSERT_TRUE(test_server_.Start()); 153c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 154c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch WebFrame* frame = test_shell_->webView()->mainFrame(); 155c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 156c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Grab a page that takes at least 1 sec to respond, but set the fetcher to 157c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // timeout in 0 sec. 1583345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick GURL url(test_server_.GetURL("slow?1")); 159c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch scoped_ptr<FetcherDelegate> delegate(new FetcherDelegate); 160c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch scoped_ptr<ResourceFetcher> fetcher(new ResourceFetcherWithTimeout( 161ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen url, frame, WebURLRequest::TargetIsMainFrame, 162ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 0, delegate->NewCallback())); 163c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 164c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch delegate->WaitForResponse(); 165c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 166c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // When we timeout, we still call the Delegate callback but we pass in empty 167c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // values. 168c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch EXPECT_TRUE(delegate->completed()); 169c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch EXPECT_TRUE(delegate->response().isNull()); 170c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch EXPECT_EQ(delegate->data(), std::string()); 17172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen EXPECT_FALSE(delegate->timed_out()); 17272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen} 17372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 17472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenclass EvilFetcherDelegate : public FetcherDelegate { 17572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen public: 17672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen void SetFetcher(ResourceFetcher* fetcher) { 17772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen fetcher_.reset(fetcher); 17872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen } 17972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 18072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen void OnURLFetchComplete(const WebURLResponse& response, 18172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen const std::string& data) { 18272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // Destroy the ResourceFetcher here. We are testing that upon returning 18372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // to the ResourceFetcher that it does not crash. 18472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen fetcher_.reset(); 18572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen FetcherDelegate::OnURLFetchComplete(response, data); 18672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen } 18772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 18872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen private: 18972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen scoped_ptr<ResourceFetcher> fetcher_; 19072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen}; 19172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 19272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian MonsenTEST_F(ResourceFetcherTests, ResourceFetcherDeletedInCallback) { 19372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen ASSERT_TRUE(test_server_.Start()); 19472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 19572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen WebFrame* frame = test_shell_->webView()->mainFrame(); 19672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 19772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // Grab a page that takes at least 1 sec to respond, but set the fetcher to 19872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // timeout in 0 sec. 19972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen GURL url(test_server_.GetURL("slow?1")); 20072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen scoped_ptr<EvilFetcherDelegate> delegate(new EvilFetcherDelegate); 20172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen scoped_ptr<ResourceFetcher> fetcher(new ResourceFetcherWithTimeout( 202ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen url, frame, WebURLRequest::TargetIsMainFrame, 203ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 0, delegate->NewCallback())); 20472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen delegate->SetFetcher(fetcher.release()); 20572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 20672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen delegate->WaitForResponse(); 20772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen EXPECT_FALSE(delegate->timed_out()); 208c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 209c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 210c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} // namespace 211