195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley// Copyright (c) 2012 The Chromium Authors. All rights reserved.
295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley// Use of this source code is governed by a BSD-style license that can be
395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley// found in the LICENSE file.
495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley#include "chrome/browser/ui/webui/extensions/command_handler.h"
695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley#include "base/bind.h"
895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley#include "base/values.h"
995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley#include "chrome/browser/extensions/api/commands/command_service.h"
1095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley#include "chrome/browser/extensions/extension_commands_global_registry.h"
1195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley#include "chrome/browser/extensions/extension_keybinding_registry.h"
1295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley#include "chrome/browser/profiles/profile.h"
1395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley#include "chrome/grit/generated_resources.h"
1495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley#include "content/public/browser/web_ui.h"
1595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley#include "content/public/browser/web_ui_data_source.h"
1695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley#include "extensions/browser/extension_registry.h"
1795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley#include "extensions/browser/extension_system.h"
1895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley#include "extensions/common/extension_set.h"
1995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley#include "ui/base/l10n/l10n_util.h"
2095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
2195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langleynamespace extensions {
2295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
2395c29f3cd1f6c08c6c0927868683392eea727ccAdam LangleyCommandHandler::CommandHandler(Profile* profile)
2495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley    : profile_(profile),
2595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley      extension_registry_observer_(this) {
2695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley}
2795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
2895c29f3cd1f6c08c6c0927868683392eea727ccAdam LangleyCommandHandler::~CommandHandler() {
2995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley}
3095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
3195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langleyvoid CommandHandler::GetLocalizedValues(content::WebUIDataSource* source) {
3295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  source->AddString("extensionCommandsOverlay",
3395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley      l10n_util::GetStringUTF16(IDS_EXTENSION_COMMANDS_DIALOG_TITLE));
3495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  source->AddString("extensionCommandsEmpty",
3595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley      l10n_util::GetStringUTF16(IDS_EXTENSION_COMMANDS_EMPTY));
3695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  source->AddString("extensionCommandsInactive",
3795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley      l10n_util::GetStringUTF16(IDS_EXTENSION_COMMANDS_INACTIVE));
3895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  source->AddString("extensionCommandsStartTyping",
3995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley      l10n_util::GetStringUTF16(IDS_EXTENSION_TYPE_SHORTCUT));
4095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  source->AddString("extensionCommandsDelete",
4195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley      l10n_util::GetStringUTF16(IDS_EXTENSION_DELETE_SHORTCUT));
4295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  source->AddString("extensionCommandsGlobal",
4395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley      l10n_util::GetStringUTF16(IDS_EXTENSION_COMMANDS_GLOBAL));
4495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  source->AddString("extensionCommandsRegular",
4595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley      l10n_util::GetStringUTF16(IDS_EXTENSION_COMMANDS_NOT_GLOBAL));
4695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  source->AddString("ok", l10n_util::GetStringUTF16(IDS_OK));
4795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley}
4895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
4995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langleyvoid CommandHandler::RegisterMessages() {
5095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  extension_registry_observer_.Add(ExtensionRegistry::Get(profile_));
5195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
5295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  web_ui()->RegisterMessageCallback("extensionCommandsRequestExtensionsData",
5395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley      base::Bind(&CommandHandler::HandleRequestExtensionsData,
5495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley      base::Unretained(this)));
5595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  web_ui()->RegisterMessageCallback("setShortcutHandlingSuspended",
5695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley      base::Bind(&CommandHandler::HandleSetShortcutHandlingSuspended,
5795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley      base::Unretained(this)));
5895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  web_ui()->RegisterMessageCallback("setExtensionCommandShortcut",
5995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley      base::Bind(&CommandHandler::HandleSetExtensionCommandShortcut,
6095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley      base::Unretained(this)));
6195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  web_ui()->RegisterMessageCallback("setCommandScope",
6295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley      base::Bind(&CommandHandler::HandleSetCommandScope,
6395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley      base::Unretained(this)));
6495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley}
6595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
6695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langleyvoid CommandHandler::OnExtensionLoaded(content::BrowserContext* browser_context,
6795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley                                       const Extension* extension) {
6895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  UpdateCommandDataOnPage();
6995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley}
7095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
7195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langleyvoid CommandHandler::OnExtensionUnloaded(
7295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley    content::BrowserContext* browser_context,
7395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley    const Extension* extension,
7495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley    UnloadedExtensionInfo::Reason reason) {
7595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  UpdateCommandDataOnPage();
7695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley}
7795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
7895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langleyvoid CommandHandler::UpdateCommandDataOnPage() {
7995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  base::DictionaryValue results;
8095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  GetAllCommands(&results);
8195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  web_ui()->CallJavascriptFunction(
8295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley      "extensions.ExtensionCommandsOverlay.returnExtensionsData", results);
8395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley}
8495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
8595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langleyvoid CommandHandler::HandleRequestExtensionsData(const base::ListValue* args) {
8695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  UpdateCommandDataOnPage();
8795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley}
8895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
8995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langleyvoid CommandHandler::HandleSetExtensionCommandShortcut(
9095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley    const base::ListValue* args) {
9195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  std::string extension_id;
9295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  std::string command_name;
9395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  std::string keystroke;
9495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  if (!args->GetString(0, &extension_id) ||
9595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley      !args->GetString(1, &command_name) ||
9695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley      !args->GetString(2, &keystroke)) {
9795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley    NOTREACHED();
9895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley    return;
9995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  }
10095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
10195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  Profile* profile = Profile::FromWebUI(web_ui());
10295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  CommandService* command_service = CommandService::Get(profile);
10395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  command_service->UpdateKeybindingPrefs(extension_id, command_name, keystroke);
10495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
10595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  UpdateCommandDataOnPage();
10695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley}
10795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
10895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langleyvoid CommandHandler::HandleSetCommandScope(
10995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley    const base::ListValue* args) {
11095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  std::string extension_id;
11195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  std::string command_name;
11295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  bool global;
11395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  if (!args->GetString(0, &extension_id) ||
11495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley      !args->GetString(1, &command_name) ||
11595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley      !args->GetBoolean(2, &global)) {
11695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley    NOTREACHED();
11795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley    return;
11895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  }
11995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
12095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  Profile* profile = Profile::FromWebUI(web_ui());
12195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  CommandService* command_service = CommandService::Get(profile);
12295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  if (command_service->SetScope(extension_id, command_name, global))
12395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley    UpdateCommandDataOnPage();
12495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley}
12595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
12695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langleyvoid CommandHandler::HandleSetShortcutHandlingSuspended(
12795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley    const base::ListValue* args) {
12895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  bool suspended;
12995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  if (args->GetBoolean(0, &suspended)) {
13095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley    // Suspend/Resume normal shortcut handling.
13195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley    ExtensionKeybindingRegistry::SetShortcutHandlingSuspended(suspended);
13295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
13395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley    // Suspend/Resume global shortcut handling.
13495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley    ExtensionCommandsGlobalRegistry::SetShortcutHandlingSuspended(suspended);
13595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  }
13695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley}
13795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
13895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langleyvoid CommandHandler::GetAllCommands(base::DictionaryValue* commands) {
13995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  base::ListValue* results = new base::ListValue;
14095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
14195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  Profile* profile = Profile::FromWebUI(web_ui());
14295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  CommandService* command_service = CommandService::Get(profile);
14395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
14495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  const ExtensionSet& extensions =
14595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley      ExtensionRegistry::Get(profile)->enabled_extensions();
14695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  for (ExtensionSet::const_iterator extension = extensions.begin();
14795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley       extension != extensions.end();
14895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley       ++extension) {
14995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley    scoped_ptr<base::DictionaryValue> extension_dict(new base::DictionaryValue);
15095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley    extension_dict->SetString("name", (*extension)->name());
15195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley    extension_dict->SetString("id", (*extension)->id());
15295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
15395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley    // Add the keybindings to a list structure.
15495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley    scoped_ptr<base::ListValue> extensions_list(new base::ListValue());
15595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
15695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley    bool active = false;
15795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
15895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley    Command browser_action;
15995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley    if (command_service->GetBrowserActionCommand((*extension)->id(),
16095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley                                                 CommandService::ALL,
16195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley                                                 &browser_action,
16295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley                                                 &active)) {
16395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley      extensions_list->Append(
16495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley          browser_action.ToValue((extension->get()), active));
16595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley    }
16695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
16795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley    Command page_action;
16895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley    if (command_service->GetPageActionCommand((*extension)->id(),
16995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley                                              CommandService::ALL,
17095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley                                              &page_action,
17195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley                                              &active)) {
17295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley      extensions_list->Append(page_action.ToValue((extension->get()), active));
17395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley    }
17495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
17595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley    CommandMap named_commands;
17695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley    if (command_service->GetNamedCommands((*extension)->id(),
17795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley                                          CommandService::ALL,
17895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley                                          CommandService::ANY_SCOPE,
17995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley                                          &named_commands)) {
180d493d5289dd834b65232899c2cd8fe83baddfd44Adam Langley      for (CommandMap::const_iterator iter = named_commands.begin();
181d493d5289dd834b65232899c2cd8fe83baddfd44Adam Langley           iter != named_commands.end();
18295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley           ++iter) {
18395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley        Command command = command_service->FindCommandByName(
18495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley            (*extension)->id(), iter->second.command_name());
18595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley        ui::Accelerator shortcut_assigned = command.accelerator();
18695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
18795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley        active = (shortcut_assigned.key_code() != ui::VKEY_UNKNOWN);
18895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
18995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley        extensions_list->Append(
19095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley            iter->second.ToValue((extension->get()), active));
19195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley      }
19295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley    }
19395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
19495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley    if (!extensions_list->empty()) {
19595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley      extension_dict->Set("commands", extensions_list.release());
19695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley      results->Append(extension_dict.release());
19795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley    }
19895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  }
19995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
20095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  commands->Set("commands", results);
20195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley}
20295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
20395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley}  // namespace extensions
20495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley