// Copyright (c) 2012 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/webstore_private/webstore_private_api.h"

#include "base/bind_helpers.h"
#include "base/command_line.h"
#include "base/lazy_instance.h"
#include "base/memory/scoped_vector.h"
#include "base/prefs/pref_service.h"
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
#include "base/values.h"
#include "chrome/browser/about_flags.h"
#include "chrome/browser/apps/app_launcher_util.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/chrome_notification_types.h"
#include "chrome/browser/extensions/crx_installer.h"
#include "chrome/browser/extensions/extension_function_dispatcher.h"
#include "chrome/browser/extensions/extension_prefs.h"
#include "chrome/browser/extensions/extension_service.h"
#include "chrome/browser/extensions/extension_system.h"
#include "chrome/browser/extensions/webstore_installer.h"
#include "chrome/browser/gpu/gpu_feature_checker.h"
#include "chrome/browser/profiles/profile_manager.h"
#include "chrome/browser/signin/signin_manager.h"
#include "chrome/browser/signin/signin_manager_factory.h"
#include "chrome/browser/sync/profile_sync_service.h"
#include "chrome/browser/sync/profile_sync_service_factory.h"
#include "chrome/browser/ui/app_list/app_list_service.h"
#include "chrome/common/extensions/extension.h"
#include "chrome/common/extensions/extension_constants.h"
#include "chrome/common/extensions/extension_l10n_util.h"
#include "chrome/common/pref_names.h"
#include "content/public/browser/gpu_data_manager.h"
#include "content/public/browser/notification_details.h"
#include "content/public/browser/notification_source.h"
#include "content/public/browser/web_contents.h"
#include "extensions/common/error_utils.h"
#include "grit/chromium_strings.h"
#include "grit/generated_resources.h"
#include "ui/base/l10n/l10n_util.h"

using content::GpuDataManager;

namespace extensions {

namespace BeginInstallWithManifest3 =
    api::webstore_private::BeginInstallWithManifest3;
namespace CompleteInstall = api::webstore_private::CompleteInstall;
namespace GetBrowserLogin = api::webstore_private::GetBrowserLogin;
namespace GetIsLauncherEnabled = api::webstore_private::GetIsLauncherEnabled;
namespace GetStoreLogin = api::webstore_private::GetStoreLogin;
namespace GetWebGLStatus = api::webstore_private::GetWebGLStatus;
namespace InstallBundle = api::webstore_private::InstallBundle;
namespace IsInIncognitoMode = api::webstore_private::IsInIncognitoMode;
namespace SetStoreLogin = api::webstore_private::SetStoreLogin;

namespace {

// Holds the Approvals between the time we prompt and start the installs.
class PendingApprovals {
 public:
  PendingApprovals();
  ~PendingApprovals();

  void PushApproval(scoped_ptr<WebstoreInstaller::Approval> approval);
  scoped_ptr<WebstoreInstaller::Approval> PopApproval(
      Profile* profile, const std::string& id);
 private:
  typedef ScopedVector<WebstoreInstaller::Approval> ApprovalList;

  ApprovalList approvals_;

  DISALLOW_COPY_AND_ASSIGN(PendingApprovals);
};

PendingApprovals::PendingApprovals() {}
PendingApprovals::~PendingApprovals() {}

void PendingApprovals::PushApproval(
    scoped_ptr<WebstoreInstaller::Approval> approval) {
  approvals_.push_back(approval.release());
}

scoped_ptr<WebstoreInstaller::Approval> PendingApprovals::PopApproval(
    Profile* profile, const std::string& id) {
  for (size_t i = 0; i < approvals_.size(); ++i) {
    WebstoreInstaller::Approval* approval = approvals_[i];
    if (approval->extension_id == id &&
        profile->IsSameProfile(approval->profile)) {
      approvals_.weak_erase(approvals_.begin() + i);
      return scoped_ptr<WebstoreInstaller::Approval>(approval);
    }
  }
  return scoped_ptr<WebstoreInstaller::Approval>();
}

// Uniquely holds the profile and extension id of an install between the time we
// prompt and complete the installs.
class PendingInstalls {
 public:
  PendingInstalls();
  ~PendingInstalls();

