// 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 <set>
#include <vector>

#include "base/command_line.h"
#include "base/json/json_string_value_serializer.h"
#include "base/logging.h"
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
#include "base/threading/thread_checker.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_service.h"
#include "chrome/browser/extensions/extension_system.h"
#include "chrome/browser/extensions/extension_system_factory.h"
#include "chrome/browser/extensions/extension_tab_util.h"
#include "chrome/browser/extensions/install_tracker_factory.h"
#include "chrome/browser/prefs/pref_service_syncable.h"
#include "chrome/browser/prerender/prerender_manager.h"
#include "chrome/browser/prerender/prerender_manager_factory.h"
#include "chrome/browser/profiles/incognito_helpers.h"
#include "chrome/browser/ui/browser.h"
#include "chrome/common/chrome_constants.h"
#include "chrome/common/chrome_switches.h"
#include "chrome/common/extensions/extension.h"
#include "chrome/common/pref_names.h"
#include "components/browser_context_keyed_service/browser_context_dependency_manager.h"
#include "content/public/browser/web_contents.h"
#include "third_party/re2/re2/re2.h"
#include "url/gurl.h"

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;
    }
  }
  return call_signature;
}

// Gets the URL for a given tab ID.  Helper method for LookupTabId.  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;
  }
}

// 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.
//
// 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") {
    int tab_id;
    base::ListValue* id_list;
    base::ListValue* args = action->mutable_args();
    if (args->GetInteger(0, &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);
      }
    } 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;
        }
      }
    }
  }
}

}  // namespace

namespace extensions {

// ActivityLogFactory

ActivityLogFactory* ActivityLogFactory::GetInstance() {
  return Singleton<ActivityLogFactory>::get();
}

BrowserContextKeyedService* ActivityLogFactory::BuildServiceInstanceFor(
    content::BrowserContext* profile) const {
  return new ActivityLog(static_cast<Profile*>(profile));
}

content::BrowserContext* ActivityLogFactory::GetBrowserContextToUse(
    content::BrowserContext* context) const {
  return chrome::GetBrowserContextRedirectedInIncognito(context);
}

ActivityLogFactory::ActivityLogFactory()
    : BrowserContextKeyedServiceFactory(
        "ActivityLog",
        BrowserContextDependencyManager::GetInstance()) {
  DependsOn(ExtensionSystemFactory::GetInstance());
  DependsOn(InstallTrackerFactory::GetInstance());
}

ActivityLogFactory::~ActivityLogFactory() {
}

// ActivityLog

void ActivityLog::SetDefaultPolicy(ActivityLogPolicy::PolicyType policy_type) {
  // Can't use IsLogEnabled() here because this is called from inside Init.
  if (policy_type != policy_type_ && enabled_) {
    // 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 (policy_)
      policy_->Close();

    switch (policy_type) {
      case ActivityLogPolicy::POLICY_FULLSTREAM:
        policy_ = new FullStreamUIPolicy(profile_);
        break;
      case ActivityLogPolicy::POLICY_COUNTS:
        policy_ = new CountingPolicy(profile_);
        break;
      default:
        NOTREACHED();
    }
    policy_type_ = policy_type;
  }
}

// Use GetInstance instead of directly creating an ActivityLog.
ActivityLog::ActivityLog(Profile* profile)
    : policy_(NULL),
      policy_type_(ActivityLogPolicy::POLICY_INVALID),
      profile_(profile),
      enabled_(false),
      policy_chosen_(false),
      testing_mode_(false),
      has_threads_(true),
      tracker_(NULL),
      watchdog_extension_active_(false) {
  // This controls whether logging statements are printed, which policy is set,
  // etc.
  testing_mode_ = CommandLine::ForCurrentProcess()->HasSwitch(
    switches::kEnableExtensionActivityLogTesting);

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

  observers_ = new ObserverListThreadSafe<Observer>;

  // Check that the right threads exist. If not, we shouldn't try to do things
  // that require them.
  if (!BrowserThread::IsMessageLoopValid(BrowserThread::DB) ||
      !BrowserThread::IsMessageLoopValid(BrowserThread::FILE) ||
      !BrowserThread::IsMessageLoopValid(BrowserThread::IO)) {
    LOG(ERROR) << "Missing threads, disabling Activity Logging!";
    has_threads_ = false;
  }

  enabled_ = has_threads_
      && (CommandLine::ForCurrentProcess()->
          HasSwitch(switches::kEnableExtensionActivityLogging)
      || watchdog_extension_active_);

  if (enabled_) enabled_on_any_profile_ = true;

  ExtensionSystem::Get(profile_)->ready().Post(
      FROM_HERE,
      base::Bind(&ActivityLog::InitInstallTracker, base::Unretained(this)));
  ChooseDefaultPolicy();
}

void ActivityLog::InitInstallTracker() {
  tracker_ = InstallTrackerFactory::GetForProfile(profile_);
  tracker_->AddObserver(this);
}

void ActivityLog::ChooseDefaultPolicy() {
  if (policy_chosen_ || !enabled_) return;
  if (testing_mode_)
    SetDefaultPolicy(ActivityLogPolicy::POLICY_FULLSTREAM);
  else
    SetDefaultPolicy(ActivityLogPolicy::POLICY_COUNTS);
}

void ActivityLog::Shutdown() {
  if (tracker_) tracker_->RemoveObserver(this);
}

ActivityLog::~ActivityLog() {
  if (policy_)
    policy_->Close();
}

// static
bool ActivityLog::enabled_on_any_profile_ = false;

// static
bool ActivityLog::IsLogEnabledOnAnyProfile() {
  return enabled_on_any_profile_;
}

bool ActivityLog::IsLogEnabled() {
  // Make sure we are not enabled when there are no threads.
  DCHECK(has_threads_ || !enabled_);
  return enabled_;
}

void ActivityLog::OnExtensionLoaded(const Extension* extension) {
  if (extension->id() != kActivityLogExtensionId) return;
  if (has_threads_) {
    enabled_ = true;
    enabled_on_any_profile_ = true;
  }
  if (!watchdog_extension_active_) {
    watchdog_extension_active_ = true;
    profile_->GetPrefs()->SetBoolean(prefs::kWatchdogExtensionActive, true);
  }
  ChooseDefaultPolicy();
}

void ActivityLog::OnExtensionUnloaded(const Extension* extension) {
  if (extension->id() != kActivityLogExtensionId) return;
  // Make sure we are not enabled when there are no threads.
  DCHECK(has_threads_ || !enabled_);
  if (!CommandLine::ForCurrentProcess()->HasSwitch(
      switches::kEnableExtensionActivityLogging))
    enabled_ = false;
  if (watchdog_extension_active_) {
    watchdog_extension_active_ = false;
    profile_->GetPrefs()->SetBoolean(prefs::kWatchdogExtensionActive,
                                     false);
  }
}

// static
ActivityLog* ActivityLog::GetInstance(Profile* profile) {
  return ActivityLogFactory::GetForProfile(profile);
}

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

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

void ActivityLog::LogAction(scoped_refptr<Action> action) {
  if (!IsLogEnabled() ||
      ActivityLogAPI::IsExtensionWhitelisted(action->extension_id()))
    return;

  // 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_);
  }

