// Copyright (c) 2011 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/activity_log/activity_log.h"

#include <stddef.h>
#include <set>
#include <utility>
#include <vector>

#include "base/command_line.h"
#include "base/json/json_string_value_serializer.h"
#include "base/lazy_instance.h"
#include "base/logging.h"
#include "base/macros.h"
#include "base/memory/ptr_util.h"
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
#include "base/synchronization/lock.h"
#include "base/threading/thread_checker.h"
#include "base/values.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/chrome_notification_types.h"
#include "chrome/browser/extensions/activity_log/activity_action_constants.h"
#include "chrome/browser/extensions/activity_log/counting_policy.h"
#include "chrome/browser/extensions/activity_log/fullstream_ui_policy.h"
#include "chrome/browser/extensions/api/activity_log_private/activity_log_private_api.h"
#include "chrome/browser/extensions/extension_tab_util.h"
#include "chrome/browser/prerender/prerender_manager.h"
#include "chrome/browser/prerender/prerender_manager_factory.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/profiles/profile_manager.h"
#include "chrome/browser/ui/browser.h"
#include "chrome/common/chrome_constants.h"
#include "chrome/common/chrome_switches.h"
#include "chrome/common/pref_names.h"
#include "components/sync_preferences/pref_service_syncable.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/notification_service.h"
#include "content/public/browser/notification_source.h"
#include "content/public/browser/render_process_host.h"
#include "content/public/browser/web_contents.h"
#include "extensions/browser/api_activity_monitor.h"
#include "extensions/browser/extension_registry.h"
#include "extensions/browser/extension_registry_factory.h"
#include "extensions/browser/extension_system.h"
#include "extensions/browser/extension_system_provider.h"
#include "extensions/browser/extensions_browser_client.h"
#include "extensions/common/extension.h"
#include "extensions/common/extension_messages.h"
#include "extensions/common/one_shot_event.h"
#include "third_party/re2/src/re2/re2.h"
#include "url/gurl.h"

namespace constants = activity_log_constants;

