// 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/extension_action/extension_action_api.h"

#include <stddef.h>
#include <memory>
#include <utility>

#include "base/lazy_instance.h"
#include "base/location.h"
#include "base/metrics/histogram_macros.h"
#include "base/single_thread_task_runner.h"
#include "base/stl_util.h"
#include "base/strings/string_number_conversions.h"
#include "base/threading/thread_task_runner_handle.h"
#include "base/values.h"
#include "chrome/browser/extensions/extension_action_manager.h"
#include "chrome/browser/extensions/extension_action_runner.h"
#include "chrome/browser/extensions/extension_tab_util.h"
#include "chrome/browser/extensions/extension_ui_util.h"
#include "chrome/browser/extensions/tab_helper.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/sessions/session_tab_helper.h"
#include "chrome/browser/ui/browser.h"
#include "chrome/browser/ui/browser_finder.h"
#include "chrome/browser/ui/browser_window.h"
#include "chrome/browser/ui/tabs/tab_strip_model.h"
#include "chrome/browser/ui/toolbar/toolbar_actions_bar.h"
#include "chrome/common/extensions/api/extension_action/action_info.h"
#include "content/public/browser/notification_service.h"
#include "extensions/browser/event_router.h"
#include "extensions/browser/extension_function_registry.h"
#include "extensions/browser/extension_host.h"
#include "extensions/browser/extension_registry.h"
#include "extensions/browser/extension_util.h"
#include "extensions/browser/notification_types.h"
#include "extensions/common/error_utils.h"
#include "extensions/common/feature_switch.h"
#include "extensions/common/image_util.h"
#include "ui/gfx/image/image.h"
#include "ui/gfx/image/image_skia.h"

using content::WebContents;