  // TODO(mvrable): Add any necessary processing of incognito URLs here, for
  // crbug.com/253368

  if (policy_)
    policy_->ProcessAction(action);
  observers_->Notify(&Observer::OnExtensionActivity, action);
  if (testing_mode_)
    LOG(INFO) << action->PrintForDebug();
}

void ActivityLog::GetActions(
    const std::string& extension_id,
    const int day,
    const base::Callback
        <void(scoped_ptr<std::vector<scoped_refptr<Action> > >)>& callback) {
  if (policy_) {
    policy_->ReadData(extension_id, day, callback);
  }
}

void ActivityLog::OnScriptsExecuted(
    const content::WebContents* web_contents,
    const ExecutingScriptsMap& extension_ids,
    int32 on_page_id,
    const GURL& on_url) {
  if (!IsLogEnabled()) return;
  Profile* profile =
      Profile::FromBrowserContext(web_contents->GetBrowserContext());
  const ExtensionService* extension_service =
      ExtensionSystem::Get(profile)->extension_service();
  const ExtensionSet* extensions = extension_service->extensions();
  const prerender::PrerenderManager* prerender_manager =
      prerender::PrerenderManagerFactory::GetForProfile(
          Profile::FromBrowserContext(web_contents->GetBrowserContext()));

  for (ExecutingScriptsMap::const_iterator it = extension_ids.begin();
       it != extension_ids.end(); ++it) {
    const Extension* extension = extensions->GetByID(it->first);
    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());
      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);
    }
  }
}

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

}  // namespace extensions
