summaryrefslogtreecommitdiffstats
path: root/chrome/browser/autocomplete/network_action_predictor.cc
blob: 653cbc3489fc050b15a8e05568d3c6b0ee06967f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
// Copyright (c) 2011 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/autocomplete/network_action_predictor.h"

#include <math.h>

#include "base/i18n/case_conversion.h"
#include "base/metrics/histogram.h"
#include "base/string_util.h"
#include "base/utf_string_conversions.h"
#include "chrome/browser/autocomplete/autocomplete_match.h"
#include "chrome/browser/history/history.h"
#include "chrome/browser/history/in_memory_database.h"
#include "chrome/browser/profiles/profile.h"

namespace {

  const float kConfidenceCutoff[NetworkActionPredictor::LAST_PREDICT_ACTION] = {
    0.8f,
    0.5f
  };

}

NetworkActionPredictor::NetworkActionPredictor(Profile* profile)
  : profile_(profile) {
}

NetworkActionPredictor::~NetworkActionPredictor() {
}

// Given a match, return a recommended action.
NetworkActionPredictor::Action
    NetworkActionPredictor::RecommendAction(
        const string16& user_text, const AutocompleteMatch& match) const {
  HistoryService* history_service =
      profile_->GetHistoryService(Profile::EXPLICIT_ACCESS);
  if (!history_service)
    return ACTION_NONE;

  history::URLDatabase* url_db = history_service->InMemoryDatabase();
  if (!url_db)
    return ACTION_NONE;

  history::URLRow url_row;
  history::URLID url_id = url_db->GetRowForURL(match.destination_url, &url_row);

  if (url_id == 0)
    return ACTION_NONE;

  const double base_score = 1.0;

  // This constant is ln(1/0.65) so we end up decaying to 65% of the base score
  // for each week that passes.
  const double kLnDecayPercent = 0.43078291609245;
  base::TimeDelta time_passed = base::Time::Now() - url_row.last_visit();

  // Clamp to 0.
  const double decay_exponent = std::max(0.0,
      kLnDecayPercent * static_cast<double>(time_passed.InMicroseconds()) /
          base::Time::kMicrosecondsPerWeek);

  const double kMaxDecaySpeedDivisor = 5.0;
  const double kNumUsesPerDecaySpeedDivisorIncrement = 2.0;
  const double decay_divisor = std::min(kMaxDecaySpeedDivisor,
      (url_row.typed_count() + kNumUsesPerDecaySpeedDivisorIncrement - 1) /
          kNumUsesPerDecaySpeedDivisorIncrement);

  const double confidence = base_score / exp(decay_exponent / decay_divisor);
  CHECK(confidence >= 0.0 && confidence <= 1.0);

  UMA_HISTOGRAM_COUNTS_100("NetworkActionPredictor.Confidence",
                           confidence * 100);

  for (int i = 0; i < LAST_PREDICT_ACTION; ++i)
    if (confidence >= kConfidenceCutoff[i])
      return static_cast<Action>(i);
  return ACTION_NONE;
}

// Return true if the suggestion type warrants a TCP/IP preconnection.
// i.e., it is now quite likely that the user will select the related domain.
// static
bool NetworkActionPredictor::IsPreconnectable(const AutocompleteMatch& match) {
  switch (match.type) {
    // Matches using the user's default search engine.
    case AutocompleteMatch::SEARCH_WHAT_YOU_TYPED:
    case AutocompleteMatch::SEARCH_HISTORY:
    case AutocompleteMatch::SEARCH_SUGGEST:
      // A match that uses a non-default search engine (e.g. for tab-to-search).
    case AutocompleteMatch::SEARCH_OTHER_ENGINE:
      return true;

    default:
      return false;
  }
}