namespace extensions {

namespace {

using constants::kArgUrlPlaceholder;
using content::BrowserThread;

// If DOM API methods start with this string, we flag them as being of type
// DomActionType::XHR.
const char kDomXhrPrefix[] = "XMLHttpRequest.";

// 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, "bookmarks.create", 0, DICT_LOOKUP, "url"},
    {Action::ACTION_API_CALL, "bookmarks.update", 1, DICT_LOOKUP, "url"},
    {Action::ACTION_API_CALL, "cookies.get", 0, DICT_LOOKUP, "url"},
    {Action::ACTION_API_CALL, "cookies.getAll", 0, DICT_LOOKUP, "url"},
    {Action::ACTION_API_CALL, "cookies.remove", 0, DICT_LOOKUP, "url"},
    {Action::ACTION_API_CALL, "cookies.set", 0, DICT_LOOKUP, "url"},
    {Action::ACTION_API_CALL, "downloads.download", 0, DICT_LOOKUP, "url"},
    {Action::ACTION_API_CALL, "history.addUrl", 0, DICT_LOOKUP, "url"},
    {Action::ACTION_API_CALL, "history.deleteUrl", 0, DICT_LOOKUP, "url"},
    {Action::ACTION_API_CALL, "history.getVisits", 0, DICT_LOOKUP, "url"},
    {Action::ACTION_API_CALL, "webstore.install", 0, NONE, NULL},
    {Action::ACTION_API_CALL, "windows.create", 0, DICT_LOOKUP, "url"},
    {Action::ACTION_DOM_ACCESS, "Document.location", 0, NONE, NULL},
    {Action::ACTION_DOM_ACCESS, "HTMLAnchorElement.href", 0, NONE, NULL},
    {Action::ACTION_DOM_ACCESS, "HTMLButtonElement.formAction", 0, NONE, NULL},
    {Action::ACTION_DOM_ACCESS, "HTMLEmbedElement.src", 0, NONE, NULL},
    {Action::ACTION_DOM_ACCESS, "HTMLFormElement.action", 0, NONE, NULL},
    {Action::ACTION_DOM_ACCESS, "HTMLFrameElement.src", 0, NONE, NULL},
    {Action::ACTION_DOM_ACCESS, "HTMLHtmlElement.manifest", 0, NONE, NULL},
    {Action::ACTION_DOM_ACCESS, "HTMLIFrameElement.src", 0, NONE, NULL},
    {Action::ACTION_DOM_ACCESS, "HTMLImageElement.longDesc", 0, NONE, NULL},
    {Action::ACTION_DOM_ACCESS, "HTMLImageElement.src", 0, NONE, NULL},
    {Action::ACTION_DOM_ACCESS, "HTMLImageElement.lowsrc", 0, NONE, NULL},
    {Action::ACTION_DOM_ACCESS, "HTMLInputElement.formAction", 0, NONE, NULL},
    {Action::ACTION_DOM_ACCESS, "HTMLInputElement.src", 0, NONE, NULL},
    {Action::ACTION_DOM_ACCESS, "HTMLLinkElement.href", 0, NONE, NULL},
    {Action::ACTION_DOM_ACCESS, "HTMLMediaElement.src", 0, NONE, NULL},
    {Action::ACTION_DOM_ACCESS, "HTMLMediaElement.currentSrc", 0, NONE, NULL},
    {Action::ACTION_DOM_ACCESS, "HTMLModElement.cite", 0, NONE, NULL},
    {Action::ACTION_DOM_ACCESS, "HTMLObjectElement.data", 0, NONE, NULL},
    {Action::ACTION_DOM_ACCESS, "HTMLQuoteElement.cite", 0, NONE, NULL},
    {Action::ACTION_DOM_ACCESS, "HTMLScriptElement.src", 0, NONE, NULL},
    {Action::ACTION_DOM_ACCESS, "HTMLSourceElement.src", 0, NONE, NULL},
    {Action::ACTION_DOM_ACCESS, "HTMLTrackElement.src", 0, NONE, NULL},
    {Action::ACTION_DOM_ACCESS, "HTMLVideoElement.poster", 0, NONE, NULL},
    {Action::ACTION_DOM_ACCESS, "Location.assign", 0, NONE, NULL},
    {Action::ACTION_DOM_ACCESS, "Location.replace", 0, NONE, NULL},
    {Action::ACTION_DOM_ACCESS, "Window.location", 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 base::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;
    }
  }
  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_;

  friend struct base::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,
                    Profile* profile,
                    GURL* url,
                    bool* is_incognito) {
  content::WebContents* contents = NULL;
  Browser* browser = NULL;
  bool found = ExtensionTabUtil::GetTabById(
      tab_id,
      profile,
      true,  // Search incognito tabs, too.
      &browser,
      NULL,
      &contents,
      NULL);

  if (found) {
    *url = contents->GetURL();
    *is_incognito = browser->profile()->IsOffTheRecord();
    return true;
  } else {
    return false;
  }
}

// Resolves an argument URL relative to a base page URL.  If the page URL is
// not valid, then only absolute argument URLs are supported.
bool ResolveUrl(const GURL& base, const std::string& arg, GURL* arg_out) {
  if (base.is_valid())
    *arg_out = base.Resolve(arg);
  else
    *arg_out = GURL(arg);

  return arg_out->is_valid();
}

