diff options
Diffstat (limited to 'chrome')
25 files changed, 430 insertions, 74 deletions
diff --git a/chrome/browser/alternate_nav_url_fetcher.cc b/chrome/browser/alternate_nav_url_fetcher.cc index 7523f66..ee8c7b6 100644 --- a/chrome/browser/alternate_nav_url_fetcher.cc +++ b/chrome/browser/alternate_nav_url_fetcher.cc @@ -1,4 +1,4 @@ -// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. +// Copyright (c) 2010 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. @@ -6,6 +6,7 @@ #include "app/l10n_util.h" #include "app/resource_bundle.h" +#include "chrome/browser/intranet_redirect_detector.h" #include "chrome/browser/profile.h" #include "chrome/browser/tab_contents/navigation_controller.h" #include "chrome/browser/tab_contents/navigation_entry.h" @@ -82,37 +83,7 @@ void AlternateNavURLFetcher::OnURLFetchComplete(const URLFetcher* source, const ResponseCookies& cookies, const std::string& data) { DCHECK(fetcher_.get() == source); - if (status.is_success() && - // HTTP 2xx, 401, and 407 all indicate that the target address exists. - (((response_code / 100) == 2) || - (response_code == 401) || (response_code == 407))) { - state_ = SUCCEEDED; - - // The following TLD+1s are used as destinations by ISPs/DNS providers/etc. - // who return provider-controlled pages to arbitrary user navigation - // attempts. Because this can result in infobars on large fractions of user - // searches, we don't show automatic infobars for these. Note that users - // can still choose to explicitly navigate to or search for pages in these - // domains, and can still get infobars for cases that wind up on other - // domains (e.g. legit intranet sites), we're just trying to avoid - // erroneously harassing the user with our own UI prompts. - const char* kBlacklistedSites[] = { - // NOTE: Use complete URLs, because GURL() doesn't do fixup! - "http://comcast.com/", - "http://opendns.com/", - "http://verizon.net/", - }; - for (size_t i = 0; i < arraysize(kBlacklistedSites); ++i) { - if (net::RegistryControlledDomainService::SameDomainOrHost( - url, GURL(kBlacklistedSites[i]))) { - state_ = FAILED; - break; - } - } - } else { - state_ = FAILED; - } - + SetStatusFromURLFetch(url, status, response_code); ShowInfobarIfPossible(); } @@ -150,6 +121,47 @@ void AlternateNavURLFetcher::InfoBarClosed() { delete this; } +void AlternateNavURLFetcher::SetStatusFromURLFetch( + const GURL& url, + const URLRequestStatus& status, + int response_code) { + if (!status.is_success() || + // HTTP 2xx, 401, and 407 all indicate that the target address exists. + (((response_code / 100) != 2) && + (response_code != 401) && (response_code != 407)) || + // Fail if we're redirected to a common location. This is the "automatic + // heuristic" version of the explicit blacklist below; see comments there. + net::RegistryControlledDomainService::SameDomainOrHost(url, + IntranetRedirectDetector::RedirectOrigin())) { + state_ = FAILED; + return; + } + + // The following TLD+1s are used as destinations by ISPs/DNS providers/etc. + // who return provider-controlled pages to arbitrary user navigation attempts. + // Because this can result in infobars on large fractions of user searches, we + // don't show automatic infobars for these. Note that users can still choose + // to explicitly navigate to or search for pages in these domains, and can + // still get infobars for cases that wind up on other domains (e.g. legit + // intranet sites), we're just trying to avoid erroneously harassing the user + // with our own UI prompts. + const char* kBlacklistedSites[] = { + // NOTE: Use complete URLs, because GURL() doesn't do fixup! + "http://comcast.com/", + "http://opendns.com/", + "http://verizon.net/", + }; + for (size_t i = 0; i < arraysize(kBlacklistedSites); ++i) { + if (net::RegistryControlledDomainService::SameDomainOrHost(url, + GURL(kBlacklistedSites[i]))) { + state_ = FAILED; + return; + } + } + + state_ = SUCCEEDED; +} + void AlternateNavURLFetcher::ShowInfobarIfPossible() { if (!navigated_to_entry_ || state_ != SUCCEEDED) { if (state_ == FAILED) diff --git a/chrome/browser/alternate_nav_url_fetcher.h b/chrome/browser/alternate_nav_url_fetcher.h index 40a92f2..943f23e 100644 --- a/chrome/browser/alternate_nav_url_fetcher.h +++ b/chrome/browser/alternate_nav_url_fetcher.h @@ -1,4 +1,4 @@ -// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. +// Copyright (c) 2010 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. @@ -62,6 +62,12 @@ class AlternateNavURLFetcher : public NotificationObserver, virtual void InfoBarClosed(); private: + // Sets |state_| to either SUCCEEDED or FAILED depending on the result of the + // fetch. + void SetStatusFromURLFetch(const GURL& url, + const URLRequestStatus& status, + int response_code); + // Displays the infobar if all conditions are met (the page has loaded and // the fetch of the alternate URL succeeded). void ShowInfobarIfPossible(); diff --git a/chrome/browser/browser_main.cc b/chrome/browser/browser_main.cc index c5e4484..995f625 100644 --- a/chrome/browser/browser_main.cc +++ b/chrome/browser/browser_main.cc @@ -1,4 +1,4 @@ -// Copyright (c) 2006-2009 The Chromium Authors. All rights reserved. +// Copyright (c) 2010 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. @@ -797,19 +797,19 @@ int BrowserMain(const MainFunctionParams& parameters) { RegisterMetadataURLRequestHandler(); // In unittest mode, this will do nothing. In normal mode, this will create - // the global GoogleURLTracker instance, which will promptly go to sleep for - // five seconds (to avoid slowing startup), and wake up afterwards to see if - // it should do anything else. If we don't cause this creation now, it won't - // happen until someone else asks for the tracker, at which point we may no - // longer want to sleep for five seconds. + // the global GoogleURLTracker and IntranetRedirectDetector instances, which + // will promptly go to sleep for five and seven seconds, respectively (to + // avoid slowing startup), and wake up afterwards to see if they should do + // anything else. // // A simpler way of doing all this would be to have some function which could - // give the time elapsed since startup, and simply have the tracker check that - // when asked to initialize itself, but this doesn't seem to exist. + // give the time elapsed since startup, and simply have these objects check + // that when asked to initialize themselves, but this doesn't seem to exist. // - // This can't be created in the BrowserProcessImpl constructor because it - // needs to read prefs that get set after that runs. + // These can't be created in the BrowserProcessImpl constructor because they + // need to read prefs that get set after that runs. browser_process->google_url_tracker(); + browser_process->intranet_redirect_detector(); // Have Chrome plugins write their data to the profile directory. PluginService::GetInstance()->SetChromePluginDataDir(profile->GetPath()); diff --git a/chrome/browser/browser_prefs.cc b/chrome/browser/browser_prefs.cc index ae3abf9..300f762 100644 --- a/chrome/browser/browser_prefs.cc +++ b/chrome/browser/browser_prefs.cc @@ -1,4 +1,4 @@ -// Copyright (c) 2009 The Chromium Authors. All rights reserved. +// Copyright (c) 2010 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. @@ -17,6 +17,7 @@ #include "chrome/browser/form_field_history_manager.h" #include "chrome/browser/google_url_tracker.h" #include "chrome/browser/host_zoom_map.h" +#include "chrome/browser/intranet_redirect_detector.h" #include "chrome/browser/metrics/metrics_service.h" #include "chrome/browser/net/dns_global.h" #include "chrome/browser/page_info_model.h" @@ -63,6 +64,7 @@ void RegisterLocalState(PrefService* local_state) { WebCacheManager::RegisterPrefs(local_state); ExternalProtocolHandler::RegisterPrefs(local_state); GoogleURLTracker::RegisterPrefs(local_state); + IntranetRedirectDetector::RegisterPrefs(local_state); KeywordEditorController::RegisterPrefs(local_state); MetricsLog::RegisterPrefs(local_state); MetricsService::RegisterPrefs(local_state); diff --git a/chrome/browser/browser_process.h b/chrome/browser/browser_process.h index d826321..d1ba1a3 100644 --- a/chrome/browser/browser_process.h +++ b/chrome/browser/browser_process.h @@ -1,4 +1,4 @@ -// Copyright (c) 2009 The Chromium Authors. All rights reserved. +// Copyright (c) 2010 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. @@ -21,6 +21,7 @@ class Clipboard; class DevToolsManager; class DownloadRequestManager; class GoogleURLTracker; +class IntranetRedirectDetector; class IconManager; class MetricsService; class NotificationUIManager; @@ -122,6 +123,7 @@ class BrowserProcess { virtual printing::PrintJobManager* print_job_manager() = 0; virtual GoogleURLTracker* google_url_tracker() = 0; + virtual IntranetRedirectDetector* intranet_redirect_detector() = 0; // Returns the locale used by the application. virtual const std::string& GetApplicationLocale() = 0; diff --git a/chrome/browser/browser_process_impl.cc b/chrome/browser/browser_process_impl.cc index f19e6a6..481d210 100644 --- a/chrome/browser/browser_process_impl.cc +++ b/chrome/browser/browser_process_impl.cc @@ -1,4 +1,4 @@ -// Copyright (c) 2009 The Chromium Authors. All rights reserved. +// Copyright (c) 2010 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. @@ -20,6 +20,7 @@ #include "chrome/browser/download/save_file_manager.h" #include "chrome/browser/google_url_tracker.h" #include "chrome/browser/icon_manager.h" +#include "chrome/browser/intranet_redirect_detector.h" #include "chrome/browser/metrics/metrics_service.h" #include "chrome/browser/net/dns_global.h" #include "chrome/browser/net/sdch_dictionary_fetcher.h" @@ -182,12 +183,14 @@ BrowserProcessImpl::~BrowserProcessImpl() { // any pending URLFetchers, and avoid creating any more. SdchDictionaryFetcher::Shutdown(); - // We need to destroy the MetricsService and GoogleURLTracker before the - // io_thread_ gets destroyed, since both destructors can call the URLFetcher - // destructor, which does an PostDelayedTask operation on the IO thread. (The - // IO thread will handle that URLFetcher operation before going away.) + // We need to destroy the MetricsService, GoogleURLTracker, and + // IntranetRedirectDetector before the io_thread_ gets destroyed, since their + // destructors can call the URLFetcher destructor, which does a + // PostDelayedTask operation on the IO thread. (The IO thread will handle + // that URLFetcher operation before going away.) metrics_service_.reset(); google_url_tracker_.reset(); + intranet_redirect_detector_.reset(); // Need to clear profiles (download managers) before the io_thread_. profile_manager_.reset(); @@ -461,6 +464,13 @@ void BrowserProcessImpl::CreateGoogleURLTracker() { google_url_tracker_.swap(google_url_tracker); } +void BrowserProcessImpl::CreateIntranetRedirectDetector() { + DCHECK(intranet_redirect_detector_.get() == NULL); + scoped_ptr<IntranetRedirectDetector> intranet_redirect_detector( + new IntranetRedirectDetector); + intranet_redirect_detector_.swap(intranet_redirect_detector); +} + void BrowserProcessImpl::CreateNotificationUIManager() { DCHECK(notification_ui_manager_.get() == NULL); notification_ui_manager_.reset(NotificationUIManager::Create()); diff --git a/chrome/browser/browser_process_impl.h b/chrome/browser/browser_process_impl.h index 51d0cf5..2c815ee 100644 --- a/chrome/browser/browser_process_impl.h +++ b/chrome/browser/browser_process_impl.h @@ -1,4 +1,4 @@ -// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. +// Copyright (c) 2010 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. @@ -182,6 +182,13 @@ class BrowserProcessImpl : public BrowserProcess, public NonThreadSafe { return google_url_tracker_.get(); } + virtual IntranetRedirectDetector* intranet_redirect_detector() { + DCHECK(CalledOnValidThread()); + if (!intranet_redirect_detector_.get()) + CreateIntranetRedirectDetector(); + return intranet_redirect_detector_.get(); + } + virtual const std::string& GetApplicationLocale() { DCHECK(!locale_.empty()); return locale_; @@ -225,6 +232,7 @@ class BrowserProcessImpl : public BrowserProcess, public NonThreadSafe { void CreateDebuggerWrapper(int port); void CreateDevToolsManager(); void CreateGoogleURLTracker(); + void CreateIntranetRedirectDetector(); void CreateNotificationUIManager(); #if defined(IPC_MESSAGE_LOG_ENABLED) @@ -282,6 +290,7 @@ class BrowserProcessImpl : public BrowserProcess, public NonThreadSafe { scoped_ptr<AutomationProviderList> automation_provider_list_; scoped_ptr<GoogleURLTracker> google_url_tracker_; + scoped_ptr<IntranetRedirectDetector> intranet_redirect_detector_; scoped_ptr<NotificationService> main_notification_service_; diff --git a/chrome/browser/extensions/cross_origin_xhr_apitest.cc b/chrome/browser/extensions/cross_origin_xhr_apitest.cc index 5a98322..c43c612 100644 --- a/chrome/browser/extensions/cross_origin_xhr_apitest.cc +++ b/chrome/browser/extensions/cross_origin_xhr_apitest.cc @@ -1,8 +1,9 @@ -// Copyright (c) 2009 The Chromium Authors. All rights reserved. +// Copyright (c) 2010 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 "chrome/browser/extensions/extension_apitest.h" +#include "net/base/mock_host_resolver.h" IN_PROC_BROWSER_TEST_F(ExtensionApiTest, CrossOriginXHR) { host_resolver()->AddRule("*.com", "127.0.0.1"); diff --git a/chrome/browser/extensions/execute_script_apitest.cc b/chrome/browser/extensions/execute_script_apitest.cc index 07662b6c..4c7aa87 100644 --- a/chrome/browser/extensions/execute_script_apitest.cc +++ b/chrome/browser/extensions/execute_script_apitest.cc @@ -1,8 +1,9 @@ -// Copyright (c) 2009 The Chromium Authors. All rights reserved. +// Copyright (c) 20109 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 "chrome/browser/extensions/extension_apitest.h" +#include "net/base/mock_host_resolver.h" // This test failed at times on the Vista dbg builder and has been marked as // flaky for now. Bug http://code.google.com/p/chromium/issues/detail?id=28630 diff --git a/chrome/browser/extensions/extension_history_apitest.cc b/chrome/browser/extensions/extension_history_apitest.cc index 910012f..94873b3 100644 --- a/chrome/browser/extensions/extension_history_apitest.cc +++ b/chrome/browser/extensions/extension_history_apitest.cc @@ -1,10 +1,11 @@ -// Copyright (c) 2009 The Chromium Authors. All rights reserved. +// Copyright (c) 2010 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 "base/command_line.h" #include "chrome/browser/extensions/extension_apitest.h" #include "chrome/common/chrome_switches.h" +#include "net/base/mock_host_resolver.h" // Flaky, http://crbug.com/26296. IN_PROC_BROWSER_TEST_F(ExtensionApiTest, DISABLED_History) { diff --git a/chrome/browser/extensions/extension_javascript_url_apitest.cc b/chrome/browser/extensions/extension_javascript_url_apitest.cc index aaa7b30..657f82d 100644 --- a/chrome/browser/extensions/extension_javascript_url_apitest.cc +++ b/chrome/browser/extensions/extension_javascript_url_apitest.cc @@ -1,8 +1,9 @@ -// Copyright (c) 2009 The Chromium Authors. All rights reserved. +// Copyright (c) 2010 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 "chrome/browser/extensions/extension_apitest.h" +#include "net/base/mock_host_resolver.h" IN_PROC_BROWSER_TEST_F(ExtensionApiTest, JavaScriptURLPermissions) { host_resolver()->AddRule("a.com", "127.0.0.1"); diff --git a/chrome/browser/extensions/incognito_noscript_apitest.cc b/chrome/browser/extensions/incognito_noscript_apitest.cc index 69f3876..fa78e67 100755 --- a/chrome/browser/extensions/incognito_noscript_apitest.cc +++ b/chrome/browser/extensions/incognito_noscript_apitest.cc @@ -1,4 +1,4 @@ -// Copyright (c) 2009 The Chromium Authors. All rights reserved. +// Copyright (c) 2010 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. @@ -10,6 +10,7 @@ #include "chrome/browser/tab_contents/tab_contents.h" #include "chrome/common/url_constants.h" #include "chrome/test/ui_test_utils.h" +#include "net/base/mock_host_resolver.h" IN_PROC_BROWSER_TEST_F(ExtensionBrowserTest, IncognitoNoScript) { host_resolver()->AddRule("*", "127.0.0.1"); @@ -37,8 +38,8 @@ IN_PROC_BROWSER_TEST_F(ExtensionBrowserTest, IncognitoNoScript) { NULL); otr_browser->window()->Show(); ui_test_utils::WaitForNavigationInCurrentTab(otr_browser); - - string16 title; + + string16 title; ui_test_utils::GetCurrentTabTitle(otr_browser, &title); ASSERT_EQ("Unmodified", UTF16ToASCII(title)); } diff --git a/chrome/browser/first_run.h b/chrome/browser/first_run.h index 6b8a9d39..3b2d996 100644 --- a/chrome/browser/first_run.h +++ b/chrome/browser/first_run.h @@ -1,4 +1,4 @@ -// Copyright (c) 2009 The Chromium Authors. All rights reserved. +// Copyright (c) 2010 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. @@ -136,8 +136,9 @@ class Upgrade { }; #endif -// A subclass of BrowserProcessImpl that does not have a GoogleURLTracker -// so we don't fetch as we have no IO thread (see bug #1292702). +// A subclass of BrowserProcessImpl that does not have a GoogleURLTracker or +// IntranetRedirectDetector so we don't do any URL fetches (as we have no IO +// thread to fetch on). class FirstRunBrowserProcess : public BrowserProcessImpl { public: explicit FirstRunBrowserProcess(const CommandLine& command_line) @@ -146,6 +147,9 @@ class FirstRunBrowserProcess : public BrowserProcessImpl { virtual ~FirstRunBrowserProcess() { } virtual GoogleURLTracker* google_url_tracker() { return NULL; } + virtual IntranetRedirectDetector* intranet_redirect_detector() { + return NULL; + } private: DISALLOW_COPY_AND_ASSIGN(FirstRunBrowserProcess); diff --git a/chrome/browser/intranet_redirect_detector.cc b/chrome/browser/intranet_redirect_detector.cc new file mode 100644 index 0000000..04b0a5a --- /dev/null +++ b/chrome/browser/intranet_redirect_detector.cc @@ -0,0 +1,171 @@ +// Copyright (c) 2010 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 "chrome/browser/intranet_redirect_detector.h" + +#include "base/rand_util.h" +#include "base/stl_util-inl.h" +#include "base/utf_string_conversions.h" +#include "chrome/browser/browser_process.h" +#include "chrome/browser/profile.h" +#include "chrome/common/notification_service.h" +#include "chrome/common/pref_names.h" +#include "chrome/common/pref_service.h" +#include "net/base/load_flags.h" +#include "net/base/net_errors.h" +#include "net/base/registry_controlled_domain.h" +#include "net/url_request/url_request_status.h" + +const size_t IntranetRedirectDetector::kNumCharsInHostnames = 10; + +IntranetRedirectDetector::IntranetRedirectDetector() + : redirect_origin_(WideToUTF8(g_browser_process->local_state()->GetString( + prefs::kLastKnownIntranetRedirectOrigin))), + ALLOW_THIS_IN_INITIALIZER_LIST(fetcher_factory_(this)), + in_startup_sleep_(true), + request_context_available_(!!Profile::GetDefaultRequestContext()) { + registrar_.Add(this, NotificationType::DEFAULT_REQUEST_CONTEXT_AVAILABLE, + NotificationService::AllSources()); + + // Because this function can be called during startup, when kicking off a URL + // fetch can eat up 20 ms of time, we delay seven seconds, which is hopefully + // long enough to be after startup, but still get results back quickly. + // Ideally, instead of this timer, we'd do something like "check if the + // browser is starting up, and if so, come back later", but there is currently + // no function to do this. + static const int kStartFetchDelayMS = 7000; + MessageLoop::current()->PostDelayedTask(FROM_HERE, + fetcher_factory_.NewRunnableMethod( + &IntranetRedirectDetector::FinishSleep), + kStartFetchDelayMS); +} + +IntranetRedirectDetector::~IntranetRedirectDetector() { + STLDeleteElements(&fetchers_); +} + +// static +GURL IntranetRedirectDetector::RedirectOrigin() { + const IntranetRedirectDetector* const detector = + g_browser_process->intranet_redirect_detector(); + return detector ? detector->redirect_origin_ : GURL(); +} + +// static +void IntranetRedirectDetector::RegisterPrefs(PrefService* prefs) { + prefs->RegisterStringPref(prefs::kLastKnownIntranetRedirectOrigin, + std::wstring()); +} + +void IntranetRedirectDetector::FinishSleep() { + in_startup_sleep_ = false; + StartFetchesIfPossible(); +} + +void IntranetRedirectDetector::StartFetchesIfPossible() { + // Bail if a fetch isn't appropriate right now. This function will be called + // again each time one of the preconditions changes, so we'll fetch + // immediately once all of them are met. + if (in_startup_sleep_ || !request_context_available_) + return; + + // We shouldn't somehow run twice. + DCHECK(fetchers_.empty() && resulting_origins_.empty()); + + // Start three fetchers on random hostnames. + for (size_t i = 0; i < 3; ++i) { + std::string url_string("http://"); + for (size_t j = 0; j < kNumCharsInHostnames; ++j) + url_string += ('a' + base::RandInt(0, 'z' - 'a')); + GURL random_url(url_string + '/'); + URLFetcher* fetcher = new URLFetcher(random_url, URLFetcher::HEAD, this); + // We don't want these fetches to affect existing state in the profile. + fetcher->set_load_flags(net::LOAD_DISABLE_CACHE | + net::LOAD_DO_NOT_SAVE_COOKIES); + fetcher->set_request_context(Profile::GetDefaultRequestContext()); + fetcher->Start(); + fetchers_.insert(fetcher); + } +} + +void IntranetRedirectDetector::OnURLFetchComplete( + const URLFetcher* source, + const GURL& url, + const URLRequestStatus& status, + int response_code, + const ResponseCookies& cookies, + const std::string& data) { + // Delete the fetcher on this function's exit. + Fetchers::iterator fetcher = fetchers_.find(const_cast<URLFetcher*>(source)); + DCHECK(fetcher != fetchers_.end()); + scoped_ptr<URLFetcher> clean_up_fetcher(*fetcher); + fetchers_.erase(fetcher); + + // If any two fetches result in the same domain/host, we set the redirect + // origin to that; otherwise we set it to nothing. + if (!status.is_success() || (response_code != 200)) { + if ((resulting_origins_.empty()) || + ((resulting_origins_.size() == 1) && + resulting_origins_.front().is_valid())) { + resulting_origins_.push_back(GURL()); + return; + } + redirect_origin_ = GURL(); + } else { + DCHECK(url.is_valid()); + GURL origin(url.GetOrigin()); + if (resulting_origins_.empty()) { + resulting_origins_.push_back(origin); + return; + } + if (net::RegistryControlledDomainService::SameDomainOrHost( + resulting_origins_.front(), origin)) { + redirect_origin_ = origin; + if (!fetchers_.empty()) { + // Cancel remaining fetch, we don't need it. + DCHECK(fetchers_.size() == 1); + delete (*fetchers_.begin()); + fetchers_.clear(); + } + } + if (resulting_origins_.size() == 1) { + resulting_origins_.push_back(origin); + return; + } + DCHECK(resulting_origins_.size() == 2); + redirect_origin_ = net::RegistryControlledDomainService::SameDomainOrHost( + resulting_origins_.back(), origin) ? origin : GURL(); + } + + g_browser_process->local_state()->SetString( + prefs::kLastKnownIntranetRedirectOrigin, redirect_origin_.is_valid() ? + UTF8ToWide(redirect_origin_.spec()) : std::wstring()); +} + +void IntranetRedirectDetector::Observe(NotificationType type, + const NotificationSource& source, + const NotificationDetails& details) { + DCHECK_EQ(NotificationType::DEFAULT_REQUEST_CONTEXT_AVAILABLE, type.value); + request_context_available_ = true; + StartFetchesIfPossible(); +} + +IntranetRedirectHostResolverProc::IntranetRedirectHostResolverProc( + net::HostResolverProc* previous) + : net::HostResolverProc(previous) { +} + +int IntranetRedirectHostResolverProc::Resolve(const std::string& host, + net::AddressFamily address_family, + net::AddressList* addrlist) { + // We'd love to just ask the IntranetRedirectDetector, but we may not be on + // the same thread. So just use the heuristic that any all-lowercase a-z + // hostname with the right number of characters is likely from the detector + // (and thus should be blocked). + return ((host.length() == IntranetRedirectDetector::kNumCharsInHostnames) && + (host.find_first_not_of("abcdefghijklmnopqrstuvwxyz") == + std::string::npos)) ? + net::ERR_NAME_NOT_RESOLVED : + ResolveUsingPrevious(host, address_family, addrlist); +} diff --git a/chrome/browser/intranet_redirect_detector.h b/chrome/browser/intranet_redirect_detector.h new file mode 100644 index 0000000..f1e38ae --- /dev/null +++ b/chrome/browser/intranet_redirect_detector.h @@ -0,0 +1,106 @@ +// Copyright (c) 2010 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. + +#ifndef CHROME_BROWSER_INTRANET_REDIRECT_DETECTOR_H_ +#define CHROME_BROWSER_INTRANET_REDIRECT_DETECTOR_H_ + +#include <set> +#include <string> +#include <vector> + +#include "chrome/browser/net/url_fetcher.h" +#include "chrome/common/notification_registrar.h" +#include "googleurl/src/gurl.h" +#include "net/base/host_resolver_proc.h" + +class PrefService; + +// This object is responsible for determining whether the user is on a network +// that redirects requests for intranet hostnames to another site, and if so, +// tracking what that site is (including across restarts via a pref). For +// example, the user's ISP might convert a request for "http://query/" into a +// 302 redirect to "http://isp.domain.com/search?q=query" in order to display +// custom pages on typos, nonexistent sites, etc. +// +// We use this information in the AlternateNavURLFetcher to avoid displaying +// infobars for these cases. Our infobars are designed to allow users to get at +// intranet sites when they were erroneously taken to a search result page. In +// these cases, however, users would be shown a confusing and useless infobar +// when they really did mean to do a search. +// +// Consumers should call RedirectOrigin(), which is guaranteed to synchronously +// return a value at all times (even during startup or in unittest mode). If no +// redirection is in place, the returned GURL will be empty. +class IntranetRedirectDetector : public URLFetcher::Delegate, + public NotificationObserver { + public: + // Only the main browser process loop should call this, when setting up + // g_browser_process->intranet_redirect_detector_. No code other than the + // IntranetRedirectDetector itself should actually use + // g_browser_process->intranet_redirect_detector() (which shouldn't be hard, + // since there aren't useful public functions on this object for consumers to + // access anyway). + IntranetRedirectDetector(); + ~IntranetRedirectDetector(); + + // Returns the current redirect origin. This will be empty if no redirection + // is in place. + static GURL RedirectOrigin(); + + static void RegisterPrefs(PrefService* prefs); + + // The number of characters the fetcher will use for its randomly-generated + // hostnames. + static const size_t kNumCharsInHostnames; + + private: + typedef std::set<URLFetcher*> Fetchers; + + // Called when the five second startup sleep has finished. Runs any pending + // fetch. + void FinishSleep(); + + // Starts the fetches to determine the redirect URL if we can currently do so. + void StartFetchesIfPossible(); + + // URLFetcher::Delegate + virtual void OnURLFetchComplete(const URLFetcher* source, + const GURL& url, + const URLRequestStatus& status, + int response_code, + const ResponseCookies& cookies, + const std::string& data); + + // NotificationObserver + virtual void Observe(NotificationType type, + const NotificationSource& source, + const NotificationDetails& details); + + NotificationRegistrar registrar_; + GURL redirect_origin_; + ScopedRunnableMethodFactory<IntranetRedirectDetector> fetcher_factory_; + Fetchers fetchers_; + std::vector<GURL> resulting_origins_; + bool in_startup_sleep_; // True if we're in the seven-second "no fetching" + // period that begins at browser start. + bool request_context_available_; + // True when the profile has been loaded and the + // default request context created, so we can + // actually do the fetch with the right data. + + DISALLOW_COPY_AND_ASSIGN(IntranetRedirectDetector); +}; + +// This is for use in testing, where we don't want our fetches to actually go +// over the network. It captures the requests and causes them to fail. +class IntranetRedirectHostResolverProc : public net::HostResolverProc { + public: + explicit IntranetRedirectHostResolverProc(net::HostResolverProc* previous); + + virtual int Resolve(const std::string& host, + net::AddressFamily address_family, + net::AddressList* addrlist); +}; + +#endif // CHROME_BROWSER_INTRANET_REDIRECT_DETECTOR_H_ diff --git a/chrome/browser/net/cookie_policy_browsertest.cc b/chrome/browser/net/cookie_policy_browsertest.cc index f218575..7dbecf9 100644 --- a/chrome/browser/net/cookie_policy_browsertest.cc +++ b/chrome/browser/net/cookie_policy_browsertest.cc @@ -1,4 +1,4 @@ -// Copyright (c) 2009 The Chromium Authors. All rights reserved. +// Copyright (c) 2010 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. @@ -9,6 +9,7 @@ #include "chrome/common/pref_service.h" #include "chrome/test/in_process_browser_test.h" #include "chrome/test/ui_test_utils.h" +#include "net/base/mock_host_resolver.h" class CookiePolicyBrowserTest : public InProcessBrowserTest { public: diff --git a/chrome/browser/privacy_blacklist/blacklist_manager_browsertest.cc b/chrome/browser/privacy_blacklist/blacklist_manager_browsertest.cc index 8bbd8ac..b228af0 100644 --- a/chrome/browser/privacy_blacklist/blacklist_manager_browsertest.cc +++ b/chrome/browser/privacy_blacklist/blacklist_manager_browsertest.cc @@ -1,4 +1,4 @@ -// Copyright (c) 2009 The Chromium Authors. All rights reserved. +// Copyright (c) 2010 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. @@ -18,6 +18,7 @@ #include "chrome/test/ui_test_utils.h" #include "grit/browser_resources.h" #include "grit/generated_resources.h" +#include "net/base/mock_host_resolver.h" #include "testing/gtest/include/gtest/gtest.h" namespace { diff --git a/chrome/chrome_browser.gypi b/chrome/chrome_browser.gypi index f1a2420..b18c7b9 100755 --- a/chrome/chrome_browser.gypi +++ b/chrome/chrome_browser.gypi @@ -1097,6 +1097,8 @@ 'browser/input_window_dialog.h', 'browser/input_window_dialog_gtk.cc', 'browser/input_window_dialog_win.cc', + 'browser/intranet_redirect_detector.cc', + 'browser/intranet_redirect_detector.h', 'browser/jankometer.cc', 'browser/jankometer.h', 'browser/jumplist.cc', diff --git a/chrome/common/pref_names.cc b/chrome/common/pref_names.cc index 6c1edf9..2f95793 100644 --- a/chrome/common/pref_names.cc +++ b/chrome/common/pref_names.cc @@ -1,4 +1,4 @@ -// Copyright (c) 2009 The Chromium Authors. All rights reserved. +// Copyright (c) 2010 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. @@ -519,6 +519,10 @@ const wchar_t kShouldShowWelcomePage[] = L"show-welcome-page"; // correct Google domain/country code for whatever location the user is in. const wchar_t kLastKnownGoogleURL[] = L"browser.last_known_google_url"; +// String containing the last known intranet redirect URL, if any. See +// intranet_redirect_detector.h for more information. +const wchar_t kLastKnownIntranetRedirectOrigin[] = L""; + // Integer containing the system Country ID the first time we checked the // template URL prepopulate data. This is used to avoid adding a whole bunch of // new search engine choices if prepopulation runs when the user's Country ID diff --git a/chrome/common/pref_names.h b/chrome/common/pref_names.h index 8229a6f..4dab8c9 100644 --- a/chrome/common/pref_names.h +++ b/chrome/common/pref_names.h @@ -1,4 +1,4 @@ -// Copyright (c) 2009 The Chromium Authors. All rights reserved. +// Copyright (c) 2010 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. @@ -193,6 +193,7 @@ extern const wchar_t kShouldUseOEMFirstRunBubble[]; extern const wchar_t kShouldShowWelcomePage[]; extern const wchar_t kLastKnownGoogleURL[]; +extern const wchar_t kLastKnownIntranetRedirectOrigin[]; extern const wchar_t kCountryIDAtInstall[]; extern const wchar_t kGeoIDAtInstall[]; // OBSOLETE diff --git a/chrome/test/in_process_browser_test.cc b/chrome/test/in_process_browser_test.cc index 6c85760..4e206e8 100644 --- a/chrome/test/in_process_browser_test.cc +++ b/chrome/test/in_process_browser_test.cc @@ -1,4 +1,4 @@ -// Copyright (c) 2009 The Chromium Authors. All rights reserved. +// Copyright (c) 2010 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. @@ -15,6 +15,7 @@ #include "chrome/browser/browser_shutdown.h" #include "chrome/browser/browser_window.h" #include "chrome/browser/chrome_thread.h" +#include "chrome/browser/intranet_redirect_detector.h" #include "chrome/browser/net/url_request_mock_util.h" #include "chrome/browser/profile.h" #include "chrome/browser/profile_manager.h" @@ -32,6 +33,7 @@ #include "chrome/common/url_constants.h" #include "chrome/test/testing_browser_process.h" #include "chrome/test/ui_test_utils.h" +#include "net/base/mock_host_resolver.h" #include "sandbox/src/dep.h" #if defined(OS_LINUX) @@ -76,6 +78,9 @@ InProcessBrowserTest::InProcessBrowserTest() initial_timeout_(kInitialTimeoutInMS) { } +InProcessBrowserTest::~InProcessBrowserTest() { +} + void InProcessBrowserTest::SetUp() { // Cleanup the user data dir. FilePath user_data_dir; @@ -152,7 +157,8 @@ void InProcessBrowserTest::SetUp() { params.ui_task = NewRunnableMethod(this, &InProcessBrowserTest::RunTestOnMainThreadLoop); - host_resolver_ = new net::RuleBasedHostResolverProc(NULL); + host_resolver_ = new net::RuleBasedHostResolverProc( + new IntranetRedirectHostResolverProc(NULL)); // Something inside the browser does this lookup implicitly. Make it fail // to avoid external dependency. It won't break the tests. diff --git a/chrome/test/in_process_browser_test.h b/chrome/test/in_process_browser_test.h index ace6e07..a142626 100644 --- a/chrome/test/in_process_browser_test.h +++ b/chrome/test/in_process_browser_test.h @@ -1,11 +1,10 @@ -// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. +// Copyright (c) 2010 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. #ifndef CHROME_TEST_IN_PROCESS_BROWSER_TEST_H_ #define CHROME_TEST_IN_PROCESS_BROWSER_TEST_H_ -#include "net/base/mock_host_resolver.h" #include "net/url_request/url_request_unittest.h" #include "testing/gtest/include/gtest/gtest.h" @@ -41,6 +40,7 @@ class RuleBasedHostResolverProc; class InProcessBrowserTest : public testing::Test { public: InProcessBrowserTest(); + virtual ~InProcessBrowserTest(); // We do this so we can be used in a Task. void AddRef() {} diff --git a/chrome/test/live_sync/live_bookmarks_sync_test.cc b/chrome/test/live_sync/live_bookmarks_sync_test.cc index 8d16edc..b8836c7 100644 --- a/chrome/test/live_sync/live_bookmarks_sync_test.cc +++ b/chrome/test/live_sync/live_bookmarks_sync_test.cc @@ -1,4 +1,4 @@ -// Copyright (c) 2006-2009 The Chromium Authors. All rights reserved. +// Copyright (c) 2010 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. @@ -13,6 +13,7 @@ #include "chrome/browser/profile.h" #include "chrome/browser/profile_manager.h" #include "chrome/test/ui_test_utils.h" +#include "net/base/mock_host_resolver.h" namespace switches { const wchar_t kSyncUserForTest[] = L"sync-user-for-test"; @@ -52,6 +53,12 @@ class BookmarkLoadObserver : public BookmarkModelObserver { DISALLOW_COPY_AND_ASSIGN(BookmarkLoadObserver); }; +LiveBookmarksSyncTest::LiveBookmarksSyncTest() { +} + +LiveBookmarksSyncTest::~LiveBookmarksSyncTest() { +} + // static void LiveBookmarksSyncTest::BlockUntilLoaded(BookmarkModel* m) { if (m->IsLoaded()) diff --git a/chrome/test/live_sync/live_bookmarks_sync_test.h b/chrome/test/live_sync/live_bookmarks_sync_test.h index 1ff0251..134e82f 100644 --- a/chrome/test/live_sync/live_bookmarks_sync_test.h +++ b/chrome/test/live_sync/live_bookmarks_sync_test.h @@ -1,4 +1,4 @@ -// Copyright (c) 2006-2009 The Chromium Authors. All rights reserved. +// Copyright (c) 2010 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. @@ -16,6 +16,9 @@ class BookmarkModel; class BookmarkNode; class Profile; +namespace net { +class ScopedDefaultHostResolverProc; +} namespace switches { extern const wchar_t kSyncUserForTest[]; @@ -27,8 +30,8 @@ extern const wchar_t kSyncPasswordForTest[]; // without a valid sync server set up. class LiveBookmarksSyncTest : public InProcessBrowserTest { public: - LiveBookmarksSyncTest() { } - ~LiveBookmarksSyncTest() { } + LiveBookmarksSyncTest(); + ~LiveBookmarksSyncTest(); virtual void SetUp() { // At this point, the browser hasn't been launched, and no services are diff --git a/chrome/test/testing_browser_process.h b/chrome/test/testing_browser_process.h index 2131ed7..2bbcdcb 100644 --- a/chrome/test/testing_browser_process.h +++ b/chrome/test/testing_browser_process.h @@ -1,4 +1,4 @@ -// Copyright (c) 2009 The Chromium Authors. All rights reserved. +// Copyright (c) 2010 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. @@ -111,6 +111,10 @@ class TestingBrowserProcess : public BrowserProcess { return NULL; } + virtual IntranetRedirectDetector* intranet_redirect_detector() { + return NULL; + } + virtual AutomationProviderList* InitAutomationProviderList() { return NULL; } |