1 // Copyright (c) 2012 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/history/android/visit_sql_handler.h" 6 7 #include "base/logging.h" 8 #include "chrome/browser/history/history_database.h" 9 10 using base::Time; 11 12 namespace history { 13 14 namespace { 15 16 // The interesting columns of this handler. 17 const HistoryAndBookmarkRow::ColumnID kInterestingColumns[] = { 18 HistoryAndBookmarkRow::CREATED, HistoryAndBookmarkRow::VISIT_COUNT, 19 HistoryAndBookmarkRow::LAST_VISIT_TIME }; 20 21 } // namespace 22 23 VisitSQLHandler::VisitSQLHandler(HistoryDatabase* history_db) 24 : SQLHandler(kInterestingColumns, arraysize(kInterestingColumns)), 25 history_db_(history_db) { 26 } 27 28 VisitSQLHandler::~VisitSQLHandler() { 29 } 30 31 // The created time is updated according the given |row|. 32 // We simulate updating created time by 33 // a. Remove all visits. 34 // b. Insert a new visit which has visit time same as created time. 35 // c. Insert the number of visits according the visit count in urls table. 36 // 37 // Visit row is insertted/removed to keep consistent with urls table. 38 // a. If the visit count in urls table is less than the visit rows in visit 39 // table, all existent visits will be removed. The new visits will be 40 // insertted according the value in urls table. 41 // b. Otherwise, only add the increased number of visit count. 42 bool VisitSQLHandler::Update(const HistoryAndBookmarkRow& row, 43 const TableIDRows& ids_set) { 44 for (TableIDRows::const_iterator id = ids_set.begin(); 45 id != ids_set.end(); ++id) { 46 VisitVector visits; 47 if (!history_db_->GetVisitsForURL(id->url_id, &visits)) 48 return false; 49 int visit_count_in_table = visits.size(); 50 URLRow url_row; 51 if (!history_db_->GetURLRow(id->url_id, &url_row)) 52 return false; 53 int visit_count_needed = url_row.visit_count(); 54 55 if (visit_count_needed == 0) 56 return Delete(ids_set); 57 58 // If created time is updated or new visit count is less than the current 59 // one, delete all visit rows. 60 if (row.is_value_set_explicitly(HistoryAndBookmarkRow::CREATED) || 61 visit_count_in_table > visit_count_needed) { 62 if (!DeleteVisitsForURL(id->url_id)) 63 return false; 64 visit_count_in_table = 0; 65 } 66 67 if (row.is_value_set_explicitly(HistoryAndBookmarkRow::CREATED) && 68 visit_count_needed > 0) { 69 if (!AddVisit(id->url_id, row.created())) 70 return false; 71 visit_count_in_table++; 72 } 73 74 if (!AddVisitRows(id->url_id, visit_count_needed - visit_count_in_table, 75 url_row.last_visit())) 76 return false; 77 } 78 return true; 79 } 80 81 bool VisitSQLHandler::Insert(HistoryAndBookmarkRow* row) { 82 DCHECK(row->is_value_set_explicitly(HistoryAndBookmarkRow::URL_ID)); 83 84 URLRow url_row; 85 if (!history_db_->GetURLRow(row->url_id(), &url_row)) 86 return false; 87 88 int visit_count = url_row.visit_count(); 89 90 if (visit_count == 0) 91 return true; 92 93 // Add a row if the last visit time is different from created time. 94 if (row->is_value_set_explicitly(HistoryAndBookmarkRow::CREATED) && 95 row->created() != url_row.last_visit() && visit_count > 0) { 96 if (!AddVisit(row->url_id(), row->created())) 97 return false; 98 visit_count--; 99 } 100 101 if (!AddVisitRows(row->url_id(), visit_count, url_row.last_visit())) 102 return false; 103 104 return true; 105 } 106 107 bool VisitSQLHandler::Delete(const TableIDRows& ids_set) { 108 for (TableIDRows::const_iterator ids = ids_set.begin(); 109 ids != ids_set.end(); ++ids) { 110 DeleteVisitsForURL(ids->url_id); 111 } 112 return true; 113 } 114 115 bool VisitSQLHandler::AddVisit(URLID url_id, const Time& visit_time) { 116 // TODO : Is 'content::PAGE_TRANSITION_AUTO_BOOKMARK' proper? 117 // if not, a new content::PageTransition type will need. 118 VisitRow visit_row(url_id, visit_time, 0, 119 content::PAGE_TRANSITION_AUTO_BOOKMARK, 0); 120 return history_db_->AddVisit(&visit_row, SOURCE_BROWSED); 121 } 122 123 bool VisitSQLHandler::AddVisitRows(URLID url_id, 124 int visit_count, 125 const Time& last_visit_time) { 126 int64 last_update_value = last_visit_time.ToInternalValue(); 127 for (int i = 0; i < visit_count; i++) { 128 if (!AddVisit(url_id, Time::FromInternalValue(last_update_value - i))) 129 return false; 130 } 131 return true; 132 } 133 134 bool VisitSQLHandler::DeleteVisitsForURL(URLID url_id) { 135 VisitVector visits; 136 if (!history_db_->GetVisitsForURL(url_id, &visits)) 137 return false; 138 139 for (VisitVector::const_iterator v = visits.begin(); v != visits.end(); ++v) { 140 history_db_->DeleteVisit(*v); 141 } 142 return true; 143 } 144 145 } // namespace history. 146