1 // Copyright (c) 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "chrome/browser/predictors/logged_in_predictor_table.h"
6
7 #include <algorithm>
8 #include <utility>
9 #include "base/logging.h"
10 #include "base/metrics/histogram.h"
11 #include "base/strings/stringprintf.h"
12 #include "content/public/browser/browser_thread.h"
13 #include "net/base/registry_controlled_domains/registry_controlled_domain.h"
14 #include "sql/statement.h"
15
16 using content::BrowserThread;
17 using sql::Statement;
18 using std::string;
19
20 namespace {
21
22 const char kTableName[] = "logged_in_predictor";
23
24 } // namespace
25
26 namespace predictors {
27
LoggedInPredictorTable()28 LoggedInPredictorTable::LoggedInPredictorTable()
29 : PredictorTableBase() {
30 }
31
~LoggedInPredictorTable()32 LoggedInPredictorTable::~LoggedInPredictorTable() {
33 }
34
35 // static
GetKey(const GURL & url)36 string LoggedInPredictorTable::GetKey(const GURL& url) {
37 return GetKeyFromDomain(url.host());
38 }
39
40 // static
GetKeyFromDomain(const std::string & domain)41 string LoggedInPredictorTable::GetKeyFromDomain(const std::string& domain) {
42 string effective_domain(
43 net::registry_controlled_domains::GetDomainAndRegistry(
44 domain,
45 net::registry_controlled_domains::EXCLUDE_PRIVATE_REGISTRIES));
46 if (effective_domain.empty())
47 effective_domain = domain;
48
49 // Strip off a preceding ".", if present.
50 if (!effective_domain.empty() && effective_domain[0] == '.')
51 return effective_domain.substr(1);
52 return effective_domain;
53 }
54
AddDomainFromURL(const GURL & url)55 void LoggedInPredictorTable::AddDomainFromURL(const GURL& url) {
56 CHECK(BrowserThread::CurrentlyOn(BrowserThread::DB));
57 if (CantAccessDatabase())
58 return;
59
60 Statement statement(DB()->GetCachedStatement(SQL_FROM_HERE,
61 base::StringPrintf("INSERT OR IGNORE INTO %s (domain, time) VALUES (?,?)",
62 kTableName).c_str()));
63
64 statement.BindString(0, GetKey(url));
65 statement.BindInt64(1, base::Time::Now().ToInternalValue());
66
67 statement.Run();
68 }
69
DeleteDomainFromURL(const GURL & url)70 void LoggedInPredictorTable::DeleteDomainFromURL(const GURL& url) {
71 CHECK(BrowserThread::CurrentlyOn(BrowserThread::DB));
72 if (CantAccessDatabase())
73 return;
74
75 Statement statement(DB()->GetCachedStatement(SQL_FROM_HERE,
76 base::StringPrintf("DELETE FROM %s WHERE domain=?", kTableName).c_str()));
77
78 statement.BindString(0, GetKey(url));
79
80 statement.Run();
81 }
82
DeleteDomain(const std::string & domain)83 void LoggedInPredictorTable::DeleteDomain(const std::string& domain) {
84 DeleteDomainFromURL(GURL("http://" + domain));
85 }
86
HasUserLoggedIn(const GURL & url,bool * is_present,bool * lookup_succeeded)87 void LoggedInPredictorTable::HasUserLoggedIn(const GURL& url, bool* is_present,
88 bool* lookup_succeeded) {
89 CHECK(BrowserThread::CurrentlyOn(BrowserThread::DB));
90 *lookup_succeeded = false;
91 if (CantAccessDatabase())
92 return;
93
94 Statement statement(DB()->GetCachedStatement(SQL_FROM_HERE,
95 base::StringPrintf("SELECT count(*) FROM %s WHERE domain=?",
96 kTableName).c_str()));
97
98 statement.BindString(0, GetKey(url));
99
100 if (statement.Step()) {
101 *is_present = (statement.ColumnInt(0) > 0);
102 *lookup_succeeded = true;
103 }
104 }
105
DeleteAllCreatedBetween(const base::Time & delete_begin,const base::Time & delete_end)106 void LoggedInPredictorTable::DeleteAllCreatedBetween(
107 const base::Time& delete_begin, const base::Time& delete_end) {
108 CHECK(BrowserThread::CurrentlyOn(BrowserThread::DB));
109 if (CantAccessDatabase())
110 return;
111
112 Statement statement(DB()->GetCachedStatement(SQL_FROM_HERE,
113 base::StringPrintf("DELETE FROM %s WHERE time >= ? AND time <= ?",
114 kTableName).c_str()));
115
116 statement.BindInt64(0, delete_begin.ToInternalValue());
117 statement.BindInt64(1, delete_end.ToInternalValue());
118
119 statement.Run();
120 }
121
GetAllData(LoggedInPredictorTable::LoggedInStateMap * state_map)122 void LoggedInPredictorTable::GetAllData(
123 LoggedInPredictorTable::LoggedInStateMap* state_map) {
124 CHECK(BrowserThread::CurrentlyOn(BrowserThread::DB));
125 DCHECK(state_map != NULL);
126 state_map->clear();
127 if (CantAccessDatabase())
128 return;
129
130 Statement statement(DB()->GetUniqueStatement(
131 base::StringPrintf("SELECT * FROM %s", kTableName).c_str()));
132
133 while (statement.Step()) {
134 string domain = statement.ColumnString(0);
135 int64 value = statement.ColumnInt64(1);
136 (*state_map)[domain] = value;
137 }
138 }
139
CreateTableIfNonExistent()140 void LoggedInPredictorTable::CreateTableIfNonExistent() {
141 CHECK(BrowserThread::CurrentlyOn(BrowserThread::DB));
142 if (CantAccessDatabase())
143 return;
144
145 sql::Connection* db = DB();
146 if (db->DoesTableExist(kTableName))
147 return;
148
149 const char* table_creator =
150 "CREATE TABLE %s (domain TEXT, time INTEGER, PRIMARY KEY(domain))";
151
152 if (!db->Execute(base::StringPrintf(table_creator, kTableName).c_str()))
153 ResetDB();
154 }
155
LogDatabaseStats()156 void LoggedInPredictorTable::LogDatabaseStats() {
157 CHECK(BrowserThread::CurrentlyOn(BrowserThread::DB));
158 if (CantAccessDatabase())
159 return;
160
161 Statement statement(DB()->GetCachedStatement(SQL_FROM_HERE,
162 base::StringPrintf("SELECT count(*) FROM %s", kTableName).c_str()));
163 if (statement.Step())
164 UMA_HISTOGRAM_COUNTS("LoggedInPredictor.TableRowCount",
165 statement.ColumnInt(0));
166 }
167
168 } // namespace predictors
169