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 "components/history/core/browser/android/urls_sql_handler.h"
6 
7 #include "base/logging.h"
8 #include "base/stl_util.h"
9 #include "components/history/core/browser/url_database.h"
10 
11 using base::Time;
12 
13 namespace history {
14 
15 namespace {
16 
17 const HistoryAndBookmarkRow::ColumnID kInterestingColumns[] = {
18     HistoryAndBookmarkRow::URL, HistoryAndBookmarkRow::VISIT_COUNT,
19     HistoryAndBookmarkRow::TITLE, HistoryAndBookmarkRow::LAST_VISIT_TIME };
20 
21 }  // namespace
22 
UrlsSQLHandler(URLDatabase * url_db)23 UrlsSQLHandler::UrlsSQLHandler(URLDatabase* url_db)
24     : SQLHandler(kInterestingColumns, base::size(kInterestingColumns)),
25       url_db_(url_db) {}
26 
~UrlsSQLHandler()27 UrlsSQLHandler:: ~UrlsSQLHandler() {
28 }
29 
Insert(HistoryAndBookmarkRow * row)30 bool UrlsSQLHandler::Insert(HistoryAndBookmarkRow* row) {
31   URLRow url_row(row->url());
32 
33   URLID id = url_db_->GetRowForURL(row->url(), &url_row);
34   if (id) {
35     LOG(ERROR) << "AndroidProviderBackend::Insert Urls; url exists.";
36     return false; // We already has this row.
37   }
38 
39   if (row->is_value_set_explicitly(HistoryAndBookmarkRow::TITLE))
40     url_row.set_title(row->title());
41 
42   if (row->is_value_set_explicitly(HistoryAndBookmarkRow::LAST_VISIT_TIME))
43     url_row.set_last_visit(row->last_visit_time());
44 
45   if (row->is_value_set_explicitly(HistoryAndBookmarkRow::VISIT_COUNT))
46     url_row.set_visit_count(row->visit_count());
47 
48   // Adjust the last_visit_time if it not set.
49   if (!row->is_value_set_explicitly(HistoryAndBookmarkRow::LAST_VISIT_TIME)) {
50     if (row->is_value_set_explicitly(HistoryAndBookmarkRow::CREATED))
51       url_row.set_last_visit(row->created());
52     else if (row->is_value_set_explicitly(HistoryAndBookmarkRow::VISIT_COUNT))
53       url_row.set_last_visit(Time::Now());
54   }
55 
56   // Adjust the visit_count if it not set.
57   if (!row->is_value_set_explicitly(HistoryAndBookmarkRow::VISIT_COUNT)) {
58     int visit_count = 0;
59     if (row->is_value_set_explicitly(HistoryAndBookmarkRow::CREATED) &&
60         row->is_value_set_explicitly(HistoryAndBookmarkRow::LAST_VISIT_TIME) &&
61         row->last_visit_time() == row->created()) {
62       visit_count = 1;
63     } else {
64       if (row->is_value_set_explicitly(HistoryAndBookmarkRow::CREATED))
65         visit_count++;
66       if (row->is_value_set_explicitly(HistoryAndBookmarkRow::LAST_VISIT_TIME))
67         visit_count++;
68     }
69     url_row.set_visit_count(visit_count);
70   }
71 
72   URLID new_id = url_db_->AddURL(url_row);
73 
74   // The subsequent inserts need this information.
75   row->set_url_id(new_id);
76   return new_id;
77 }
78 
79 // Only the title, the visit time and the vist count can be updated, since the
80 // visit count and the visit time are related. If they are not both specified,
81 // The not specified one will be adjusted according the speficied one. The rule
82 // is:
83 // a. If the visit time changed and the visit count is not specified, the visit
84 //    count will be increased by one.
85 // b. If the visit count increased and the visit time is not specified, the last
86 //    visit time is set to Now.
87 // c. If the visit count is 0, it means clear the history, the last visit time
88 //    will be set to 0.
89 // d. The new visit time should great than or equal to the current one,
90 //    otherwise update failed.
91 // e. The title is free to update.
92 //
Update(const HistoryAndBookmarkRow & row,const TableIDRows & ids_set)93 bool UrlsSQLHandler::Update(const HistoryAndBookmarkRow& row,
94                             const TableIDRows& ids_set) {
95   // Directly updating the URL is not allowed, we should insert the new URL
96   // and remove the older one.
97   DCHECK(!row.is_value_set_explicitly(HistoryAndBookmarkRow::URL));
98 
99   for (TableIDRows::const_iterator ids = ids_set.begin();
100        ids != ids_set.end(); ++ids) {
101     URLRow url_row;
102     if (!url_db_->GetURLRow(ids->url_id, &url_row))
103       return false;
104 
105     URLRow update_row = url_row;
106 
107     if (row.is_value_set_explicitly(HistoryAndBookmarkRow::TITLE))
108       update_row.set_title(row.title());
109 
110     if (row.is_value_set_explicitly(HistoryAndBookmarkRow::VISIT_COUNT))
111       update_row.set_visit_count(row.visit_count());
112 
113     if (row.is_value_set_explicitly(HistoryAndBookmarkRow::LAST_VISIT_TIME)) {
114       // The new last_visit_time can't be less than current one.
115       if (row.last_visit_time() < url_row.last_visit())
116         return false;
117       update_row.set_last_visit(row.last_visit_time());
118     }
119 
120     // Adjust the visit_count if it not set.
121     if (!row.is_value_set_explicitly(HistoryAndBookmarkRow::VISIT_COUNT) &&
122         row.is_value_set_explicitly(HistoryAndBookmarkRow::LAST_VISIT_TIME) &&
123         (row.last_visit_time() != url_row.last_visit()))
124           // If last visit time is changed, visit count needs increase by 1,
125           // as a row will be added in visit database
126       update_row.set_visit_count(url_row.visit_count() + 1);
127 
128     // Adjust the last_vsit_time if it not set.
129     if (!row.is_value_set_explicitly(HistoryAndBookmarkRow::LAST_VISIT_TIME)) {
130       if (row.is_value_set_explicitly(HistoryAndBookmarkRow::VISIT_COUNT) &&
131           row.visit_count() == 0) {
132         // User want to clear history
133         update_row.set_last_visit(Time());
134       } else if (row.visit_count() > url_row.visit_count()) {
135         update_row.set_last_visit(Time::Now());
136       }
137     }
138 
139     if (!url_db_->UpdateURLRow(ids->url_id, update_row))
140       return false;
141   }
142   return true;
143 }
144 
Delete(const TableIDRows & ids_set)145 bool UrlsSQLHandler::Delete(const TableIDRows& ids_set) {
146   for (TableIDRows::const_iterator ids = ids_set.begin();
147        ids != ids_set.end(); ++ids) {
148     if (!url_db_->DeleteURLRow(ids->url_id))
149       return false;
150   }
151   return true;
152 }
153 
154 }  // namespace history
155