// 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.
//
// 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 ||
      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();

  switch (api_info->arg_url_transform) {
    case NONE: {
      // No translation needed; just extract the URL directly from a raw string
      // or from a dictionary.  Succeeds if we can find a string in the
      // argument list and that the string resolves to a valid URL.
      std::string url_string;
      if (action->args()->GetString(url_index, &url_string) &&
          ResolveUrl(action->page_url(), url_string, &arg_url)) {
        action->mutable_args()->Set(
            url_index, base::MakeUnique<base::Value>(kArgUrlPlaceholder));
      }
      break;
    }

    case DICT_LOOKUP: {
      CHECK(api_info->arg_url_dict_path);
      // Look up the URL from a dictionary at the specified location.  Succeeds
      // if we can find a dictionary in the argument list, the dictionary
      // contains the specified key, and the corresponding value resolves to a
      // valid URL.
      base::DictionaryValue* dict = NULL;
      std::string url_string;
      if (action->mutable_args()->GetDictionary(url_index, &dict) &&
          dict->GetString(api_info->arg_url_dict_path, &url_string) &&
          ResolveUrl(action->page_url(), url_string, &arg_url)) {
        dict->SetString(api_info->arg_url_dict_path, kArgUrlPlaceholder);
      }
      break;
    }

    case 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* tab_list = NULL;
      if (action->args()->GetInteger(url_index, &tab_id)) {
        // Single tab ID to translate.
        GetUrlForTabId(tab_id, profile, &arg_url, &arg_incognito);
        if (arg_url.is_valid()) {
          action->mutable_args()->Set(
              url_index, base::MakeUnique<base::Value>(kArgUrlPlaceholder));
        }
      } 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 list item is copied 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, base::MakeUnique<base::Value>(arg_url.spec()));
            extracted_index = i;
          }
        }
        if (extracted_index >= 0) {
          tab_list->Set(extracted_index,
                        base::MakeUnique<base::Value>(kArgUrlPlaceholder));
        }
      }
      break;
    }

    default:
      NOTREACHED();
  }

  if (arg_url.is_valid()) {
    action->set_arg_incognito(arg_incognito);
    action->set_arg_url(arg_url);
  }
}

// A global, thread-safe record of activity log state.
class ActivityLogState {
 public:
  ActivityLogState() {}
  ~ActivityLogState() {}

  void AddActiveContext(content::BrowserContext* context) {
    DCHECK_CURRENTLY_ON(BrowserThread::UI);
    base::AutoLock lock(lock_);
    contexts_.insert(context);
  }

  void RemoveActiveContext(content::BrowserContext* context) {
    DCHECK_CURRENTLY_ON(BrowserThread::UI);
    base::AutoLock lock(lock_);
    contexts_.erase(context);
  }

  bool IsActiveContext(content::BrowserContext* context) {
    base::AutoLock lock(lock_);
    return contexts_.count(context) > 0;
  }

  void AddWhitelistedId(const std::string& id) {
    DCHECK_CURRENTLY_ON(BrowserThread::UI);
    base::AutoLock lock(lock_);
    whitelisted_ids_.insert(id);
  }

  // We don't remove the id entry from g_activity_log_state because it may be
  // loaded in multiple profiles, and being whitelisted for the ActivityLog
  // is a global permission.

  bool IsWhitelistedId(const std::string& id) {
    base::AutoLock lock(lock_);
    return whitelisted_ids_.count(id) > 0;
  }

 private:
  std::set<const content::BrowserContext*> contexts_;
  std::set<std::string> whitelisted_ids_;
  base::Lock lock_;

  DISALLOW_COPY_AND_ASSIGN(ActivityLogState);
};

base::LazyInstance<ActivityLogState>::DestructorAtExit g_activity_log_state =
    LAZY_INSTANCE_INITIALIZER;

// Returns the ActivityLog associated with the given |browser_context| after
// checking that |browser_context| is valid.
ActivityLog* SafeGetActivityLog(content::BrowserContext* browser_context) {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);
  // There's a chance that the |browser_context| was deleted some time during
  // the thread hops.
  // TODO(devlin): We should probably be doing this more extensively throughout
  // extensions code.
  if (g_browser_process->IsShuttingDown() ||
      !g_browser_process->profile_manager()->IsValidProfile(browser_context)) {
    return nullptr;
  }
  return ActivityLog::GetInstance(browser_context);
}

