blob: 8d66064324e24d0699430d6776312ecbe332b933 [file] [log] [blame]
// Copyright 2013 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chrome/browser/extensions/api/activity_log_private/activity_log_private_api.h"
#include <stddef.h>
#include <stdint.h>
#include <memory>
#include <utility>
#include "base/bind.h"
#include "base/lazy_instance.h"
#include "base/strings/string_number_conversions.h"
#include "base/values.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/extensions/event_router_forwarder.h"
#include "chrome/browser/extensions/extension_service.h"
#include "chrome/common/extensions/api/activity_log_private.h"
#include "components/prefs/pref_service.h"
#include "content/public/browser/browser_context.h"
#include "extensions/browser/extension_system_provider.h"
#include "extensions/browser/extensions_browser_client.h"
#include "extensions/common/features/feature.h"
#include "extensions/common/features/feature_provider.h"
#include "extensions/common/hashed_extension_id.h"
namespace extensions {
namespace activity_log_private = api::activity_log_private;
using activity_log_private::ActivityResultSet;
using activity_log_private::ExtensionActivity;
using activity_log_private::Filter;
static base::LazyInstance<BrowserContextKeyedAPIFactory<ActivityLogAPI>>::
DestructorAtExit g_activity_log_private_api_factory =
LAZY_INSTANCE_INITIALIZER;
// static
BrowserContextKeyedAPIFactory<ActivityLogAPI>*
ActivityLogAPI::GetFactoryInstance() {
return g_activity_log_private_api_factory.Pointer();
}
template <>
void
BrowserContextKeyedAPIFactory<ActivityLogAPI>::DeclareFactoryDependencies() {
DependsOn(ExtensionsBrowserClient::Get()->GetExtensionSystemFactory());
DependsOn(ActivityLog::GetFactoryInstance());
}
ActivityLogAPI::ActivityLogAPI(content::BrowserContext* context)
: browser_context_(context), initialized_(false) {
if (!EventRouter::Get(browser_context_)) { // Check for testing.
DVLOG(1) << "ExtensionSystem event_router does not exist.";
return;
}
activity_log_ = extensions::ActivityLog::GetInstance(browser_context_);
DCHECK(activity_log_);
EventRouter::Get(browser_context_)->RegisterObserver(
this, activity_log_private::OnExtensionActivity::kEventName);
activity_log_->AddObserver(this);
initialized_ = true;
}
ActivityLogAPI::~ActivityLogAPI() {
}
void ActivityLogAPI::Shutdown() {
if (!initialized_) { // Check for testing.
DVLOG(1) << "ExtensionSystem event_router does not exist.";
return;
}
EventRouter::Get(browser_context_)->UnregisterObserver(this);
activity_log_->RemoveObserver(this);
}
// static
bool ActivityLogAPI::IsExtensionWhitelisted(const std::string& extension_id) {
// TODO(devlin): Pass in a HashedExtensionId to avoid this conversion.
return FeatureProvider::GetPermissionFeatures()
->GetFeature("activityLogPrivate")
->IsIdInAllowlist(HashedExtensionId(extension_id));
}
void ActivityLogAPI::OnListenerAdded(const EventListenerInfo& details) {
if (activity_log_->has_listeners())
return;
StartOrStopListeningForExtensionActivities();
}
void ActivityLogAPI::OnListenerRemoved(const EventListenerInfo& details) {
StartOrStopListeningForExtensionActivities();
}
void ActivityLogAPI::StartOrStopListeningForExtensionActivities() {
EventRouter* event_router = EventRouter::Get(browser_context_);
activity_log_->SetHasListeners(event_router->HasEventListener(
activity_log_private::OnExtensionActivity::kEventName));
}
void ActivityLogAPI::OnExtensionActivity(scoped_refptr<Action> activity) {
std::unique_ptr<base::ListValue> value(new base::ListValue());
ExtensionActivity activity_arg = activity->ConvertToExtensionActivity();
value->Append(activity_arg.ToValue());
auto event = std::make_unique<Event>(
events::ACTIVITY_LOG_PRIVATE_ON_EXTENSION_ACTIVITY,
activity_log_private::OnExtensionActivity::kEventName, std::move(value),
browser_context_);
EventRouter::Get(browser_context_)->BroadcastEvent(std::move(event));
}
bool ActivityLogPrivateGetExtensionActivitiesFunction::RunAsync() {
std::unique_ptr<activity_log_private::GetExtensionActivities::Params> params(
activity_log_private::GetExtensionActivities::Params::Create(*args_));
EXTENSION_FUNCTION_VALIDATE(params);
// Get the arguments in the right format.
Filter filter = std::move(params->filter);
Action::ActionType action_type = Action::ACTION_API_CALL;
switch (filter.activity_type) {
case activity_log_private::EXTENSION_ACTIVITY_FILTER_API_CALL:
action_type = Action::ACTION_API_CALL;
break;
case activity_log_private::EXTENSION_ACTIVITY_FILTER_API_EVENT:
action_type = Action::ACTION_API_EVENT;
break;
case activity_log_private::EXTENSION_ACTIVITY_FILTER_CONTENT_SCRIPT:
action_type = Action::ACTION_CONTENT_SCRIPT;
break;
case activity_log_private::EXTENSION_ACTIVITY_FILTER_DOM_ACCESS:
action_type = Action::ACTION_DOM_ACCESS;
break;
case activity_log_private::EXTENSION_ACTIVITY_FILTER_DOM_EVENT:
action_type = Action::ACTION_DOM_EVENT;
break;
case activity_log_private::EXTENSION_ACTIVITY_FILTER_WEB_REQUEST:
action_type = Action::ACTION_WEB_REQUEST;
break;
case activity_log_private::EXTENSION_ACTIVITY_FILTER_ANY:
default:
action_type = Action::ACTION_ANY;
}
std::string extension_id =
filter.extension_id ? *filter.extension_id : std::string();
std::string api_call = filter.api_call ? *filter.api_call : std::string();
std::string page_url = filter.page_url ? *filter.page_url : std::string();
std::string arg_url = filter.arg_url ? *filter.arg_url : std::string();
int days_ago = -1;
if (filter.days_ago)
days_ago = *filter.days_ago;
// Call the ActivityLog.
ActivityLog* activity_log = ActivityLog::GetInstance(GetProfile());
DCHECK(activity_log);
activity_log->GetFilteredActions(
extension_id,
action_type,
api_call,
page_url,
arg_url,
days_ago,
base::Bind(
&ActivityLogPrivateGetExtensionActivitiesFunction::OnLookupCompleted,
this));
return true;
}
void ActivityLogPrivateGetExtensionActivitiesFunction::OnLookupCompleted(
std::unique_ptr<std::vector<scoped_refptr<Action>>> activities) {
// Convert Actions to ExtensionActivities.
std::vector<ExtensionActivity> result_arr;
for (const auto& activity : *activities)
result_arr.push_back(activity->ConvertToExtensionActivity());
// Populate the return object.
std::unique_ptr<ActivityResultSet> result_set(new ActivityResultSet);
result_set->activities = std::move(result_arr);
results_ = activity_log_private::GetExtensionActivities::Results::Create(
*result_set);
SendResponse(true);
}
ExtensionFunction::ResponseAction
ActivityLogPrivateDeleteActivitiesFunction::Run() {
std::unique_ptr<activity_log_private::DeleteActivities::Params> params(
activity_log_private::DeleteActivities::Params::Create(*args_));
EXTENSION_FUNCTION_VALIDATE(params);
// Put the arguments in the right format.
std::vector<int64_t> action_ids;
int64_t value;
for (size_t i = 0; i < params->activity_ids.size(); i++) {
if (base::StringToInt64(params->activity_ids[i], &value))
action_ids.push_back(value);
}
ActivityLog* activity_log = ActivityLog::GetInstance(browser_context());
DCHECK(activity_log);
activity_log->RemoveActions(action_ids);
return RespondNow(NoArguments());
}
ExtensionFunction::ResponseAction
ActivityLogPrivateDeleteActivitiesByExtensionFunction::Run() {
std::unique_ptr<activity_log_private::DeleteActivitiesByExtension::Params>
params(activity_log_private::DeleteActivitiesByExtension::Params::Create(
*args_));
EXTENSION_FUNCTION_VALIDATE(params);
ActivityLog* activity_log = ActivityLog::GetInstance(browser_context());
DCHECK(activity_log);
activity_log->RemoveExtensionData(params->extension_id);
return RespondNow(NoArguments());
}
ExtensionFunction::ResponseAction
ActivityLogPrivateDeleteDatabaseFunction::Run() {
ActivityLog* activity_log = ActivityLog::GetInstance(browser_context());
DCHECK(activity_log);
activity_log->DeleteDatabase();
return RespondNow(NoArguments());
}
ExtensionFunction::ResponseAction ActivityLogPrivateDeleteUrlsFunction::Run() {
std::unique_ptr<activity_log_private::DeleteUrls::Params> params(
activity_log_private::DeleteUrls::Params::Create(*args_));
EXTENSION_FUNCTION_VALIDATE(params);
// Put the arguments in the right format.
std::vector<GURL> gurls;
const std::vector<std::string>& urls = *params->urls;
for (const std::string& url : urls)
gurls.push_back(GURL(url));
ActivityLog* activity_log = ActivityLog::GetInstance(browser_context());
DCHECK(activity_log);
activity_log->RemoveURLs(gurls);
return RespondNow(NoArguments());
}
} // namespace extensions