  bool InsertInstall(Profile* profile, const std::string& id);
  void EraseInstall(Profile* profile, const std::string& id);
 private:
  typedef std::pair<Profile*, std::string> ProfileAndExtensionId;
  typedef std::vector<ProfileAndExtensionId> InstallList;

  InstallList::iterator FindInstall(Profile* profile, const std::string& id);

  InstallList installs_;

  DISALLOW_COPY_AND_ASSIGN(PendingInstalls);
};

PendingInstalls::PendingInstalls() {}
PendingInstalls::~PendingInstalls() {}

// Returns true and inserts the profile/id pair if it is not present. Otherwise
// returns false.
bool PendingInstalls::InsertInstall(Profile* profile, const std::string& id) {
  if (FindInstall(profile, id) != installs_.end())
    return false;
  installs_.push_back(make_pair(profile, id));
  return true;
}

// Removes the given profile/id pair.
void PendingInstalls::EraseInstall(Profile* profile, const std::string& id) {
  InstallList::iterator it = FindInstall(profile, id);
  if (it != installs_.end())
    installs_.erase(it);
}

PendingInstalls::InstallList::iterator PendingInstalls::FindInstall(
    Profile* profile,
    const std::string& id) {
  for (size_t i = 0; i < installs_.size(); ++i) {
    ProfileAndExtensionId install = installs_[i];
    if (install.second == id && profile->IsSameProfile(install.first))
      return (installs_.begin() + i);
  }
  return installs_.end();
}

static base::LazyInstance<PendingApprovals> g_pending_approvals =
    LAZY_INSTANCE_INITIALIZER;
static base::LazyInstance<PendingInstalls> g_pending_installs =
    LAZY_INSTANCE_INITIALIZER;

// A preference set by the web store to indicate login information for
// purchased apps.
const char kWebstoreLogin[] = "extensions.webstore_login";
const char kAlreadyInstalledError[] = "This item is already installed";
const char kCannotSpecifyIconDataAndUrlError[] =
    "You cannot specify both icon data and an icon url";
const char kInvalidIconUrlError[] = "Invalid icon url";
const char kInvalidIdError[] = "Invalid id";
const char kInvalidManifestError[] = "Invalid manifest";
const char kNoPreviousBeginInstallWithManifestError[] =
    "* does not match a previous call to beginInstallWithManifest3";
const char kUserCancelledError[] = "User cancelled install";

WebstoreInstaller::Delegate* test_webstore_installer_delegate = NULL;

// We allow the web store to set a string containing login information when a
// purchase is made, so that when a user logs into sync with a different
// account we can recognize the situation. The Get function returns the login if
// there was previously stored data, or an empty string otherwise. The Set will
// overwrite any previous login.
std::string GetWebstoreLogin(Profile* profile) {
  if (profile->GetPrefs()->HasPrefPath(kWebstoreLogin))
    return profile->GetPrefs()->GetString(kWebstoreLogin);
  return std::string();
}

void SetWebstoreLogin(Profile* profile, const std::string& login) {
  profile->GetPrefs()->SetString(kWebstoreLogin, login);
}

}  // namespace

// static
void WebstorePrivateApi::SetWebstoreInstallerDelegateForTesting(
    WebstoreInstaller::Delegate* delegate) {
  test_webstore_installer_delegate = delegate;
}

// static
scoped_ptr<WebstoreInstaller::Approval>
WebstorePrivateApi::PopApprovalForTesting(
    Profile* profile, const std::string& extension_id) {
  return g_pending_approvals.Get().PopApproval(profile, extension_id);
}

WebstorePrivateInstallBundleFunction::WebstorePrivateInstallBundleFunction() {}
WebstorePrivateInstallBundleFunction::~WebstorePrivateInstallBundleFunction() {}

bool WebstorePrivateInstallBundleFunction::RunImpl() {
  scoped_ptr<InstallBundle::Params> params(
      InstallBundle::Params::Create(*args_));
  EXTENSION_FUNCTION_VALIDATE(params);

  BundleInstaller::ItemList items;
  if (!ReadBundleInfo(*params, &items))
    return false;

  bundle_ = new BundleInstaller(GetCurrentBrowser(), items);

  AddRef();  // Balanced in OnBundleInstallCompleted / OnBundleInstallCanceled.

  bundle_->PromptForApproval(this);
  return true;
}

bool WebstorePrivateInstallBundleFunction::
    ReadBundleInfo(const InstallBundle::Params& params,
    BundleInstaller::ItemList* items) {
  for (size_t i = 0; i < params.details.size(); ++i) {
    BundleInstaller::Item item;
    item.id = params.details[i]->id;
    item.manifest = params.details[i]->manifest;
    item.localized_name = params.details[i]->localized_name;
    items->push_back(item);
  }

  return true;
}

void WebstorePrivateInstallBundleFunction::OnBundleInstallApproved() {
  bundle_->CompleteInstall(
      &(dispatcher()->delegate()->GetAssociatedWebContents()->GetController()),
      this);
}

void WebstorePrivateInstallBundleFunction::OnBundleInstallCanceled(
    bool user_initiated) {
  if (user_initiated)
    error_ = "user_canceled";
  else
    error_ = "unknown_error";

  SendResponse(false);

  Release();  // Balanced in RunImpl().
}

void WebstorePrivateInstallBundleFunction::OnBundleInstallCompleted() {
  SendResponse(true);

  Release();  // Balanced in RunImpl().
}

WebstorePrivateBeginInstallWithManifest3Function::
    WebstorePrivateBeginInstallWithManifest3Function() {}

WebstorePrivateBeginInstallWithManifest3Function::
    ~WebstorePrivateBeginInstallWithManifest3Function() {}

bool WebstorePrivateBeginInstallWithManifest3Function::RunImpl() {
  params_ = BeginInstallWithManifest3::Params::Create(*args_);
  EXTENSION_FUNCTION_VALIDATE(params_);

  if (!extensions::Extension::IdIsValid(params_->details.id)) {
    SetResultCode(INVALID_ID);
    error_ = kInvalidIdError;
    return false;
  }

  if (params_->details.icon_data && params_->details.icon_url) {
    SetResultCode(ICON_ERROR);
    error_ = kCannotSpecifyIconDataAndUrlError;
    return false;
  }

  GURL icon_url;
  if (params_->details.icon_url) {
    std::string tmp_url;
    icon_url = source_url().Resolve(*params_->details.icon_url);
    if (!icon_url.is_valid()) {
      SetResultCode(INVALID_ICON_URL);
      error_ = kInvalidIconUrlError;
      return false;
    }
  }

  std::string icon_data = params_->details.icon_data ?
      *params_->details.icon_data : std::string();

  ExtensionService* service =
    extensions::ExtensionSystem::Get(profile_)->extension_service();
  if (service->GetInstalledExtension(params_->details.id) ||
      !g_pending_installs.Get().InsertInstall(profile_, params_->details.id)) {
    SetResultCode(ALREADY_INSTALLED);
    error_ = kAlreadyInstalledError;
    return false;
  }

  net::URLRequestContextGetter* context_getter = NULL;
  if (!icon_url.is_empty())
    context_getter = profile()->GetRequestContext();

  scoped_refptr<WebstoreInstallHelper> helper = new WebstoreInstallHelper(
      this, params_->details.id, params_->details.manifest, icon_data, icon_url,
          context_getter);

  // The helper will call us back via OnWebstoreParseSuccess or
  // OnWebstoreParseFailure.
  helper->Start();

  // Matched with a Release in OnWebstoreParseSuccess/OnWebstoreParseFailure.
  AddRef();

  // The response is sent asynchronously in OnWebstoreParseSuccess/
  // OnWebstoreParseFailure.
  return true;
}

const char* WebstorePrivateBeginInstallWithManifest3Function::
    ResultCodeToString(ResultCode code) {
  switch (code) {
    case ERROR_NONE:
      return "";
    case UNKNOWN_ERROR:
      return "unknown_error";
    case USER_CANCELLED:
      return "user_cancelled";
    case MANIFEST_ERROR:
      return "manifest_error";
    case ICON_ERROR:
      return "icon_error";
    case INVALID_ID:
      return "invalid_id";
    case PERMISSION_DENIED:
      return "permission_denied";
    case INVALID_ICON_URL:
      return "invalid_icon_url";
    case SIGNIN_FAILED:
      return "signin_failed";
    case ALREADY_INSTALLED:
      return "already_installed";
  }
  NOTREACHED();
  return "";
}

void WebstorePrivateBeginInstallWithManifest3Function::SetResultCode(
    ResultCode code) {
  results_ = BeginInstallWithManifest3::Results::Create(
      ResultCodeToString(code));
}

void WebstorePrivateBeginInstallWithManifest3Function::OnWebstoreParseSuccess(
    const std::string& id,
    const SkBitmap& icon,
    base::DictionaryValue* parsed_manifest) {
  CHECK_EQ(params_->details.id, id);
  CHECK(parsed_manifest);
  icon_ = icon;
  parsed_manifest_.reset(parsed_manifest);

  std::string localized_name = params_->details.localized_name ?
      *params_->details.localized_name : std::string();

  std::string error;
  dummy_extension_ = ExtensionInstallPrompt::GetLocalizedExtensionForDisplay(
      parsed_manifest_.get(),
      Extension::FROM_WEBSTORE,
      id,
      localized_name,
      std::string(),
      &error);

  if (!dummy_extension_.get()) {
    OnWebstoreParseFailure(params_->details.id,
                           WebstoreInstallHelper::Delegate::MANIFEST_ERROR,
                           kInvalidManifestError);
    return;
  }

  SigninManagerBase* signin_manager =
      SigninManagerFactory::GetForProfile(profile());
  if (dummy_extension_->is_platform_app() &&
      signin_manager &&
      signin_manager->GetAuthenticatedUsername().empty() &&
      signin_manager->AuthInProgress()) {
    signin_tracker_.reset(new SigninTracker(profile(), this));
    return;
  }

  SigninCompletedOrNotNeeded();
}

void WebstorePrivateBeginInstallWithManifest3Function::OnWebstoreParseFailure(
    const std::string& id,
    WebstoreInstallHelper::Delegate::InstallHelperResultCode result_code,
    const std::string& error_message) {
  CHECK_EQ(params_->details.id, id);

  // Map from WebstoreInstallHelper's result codes to ours.
  switch (result_code) {
    case WebstoreInstallHelper::Delegate::UNKNOWN_ERROR:
      SetResultCode(UNKNOWN_ERROR);
      break;
    case WebstoreInstallHelper::Delegate::ICON_ERROR:
      SetResultCode(ICON_ERROR);
      break;
    case WebstoreInstallHelper::Delegate::MANIFEST_ERROR:
      SetResultCode(MANIFEST_ERROR);
      break;
    default:
      CHECK(false);
  }
  error_ = error_message;
  g_pending_installs.Get().EraseInstall(profile_, id);
  SendResponse(false);

  // Matches the AddRef in RunImpl().
  Release();
}

void WebstorePrivateBeginInstallWithManifest3Function::SigninFailed(
    const GoogleServiceAuthError& error) {
  signin_tracker_.reset();

  SetResultCode(SIGNIN_FAILED);
  error_ = error.ToString();
  g_pending_installs.Get().EraseInstall(profile_, params_->details.id);
  SendResponse(false);

  // Matches the AddRef in RunImpl().
  Release();
}

void WebstorePrivateBeginInstallWithManifest3Function::SigninSuccess() {
  signin_tracker_.reset();

  SigninCompletedOrNotNeeded();
}

void WebstorePrivateBeginInstallWithManifest3Function::
    SigninCompletedOrNotNeeded() {
  content::WebContents* web_contents = GetAssociatedWebContents();
  if (!web_contents)  // The browser window has gone away.
    return;
  install_prompt_.reset(new ExtensionInstallPrompt(web_contents));
  install_prompt_->ConfirmWebstoreInstall(
      this,
      dummy_extension_.get(),
      &icon_,
      ExtensionInstallPrompt::GetDefaultShowDialogCallback());
  // Control flow finishes up in InstallUIProceed or InstallUIAbort.
}

void WebstorePrivateBeginInstallWithManifest3Function::InstallUIProceed() {
  // This gets cleared in CrxInstaller::ConfirmInstall(). TODO(asargent) - in
  // the future we may also want to add time-based expiration, where a whitelist
  // entry is only valid for some number of minutes.
  scoped_ptr<WebstoreInstaller::Approval> approval(
      WebstoreInstaller::Approval::CreateWithNoInstallPrompt(
          profile(), params_->details.id, parsed_manifest_.Pass(), false));
  approval->use_app_installed_bubble = params_->details.app_install_bubble;
  approval->enable_launcher = params_->details.enable_launcher;
  // If we are enabling the launcher, we should not show the app list in order
  // to train the user to open it themselves at least once.
  approval->skip_post_install_ui = params_->details.enable_launcher;
  approval->dummy_extension = dummy_extension_;
  approval->installing_icon = gfx::ImageSkia::CreateFrom1xBitmap(icon_);
  g_pending_approvals.Get().PushApproval(approval.Pass());

  SetResultCode(ERROR_NONE);
  SendResponse(true);

  // The Permissions_Install histogram is recorded from the ExtensionService
  // for all extension installs, so we only need to record the web store
  // specific histogram here.
  ExtensionService::RecordPermissionMessagesHistogram(
      dummy_extension_.get(), "Extensions.Permissions_WebStoreInstall");

  // Matches the AddRef in RunImpl().
  Release();
}

void WebstorePrivateBeginInstallWithManifest3Function::InstallUIAbort(
    bool user_initiated) {
  error_ = kUserCancelledError;
  SetResultCode(USER_CANCELLED);
  g_pending_installs.Get().EraseInstall(profile_, params_->details.id);
  SendResponse(false);

  // The web store install histograms are a subset of the install histograms.
  // We need to record both histograms here since CrxInstaller::InstallUIAbort
  // is never called for web store install cancellations.
  std::string histogram_name = user_initiated ?
      "Extensions.Permissions_WebStoreInstallCancel" :
      "Extensions.Permissions_WebStoreInstallAbort";
  ExtensionService::RecordPermissionMessagesHistogram(dummy_extension_.get(),
                                                      histogram_name.c_str());

  histogram_name = user_initiated ?
      "Extensions.Permissions_InstallCancel" :
      "Extensions.Permissions_InstallAbort";
  ExtensionService::RecordPermissionMessagesHistogram(dummy_extension_.get(),
                                                      histogram_name.c_str());

  // Matches the AddRef in RunImpl().
  Release();
}

WebstorePrivateCompleteInstallFunction::
    WebstorePrivateCompleteInstallFunction() {}

WebstorePrivateCompleteInstallFunction::
    ~WebstorePrivateCompleteInstallFunction() {}

bool WebstorePrivateCompleteInstallFunction::RunImpl() {
  scoped_ptr<CompleteInstall::Params> params(
      CompleteInstall::Params::Create(*args_));
  EXTENSION_FUNCTION_VALIDATE(params);
  if (!extensions::Extension::IdIsValid(params->expected_id)) {
    error_ = kInvalidIdError;
    return false;
  }

  approval_ = g_pending_approvals.Get().PopApproval(profile(),
      params->expected_id).Pass();
  if (!approval_) {
    error_ = ErrorUtils::FormatErrorMessage(
        kNoPreviousBeginInstallWithManifestError, params->expected_id);
    return false;
  }

  // Balanced in OnExtensionInstallSuccess() or OnExtensionInstallFailure().
  AddRef();

  if (approval_->enable_launcher)
    AppListService::Get()->EnableAppList(profile());

  if (IsAppLauncherEnabled() && approval_->manifest->is_app()) {
    // Show the app list to show download is progressing. Don't show the app
    // list on first app install so users can be trained to open it themselves.
    if (approval_->enable_launcher)
      AppListService::Get()->CreateForProfile(profile());
    else
      AppListService::Get()->ShowForProfile(profile());
  }

  // The extension will install through the normal extension install flow, but
  // the whitelist entry will bypass the normal permissions install dialog.
  scoped_refptr<WebstoreInstaller> installer = new WebstoreInstaller(
      profile(), this,
      &(dispatcher()->delegate()->GetAssociatedWebContents()->GetController()),
      params->expected_id, approval_.Pass(),
      WebstoreInstaller::INSTALL_SOURCE_OTHER);
  installer->Start();

  return true;
}

void WebstorePrivateCompleteInstallFunction::OnExtensionInstallSuccess(
    const std::string& id) {
  if (test_webstore_installer_delegate)
    test_webstore_installer_delegate->OnExtensionInstallSuccess(id);

  LOG(INFO) << "Install success, sending response";
  g_pending_installs.Get().EraseInstall(profile_, id);
  SendResponse(true);

  // Matches the AddRef in RunImpl().
  Release();
}

void WebstorePrivateCompleteInstallFunction::OnExtensionInstallFailure(
    const std::string& id,
    const std::string& error,
    WebstoreInstaller::FailureReason reason) {
  if (test_webstore_installer_delegate) {
    test_webstore_installer_delegate->OnExtensionInstallFailure(
        id, error, reason);
  }

  error_ = error;
  LOG(INFO) << "Install failed, sending response";
  g_pending_installs.Get().EraseInstall(profile_, id);
  SendResponse(false);

  // Matches the AddRef in RunImpl().
  Release();
}

WebstorePrivateEnableAppLauncherFunction::
    WebstorePrivateEnableAppLauncherFunction() {}

WebstorePrivateEnableAppLauncherFunction::
    ~WebstorePrivateEnableAppLauncherFunction() {}

bool WebstorePrivateEnableAppLauncherFunction::RunImpl() {
  AppListService::Get()->EnableAppList(profile());
  return true;
}

bool WebstorePrivateGetBrowserLoginFunction::RunImpl() {
  GetBrowserLogin::Results::Info info;
  info.login = profile_->GetOriginalProfile()->GetPrefs()->GetString(
      prefs::kGoogleServicesUsername);
  results_ = GetBrowserLogin::Results::Create(info);
  return true;
}

bool WebstorePrivateGetStoreLoginFunction::RunImpl() {
  results_ = GetStoreLogin::Results::Create(GetWebstoreLogin(profile_));
  return true;
}

bool WebstorePrivateSetStoreLoginFunction::RunImpl() {
  scoped_ptr<SetStoreLogin::Params> params(
      SetStoreLogin::Params::Create(*args_));
  EXTENSION_FUNCTION_VALIDATE(params);
  SetWebstoreLogin(profile_, params->login);
  return true;
}

WebstorePrivateGetWebGLStatusFunction::WebstorePrivateGetWebGLStatusFunction() {
  feature_checker_ = new GPUFeatureChecker(
      gpu::GPU_FEATURE_TYPE_WEBGL,
      base::Bind(&WebstorePrivateGetWebGLStatusFunction::OnFeatureCheck,
          base::Unretained(this)));
}

WebstorePrivateGetWebGLStatusFunction::
    ~WebstorePrivateGetWebGLStatusFunction() {}

void WebstorePrivateGetWebGLStatusFunction::CreateResult(bool webgl_allowed) {
  results_ = GetWebGLStatus::Results::Create(GetWebGLStatus::Results::
      ParseWebgl_status(webgl_allowed ? "webgl_allowed" : "webgl_blocked"));
}

bool WebstorePrivateGetWebGLStatusFunction::RunImpl() {
  feature_checker_->CheckGPUFeatureAvailability();
  return true;
}

void WebstorePrivateGetWebGLStatusFunction::
    OnFeatureCheck(bool feature_allowed) {
  CreateResult(feature_allowed);
  SendResponse(true);
}

bool WebstorePrivateGetIsLauncherEnabledFunction::RunImpl() {
  results_ = GetIsLauncherEnabled::Results::Create(IsAppLauncherEnabled());
  return true;
}

bool WebstorePrivateIsInIncognitoModeFunction::RunImpl() {
  results_ = IsInIncognitoMode::Results::Create(
      profile_ != profile_->GetOriginalProfile());
  return true;
}

}  // namespace extensions
