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

Unified Diff: chrome/browser/extensions/activity_log/activity_log.cc

Issue 23545012: [Activity log] Rework extraction of URLs from argument lists (Closed) Base URL: http://git.chromium.org/chromium/src.git@master
Patch Set: Delete dead code Created 7 years, 3 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 side-by-side diff with in-line comments
Download patch
Index: chrome/browser/extensions/activity_log/activity_log.cc
diff --git a/chrome/browser/extensions/activity_log/activity_log.cc b/chrome/browser/extensions/activity_log/activity_log.cc
index 129626b4d55979935e58a436bdf24b783c9a2ec3..247e534906b7fd5e04e1b340c94b3570f9b826ca 100644
--- a/chrome/browser/extensions/activity_log/activity_log.cc
+++ b/chrome/browser/extensions/activity_log/activity_log.cc
@@ -40,23 +40,114 @@ namespace constants = activity_log_constants;
namespace {
-// Concatenate arguments.
-std::string MakeArgList(const base::ListValue* args) {
- std::string call_signature;
- base::ListValue::const_iterator it = args->begin();
- for (; it != args->end(); ++it) {
- std::string arg;
- JSONStringValueSerializer serializer(&arg);
- if (serializer.SerializeAndOmitBinaryValues(**it)) {
- if (it != args->begin())
- call_signature += ", ";
- call_signature += arg;
+using extensions::Action;
+using constants::kArgUrlPlaceholder;
+
+// Specifies a possible action to take to get an extracted URL in the ApiInfo
+// structure below.
+enum Transformation {
+ NONE,
+ DICT_LOOKUP,
+ LOOKUP_TAB_ID,
+};
+
+// Information about specific Chrome and DOM APIs, such as which contain
+// arguments that should be extracted into the arg_url field of an Action.
+struct ApiInfo {
+ // The lookup key consists of the action_type and api_name in the Action
+ // object.
+ Action::ActionType action_type;
+ const char* api_name;
+
+ // If non-negative, an index into args might contain a URL to be extracted
+ // into arg_url.
+ int arg_url_index;
+
+ // A transformation to apply to the data found at index arg_url_index in the
+ // argument list.
+ //
+ // If NONE, the data is expected to be a string which is treated as a URL.
+ //
+ // If LOOKUP_TAB_ID, the data is either an integer which is treated as a tab
+ // ID and translated (in the context of a provided Profile), or a list of tab
+ // IDs which are translated.
+ //
+ // If DICT_LOOKUP, the data is expected to be a dictionary, and
+ // arg_url_dict_path is a path (list of keys delimited by ".") where a URL
+ // string is to be found.
+ Transformation arg_url_transform;
+ const char* arg_url_dict_path;
+};
+
+static const ApiInfo kApiInfoTable[] = {
+ // Tabs APIs that require tab ID translation
+ {Action::ACTION_API_CALL, "tabs.connect", 0, LOOKUP_TAB_ID, NULL},
+ {Action::ACTION_API_CALL, "tabs.detectLanguage", 0, LOOKUP_TAB_ID, NULL},
+ {Action::ACTION_API_CALL, "tabs.duplicate", 0, LOOKUP_TAB_ID, NULL},
+ {Action::ACTION_API_CALL, "tabs.executeScript", 0, LOOKUP_TAB_ID, NULL},
+ {Action::ACTION_API_CALL, "tabs.get", 0, LOOKUP_TAB_ID, NULL},
+ {Action::ACTION_API_CALL, "tabs.insertCSS", 0, LOOKUP_TAB_ID, NULL},
+ {Action::ACTION_API_CALL, "tabs.move", 0, LOOKUP_TAB_ID, NULL},
+ {Action::ACTION_API_CALL, "tabs.reload", 0, LOOKUP_TAB_ID, NULL},
+ {Action::ACTION_API_CALL, "tabs.remove", 0, LOOKUP_TAB_ID, NULL},
+ {Action::ACTION_API_CALL, "tabs.sendMessage", 0, LOOKUP_TAB_ID, NULL},
+ {Action::ACTION_API_CALL, "tabs.update", 0, LOOKUP_TAB_ID, NULL},
+
+ {Action::ACTION_API_EVENT, "tabs.onUpdated", 0, LOOKUP_TAB_ID, NULL},
+ {Action::ACTION_API_EVENT, "tabs.onMoved", 0, LOOKUP_TAB_ID, NULL},
+ {Action::ACTION_API_EVENT, "tabs.onDetached", 0, LOOKUP_TAB_ID, NULL},
+ {Action::ACTION_API_EVENT, "tabs.onAttached", 0, LOOKUP_TAB_ID, NULL},
+ {Action::ACTION_API_EVENT, "tabs.onRemoved", 0, LOOKUP_TAB_ID, NULL},
+ {Action::ACTION_API_EVENT, "tabs.onReplaced", 0, LOOKUP_TAB_ID, NULL},
+
+ // Other APIs that accept URLs as strings
+ {Action::ACTION_API_CALL, "windows.create", 0, DICT_LOOKUP, "url"},
+
+ {Action::ACTION_DOM_ACCESS, "Location.assign", 0, NONE, NULL},
+ {Action::ACTION_DOM_ACCESS, "Location.replace", 0, NONE, NULL},
+ {Action::ACTION_DOM_ACCESS, "XMLHttpRequest.open", 1, NONE, NULL},
+};
+
+// A singleton class which provides lookups into the kApiInfoTable data
+// structure. It inserts all data into a map on first lookup.
+class ApiInfoDatabase {
+ public:
+ static ApiInfoDatabase* GetInstance() {
+ return Singleton<ApiInfoDatabase>::get();
+ }
+
+ // Retrieves an ApiInfo record for the given Action type. Returns either a
+ // pointer to the record, or NULL if no such record was found.
+ const ApiInfo* Lookup(Action::ActionType action_type,
+ const std::string& api_name) const {
+ std::map<std::string, const ApiInfo*>::const_iterator i =
+ api_database_.find(api_name);
+ if (i == api_database_.end())
+ return NULL;
+ if (i->second->action_type != action_type)
+ return NULL;
+ return i->second;
+ }
+
+ private:
+ ApiInfoDatabase() {
+ for (size_t i = 0; i < arraysize(kApiInfoTable); i++) {
+ const ApiInfo* info = &kApiInfoTable[i];
+ api_database_[info->api_name] = info;
}
}
- return call_signature;
-}
+ virtual ~ApiInfoDatabase() {}
+
+ // The map is keyed by API name only, since API names aren't be repeated
+ // across multiple action types in kApiInfoTable. However, the action type
+ // should still be checked before returning a positive match.
+ std::map<std::string, const ApiInfo*> api_database_;
-// Gets the URL for a given tab ID. Helper method for LookupTabId. Returns
+ friend struct DefaultSingletonTraits<ApiInfoDatabase>;
+ DISALLOW_COPY_AND_ASSIGN(ApiInfoDatabase);
+};
+
+// Gets the URL for a given tab ID. Helper method for ExtractUrls. Returns
// true if able to perform the lookup. The URL is stored to *url, and
// *is_incognito is set to indicate whether the URL is for an incognito tab.
bool GetUrlForTabId(int tab_id,
@@ -81,66 +172,94 @@ bool GetUrlForTabId(int tab_id,
}
}
-// Translate tab IDs to URLs in tabs API calls. Mutates the Action object in
-// place. There is a small chance that the URL translation could be wrong, if
-// the tab has already been navigated by the time of invocation.
+// Performs processing of the Action object to extract URLs from the argument
+// list and translate tab IDs to URLs, according to the API call metadata in
+// kApiInfoTable. Mutates the Action object in place. There is a small chance
+// that the tab id->URL translation could be wrong, if the tab has already been
+// navigated by the time of invocation.
//
-// If a single tab ID is translated to a URL, the URL is stored into arg_url
-// where it can more easily be searched for in the database. For APIs that
-// take a list of tab IDs, replace each tab ID with the URL in the argument
-// list; we can only extract a single URL into arg_url so arbitrarily pull out
-// the first one.
-void LookupTabIds(scoped_refptr<extensions::Action> action, Profile* profile) {
- const std::string& api_call = action->api_name();
- if (api_call == "tabs.get" || // api calls, ID as int
- api_call == "tabs.connect" ||
- api_call == "tabs.sendMessage" ||
- api_call == "tabs.duplicate" ||
- api_call == "tabs.update" ||
- api_call == "tabs.reload" ||
- api_call == "tabs.detectLanguage" ||
- api_call == "tabs.executeScript" ||
- api_call == "tabs.insertCSS" ||
- api_call == "tabs.move" || // api calls, IDs in array
- api_call == "tabs.remove" ||
- api_call == "tabs.onUpdated" || // events, ID as int
- api_call == "tabs.onMoved" ||
- api_call == "tabs.onDetached" ||
- api_call == "tabs.onAttached" ||
- api_call == "tabs.onRemoved" ||
- api_call == "tabs.onReplaced") {
+// Any extracted URL is stored into the arg_url field of the action, and the
+// URL in the argument list is replaced with the marker value "<arg_url>". For
+// APIs that take a list of tab IDs, extracts the first valid URL into arg_url
+// and overwrites the other tab IDs in the argument list with the translated
+// URL.
+void ExtractUrls(scoped_refptr<Action> action, Profile* profile) {
+ const ApiInfo* api_info = ApiInfoDatabase::GetInstance()->Lookup(
+ action->action_type(), action->api_name());
+ if (api_info == NULL)
+ return;
+
+ int url_index = api_info->arg_url_index;
+
+ if (!action->args() || url_index < 0 ||
not at google - send to devlin 2013/09/06 22:05:05 it doesn't seem that url_index can ever be < 0.
mvrable 2013/09/06 22:32:49 Not currently. I was leaving that as an option (d
+ static_cast<size_t>(url_index) >= action->args()->GetSize())
+ return;
+
+ // Do not overwrite an existing arg_url value in the Action, so that callers
+ // have the option of doing custom arg_url extraction.
+ if (action->arg_url().is_valid())
+ return;
+
+ GURL arg_url;
+ bool arg_incognito = action->page_incognito();
+
+ if (api_info->arg_url_transform == NONE) {
not at google - send to devlin 2013/09/06 22:05:05 use switch
mvrable 2013/09/06 22:32:49 Done.
+ // No translation needed; just extract the URL directly from a raw string
+ // or from a dictionary.
+ std::string url_string;
+ if (action->args()->GetString(url_index, &url_string)) {
+ arg_url = GURL(url_string);
+ if (arg_url.is_valid()) {
+ action->mutable_args()->Set(url_index,
+ new StringValue(kArgUrlPlaceholder));
+ }
+ }
+ } else if (api_info->arg_url_transform == DICT_LOOKUP) {
+ // Look up the URL from a dictionary at the specified location.
+ DictionaryValue* dict = NULL;
+ std::string url_string;
+ CHECK(api_info->arg_url_dict_path);
+
+ if (action->mutable_args()->GetDictionary(url_index, &dict) &&
+ dict->GetString(api_info->arg_url_dict_path, &url_string)) {
+ arg_url = GURL(url_string);
+ if (arg_url.is_valid())
+ dict->SetString(api_info->arg_url_dict_path, kArgUrlPlaceholder);
+ }
+ } else if (api_info->arg_url_transform == LOOKUP_TAB_ID) {
+ // Translation of tab IDs to URLs has been requested. There are two cases
+ // to consider: either a single integer or a list of integers (when
+ // multiple tabs are manipulated).
int tab_id;
- base::ListValue* id_list;
- base::ListValue* args = action->mutable_args();
- if (args->GetInteger(0, &tab_id)) {
+ base::ListValue* tab_list = NULL;
+ if (action->args()->GetInteger(url_index, &tab_id)) {
// Single tab ID to translate.
- GURL url;
- bool is_incognito;
- if (GetUrlForTabId(tab_id, profile, &url, &is_incognito)) {
- action->set_arg_url(url);
- action->set_arg_incognito(is_incognito);
+ GetUrlForTabId(tab_id, profile, &arg_url, &arg_incognito);
+ if (arg_url.is_valid()) {
+ action->mutable_args()->Set(url_index,
+ new StringValue(kArgUrlPlaceholder));
}
- } else if ((api_call == "tabs.move" || api_call == "tabs.remove") &&
- args->GetList(0, &id_list)) {
- // Array of tab IDs to translate.
- for (int i = 0; i < static_cast<int>(id_list->GetSize()); ++i) {
- if (id_list->GetInteger(i, &tab_id)) {
- GURL url;
- bool is_incognito;
- if (GetUrlForTabId(tab_id, profile, &url, &is_incognito) &&
- !is_incognito) {
- id_list->Set(i, new base::StringValue(url.spec()));
- if (i == 0) {
- action->set_arg_url(url);
- action->set_arg_incognito(is_incognito);
- }
- }
- } else {
- LOG(ERROR) << "The tab ID array is malformed at index " << i;
+ } else if (action->mutable_args()->GetList(url_index, &tab_list)) {
+ // A list of possible IDs to translate. Work through in reverse order
+ // so the last one translated is left in arg_url.
+ int extracted_index = -1; // Which item in the list is stored to arg_url?
+ for (int i = tab_list->GetSize() - 1; i >= 0; --i) {
+ if (tab_list->GetInteger(i, &tab_id) &&
+ GetUrlForTabId(tab_id, profile, &arg_url, &arg_incognito)) {
+ if (!arg_incognito)
+ tab_list->Set(i, new base::StringValue(arg_url.spec()));
+ extracted_index = i;
}
}
+ if (extracted_index >= 0)
+ tab_list->Set(extracted_index, new StringValue(kArgUrlPlaceholder));
}
}
+
+ if (arg_url.is_valid()) {
+ action->set_arg_incognito(arg_incognito);
+ action->set_arg_url(arg_url);
+ }
}
} // namespace
@@ -352,11 +471,7 @@ void ActivityLog::LogAction(scoped_refptr<Action> action) {
// Perform some preprocessing of the Action data: convert tab IDs to URLs and
// mask out incognito URLs if appropriate.
- if ((action->action_type() == Action::ACTION_API_CALL ||
- action->action_type() == Action::ACTION_API_EVENT) &&
- StartsWithASCII(action->api_name(), "tabs.", true)) {
- LookupTabIds(action, profile_);
- }
+ ExtractUrls(action, profile_);
if (IsDatabaseEnabled() && policy_)
policy_->ProcessAction(action);

Powered by Google App Engine
This is Rietveld 408576698