Home | History | Annotate | Download | only in android
      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