15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/json/json_string_value_serializer.h"
62a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/prefs/pref_service.h"
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/net/predictor.h"
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/profiles/profile.h"
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/ui/browser.h"
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/common/pref_names.h"
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/test/base/in_process_browser_test.h"
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/test/base/ui_test_utils.h"
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/base/net_errors.h"
142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "net/dns/host_resolver_proc.h"
152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "net/dns/mock_host_resolver.h"
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "testing/gmock/include/gmock/gmock.h"
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using content::BrowserThread;
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using testing::HasSubstr;
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace {
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Records a history of all hostnames for which resolving has been requested,
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// and immediately fails the resolution requests themselves.
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class HostResolutionRequestRecorder : public net::HostResolverProc {
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  HostResolutionRequestRecorder()
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      : HostResolverProc(NULL),
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        is_waiting_for_hostname_(false) {
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual int Resolve(const std::string& host,
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                      net::AddressFamily address_family,
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                      net::HostResolverFlags host_resolver_flags,
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                      net::AddressList* addrlist,
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                      int* os_error) OVERRIDE {
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    BrowserThread::PostTask(
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        BrowserThread::UI,
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        FROM_HERE,
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        base::Bind(&HostResolutionRequestRecorder::AddToHistory,
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   base::Unretained(this),
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   host));
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return net::ERR_NAME_NOT_RESOLVED;
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool HasHostBeenRequested(const std::string& hostname) {
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return std::find(requested_hostnames_.begin(),
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     requested_hostnames_.end(),
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     hostname) != requested_hostnames_.end();
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void WaitUntilHostHasBeenRequested(const std::string& hostname) {
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK(!is_waiting_for_hostname_);
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (HasHostBeenRequested(hostname))
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return;
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    waiting_for_hostname_ = hostname;
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    is_waiting_for_hostname_ = true;
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    content::RunMessageLoop();
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual ~HostResolutionRequestRecorder() {}
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void AddToHistory(const std::string& hostname) {
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    requested_hostnames_.push_back(hostname);
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (is_waiting_for_hostname_ && waiting_for_hostname_ == hostname) {
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      is_waiting_for_hostname_ = false;
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      waiting_for_hostname_.clear();
7290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      base::MessageLoop::current()->Quit();
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The hostname which WaitUntilHostHasBeenRequested is currently waiting for
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // to be requested.
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string waiting_for_hostname_;
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Whether WaitUntilHostHasBeenRequested is waiting for a hostname to be
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // requested and thus is running a nested message loop.
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool is_waiting_for_hostname_;
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // A list of hostnames for which resolution has already been requested. Only
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // to be accessed from the UI thread.
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::vector<std::string> requested_hostnames_;
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(HostResolutionRequestRecorder);
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace chrome_browser_net {
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class PredictorBrowserTest : public InProcessBrowserTest {
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PredictorBrowserTest()
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      : startup_url_("http://host1:1"),
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        referring_url_("http://host2:1"),
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        target_url_("http://host3:1"),
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        host_resolution_request_recorder_(new HostResolutionRequestRecorder) {
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) protected:
10568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  virtual void SetUpInProcessBrowserTestFixture() OVERRIDE {
10668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    scoped_host_resolver_proc_.reset(new net::ScopedDefaultHostResolverProc(
10768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)        host_resolution_request_recorder_.get()));
10868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    InProcessBrowserTest::SetUpInProcessBrowserTestFixture();
10968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  }
11068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
11168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  virtual void TearDownInProcessBrowserTestFixture() OVERRIDE {
11268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    InProcessBrowserTest::TearDownInProcessBrowserTestFixture();
11368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    scoped_host_resolver_proc_.reset();
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void LearnAboutInitialNavigation(const GURL& url) {
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Predictor* predictor = browser()->profile()->GetNetworkPredictor();
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    BrowserThread::PostTask(BrowserThread::IO,
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            FROM_HERE,
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            base::Bind(&Predictor::LearnAboutInitialNavigation,
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                       base::Unretained(predictor),
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                       url));
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    content::RunAllPendingInMessageLoop(BrowserThread::IO);
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void LearnFromNavigation(const GURL& referring_url, const GURL& target_url) {
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Predictor* predictor = browser()->profile()->GetNetworkPredictor();
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    BrowserThread::PostTask(BrowserThread::IO,
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            FROM_HERE,
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            base::Bind(&Predictor::LearnFromNavigation,
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                       base::Unretained(predictor),
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                       referring_url,
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                       target_url));
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    content::RunAllPendingInMessageLoop(BrowserThread::IO);
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void PrepareFrameSubresources(const GURL& url) {
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Predictor* predictor = browser()->profile()->GetNetworkPredictor();
13990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    predictor->PredictFrameSubresources(url, GURL());
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void GetListFromPrefsAsString(const char* list_path,
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                std::string* value_as_string) const {
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PrefService* prefs = browser()->profile()->GetPrefs();
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const base::ListValue* list_value = prefs->GetList(list_path);
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    JSONStringValueSerializer serializer(value_as_string);
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    serializer.Serialize(*list_value);
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void WaitUntilHostHasBeenRequested(const std::string& hostname) {
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    host_resolution_request_recorder_->WaitUntilHostHasBeenRequested(hostname);
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const GURL startup_url_;
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const GURL referring_url_;
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const GURL target_url_;
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_refptr<HostResolutionRequestRecorder>
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      host_resolution_request_recorder_;
16168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  scoped_ptr<net::ScopedDefaultHostResolverProc> scoped_host_resolver_proc_;
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)IN_PROC_BROWSER_TEST_F(PredictorBrowserTest, PRE_ShutdownStartupCycle) {
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Prepare state that will be serialized on this shut-down and read on next
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // start-up.
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  LearnAboutInitialNavigation(startup_url_);
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  LearnFromNavigation(referring_url_, target_url_);
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)IN_PROC_BROWSER_TEST_F(PredictorBrowserTest, ShutdownStartupCycle) {
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Make sure that the Preferences file is actually wiped of all DNS prefetch
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // related data after start-up.
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string cleared_startup_list;
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string cleared_referral_list;
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GetListFromPrefsAsString(prefs::kDnsPrefetchingStartupList,
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           &cleared_startup_list);
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GetListFromPrefsAsString(prefs::kDnsPrefetchingHostReferralList,
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           &cleared_referral_list);
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_THAT(cleared_startup_list, Not(HasSubstr(startup_url_.host())));
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_THAT(cleared_referral_list, Not(HasSubstr(referring_url_.host())));
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_THAT(cleared_referral_list, Not(HasSubstr(target_url_.host())));
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // But also make sure this data has been first loaded into the Predictor, by
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // inspecting that the Predictor starts making the expected hostname requests.
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PrepareFrameSubresources(referring_url_);
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  WaitUntilHostHasBeenRequested(startup_url_.host());
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  WaitUntilHostHasBeenRequested(target_url_.host());
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace chrome_browser_net
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
194