// Calls into the ActivityLog to log an api event or function call.
// Must be called on the UI thread.
void LogApiActivityOnUI(content::BrowserContext* browser_context,
                        const std::string& extension_id,
                        const std::string& activity_name,
                        std::unique_ptr<base::ListValue> args,
                        Action::ActionType type) {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);
  ActivityLog* activity_log = SafeGetActivityLog(browser_context);
  if (!activity_log || !activity_log->ShouldLog(extension_id))
    return;
  scoped_refptr<Action> action =
      new Action(extension_id, base::Time::Now(), type, activity_name);
  action->set_args(std::move(args));
  activity_log->LogAction(action);
}

// Generic thread-safe handler for API calls and events.
void LogApiActivity(content::BrowserContext* browser_context,
                    const std::string& extension_id,
                    const std::string& activity_name,
                    const base::ListValue& args,
                    Action::ActionType type) {
  ActivityLogState& state = g_activity_log_state.Get();
  if (!state.IsActiveContext(browser_context) ||
      state.IsWhitelistedId(extension_id))
    return;
  if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) {
    BrowserThread::PostTask(
        BrowserThread::UI, FROM_HERE,
        base::BindOnce(&LogApiActivityOnUI, browser_context, extension_id,
                       activity_name, base::Passed(args.CreateDeepCopy()),
                       type));
    return;
  }
  LogApiActivityOnUI(browser_context, extension_id, activity_name,
                     args.CreateDeepCopy(), type);
}

// Handler for API events. Thread-safe.
void LogApiEvent(content::BrowserContext* browser_context,
                 const std::string& extension_id,
                 const std::string& event_name,
                 const base::ListValue& args) {
  LogApiActivity(browser_context, extension_id, event_name, args,
                 Action::ACTION_API_EVENT);
}

// Handler for API function calls. Thread-safe.
void LogApiFunction(content::BrowserContext* browser_context,
                    const std::string& extension_id,
                    const std::string& event_name,
                    const base::ListValue& args) {
  LogApiActivity(browser_context, extension_id, event_name, args,
                 Action::ACTION_API_CALL);
}

// Calls into the ActivityLog to log a webRequest usage.
// Must be called on the UI thread.
void LogWebRequestActivityOnUI(content::BrowserContext* browser_context,
                               const std::string& extension_id,
                               const GURL& url,
                               bool is_incognito,
                               const std::string& api_call,
                               std::unique_ptr<base::DictionaryValue> details) {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);
  ActivityLog* activity_log = SafeGetActivityLog(browser_context);
  if (!activity_log || !activity_log->ShouldLog(extension_id))
    return;
  scoped_refptr<Action> action = new Action(
      extension_id, base::Time::Now(), Action::ACTION_WEB_REQUEST, api_call);
  action->set_page_url(url);
  action->set_page_incognito(is_incognito);
  action->mutable_other()->Set(activity_log_constants::kActionWebRequest,
                               std::move(details));
  activity_log->LogAction(action);
}

// Handler for webRequest use. Thread-safe.
void LogWebRequestActivity(content::BrowserContext* browser_context,
                           const std::string& extension_id,
                           const GURL& url,
                           bool is_incognito,
                           const std::string& api_call,
                           std::unique_ptr<base::DictionaryValue> details) {
  ActivityLogState& state = g_activity_log_state.Get();
  if (!state.IsActiveContext(browser_context) ||
      state.IsWhitelistedId(extension_id))
    return;
  if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) {
    BrowserThread::PostTask(
        BrowserThread::UI, FROM_HERE,
        base::BindOnce(&LogWebRequestActivityOnUI, browser_context,
                       extension_id, url, is_incognito, api_call,
                       base::Passed(&details)));
    return;
  }
  LogWebRequestActivityOnUI(browser_context, extension_id, url, is_incognito,
                            api_call, std::move(details));
}

