OLD | NEW |
---|---|
(Empty) | |
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 "base/files/file_path.h" | |
6 #include "base/json/json_string_value_serializer.h" | |
7 #include "base/logging.h" | |
8 #include "base/string16.h" | |
9 #include "chrome/common/extensions/extension.h" | |
10 #include "chrome/browser/extensions/activity_log/activity_database.h" | |
11 #include "chrome/browser/extensions/activity_log/api_actions.h" | |
12 #include "chrome/browser/extensions/activity_log/blocked_actions.h" | |
13 #include "chrome/browser/extensions/activity_log/dom_actions.h" | |
14 #include "chrome/browser/extensions/activity_log/fullstream_ui_policy.h" | |
15 #include "chrome/browser/profiles/profile.h" | |
16 #include "chrome/common/chrome_constants.h" | |
17 #include "googleurl/src/gurl.h" | |
18 #include "sql/error_delegate_util.h" | |
19 | |
20 using namespace base; | |
21 using namespace content; | |
22 | |
23 namespace extensions { | |
24 | |
25 // TODO(dbabic) This would be a fine error handler for all sql-based policies, | |
26 // so it would make sense to introduce another class in the hierarchy, | |
27 // SQLiteBasedPolicy as a super class of FullStreamUIPolicy and move this | |
28 // error handler (as well as other SQLite-related functionality) there. | |
29 | |
30 // This handles errors from the database. | |
31 class KillActivityDatabaseErrorDelegate : public sql::ErrorDelegate { | |
32 public: | |
33 explicit KillActivityDatabaseErrorDelegate(FullStreamUIPolicy* backend) | |
34 : backend_(backend), | |
35 scheduled_death_(false) {} | |
36 | |
37 virtual int OnError(int error, | |
38 sql::Connection* connection, | |
39 sql::Statement* stmt) OVERRIDE { | |
40 if (!scheduled_death_ && sql::IsErrorCatastrophic(error)) { | |
41 ScheduleDeath(); | |
42 } | |
43 return error; | |
44 } | |
45 | |
46 // Schedules death if an error wasn't already reported. | |
47 void ScheduleDeath() { | |
48 if (!scheduled_death_) { | |
49 scheduled_death_ = true; | |
50 backend_->KillActivityLogDatabase(); | |
51 } | |
52 } | |
53 | |
54 bool scheduled_death() const { | |
55 return scheduled_death_; | |
56 } | |
57 | |
58 private: | |
59 FullStreamUIPolicy* backend_; | |
60 bool scheduled_death_; | |
61 | |
62 DISALLOW_COPY_AND_ASSIGN(KillActivityDatabaseErrorDelegate); | |
63 }; | |
64 | |
65 FullStreamUIPolicy::FullStreamUIPolicy(Profile* profile) | |
66 : ActivityLogPolicy(profile) { | |
67 // We normally dispatch DB requests to the DB thread, but the thread might | |
68 // not exist if we are under test conditions. Substitute the UI thread for | |
69 // this case. | |
70 if (BrowserThread::IsMessageLoopValid(BrowserThread::DB)) { | |
71 dispatch_thread_ = BrowserThread::DB; | |
72 } else { | |
73 LOG(ERROR) << "BrowserThread::DB does not exist, running on UI thread!"; | |
74 dispatch_thread_ = BrowserThread::UI; | |
75 } | |
76 | |
77 db_ = new ActivityDatabase(); | |
78 FilePath base_dir = profile->GetPath(); | |
felt
2013/05/22 21:17:59
Isn't this redundant with base::FilePath profile_b
dbabic
2013/05/23 01:35:04
Done. Good catch!
| |
79 FilePath database_name = base_dir.Append( | |
80 chrome::kExtensionActivityLogFilename); | |
81 KillActivityDatabaseErrorDelegate* error_delegate = | |
82 new KillActivityDatabaseErrorDelegate(this); | |
83 db_->SetErrorDelegate(error_delegate); | |
84 ScheduleAndForget(&ActivityDatabase::Init, database_name); | |
85 } | |
86 | |
87 FullStreamUIPolicy::~FullStreamUIPolicy() { | |
88 ScheduleAndForget(&ActivityDatabase::Close); | |
89 } | |
90 | |
91 // Get data as a set of key-value pairs. The keys are policy-specific. | |
92 void FullStreamUIPolicy::ReadData(const std::string& extension_id, | |
93 const int day, | |
94 const | |
95 Callback<void(scoped_ptr<std::vector<scoped_refptr<Action> > >)>& callback) | |
96 const { | |
97 | |
98 BrowserThread::PostTaskAndReplyWithResult( | |
99 dispatch_thread_, | |
100 FROM_HERE, | |
101 base::Bind(&ActivityDatabase::GetActions, | |
102 base::Unretained(db_), | |
103 extension_id, | |
104 day), | |
105 callback); | |
106 } | |
107 | |
108 void FullStreamUIPolicy::GetKey(ActivityLogPolicy::KeyType key_ty, | |
109 std::string& key) const { | |
110 switch (key_ty) { | |
111 case PARAM_KEY_REASON: | |
112 key = "fsuip.reason"; | |
113 break; | |
114 case PARAM_KEY_DOM_ACTION: | |
115 key = "fsuip.domact"; | |
116 break; | |
117 case PARAM_KEY_URL_TITLE: | |
118 key = "fsuip.urltitle"; | |
119 break; | |
120 case PARAM_KEY_DETAILS_STRING: | |
121 key = "fsuip.details"; | |
122 break; | |
123 default: | |
124 key = ""; | |
125 } | |
126 } | |
127 | |
128 void FullStreamUIPolicy::KillActivityLogDatabase() { | |
129 ScheduleAndForget(&ActivityDatabase::KillDatabase); | |
130 } | |
131 | |
132 void FullStreamUIPolicy::ProcessArguments( | |
133 const base::ListValue* args, | |
134 std::stringstream& processed_args) const { | |
felt
2013/05/22 21:17:59
Style guide says not to use stringstreams. Can you
dbabic
2013/05/23 01:35:04
String concatenation, as implemented in MakeArgLis
felt
2013/05/23 04:20:01
Why is MakeArgList quadratic in the size of the st
| |
135 if (args) { | |
136 ListValue::const_iterator it = args->begin(); | |
137 for (; it != args->end(); ++it) { | |
138 std::string arg; | |
139 JSONStringValueSerializer serializer(&arg); | |
140 if (serializer.SerializeAndOmitBinaryValues(**it)) { | |
141 if (it != args->begin()) { | |
142 processed_args << ", "; | |
143 } | |
144 processed_args << arg; | |
145 } | |
146 } | |
147 } | |
148 } | |
149 | |
150 void FullStreamUIPolicy::DoProcessAction( | |
151 ActionType action_ty, | |
152 const Extension& extension, | |
153 const std::string& name, | |
154 const GURL* url_param, | |
155 const base::ListValue* args, | |
156 const base::DictionaryValue* details) { | |
157 | |
158 std::stringstream concatenated_args; | |
159 ProcessArguments(args, concatenated_args); | |
160 const Time now = Time::Now(); | |
161 // TODO(dbabic,felt) Drop the dummy string in the next revision | |
162 const std::string dummy; | |
163 GURL url_obj; | |
164 if (url_param) { | |
165 url_obj = *url_param; | |
166 } | |
167 scoped_refptr<Action> action; | |
168 | |
169 switch (action_ty) { | |
170 case ACTION_API: { | |
171 action = new APIAction( | |
172 extension.id(), | |
173 now, | |
174 APIAction::CALL, | |
175 name, | |
176 concatenated_args.str(), | |
177 dummy /* TODO(dbabic,felt) Drop in the next revision */); | |
178 break; | |
179 } | |
180 case ACTION_EVENT: { | |
181 action = new APIAction( | |
182 extension.id(), | |
183 now, | |
184 APIAction::EVENT_CALLBACK, | |
185 name, | |
186 concatenated_args.str(), | |
187 dummy /* TODO(dbabic,felt) Drop in the next revision */); | |
188 break; | |
189 } | |
190 case ACTION_BLOCKED: { | |
191 std::string key; | |
192 int reason = 0; | |
193 if (details) { | |
194 GetKey(PARAM_KEY_REASON, key); | |
195 details->GetInteger(key, &reason); | |
196 } | |
197 | |
198 action = new BlockedAction( | |
199 extension.id(), | |
200 now, | |
201 name, | |
202 concatenated_args.str(), | |
203 static_cast<BlockedAction::Reason>(reason), | |
204 dummy /* TODO(dbabic,felt) Drop in the next revision */); | |
205 break; | |
206 } | |
207 case ACTION_DOM: { | |
208 std::string key; | |
209 string16 value; | |
210 DOMAction::DOMActionType action_ty = DOMAction::MODIFIED; | |
211 | |
212 if (details) { | |
213 int action_id = 0; | |
214 GetKey(PARAM_KEY_DOM_ACTION, key); | |
215 details->GetInteger(key, &action_id); | |
216 action_ty = static_cast<DOMAction::DOMActionType>(action_id); | |
217 GetKey(PARAM_KEY_URL_TITLE, key); | |
218 details->GetString(key, &value); | |
219 } | |
220 | |
221 action = new DOMAction( | |
222 extension.id(), | |
223 now, | |
224 action_ty, | |
225 url_obj, | |
226 value, | |
227 name, | |
228 concatenated_args.str(), | |
229 dummy /* TODO(dbabic,felt) Drop in the next revision */); | |
230 break; | |
231 } | |
232 case ACTION_WEB_REQUEST: { | |
233 std::string key; | |
234 std::string details_string; | |
235 if (details) { | |
236 GetKey(PARAM_KEY_DETAILS_STRING, key); | |
237 details->GetString(key, &details_string); | |
238 } | |
239 | |
240 action = new DOMAction( | |
241 extension.id(), | |
242 now, | |
243 DOMAction::WEBREQUEST, | |
244 url_obj, | |
245 string16(), | |
246 name, | |
247 details_string, | |
248 dummy /* TODO(dbabic,felt) Drop in the next revision */); | |
249 break; | |
250 } | |
251 case ACTION_ON_SCRIPTS: { | |
252 std::string key; | |
253 string16 value; | |
254 if (details) { | |
255 GetKey(PARAM_KEY_URL_TITLE, key); | |
256 details->GetString(key, &value); | |
257 } | |
258 | |
259 action = new DOMAction( | |
260 extension.id(), | |
261 now, | |
262 DOMAction::INSERTED, | |
263 url_obj, | |
264 value, | |
265 name, | |
266 concatenated_args.str(), | |
267 dummy /* TODO(dbabic,felt) Drop in the next revision */); | |
268 break; | |
269 } | |
270 default: | |
271 CHECK(false && "Unknown action type."); | |
272 } | |
273 | |
274 ScheduleAndForget(&ActivityDatabase::RecordAction, action); | |
275 } | |
276 | |
277 } // End of the extensions namespace | |
OLD | NEW |