190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// Copyright (c) 2013 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 "chrome/browser/net/connect_interceptor.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/net/predictor.h"
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/base/load_flags.h"
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/url_request/url_request.h"
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace chrome_browser_net {
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ConnectInterceptor::ConnectInterceptor(Predictor* predictor)
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : timed_cache_(base::TimeDelta::FromSeconds(
1590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)          Predictor::kMaxUnusedSocketLifetimeSecondsWithoutAGet)),
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      predictor_(predictor) {
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(predictor);
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ConnectInterceptor::~ConnectInterceptor() {
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)void ConnectInterceptor::WitnessURLRequest(net::URLRequest* request) {
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GURL request_scheme_host(Predictor::CanonicalizeUrl(request->url()));
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (request_scheme_host == GURL::EmptyGURL())
262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Learn what URLs are likely to be needed during next startup.
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  predictor_->LearnAboutInitialNavigation(request_scheme_host);
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool redirected_host = false;
323240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  bool is_subresource = !(request->load_flags() & net::LOAD_MAIN_FRAME);
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (request->referrer().empty()) {
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (request->url() != request->original_url()) {
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // This request was completed with a redirect.
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      GURL original_scheme_host(request->original_url().GetWithEmptyPath());
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (request_scheme_host != original_scheme_host) {
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        redirected_host = true;
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // Don't learn from redirects that take path as an argument, but do
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // learn from short-hand typing entries, such as "cnn.com" redirects to
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // "www.cnn.com".  We can't just check for has_path(), as a mere "/"
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // will count as a path, so we check that the path is at most a "/"
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // (1 character long) to decide the redirect is "definitive" and has no
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // significant path.
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // TODO(jar): It may be ok to learn from all redirects, as the adaptive
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // system will not respond until several identical redirects have taken
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // place.  Hence a use of a path (that changes) wouldn't really be
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // learned from anyway.
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (request->original_url().path().length() <= 1 &&
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            timed_cache_.WasRecentlySeen(original_scheme_host)) {
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          // TODO(jar): These definite redirects could be learned much faster.
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          predictor_->LearnFromNavigation(original_scheme_host,
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                          request_scheme_host);
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    GURL referring_scheme_host = GURL(request->referrer()).GetWithEmptyPath();
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Learn about our referring URL, for use in the future.
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (is_subresource && timed_cache_.WasRecentlySeen(referring_scheme_host))
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      predictor_->LearnFromNavigation(referring_scheme_host,
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                      request_scheme_host);
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (referring_scheme_host == request_scheme_host) {
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // We've already made any/all predictions when we navigated to the
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // referring host, so we can bail out here.
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // We don't update the RecentlySeen() time because any preconnections
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // need to be made at the first navigation (i.e., when referer was loaded)
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // and wouldn't have waited for this current request navigation.
692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return;
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  timed_cache_.SetRecentlySeen(request_scheme_host);
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Subresources for main frames usually get predicted when we detected the
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // main frame request - way back in RenderViewHost::Navigate.  So only handle
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // predictions now for subresources or for redirected hosts.
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if ((request->load_flags() & net::LOAD_SUB_FRAME) || redirected_host)
7890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    predictor_->PredictFrameSubresources(request_scheme_host,
7990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                                         request->first_party_for_cookies());
802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return;
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace chrome_browser_net
84