void SetActivityHandlers() {
  // Set up event handlers. We don't have to worry about unsetting these,
  // because we check whether or not the activity log is active for the context
  // in the monitor methods.
  activity_monitor::Monitor current_function_monitor =
      activity_monitor::GetApiFunctionMonitor();
  DCHECK(!current_function_monitor ||
         current_function_monitor == &LogApiFunction);
  if (!current_function_monitor)
    activity_monitor::SetApiFunctionMonitor(&LogApiFunction);

  activity_monitor::Monitor current_event_monitor =
      activity_monitor::GetApiEventMonitor();
  DCHECK(!current_event_monitor || current_event_monitor == &LogApiEvent);
  if (!current_event_monitor)
    activity_monitor::SetApiEventMonitor(&LogApiEvent);

  activity_monitor::WebRequestMonitor current_web_request_monitor =
      activity_monitor::GetWebRequestMonitor();
  DCHECK(!current_web_request_monitor ||
         current_web_request_monitor == &LogWebRequestActivity);
  if (!current_web_request_monitor)
    activity_monitor::SetWebRequestMonitor(&LogWebRequestActivity);
}

}  // namespace

// SET THINGS UP. --------------------------------------------------------------

static base::LazyInstance<
    BrowserContextKeyedAPIFactory<ActivityLog>>::DestructorAtExit g_factory =
    LAZY_INSTANCE_INITIALIZER;

BrowserContextKeyedAPIFactory<ActivityLog>* ActivityLog::GetFactoryInstance() {
  return g_factory.Pointer();
}

// static
ActivityLog* ActivityLog::GetInstance(content::BrowserContext* context) {
  return ActivityLog::GetFactoryInstance()->Get(
      Profile::FromBrowserContext(context));
}

// Use GetInstance instead of directly creating an ActivityLog.
ActivityLog::ActivityLog(content::BrowserContext* context)
    : database_policy_(NULL),
      database_policy_type_(ActivityLogPolicy::POLICY_INVALID),
      profile_(Profile::FromBrowserContext(context)),
      extension_system_(ExtensionSystem::Get(context)),
      db_enabled_(false),
      testing_mode_(false),
      extension_registry_observer_(this),
      active_consumers_(0),
      cached_consumer_count_(0),
      is_active_(false),
      weak_factory_(this) {
  SetActivityHandlers();

  // This controls whether logging statements are printed & which policy is set.
  testing_mode_ = base::CommandLine::ForCurrentProcess()->HasSwitch(
      switches::kEnableExtensionActivityLogTesting);

  // Check if the watchdog extension is previously installed and active.
  cached_consumer_count_ =
      profile_->GetPrefs()->GetInteger(prefs::kWatchdogExtensionActive);

  observers_ = new base::ObserverListThreadSafe<Observer>;

  extension_registry_observer_.Add(ExtensionRegistry::Get(profile_));
  CheckActive(true);  // use cached
  extension_system_->ready().Post(
      FROM_HERE,
      base::Bind(&ActivityLog::OnExtensionSystemReady,
                 weak_factory_.GetWeakPtr()));
}

void ActivityLog::SetDatabasePolicy(
    ActivityLogPolicy::PolicyType policy_type) {
  if (database_policy_type_ == policy_type)
    return;
  if (!IsDatabaseEnabled() && !IsWatchdogAppActive())
    return;

  // Deleting the old policy takes place asynchronously, on the database
  // thread.  Initializing a new policy below similarly happens
  // asynchronously.  Since the two operations are both queued for the
  // database, the queue ordering should ensure that the deletion completes
  // before database initialization occurs.
  //
  // However, changing policies at runtime is still not recommended, and
  // likely only should be done for unit tests.
  if (database_policy_)
    database_policy_->Close();

  switch (policy_type) {
    case ActivityLogPolicy::POLICY_FULLSTREAM:
      database_policy_ = new FullStreamUIPolicy(profile_);
      break;
    case ActivityLogPolicy::POLICY_COUNTS:
      database_policy_ = new CountingPolicy(profile_);
      break;
    default:
      NOTREACHED();
  }
  database_policy_->Init();
  database_policy_type_ = policy_type;
}

