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 28 LoggedInPredictorTable::LoggedInPredictorTable() 29 : PredictorTableBase() { 30 } 31 32 LoggedInPredictorTable::~LoggedInPredictorTable() { 33 } 34 35 // static 36 string LoggedInPredictorTable::GetKey(const GURL& url) { 37 return GetKeyFromDomain(url.host()); 38 } 39 40 // static 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 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 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 83 void LoggedInPredictorTable::DeleteDomain(const std::string& domain) { 84 DeleteDomainFromURL(GURL("http://" + domain)); 85 } 86 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 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 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 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 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