Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(15)

Side by Side Diff: chrome/browser/extensions/activity_log/api_actions.cc

Issue 19690003: Extension activity log database refactoring (step 3) (Closed) Base URL: http://git.chromium.org/chromium/src.git@refactor2
Patch Set: Do not set bad BlockedChromeActivityDetail::Reason values Created 7 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(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/json/json_string_value_serializer.h"
6 #include "base/logging.h"
7 #include "base/memory/singleton.h"
8 #include "base/strings/string_number_conversions.h"
9 #include "base/strings/stringprintf.h"
10 #include "chrome/browser/extensions/activity_log/api_actions.h"
11 #include "chrome/browser/extensions/activity_log/api_name_constants.h"
12 #include "chrome/browser/extensions/activity_log/fullstream_ui_policy.h"
13 #include "chrome/browser/extensions/extension_tab_util.h"
14 #include "chrome/browser/ui/browser.h"
15 #include "content/public/browser/browser_thread.h"
16 #include "content/public/browser/web_contents.h"
17 #include "url/gurl.h"
18
19 using content::BrowserThread;
20
21 namespace {
22
23 // Gets the URL for a given tab ID. Helper method for APIAction::LookupTabId.
24 std::string GetURLForTabId(const int tab_id, Profile* profile) {
25 content::WebContents* contents = NULL;
26 Browser* browser = NULL;
27 bool found = ExtensionTabUtil::GetTabById(tab_id,
28 profile,
29 true, // search incognito tabs too
30 &browser,
31 NULL,
32 &contents,
33 NULL);
34 if (found) {
35 // Check whether the profile the tab was found in is a normal or incognito
36 // profile.
37 if (!browser->profile()->IsOffTheRecord()) {
38 GURL url = contents->GetURL();
39 return std::string(url.spec());
40 } else {
41 return std::string(extensions::APIAction::kIncognitoUrl);
42 }
43 } else {
44 return std::string();
45 }
46 }
47
48 // Sets up the hashmap for mapping extension strings to "ints". The hashmap is
49 // only set up once because it's quite long; the value is then cached.
50 class APINameMap {
51 public:
52 APINameMap() {
53 SetupMap();
54 }
55
56 // activity_log_api_name_constants.h lists all known API calls as of 5/17.
57 // This code maps each of those API calls (and events) to short strings
58 // (integers converted to strings). They're all strings because (1) sqlite
59 // databases are all strings underneath anyway and (2) the Lookup function
60 // will simply return the original api_call string if we don't have it in our
61 // lookup table.
62 void SetupMap() {
63 for (size_t i = 0;
64 i < arraysize(activity_log_api_name_constants::kNames);
65 ++i) {
66 std::string name =
67 std::string(activity_log_api_name_constants::kNames[i]);
68 std::string num = base::IntToString(i);
69 names_to_nums_[name] = num;
70 nums_to_names_[num] = name;
71 }
72 }
73
74 static APINameMap* GetInstance() {
75 return Singleton<APINameMap>::get();
76 }
77
78 // This matches an api call to a number, if it's in the lookup table. If not,
79 // it returns the original api call.
80 const std::string& ApiToShortname(const std::string& api_call) {
81 std::map<std::string, std::string>::iterator it =
82 names_to_nums_.find(api_call);
83 if (it == names_to_nums_.end())
84 return api_call;
85 else
86 return it->second;
87 }
88
89 // This matches a number to an API call -- it's the opposite of
90 // ApiToShortname.
91 const std::string& ShortnameToApi(const std::string& shortname) {
92 std::map<std::string, std::string>::iterator it =
93 nums_to_names_.find(shortname);
94 if (it == nums_to_names_.end())
95 return shortname;
96 else
97 return it->second;
98 }
99
100 private:
101 std::map<std::string, std::string> names_to_nums_; // <name, number label>
102 std::map<std::string, std::string> nums_to_names_; // <number label, name>
103 };
104
105 std::string Serialize(const base::Value& value) {
106 std::string value_as_text;
107 JSONStringValueSerializer serializer(&value_as_text);
108 serializer.SerializeAndOmitBinaryValues(value);
109 return value_as_text;
110 }
111
112 } // namespace
113
114 namespace extensions {
115
116 using api::activity_log_private::ExtensionActivity;
117 using api::activity_log_private::DomActivityDetail;
118 using api::activity_log_private::ChromeActivityDetail;
119 using api::activity_log_private::BlockedChromeActivityDetail;
120
121 // We should log the arguments to these API calls, even if argument logging is
122 // disabled by default.
123 const char* APIAction::kAlwaysLog[] =
124 {"extension.connect", "extension.sendMessage",
125 "tabs.executeScript", "tabs.insertCSS" };
126 const int APIAction::kSizeAlwaysLog = arraysize(kAlwaysLog);
127
128 // A string used in place of the real URL when the URL is hidden because it is
129 // in an incognito window. Extension activity logs mentioning kIncognitoUrl
130 // let the user know that an extension is manipulating incognito tabs without
131 // recording specific data about the pages.
132 const char* APIAction::kIncognitoUrl = "http://incognito/";
133
134 APIAction::APIAction(const std::string& extension_id,
135 const base::Time& time,
136 const Type type,
137 const std::string& api_call,
138 const std::string& args,
139 const base::ListValue& args_list,
140 const std::string& extra)
141 : Action(extension_id, time, ExtensionActivity::ACTIVITY_TYPE_CHROME),
142 type_(type),
143 api_call_(api_call),
144 args_(args),
145 args_list_(args_list.DeepCopy()),
146 extra_(extra) { }
147
148 APIAction::~APIAction() {
149 }
150
151 scoped_ptr<ExtensionActivity> APIAction::ConvertToExtensionActivity() {
152 scoped_ptr<ExtensionActivity> formatted_activity;
153 formatted_activity.reset(new ExtensionActivity);
154 formatted_activity->extension_id.reset(
155 new std::string(extension_id()));
156 formatted_activity->activity_type = activity_type();
157 formatted_activity->time.reset(new double(time().ToJsTime()));
158 ChromeActivityDetail* details = new ChromeActivityDetail;
159 details->api_activity_type = ChromeActivityDetail::ParseApiActivityType(
160 TypeAsString());
161 details->api_call.reset(new std::string(api_call_));
162 details->args.reset(new std::string(args_));
163 details->extra.reset(new std::string(extra_));
164 formatted_activity->chrome_activity_detail.reset(details);
165 return formatted_activity.Pass();
166 }
167
168 bool APIAction::Record(sql::Connection* db) {
169 std::string sql_str =
170 "INSERT INTO " + std::string(FullStreamUIPolicy::kTableName) +
171 " (extension_id, time, action_type, api_name, args) VALUES"
172 " (?,?,?,?,?)";
173 sql::Statement statement(db->GetCachedStatement(
174 sql::StatementID(SQL_FROM_HERE), sql_str.c_str()));
175 statement.BindString(0, extension_id());
176 statement.BindInt64(1, time().ToInternalValue());
177 switch (type_) {
178 case CALL:
179 statement.BindInt(2, static_cast<int>(Action::ACTION_API_CALL));
180 break;
181 case EVENT_CALLBACK:
182 statement.BindInt(2, static_cast<int>(Action::ACTION_API_EVENT));
183 break;
184 default:
185 LOG(ERROR) << "Invalid action type: " << type_;
186 return false;
187 }
188 statement.BindString(3, api_call_);
189 statement.BindString(4, Serialize(*args_list_));
190 if (!statement.Run()) {
191 LOG(ERROR) << "Activity log database I/O failed: " << sql_str;
192 statement.Clear();
193 return false;
194 }
195 return true;
196 }
197
198 // static
199 void APIAction::LookupTabId(const std::string& api_call,
200 base::ListValue* args,
201 Profile* profile) {
202 if (api_call == "tabs.get" || // api calls, ID as int
203 api_call == "tabs.connect" ||
204 api_call == "tabs.sendMessage" ||
205 api_call == "tabs.duplicate" ||
206 api_call == "tabs.update" ||
207 api_call == "tabs.reload" ||
208 api_call == "tabs.detectLanguage" ||
209 api_call == "tabs.executeScript" ||
210 api_call == "tabs.insertCSS" ||
211 api_call == "tabs.move" || // api calls, IDs in array
212 api_call == "tabs.remove" ||
213 api_call == "tabs.onUpdated" || // events, ID as int
214 api_call == "tabs.onMoved" ||
215 api_call == "tabs.onDetached" ||
216 api_call == "tabs.onAttached" ||
217 api_call == "tabs.onRemoved" ||
218 api_call == "tabs.onReplaced") {
219 int tab_id;
220 base::ListValue* id_list;
221 if (args->GetInteger(0, &tab_id)) {
222 std::string url = GetURLForTabId(tab_id, profile);
223 if (url != std::string())
224 args->Set(0, new base::StringValue(url));
225 } else if ((api_call == "tabs.move" || api_call == "tabs.remove") &&
226 args->GetList(0, &id_list)) {
227 for (int i = 0; i < static_cast<int>(id_list->GetSize()); ++i) {
228 if (id_list->GetInteger(i, &tab_id)) {
229 std::string url = GetURLForTabId(tab_id, profile);
230 if (url != std::string())
231 id_list->Set(i, new base::StringValue(url));
232 } else {
233 LOG(ERROR) << "The tab ID array is malformed at index " << i;
234 }
235 }
236 }
237 }
238 }
239
240 std::string APIAction::PrintForDebug() {
241 return "ID: " + extension_id() + ", CATEGORY: " + TypeAsString() +
242 ", API: " + api_call_ + ", ARGS: " + args_;
243 }
244
245 std::string APIAction::TypeAsString() const {
246 switch (type_) {
247 case CALL:
248 return "call";
249 case EVENT_CALLBACK:
250 return "event_callback";
251 default:
252 return "unknown_type";
253 }
254 }
255
256 } // namespace extensions
257
OLDNEW
« no previous file with comments | « chrome/browser/extensions/activity_log/api_actions.h ('k') | chrome/browser/extensions/activity_log/blocked_actions.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698