ActivityLog::~ActivityLog() {
  if (database_policy_)
    database_policy_->Close();
  if (is_active_)
    g_activity_log_state.Get().RemoveActiveContext(profile_);
}

// MAINTAIN STATUS. ------------------------------------------------------------

void ActivityLog::ChooseDatabasePolicy() {
  if (!(IsDatabaseEnabled() || IsWatchdogAppActive()))
    return;
  if (testing_mode_)
    SetDatabasePolicy(ActivityLogPolicy::POLICY_FULLSTREAM);
  else
    SetDatabasePolicy(ActivityLogPolicy::POLICY_COUNTS);
}

bool ActivityLog::IsDatabaseEnabled() {
  return db_enabled_;
}

bool ActivityLog::IsWatchdogAppActive() {
  return active_consumers_ > 0;
}

void ActivityLog::UpdateCachedConsumerCount() {
  cached_consumer_count_ = active_consumers_;
  profile_->GetPrefs()->SetInteger(prefs::kWatchdogExtensionActive,
                                   cached_consumer_count_);
}

void ActivityLog::SetWatchdogAppActiveForTesting(bool active) {
  active_consumers_ = active ? 1 : 0;
  CheckActive(false);  // don't use cached
}

void ActivityLog::OnExtensionLoaded(content::BrowserContext* browser_context,
                                    const Extension* extension) {
  if (!ActivityLogAPI::IsExtensionWhitelisted(extension->id()))
    return;
  g_activity_log_state.Get().AddWhitelistedId(extension->id());
  ++active_consumers_;

  if (!extension_system_->ready().is_signaled())
    return;

  CheckActive(false);  // don't use cached
  UpdateCachedConsumerCount();
}

void ActivityLog::OnExtensionUnloaded(content::BrowserContext* browser_context,
                                      const Extension* extension,
                                      UnloadedExtensionReason reason) {
  if (!ActivityLogAPI::IsExtensionWhitelisted(extension->id()))
    return;
  --active_consumers_;

  if (!extension_system_->ready().is_signaled())
    return;

  CheckActive(false);  // don't use cached
  UpdateCachedConsumerCount();
}

// OnExtensionUnloaded will also be called right before this.
void ActivityLog::OnExtensionUninstalled(
    content::BrowserContext* browser_context,
    const Extension* extension,
    extensions::UninstallReason reason) {
  if (ActivityLogAPI::IsExtensionWhitelisted(extension->id()) &&
      !base::CommandLine::ForCurrentProcess()->HasSwitch(
          switches::kEnableExtensionActivityLogging) &&
      active_consumers_ == 0) {
    DeleteDatabase();
  } else if (database_policy_) {
    database_policy_->RemoveExtensionData(extension->id());
  }
}

void ActivityLog::AddObserver(ActivityLog::Observer* observer) {
  observers_->AddObserver(observer);
}

void ActivityLog::RemoveObserver(ActivityLog::Observer* observer) {
  observers_->RemoveObserver(observer);
}

// static
void ActivityLog::RegisterProfilePrefs(
    user_prefs::PrefRegistrySyncable* registry) {
  registry->RegisterIntegerPref(prefs::kWatchdogExtensionActive, false);
}

// LOG ACTIONS. ----------------------------------------------------------------

