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