1// Copyright (c) 2012 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "chrome/browser/ui/webui/options/handler_options_handler.h"
6
7#include <vector>
8
9#include "base/bind.h"
10#include "base/bind_helpers.h"
11#include "base/prefs/pref_service.h"
12#include "base/strings/utf_string_conversions.h"
13#include "base/values.h"
14#include "chrome/browser/chrome_notification_types.h"
15#include "chrome/browser/custom_handlers/protocol_handler_registry_factory.h"
16#include "chrome/browser/profiles/profile.h"
17#include "content/public/browser/web_ui.h"
18#include "grit/generated_resources.h"
19#include "ui/base/l10n/l10n_util.h"
20
21namespace options {
22
23HandlerOptionsHandler::HandlerOptionsHandler() {
24}
25
26HandlerOptionsHandler::~HandlerOptionsHandler() {
27}
28
29void HandlerOptionsHandler::GetLocalizedValues(
30    DictionaryValue* localized_strings) {
31  DCHECK(localized_strings);
32
33  static OptionsStringResource resources[] = {
34      { "handlers_tab_label", IDS_HANDLERS_TAB_LABEL },
35      { "handlers_allow", IDS_HANDLERS_ALLOW_RADIO },
36      { "handlers_block", IDS_HANDLERS_DONOTALLOW_RADIO },
37      { "handlers_type_column_header", IDS_HANDLERS_TYPE_COLUMN_HEADER },
38      { "handlers_site_column_header", IDS_HANDLERS_SITE_COLUMN_HEADER },
39      { "handlers_remove_link", IDS_HANDLERS_REMOVE_HANDLER_LINK },
40      { "handlers_none_handler", IDS_HANDLERS_NONE_HANDLER },
41      { "handlers_active_heading", IDS_HANDLERS_ACTIVE_HEADING },
42      { "handlers_ignored_heading", IDS_HANDLERS_IGNORED_HEADING },
43  };
44  RegisterTitle(localized_strings, "handlersPage",
45                IDS_HANDLER_OPTIONS_WINDOW_TITLE);
46  RegisterStrings(localized_strings, resources, arraysize(resources));
47}
48
49void HandlerOptionsHandler::InitializeHandler() {
50  notification_registrar_.Add(
51      this, chrome::NOTIFICATION_PROTOCOL_HANDLER_REGISTRY_CHANGED,
52      content::Source<Profile>(Profile::FromWebUI(web_ui())));
53}
54
55void HandlerOptionsHandler::InitializePage() {
56  UpdateHandlerList();
57}
58
59void HandlerOptionsHandler::RegisterMessages() {
60  web_ui()->RegisterMessageCallback("clearDefault",
61      base::Bind(&HandlerOptionsHandler::ClearDefault,
62                 base::Unretained(this)));
63  web_ui()->RegisterMessageCallback("removeHandler",
64      base::Bind(&HandlerOptionsHandler::RemoveHandler,
65                 base::Unretained(this)));
66  web_ui()->RegisterMessageCallback("setHandlersEnabled",
67      base::Bind(&HandlerOptionsHandler::SetHandlersEnabled,
68                 base::Unretained(this)));
69  web_ui()->RegisterMessageCallback("setDefault",
70      base::Bind(&HandlerOptionsHandler::SetDefault,
71                 base::Unretained(this)));
72  web_ui()->RegisterMessageCallback("removeIgnoredHandler",
73      base::Bind(&HandlerOptionsHandler::RemoveIgnoredHandler,
74                 base::Unretained(this)));
75}
76
77ProtocolHandlerRegistry* HandlerOptionsHandler::GetProtocolHandlerRegistry() {
78  return ProtocolHandlerRegistryFactory::GetForProfile(
79      Profile::FromWebUI(web_ui()));
80}
81
82static void GetHandlersAsListValue(
83    const ProtocolHandlerRegistry::ProtocolHandlerList& handlers,
84    ListValue* handler_list) {
85  ProtocolHandlerRegistry::ProtocolHandlerList::const_iterator handler;
86  for (handler = handlers.begin(); handler != handlers.end(); ++handler) {
87    ListValue* handlerValue = new ListValue();
88    handlerValue->Append(new base::StringValue(handler->protocol()));
89    handlerValue->Append(new base::StringValue(handler->url().spec()));
90    handlerValue->Append(new base::StringValue(handler->title()));
91    handler_list->Append(handlerValue);
92  }
93}
94
95void HandlerOptionsHandler::GetHandlersForProtocol(
96    const std::string& protocol,
97    DictionaryValue* handlers_value) {
98  ProtocolHandlerRegistry* registry = GetProtocolHandlerRegistry();
99  handlers_value->SetString("protocol", protocol);
100  handlers_value->SetInteger("default_handler",
101      registry->GetHandlerIndex(protocol));
102
103  ListValue* handlers_list = new ListValue();
104  GetHandlersAsListValue(registry->GetHandlersFor(protocol), handlers_list);
105  handlers_value->Set("handlers", handlers_list);
106}
107
108void HandlerOptionsHandler::GetIgnoredHandlers(ListValue* handlers) {
109  ProtocolHandlerRegistry* registry = GetProtocolHandlerRegistry();
110  ProtocolHandlerRegistry::ProtocolHandlerList ignored_handlers =
111      registry->GetIgnoredHandlers();
112  return GetHandlersAsListValue(ignored_handlers, handlers);
113}
114
115void HandlerOptionsHandler::UpdateHandlerList() {
116  ProtocolHandlerRegistry* registry = GetProtocolHandlerRegistry();
117  std::vector<std::string> protocols;
118  registry->GetRegisteredProtocols(&protocols);
119
120  ListValue handlers;
121  for (std::vector<std::string>::iterator protocol = protocols.begin();
122       protocol != protocols.end(); protocol++) {
123    DictionaryValue* handler_value = new DictionaryValue();
124    GetHandlersForProtocol(*protocol, handler_value);
125    handlers.Append(handler_value);
126  }
127
128  scoped_ptr<ListValue> ignored_handlers(new ListValue());
129  GetIgnoredHandlers(ignored_handlers.get());
130  web_ui()->CallJavascriptFunction("HandlerOptions.setHandlers", handlers);
131  web_ui()->CallJavascriptFunction("HandlerOptions.setIgnoredHandlers",
132                                   *ignored_handlers);
133}
134
135void HandlerOptionsHandler::RemoveHandler(const ListValue* args) {
136  const ListValue* list;
137  if (!args->GetList(0, &list)) {
138    NOTREACHED();
139    return;
140  }
141
142  ProtocolHandler handler(ParseHandlerFromArgs(list));
143  GetProtocolHandlerRegistry()->RemoveHandler(handler);
144
145  // No need to call UpdateHandlerList() - we should receive a notification
146  // that the ProtocolHandlerRegistry has changed and we will update the view
147  // then.
148}
149
150void HandlerOptionsHandler::RemoveIgnoredHandler(const ListValue* args) {
151  const ListValue* list;
152  if (!args->GetList(0, &list)) {
153    NOTREACHED();
154    return;
155  }
156
157  ProtocolHandler handler(ParseHandlerFromArgs(list));
158  GetProtocolHandlerRegistry()->RemoveIgnoredHandler(handler);
159}
160
161void HandlerOptionsHandler::SetHandlersEnabled(const ListValue* args) {
162  bool enabled = true;
163  CHECK(args->GetBoolean(0, &enabled));
164  if (enabled)
165    GetProtocolHandlerRegistry()->Enable();
166  else
167    GetProtocolHandlerRegistry()->Disable();
168}
169
170void HandlerOptionsHandler::ClearDefault(const ListValue* args) {
171  const Value* value;
172  CHECK(args->Get(0, &value));
173  std::string protocol_to_clear;
174  CHECK(value->GetAsString(&protocol_to_clear));
175  GetProtocolHandlerRegistry()->ClearDefault(protocol_to_clear);
176}
177
178void HandlerOptionsHandler::SetDefault(const ListValue* args) {
179  const ListValue* list;
180  CHECK(args->GetList(0, &list));
181  const ProtocolHandler& handler(ParseHandlerFromArgs(list));
182  CHECK(!handler.IsEmpty());
183  GetProtocolHandlerRegistry()->OnAcceptRegisterProtocolHandler(handler);
184}
185
186ProtocolHandler HandlerOptionsHandler::ParseHandlerFromArgs(
187    const ListValue* args) const {
188  base::string16 protocol;
189  base::string16 url;
190  base::string16 title;
191  bool ok = args->GetString(0, &protocol) && args->GetString(1, &url) &&
192    args->GetString(2, &title);
193  if (!ok)
194    return ProtocolHandler::EmptyProtocolHandler();
195  return ProtocolHandler::CreateProtocolHandler(UTF16ToUTF8(protocol),
196                                                GURL(UTF16ToUTF8(url)),
197                                                title);
198}
199
200void HandlerOptionsHandler::Observe(
201    int type,
202    const content::NotificationSource& source,
203    const content::NotificationDetails& details) {
204  if (type == chrome::NOTIFICATION_PROTOCOL_HANDLER_REGISTRY_CHANGED)
205    UpdateHandlerList();
206  else
207    NOTREACHED();
208}
209
210}  // namespace options
211