void ActivityLog::LogAction(scoped_refptr<Action> action) {
  DCHECK(ShouldLog(action->extension_id()));

  // Perform some preprocessing of the Action data: convert tab IDs to URLs and
  // mask out incognito URLs if appropriate.
  ExtractUrls(action, profile_);

  // Mark DOM XHR requests as such, for easier processing later.
  if (action->action_type() == Action::ACTION_DOM_ACCESS &&
      base::StartsWith(action->api_name(), kDomXhrPrefix,
                       base::CompareCase::SENSITIVE) &&
      action->other()) {
    base::DictionaryValue* other = action->mutable_other();
    int dom_verb = -1;
    if (other->GetInteger(constants::kActionDomVerb, &dom_verb) &&
        dom_verb == DomActionType::METHOD) {
      other->SetInteger(constants::kActionDomVerb, DomActionType::XHR);
    }
  }
  if (IsDatabaseEnabled() && database_policy_)
    database_policy_->ProcessAction(action);
  if (IsWatchdogAppActive())
    observers_->Notify(FROM_HERE, &Observer::OnExtensionActivity, action);
  if (testing_mode_)
    VLOG(1) << action->PrintForDebug();
}

bool ActivityLog::ShouldLog(const std::string& extension_id) const {
  return is_active_ && !ActivityLogAPI::IsExtensionWhitelisted(extension_id);
}

void ActivityLog::OnScriptsExecuted(
    const content::WebContents* web_contents,
    const ExecutingScriptsMap& extension_ids,
    const GURL& on_url) {
  if (!is_active_)
    return;
  ExtensionRegistry* registry = ExtensionRegistry::Get(profile_);
  for (ExecutingScriptsMap::const_iterator it = extension_ids.begin();
       it != extension_ids.end(); ++it) {
    const Extension* extension =
        registry->GetExtensionById(it->first, ExtensionRegistry::ENABLED);
    if (!extension || ActivityLogAPI::IsExtensionWhitelisted(extension->id()))
      continue;

    // If OnScriptsExecuted is fired because of tabs.executeScript, the list
    // of content scripts will be empty.  We don't want to log it because
    // the call to tabs.executeScript will have already been logged anyway.
    if (!it->second.empty()) {
      scoped_refptr<Action> action;
      action = new Action(extension->id(),
                          base::Time::Now(),
                          Action::ACTION_CONTENT_SCRIPT,
                          "");  // no API call here
      action->set_page_url(on_url);
      action->set_page_title(base::UTF16ToUTF8(web_contents->GetTitle()));
      action->set_page_incognito(
          web_contents->GetBrowserContext()->IsOffTheRecord());

      const prerender::PrerenderManager* prerender_manager =
          prerender::PrerenderManagerFactory::GetForBrowserContext(profile_);
      if (prerender_manager &&
          prerender_manager->IsWebContentsPrerendering(web_contents, NULL))
        action->mutable_other()->SetBoolean(constants::kActionPrerender, true);
      for (std::set<std::string>::const_iterator it2 = it->second.begin();
           it2 != it->second.end();
           ++it2) {
        action->mutable_args()->AppendString(*it2);
      }
      LogAction(action);
    }
  }
}

// LOOKUP ACTIONS. -------------------------------------------------------------

void ActivityLog::GetFilteredActions(
    const std::string& extension_id,
    const Action::ActionType type,
    const std::string& api_name,
    const std::string& page_url,
    const std::string& arg_url,
    const int daysAgo,
    const base::Callback<
        void(std::unique_ptr<std::vector<scoped_refptr<Action>>>)>& callback) {
  if (database_policy_) {
    database_policy_->ReadFilteredData(
        extension_id, type, api_name, page_url, arg_url, daysAgo, callback);
  }
}

// DELETE ACTIONS. -------------------------------------------------------------

void ActivityLog::RemoveActions(const std::vector<int64_t>& action_ids) {
  if (!database_policy_)
    return;
  database_policy_->RemoveActions(action_ids);
}

void ActivityLog::RemoveURLs(const std::vector<GURL>& restrict_urls) {
  if (!database_policy_)
    return;
  database_policy_->RemoveURLs(restrict_urls);
}

