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