namespace extensions {

namespace {

// Whether the browser action is visible in the toolbar.
const char kBrowserActionVisible[] = "browser_action_visible";

// Errors.
const char kNoExtensionActionError[] =
    "This extension has no action specified.";
const char kNoTabError[] = "No tab with id: *.";
const char kOpenPopupError[] =
    "Failed to show popup either because there is an existing popup or another "
    "error occurred.";
const char kInvalidColorError[] =
    "The color specification could not be parsed.";

bool g_report_error_for_invisible_icon = false;

}  // namespace

//
// ExtensionActionAPI::Observer
//

void ExtensionActionAPI::Observer::OnExtensionActionUpdated(
    ExtensionAction* extension_action,
    content::WebContents* web_contents,
    content::BrowserContext* browser_context) {
}

void ExtensionActionAPI::Observer::OnExtensionActionVisibilityChanged(
    const std::string& extension_id,
    bool is_now_visible) {
}

void ExtensionActionAPI::Observer::OnPageActionsUpdated(
    content::WebContents* web_contents) {
}

void ExtensionActionAPI::Observer::OnExtensionActionAPIShuttingDown() {
}

ExtensionActionAPI::Observer::~Observer() {
}

//
// ExtensionActionAPI
//

static base::LazyInstance<BrowserContextKeyedAPIFactory<ExtensionActionAPI>>::
    DestructorAtExit g_extension_action_api_factory = LAZY_INSTANCE_INITIALIZER;

ExtensionActionAPI::ExtensionActionAPI(content::BrowserContext* context)
    : browser_context_(context),
      extension_prefs_(nullptr) {
  ExtensionFunctionRegistry& registry =
      ExtensionFunctionRegistry::GetInstance();

  // Browser Actions
  registry.RegisterFunction<BrowserActionSetIconFunction>();
  registry.RegisterFunction<BrowserActionSetTitleFunction>();
  registry.RegisterFunction<BrowserActionSetBadgeTextFunction>();
  registry.RegisterFunction<BrowserActionSetBadgeBackgroundColorFunction>();
  registry.RegisterFunction<BrowserActionSetPopupFunction>();
  registry.RegisterFunction<BrowserActionGetTitleFunction>();
  registry.RegisterFunction<BrowserActionGetBadgeTextFunction>();
  registry.RegisterFunction<BrowserActionGetBadgeBackgroundColorFunction>();
  registry.RegisterFunction<BrowserActionGetPopupFunction>();
  registry.RegisterFunction<BrowserActionEnableFunction>();
  registry.RegisterFunction<BrowserActionDisableFunction>();
  registry.RegisterFunction<BrowserActionOpenPopupFunction>();

  // Page Actions
  registry.RegisterFunction<PageActionShowFunction>();
  registry.RegisterFunction<PageActionHideFunction>();
  registry.RegisterFunction<PageActionSetIconFunction>();
  registry.RegisterFunction<PageActionSetTitleFunction>();
  registry.RegisterFunction<PageActionSetPopupFunction>();
  registry.RegisterFunction<PageActionGetTitleFunction>();
  registry.RegisterFunction<PageActionGetPopupFunction>();
}

ExtensionActionAPI::~ExtensionActionAPI() {
}

// static
BrowserContextKeyedAPIFactory<ExtensionActionAPI>*
ExtensionActionAPI::GetFactoryInstance() {
  return g_extension_action_api_factory.Pointer();
}

// static
ExtensionActionAPI* ExtensionActionAPI::Get(content::BrowserContext* context) {
  return BrowserContextKeyedAPIFactory<ExtensionActionAPI>::Get(context);
}

void ExtensionActionAPI::AddObserver(Observer* observer) {
  observers_.AddObserver(observer);
}

void ExtensionActionAPI::RemoveObserver(Observer* observer) {
  observers_.RemoveObserver(observer);
}

bool ExtensionActionAPI::GetBrowserActionVisibility(
    const std::string& extension_id) {
  bool visible = false;
  ExtensionPrefs* prefs = GetExtensionPrefs();
  if (!prefs || !prefs->ReadPrefAsBoolean(extension_id,
                                          kBrowserActionVisible,
                                          &visible)) {
    return true;
  }
  return visible;
}

void ExtensionActionAPI::SetBrowserActionVisibility(
    const std::string& extension_id,
    bool visible) {
  if (GetBrowserActionVisibility(extension_id) == visible)
    return;

  GetExtensionPrefs()->UpdateExtensionPref(
      extension_id, kBrowserActionVisible,
      std::make_unique<base::Value>(visible));
  for (auto& observer : observers_)
    observer.OnExtensionActionVisibilityChanged(extension_id, visible);
}

bool ExtensionActionAPI::ShowExtensionActionPopup(
    const Extension* extension,
    Browser* browser,
    bool grant_active_tab_permissions) {
  ExtensionAction* extension_action =
      ExtensionActionManager::Get(browser_context_)->GetExtensionAction(
          *extension);
  if (!extension_action)
    return false;

  // Don't support showing action popups in a popup window.
  if (!browser->SupportsWindowFeature(Browser::FEATURE_TOOLBAR))
    return false;

  ToolbarActionsBar* toolbar_actions_bar =
      browser->window()->GetToolbarActionsBar();
  // ToolbarActionsBar could be null if, e.g., this is a popup window with no
  // toolbar.
  return toolbar_actions_bar &&
         toolbar_actions_bar->ShowToolbarActionPopup(
             extension->id(), grant_active_tab_permissions);
}

void ExtensionActionAPI::NotifyChange(ExtensionAction* extension_action,
                                      content::WebContents* web_contents,
                                      content::BrowserContext* context) {
  for (auto& observer : observers_)
    observer.OnExtensionActionUpdated(extension_action, web_contents, context);

  if (extension_action->action_type() == ActionInfo::TYPE_PAGE)
    NotifyPageActionsChanged(web_contents);
}

void ExtensionActionAPI::DispatchExtensionActionClicked(
    const ExtensionAction& extension_action,
    WebContents* web_contents,
    const Extension* extension) {
  events::HistogramValue histogram_value = events::UNKNOWN;
  const char* event_name = NULL;
  switch (extension_action.action_type()) {
    case ActionInfo::TYPE_BROWSER:
      histogram_value = events::BROWSER_ACTION_ON_CLICKED;
      event_name = "browserAction.onClicked";
      break;
    case ActionInfo::TYPE_PAGE:
      histogram_value = events::PAGE_ACTION_ON_CLICKED;
      event_name = "pageAction.onClicked";
      break;
    case ActionInfo::TYPE_SYSTEM_INDICATOR:
      // The System Indicator handles its own clicks.
      NOTREACHED();
      break;
  }

  if (event_name) {
    std::unique_ptr<base::ListValue> args(new base::ListValue());
    args->Append(ExtensionTabUtil::CreateTabObject(
                     web_contents, ExtensionTabUtil::kScrubTab, extension)
                     ->ToValue());

    DispatchEventToExtension(web_contents->GetBrowserContext(),
                             extension_action.extension_id(), histogram_value,
                             event_name, std::move(args));
  }
}

void ExtensionActionAPI::ClearAllValuesForTab(
    content::WebContents* web_contents) {
  DCHECK(web_contents);
  const SessionID tab_id = SessionTabHelper::IdForTab(web_contents);
  content::BrowserContext* browser_context = web_contents->GetBrowserContext();
  const ExtensionSet& enabled_extensions =
      ExtensionRegistry::Get(browser_context_)->enabled_extensions();
  ExtensionActionManager* action_manager =
      ExtensionActionManager::Get(browser_context_);

  for (ExtensionSet::const_iterator iter = enabled_extensions.begin();
       iter != enabled_extensions.end(); ++iter) {
    ExtensionAction* extension_action =
        action_manager->GetExtensionAction(**iter);
    if (extension_action) {
      extension_action->ClearAllValuesForTab(tab_id.id());
      NotifyChange(extension_action, web_contents, browser_context);
    }
  }
}

ExtensionPrefs* ExtensionActionAPI::GetExtensionPrefs() {
  // This lazy initialization is more than just an optimization, because it
  // allows tests to associate a new ExtensionPrefs with the browser context
  // before we access it.
  if (!extension_prefs_)
    extension_prefs_ = ExtensionPrefs::Get(browser_context_);
  return extension_prefs_;
}

void ExtensionActionAPI::DispatchEventToExtension(
    content::BrowserContext* context,
    const std::string& extension_id,
    events::HistogramValue histogram_value,
    const std::string& event_name,
    std::unique_ptr<base::ListValue> event_args) {
  if (!EventRouter::Get(context))
    return;

  auto event = std::make_unique<Event>(histogram_value, event_name,
                                       std::move(event_args), context);
  event->user_gesture = EventRouter::USER_GESTURE_ENABLED;
  EventRouter::Get(context)
      ->DispatchEventToExtension(extension_id, std::move(event));
}

void ExtensionActionAPI::NotifyPageActionsChanged(
    content::WebContents* web_contents) {
  Browser* browser = chrome::FindBrowserWithWebContents(web_contents);
  if (!browser)
    return;

  for (auto& observer : observers_)
    observer.OnPageActionsUpdated(web_contents);
}

void ExtensionActionAPI::Shutdown() {
  for (auto& observer : observers_)
    observer.OnExtensionActionAPIShuttingDown();
}

//
// ExtensionActionFunction
//

ExtensionActionFunction::ExtensionActionFunction()
    : details_(NULL),
      tab_id_(ExtensionAction::kDefaultTabId),
      contents_(NULL),
      extension_action_(NULL) {
}

ExtensionActionFunction::~ExtensionActionFunction() {
}

ExtensionFunction::ResponseAction ExtensionActionFunction::Run() {
  ExtensionActionManager* manager =
      ExtensionActionManager::Get(browser_context());
  if (base::StartsWith(name(), "systemIndicator.",
                       base::CompareCase::INSENSITIVE_ASCII)) {
    extension_action_ = manager->GetSystemIndicator(*extension());
  } else {
    extension_action_ = manager->GetBrowserAction(*extension());
    if (!extension_action_) {
      extension_action_ = manager->GetPageAction(*extension());
    }
  }
  if (!extension_action_) {
    // TODO(kalman): ideally the browserAction/pageAction APIs wouldn't event
    // exist for extensions that don't have one declared. This should come as
    // part of the Feature system.
    return RespondNow(Error(kNoExtensionActionError));
  }

  // Populates the tab_id_ and details_ members.
  EXTENSION_FUNCTION_VALIDATE(ExtractDataFromArguments());

  // Find the WebContents that contains this tab id if one is required.
  if (tab_id_ != ExtensionAction::kDefaultTabId) {
    ExtensionTabUtil::GetTabById(tab_id_, browser_context(),
                                 include_incognito_information(), nullptr,
                                 nullptr, &contents_, nullptr);
    if (!contents_)
      return RespondNow(Error(kNoTabError, base::IntToString(tab_id_)));
  } else {
    // Only browser actions and system indicators have a default tabId.
    ActionInfo::Type action_type = extension_action_->action_type();
    EXTENSION_FUNCTION_VALIDATE(
        action_type == ActionInfo::TYPE_BROWSER ||
        action_type == ActionInfo::TYPE_SYSTEM_INDICATOR);
  }
  return RunExtensionAction();
}

bool ExtensionActionFunction::ExtractDataFromArguments() {
  // There may or may not be details (depends on the function).
  // The tabId might appear in details (if it exists), as the first
  // argument besides the action type (depends on the function), or be omitted
  // entirely.
  base::Value* first_arg = NULL;
  if (!args_->Get(0, &first_arg))
    return true;

  switch (first_arg->type()) {
    case base::Value::Type::INTEGER:
      CHECK(first_arg->GetAsInteger(&tab_id_));
      break;

    case base::Value::Type::DICTIONARY: {
      // Found the details argument.
      details_ = static_cast<base::DictionaryValue*>(first_arg);
      // Still need to check for the tabId within details.
      base::Value* tab_id_value = NULL;
      if (details_->Get("tabId", &tab_id_value)) {
        switch (tab_id_value->type()) {
          case base::Value::Type::NONE:
            // OK; tabId is optional, leave it default.
            return true;
          case base::Value::Type::INTEGER:
            CHECK(tab_id_value->GetAsInteger(&tab_id_));
            return true;
          default:
            // Boom.
            return false;
        }
      }
      // Not found; tabId is optional, leave it default.
      break;
    }

    case base::Value::Type::NONE:
      // The tabId might be an optional argument.
      break;

    default:
      return false;
  }

  return true;
}

void ExtensionActionFunction::NotifyChange() {
  ExtensionActionAPI::Get(browser_context())
      ->NotifyChange(extension_action_, contents_, browser_context());
}

void ExtensionActionFunction::SetVisible(bool visible) {
  if (extension_action_->GetIsVisible(tab_id_) == visible)
    return;
  extension_action_->SetIsVisible(tab_id_, visible);
  NotifyChange();
}

ExtensionFunction::ResponseAction
ExtensionActionShowFunction::RunExtensionAction() {
  SetVisible(true);
  return RespondNow(NoArguments());
}

ExtensionFunction::ResponseAction
ExtensionActionHideFunction::RunExtensionAction() {
  SetVisible(false);
  return RespondNow(NoArguments());
}

// static
void ExtensionActionSetIconFunction::SetReportErrorForInvisibleIconForTesting(
    bool value) {
  g_report_error_for_invisible_icon = value;
}

ExtensionFunction::ResponseAction
ExtensionActionSetIconFunction::RunExtensionAction() {
  EXTENSION_FUNCTION_VALIDATE(details_);

  // setIcon can take a variant argument: either a dictionary of canvas
  // ImageData, or an icon index.
  base::DictionaryValue* canvas_set = NULL;
  int icon_index;
  if (details_->GetDictionary("imageData", &canvas_set)) {
    gfx::ImageSkia icon;

    EXTENSION_FUNCTION_VALIDATE(
        ExtensionAction::ParseIconFromCanvasDictionary(*canvas_set, &icon));

    if (icon.isNull())
      return RespondNow(Error("Icon invalid."));

    gfx::Image icon_image(icon);
    const SkBitmap bitmap = icon_image.AsBitmap();
    const bool is_visible = image_util::IsIconSufficientlyVisible(bitmap);
    UMA_HISTOGRAM_BOOLEAN("Extensions.DynamicExtensionActionIconWasVisible",
                          is_visible);
    const bool is_visible_rendered =
        extensions::ui_util::IsRenderedIconSufficientlyVisibleForBrowserContext(
            bitmap, browser_context());
    UMA_HISTOGRAM_BOOLEAN(
        "Extensions.DynamicExtensionActionIconWasVisibleRendered",
        is_visible_rendered);

    if (!is_visible && g_report_error_for_invisible_icon)
      return RespondNow(Error("Icon not sufficiently visible."));

    extension_action_->SetIcon(tab_id_, icon_image);
  } else if (details_->GetInteger("iconIndex", &icon_index)) {
    // Obsolete argument: ignore it.
    return RespondNow(NoArguments());
  } else {
    EXTENSION_FUNCTION_VALIDATE(false);
  }
  NotifyChange();
  return RespondNow(NoArguments());
}

ExtensionFunction::ResponseAction
ExtensionActionSetTitleFunction::RunExtensionAction() {
  EXTENSION_FUNCTION_VALIDATE(details_);
  std::string title;
  EXTENSION_FUNCTION_VALIDATE(details_->GetString("title", &title));
  extension_action_->SetTitle(tab_id_, title);
  NotifyChange();
  return RespondNow(NoArguments());
}

ExtensionFunction::ResponseAction
ExtensionActionSetPopupFunction::RunExtensionAction() {
  EXTENSION_FUNCTION_VALIDATE(details_);
  std::string popup_string;
  EXTENSION_FUNCTION_VALIDATE(details_->GetString("popup", &popup_string));

  GURL popup_url;
  if (!popup_string.empty())
    popup_url = extension()->GetResourceURL(popup_string);

  extension_action_->SetPopupUrl(tab_id_, popup_url);
  NotifyChange();
  return RespondNow(NoArguments());
}

ExtensionFunction::ResponseAction
ExtensionActionSetBadgeTextFunction::RunExtensionAction() {
  EXTENSION_FUNCTION_VALIDATE(details_);
  std::string badge_text;
  EXTENSION_FUNCTION_VALIDATE(details_->GetString("text", &badge_text));
  extension_action_->SetBadgeText(tab_id_, badge_text);
  NotifyChange();
  return RespondNow(NoArguments());
}

ExtensionFunction::ResponseAction
ExtensionActionSetBadgeBackgroundColorFunction::RunExtensionAction() {
  EXTENSION_FUNCTION_VALIDATE(details_);
  base::Value* color_value = NULL;
  EXTENSION_FUNCTION_VALIDATE(details_->Get("color", &color_value));
  SkColor color = 0;
  if (color_value->is_list()) {
    base::ListValue* list = NULL;
    EXTENSION_FUNCTION_VALIDATE(details_->GetList("color", &list));
    EXTENSION_FUNCTION_VALIDATE(list->GetSize() == 4);

    int color_array[4] = {0};
    for (size_t i = 0; i < base::size(color_array); ++i) {
      EXTENSION_FUNCTION_VALIDATE(list->GetInteger(i, &color_array[i]));
    }

    color = SkColorSetARGB(color_array[3], color_array[0],
                           color_array[1], color_array[2]);
  } else if (color_value->is_string()) {
    std::string color_string;
    EXTENSION_FUNCTION_VALIDATE(details_->GetString("color", &color_string));
    if (!image_util::ParseCssColorString(color_string, &color))
      return RespondNow(Error(kInvalidColorError));
  }

  extension_action_->SetBadgeBackgroundColor(tab_id_, color);
  NotifyChange();
  return RespondNow(NoArguments());
}

ExtensionFunction::ResponseAction
ExtensionActionGetTitleFunction::RunExtensionAction() {
  return RespondNow(OneArgument(
      std::make_unique<base::Value>(extension_action_->GetTitle(tab_id_))));
}

ExtensionFunction::ResponseAction
ExtensionActionGetPopupFunction::RunExtensionAction() {
  return RespondNow(OneArgument(std::make_unique<base::Value>(
      extension_action_->GetPopupUrl(tab_id_).spec())));
}

ExtensionFunction::ResponseAction
ExtensionActionGetBadgeTextFunction::RunExtensionAction() {
  return RespondNow(OneArgument(
      std::make_unique<base::Value>(extension_action_->GetBadgeText(tab_id_))));
}

ExtensionFunction::ResponseAction
ExtensionActionGetBadgeBackgroundColorFunction::RunExtensionAction() {
  std::unique_ptr<base::ListValue> list(new base::ListValue());
  SkColor color = extension_action_->GetBadgeBackgroundColor(tab_id_);
  list->AppendInteger(static_cast<int>(SkColorGetR(color)));
  list->AppendInteger(static_cast<int>(SkColorGetG(color)));
  list->AppendInteger(static_cast<int>(SkColorGetB(color)));
  list->AppendInteger(static_cast<int>(SkColorGetA(color)));
  return RespondNow(OneArgument(std::move(list)));
}

BrowserActionOpenPopupFunction::BrowserActionOpenPopupFunction() = default;

ExtensionFunction::ResponseAction BrowserActionOpenPopupFunction::Run() {
  // We only allow the popup in the active window.
  Profile* profile = Profile::FromBrowserContext(browser_context());
  Browser* browser = chrome::FindLastActiveWithProfile(profile);
  // It's possible that the last active browser actually corresponds to the
  // associated incognito profile, and this won't be returned by
  // FindLastActiveWithProfile. If the browser we found isn't active and the
  // extension can operate incognito, then check the last active incognito, too.
  if ((!browser || !browser->window()->IsActive()) &&
      util::IsIncognitoEnabled(extension()->id(), profile) &&
      profile->HasOffTheRecordProfile()) {
    browser =
        chrome::FindLastActiveWithProfile(profile->GetOffTheRecordProfile());
  }

  // If there's no active browser, or the Toolbar isn't visible, abort.
  // Otherwise, try to open a popup in the active browser.
  // TODO(justinlin): Remove toolbar check when http://crbug.com/308645 is
  // fixed.
  if (!browser || !browser->window()->IsActive() ||
      !browser->window()->IsToolbarVisible() ||
      !ExtensionActionAPI::Get(profile)->ShowExtensionActionPopup(
          extension_.get(), browser, false)) {
    return RespondNow(Error(kOpenPopupError));
  }

  // Even if this is for an incognito window, we want to use the normal profile.
  // If the extension is spanning, then extension hosts are created with the
  // original profile, and if it's split, then we know the api call came from
  // the right profile.
  registrar_.Add(this, NOTIFICATION_EXTENSION_HOST_DID_STOP_FIRST_LOAD,
                 content::Source<Profile>(profile));

  // Set a timeout for waiting for the notification that the popup is loaded.
  // Waiting is required so that the popup view can be retrieved by the custom
  // bindings for the response callback. It's also needed to keep this function
  // instance around until a notification is observed.
  base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
      FROM_HERE,
      base::BindOnce(&BrowserActionOpenPopupFunction::OpenPopupTimedOut, this),
      base::TimeDelta::FromSeconds(10));
  return RespondLater();
}

void BrowserActionOpenPopupFunction::OpenPopupTimedOut() {
  if (did_respond())
    return;

  DVLOG(1) << "chrome.browserAction.openPopup did not show a popup.";
  Respond(Error(kOpenPopupError));
}

void BrowserActionOpenPopupFunction::Observe(
    int type,
    const content::NotificationSource& source,
    const content::NotificationDetails& details) {
  DCHECK_EQ(NOTIFICATION_EXTENSION_HOST_DID_STOP_FIRST_LOAD, type);
  if (did_respond())
    return;

  ExtensionHost* host = content::Details<ExtensionHost>(details).ptr();
  if (host->extension_host_type() != VIEW_TYPE_EXTENSION_POPUP ||
      host->extension()->id() != extension_->id())
    return;

  Respond(NoArguments());
  registrar_.RemoveAll();
}

}  // namespace extensions