void ActivityLog::RemoveURLs(const std::set<GURL>& restrict_urls) {
  if (!database_policy_)
    return;

  std::vector<GURL> urls;
  for (std::set<GURL>::const_iterator it = restrict_urls.begin();
       it != restrict_urls.end(); ++it) {
    urls.push_back(*it);
  }
  database_policy_->RemoveURLs(urls);
}

void ActivityLog::RemoveURL(const GURL& url) {
  if (url.is_empty())
    return;
  std::vector<GURL> urls;
  urls.push_back(url);
  RemoveURLs(urls);
}

void ActivityLog::DeleteDatabase() {
  if (!database_policy_)
    return;
  database_policy_->DeleteDatabase();
}

void ActivityLog::CheckActive(bool use_cached) {
  bool has_consumer =
      active_consumers_ || (use_cached && cached_consumer_count_);
  bool needs_db =
      has_consumer || base::CommandLine::ForCurrentProcess()->HasSwitch(
                          switches::kEnableExtensionActivityLogging);
  bool should_be_active = needs_db || has_consumer;

  if (should_be_active == is_active_)
    return;

  ActivityLogState& state = g_activity_log_state.Get();
  content::BrowserContext* off_the_record =
      profile_->HasOffTheRecordProfile() ? profile_->GetOffTheRecordProfile()
                                         : nullptr;
  bool has_db = db_enabled_ && database_policy_;
  bool old_is_active = is_active_;

  if (should_be_active) {
    if (needs_db && !has_db) {
      db_enabled_ = true;
      ChooseDatabasePolicy();
    }

    state.AddActiveContext(profile_);
    if (off_the_record)
      state.AddActiveContext(off_the_record);
    registrar_.Add(this, chrome::NOTIFICATION_PROFILE_CREATED,
                   content::NotificationService::AllSources());
    registrar_.Add(this, chrome::NOTIFICATION_PROFILE_DESTROYED,
                   content::NotificationService::AllSources());
    is_active_ = true;
  } else {
    if (has_db && !needs_db)
      db_enabled_ = false;
    state.RemoveActiveContext(profile_);
    if (off_the_record)
      state.RemoveActiveContext(off_the_record);
    registrar_.RemoveAll();
    is_active_ = false;
  }

  DCHECK_NE(is_active_, old_is_active);
  for (content::RenderProcessHost::iterator iter(
           content::RenderProcessHost::AllHostsIterator());
       !iter.IsAtEnd(); iter.Advance()) {
    content::RenderProcessHost* host = iter.GetCurrentValue();
    if (profile_->IsSameProfile(
            Profile::FromBrowserContext(host->GetBrowserContext()))) {
      host->Send(new ExtensionMsg_SetActivityLoggingEnabled(is_active_));
    }
  }
}

void ActivityLog::Observe(int type,
                          const content::NotificationSource& source,
                          const content::NotificationDetails& details) {
  DCHECK(is_active_);
  switch (type) {
    case chrome::NOTIFICATION_PROFILE_CREATED: {
      Profile* profile = content::Source<Profile>(source).ptr();
      if (profile_->IsSameProfile(profile))
        g_activity_log_state.Get().AddActiveContext(profile);
      break;
    }
    case chrome::NOTIFICATION_PROFILE_DESTROYED: {
      Profile* profile = content::Source<Profile>(source).ptr();
      if (profile_->IsSameProfile(profile))
        g_activity_log_state.Get().RemoveActiveContext(profile);
      break;
    }
    default:
      NOTREACHED();
  }
}

void ActivityLog::OnExtensionSystemReady() {
  if (active_consumers_ != cached_consumer_count_) {
    CheckActive(false);
    UpdateCachedConsumerCount();
  }
}

template <>
void BrowserContextKeyedAPIFactory<ActivityLog>::DeclareFactoryDependencies() {
  DependsOn(ExtensionsBrowserClient::Get()->GetExtensionSystemFactory());
  DependsOn(ExtensionRegistryFactory::GetInstance());
}

}  // namespace extensions
