1 // Copyright (c) 2011 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/content_settings_handler.h"
6
7 #include "base/callback.h"
8 #include "base/command_line.h"
9 #include "base/utf_string_conversions.h"
10 #include "base/values.h"
11 #include "chrome/browser/browser_process.h"
12 #include "chrome/browser/content_settings/content_settings_details.h"
13 #include "chrome/browser/content_settings/host_content_settings_map.h"
14 #include "chrome/browser/geolocation/geolocation_content_settings_map.h"
15 #include "chrome/browser/notifications/desktop_notification_service.h"
16 #include "chrome/browser/notifications/desktop_notification_service_factory.h"
17 #include "chrome/browser/profiles/profile.h"
18 #include "chrome/browser/ui/browser_list.h"
19 #include "chrome/common/chrome_switches.h"
20 #include "chrome/common/content_settings_helper.h"
21 #include "chrome/common/pref_names.h"
22 #include "chrome/common/url_constants.h"
23 #include "content/common/notification_service.h"
24 #include "content/common/notification_source.h"
25 #include "content/common/notification_type.h"
26 #include "grit/generated_resources.h"
27 #include "grit/locale_settings.h"
28 #include "ui/base/l10n/l10n_util.h"
29
30 namespace {
31
32 const char* kDisplayPattern = "displayPattern";
33 const char* kSetting = "setting";
34 const char* kOrigin = "origin";
35 const char* kEmbeddingOrigin = "embeddingOrigin";
36
37 const char* const kContentSettingsTypeGroupNames[] = {
38 "cookies",
39 "images",
40 "javascript",
41 "plugins",
42 "popups",
43 "location",
44 "notifications",
45 "prerender",
46 };
47 COMPILE_ASSERT(arraysize(kContentSettingsTypeGroupNames) ==
48 CONTENT_SETTINGS_NUM_TYPES,
49 invalid_content_settings_type_group_names_size);
50
51
ContentSettingsTypeFromGroupName(const std::string & name)52 ContentSettingsType ContentSettingsTypeFromGroupName(const std::string& name) {
53
54 for (int content_settings_type = CONTENT_SETTINGS_TYPE_COOKIES;
55 content_settings_type < CONTENT_SETTINGS_NUM_TYPES;
56 ++content_settings_type) {
57 if (name == kContentSettingsTypeGroupNames[content_settings_type])
58 return static_cast<ContentSettingsType>(content_settings_type);
59 }
60
61 NOTREACHED() << name << " is not a recognized content settings type.";
62 return CONTENT_SETTINGS_TYPE_DEFAULT;
63 }
64
ContentSettingToString(ContentSetting setting)65 std::string ContentSettingToString(ContentSetting setting) {
66 switch (setting) {
67 case CONTENT_SETTING_ALLOW:
68 return "allow";
69 case CONTENT_SETTING_ASK:
70 return "ask";
71 case CONTENT_SETTING_BLOCK:
72 return "block";
73 case CONTENT_SETTING_SESSION_ONLY:
74 return "session";
75 case CONTENT_SETTING_DEFAULT:
76 return "default";
77 case CONTENT_SETTING_NUM_SETTINGS:
78 NOTREACHED();
79 }
80
81 return "";
82 }
83
ContentSettingFromString(const std::string & name)84 ContentSetting ContentSettingFromString(const std::string& name) {
85 if (name == "allow")
86 return CONTENT_SETTING_ALLOW;
87 if (name == "ask")
88 return CONTENT_SETTING_ASK;
89 if (name == "block")
90 return CONTENT_SETTING_BLOCK;
91 if (name == "session")
92 return CONTENT_SETTING_SESSION_ONLY;
93
94 NOTREACHED() << name << " is not a recognized content setting.";
95 return CONTENT_SETTING_DEFAULT;
96 }
97
GeolocationExceptionToString(const GURL & origin,const GURL & embedding_origin)98 std::string GeolocationExceptionToString(const GURL& origin,
99 const GURL& embedding_origin) {
100 if (origin == embedding_origin)
101 return content_settings_helper::OriginToString(origin);
102
103 // TODO(estade): the page needs to use CSS to indent the string.
104 std::string indent(" ");
105 if (embedding_origin.is_empty()) {
106 // NOTE: As long as the user cannot add/edit entries from the exceptions
107 // dialog, it's impossible to actually have a non-default setting for some
108 // origin "embedded on any other site", so this row will never appear. If
109 // we add the ability to add/edit exceptions, we'll need to decide when to
110 // display this and how "removing" it will function.
111 return indent +
112 l10n_util::GetStringUTF8(IDS_EXCEPTIONS_GEOLOCATION_EMBEDDED_ANY_OTHER);
113 }
114
115 return indent + l10n_util::GetStringFUTF8(
116 IDS_EXCEPTIONS_GEOLOCATION_EMBEDDED_ON_HOST,
117 UTF8ToUTF16(content_settings_helper::OriginToString(embedding_origin)));
118 }
119
120 // Create a DictionaryValue* that will act as a data source for a single row
121 // in a HostContentSettingsMap-controlled exceptions table (e.g., cookies).
122 // Ownership of the pointer is passed to the caller.
GetExceptionForPage(const ContentSettingsPattern & pattern,ContentSetting setting)123 DictionaryValue* GetExceptionForPage(
124 const ContentSettingsPattern& pattern,
125 ContentSetting setting) {
126 DictionaryValue* exception = new DictionaryValue();
127 exception->Set(
128 kDisplayPattern,
129 new StringValue(pattern.AsString()));
130 exception->Set(
131 kSetting,
132 new StringValue(ContentSettingToString(setting)));
133 return exception;
134 }
135
136 // Create a DictionaryValue* that will act as a data source for a single row
137 // in the Geolocation exceptions table. Ownership of the pointer is passed to
138 // the caller.
GetGeolocationExceptionForPage(const GURL & origin,const GURL & embedding_origin,ContentSetting setting)139 DictionaryValue* GetGeolocationExceptionForPage(const GURL& origin,
140 const GURL& embedding_origin,
141 ContentSetting setting) {
142 DictionaryValue* exception = new DictionaryValue();
143 exception->Set(
144 kDisplayPattern,
145 new StringValue(GeolocationExceptionToString(origin, embedding_origin)));
146 exception->Set(
147 kSetting,
148 new StringValue(ContentSettingToString(setting)));
149 exception->Set(
150 kOrigin,
151 new StringValue(origin.spec()));
152 exception->Set(
153 kEmbeddingOrigin,
154 new StringValue(embedding_origin.spec()));
155 return exception;
156 }
157
158 // Create a DictionaryValue* that will act as a data source for a single row
159 // in the desktop notifications exceptions table. Ownership of the pointer is
160 // passed to the caller.
GetNotificationExceptionForPage(const GURL & url,ContentSetting setting)161 DictionaryValue* GetNotificationExceptionForPage(
162 const GURL& url,
163 ContentSetting setting) {
164 DictionaryValue* exception = new DictionaryValue();
165 exception->Set(
166 kDisplayPattern,
167 new StringValue(content_settings_helper::OriginToString(url)));
168 exception->Set(
169 kSetting,
170 new StringValue(ContentSettingToString(setting)));
171 exception->Set(
172 kOrigin,
173 new StringValue(url.spec()));
174 return exception;
175 }
176
177 } // namespace
178
ContentSettingsHandler()179 ContentSettingsHandler::ContentSettingsHandler() {
180 }
181
~ContentSettingsHandler()182 ContentSettingsHandler::~ContentSettingsHandler() {
183 }
184
GetLocalizedValues(DictionaryValue * localized_strings)185 void ContentSettingsHandler::GetLocalizedValues(
186 DictionaryValue* localized_strings) {
187 DCHECK(localized_strings);
188
189 static OptionsStringResource resources[] = {
190 { "content_exceptions", IDS_COOKIES_EXCEPTIONS_BUTTON },
191 { "allowException", IDS_EXCEPTIONS_ALLOW_BUTTON },
192 { "blockException", IDS_EXCEPTIONS_BLOCK_BUTTON },
193 { "sessionException", IDS_EXCEPTIONS_SESSION_ONLY_BUTTON },
194 { "askException", IDS_EXCEPTIONS_ASK_BUTTON },
195 { "addExceptionRow", IDS_EXCEPTIONS_ADD_BUTTON },
196 { "removeExceptionRow", IDS_EXCEPTIONS_REMOVE_BUTTON },
197 { "editExceptionRow", IDS_EXCEPTIONS_EDIT_BUTTON },
198 { "otr_exceptions_explanation", IDS_EXCEPTIONS_OTR_LABEL },
199 { "examplePattern", IDS_EXCEPTIONS_PATTERN_EXAMPLE },
200 { "addNewExceptionInstructions", IDS_EXCEPTIONS_ADD_NEW_INSTRUCTIONS },
201 { "manage_exceptions", IDS_EXCEPTIONS_MANAGE },
202 { "exceptionPatternHeader", IDS_EXCEPTIONS_PATTERN_HEADER },
203 { "exceptionBehaviorHeader", IDS_EXCEPTIONS_ACTION_HEADER },
204 // Cookies filter.
205 { "cookies_tab_label", IDS_COOKIES_TAB_LABEL },
206 { "cookies_header", IDS_COOKIES_HEADER },
207 { "cookies_allow", IDS_COOKIES_ALLOW_RADIO },
208 { "cookies_ask", IDS_COOKIES_ASK_EVERY_TIME_RADIO },
209 { "cookies_block", IDS_COOKIES_BLOCK_RADIO },
210 { "cookies_block_3rd_party", IDS_COOKIES_BLOCK_3RDPARTY_CHKBOX },
211 { "cookies_clear_when_close", IDS_COOKIES_CLEAR_WHEN_CLOSE_CHKBOX },
212 { "cookies_lso_clear_when_close", IDS_COOKIES_LSO_CLEAR_WHEN_CLOSE_CHKBOX },
213 { "cookies_show_cookies", IDS_COOKIES_SHOW_COOKIES_BUTTON },
214 { "flash_storage_settings", IDS_FLASH_STORAGE_SETTINGS },
215 { "flash_storage_url", IDS_FLASH_STORAGE_URL },
216 // Image filter.
217 { "images_tab_label", IDS_IMAGES_TAB_LABEL },
218 { "images_header", IDS_IMAGES_HEADER },
219 { "images_allow", IDS_IMAGES_LOAD_RADIO },
220 { "images_block", IDS_IMAGES_NOLOAD_RADIO },
221 // JavaScript filter.
222 { "javascript_tab_label", IDS_JAVASCRIPT_TAB_LABEL },
223 { "javascript_header", IDS_JAVASCRIPT_HEADER },
224 { "javascript_allow", IDS_JS_ALLOW_RADIO },
225 { "javascript_block", IDS_JS_DONOTALLOW_RADIO },
226 // Plug-ins filter.
227 { "plugins_tab_label", IDS_PLUGIN_TAB_LABEL },
228 { "plugins_header", IDS_PLUGIN_HEADER },
229 { "plugins_ask", IDS_PLUGIN_ASK_RADIO },
230 { "plugins_allow", IDS_PLUGIN_LOAD_RADIO },
231 { "plugins_block", IDS_PLUGIN_NOLOAD_RADIO },
232 { "disable_individual_plugins", IDS_PLUGIN_SELECTIVE_DISABLE },
233 // Pop-ups filter.
234 { "popups_tab_label", IDS_POPUP_TAB_LABEL },
235 { "popups_header", IDS_POPUP_HEADER },
236 { "popups_allow", IDS_POPUP_ALLOW_RADIO },
237 { "popups_block", IDS_POPUP_BLOCK_RADIO },
238 // Location filter.
239 { "location_tab_label", IDS_GEOLOCATION_TAB_LABEL },
240 { "location_header", IDS_GEOLOCATION_HEADER },
241 { "location_allow", IDS_GEOLOCATION_ALLOW_RADIO },
242 { "location_ask", IDS_GEOLOCATION_ASK_RADIO },
243 { "location_block", IDS_GEOLOCATION_BLOCK_RADIO },
244 // Notifications filter.
245 { "notifications_tab_label", IDS_NOTIFICATIONS_TAB_LABEL },
246 { "notifications_header", IDS_NOTIFICATIONS_HEADER },
247 { "notifications_allow", IDS_NOTIFICATIONS_ALLOW_RADIO },
248 { "notifications_ask", IDS_NOTIFICATIONS_ASK_RADIO },
249 { "notifications_block", IDS_NOTIFICATIONS_BLOCK_RADIO },
250 };
251
252 RegisterStrings(localized_strings, resources, arraysize(resources));
253 RegisterTitle(localized_strings, "contentSettingsPage",
254 IDS_CONTENT_SETTINGS_TITLE);
255 localized_strings->SetBoolean("enable_click_to_play",
256 CommandLine::ForCurrentProcess()->HasSwitch(
257 switches::kEnableClickToPlay));
258 }
259
Initialize()260 void ContentSettingsHandler::Initialize() {
261 const HostContentSettingsMap* settings_map = GetContentSettingsMap();
262 scoped_ptr<Value> block_3rd_party(Value::CreateBooleanValue(
263 settings_map->BlockThirdPartyCookies()));
264 web_ui_->CallJavascriptFunction("ContentSettings.setBlockThirdPartyCookies",
265 *block_3rd_party.get());
266
267 notification_registrar_.Add(
268 this, NotificationType::OTR_PROFILE_CREATED,
269 NotificationService::AllSources());
270 notification_registrar_.Add(
271 this, NotificationType::PROFILE_DESTROYED,
272 NotificationService::AllSources());
273
274 UpdateAllExceptionsViewsFromModel();
275 notification_registrar_.Add(
276 this, NotificationType::CONTENT_SETTINGS_CHANGED,
277 NotificationService::AllSources());
278 notification_registrar_.Add(
279 this, NotificationType::DESKTOP_NOTIFICATION_DEFAULT_CHANGED,
280 NotificationService::AllSources());
281 notification_registrar_.Add(
282 this, NotificationType::DESKTOP_NOTIFICATION_SETTINGS_CHANGED,
283 NotificationService::AllSources());
284
285 PrefService* prefs = web_ui_->GetProfile()->GetPrefs();
286 pref_change_registrar_.Init(prefs);
287 pref_change_registrar_.Add(prefs::kGeolocationDefaultContentSetting, this);
288 pref_change_registrar_.Add(prefs::kGeolocationContentSettings, this);
289 }
290
Observe(NotificationType type,const NotificationSource & source,const NotificationDetails & details)291 void ContentSettingsHandler::Observe(NotificationType type,
292 const NotificationSource& source,
293 const NotificationDetails& details) {
294 switch (type.value) {
295 case NotificationType::PROFILE_DESTROYED: {
296 Profile* profile = static_cast<Source<Profile> >(source).ptr();
297 if (profile->IsOffTheRecord()) {
298 web_ui_->CallJavascriptFunction(
299 "ContentSettingsExceptionsArea.OTRProfileDestroyed");
300 }
301 break;
302 }
303
304 case NotificationType::OTR_PROFILE_CREATED: {
305 UpdateAllOTRExceptionsViewsFromModel();
306 break;
307 }
308
309 case NotificationType::CONTENT_SETTINGS_CHANGED: {
310 const ContentSettingsDetails* settings_details =
311 Details<const ContentSettingsDetails>(details).ptr();
312
313 // TODO(estade): we pretend update_all() is always true.
314 if (settings_details->update_all_types())
315 UpdateAllExceptionsViewsFromModel();
316 else
317 UpdateExceptionsViewFromModel(settings_details->type());
318 break;
319 }
320
321 case NotificationType::PREF_CHANGED: {
322 const std::string& pref_name = *Details<std::string>(details).ptr();
323 if (pref_name == prefs::kGeolocationDefaultContentSetting)
324 UpdateSettingDefaultFromModel(CONTENT_SETTINGS_TYPE_GEOLOCATION);
325 else if (pref_name == prefs::kGeolocationContentSettings)
326 UpdateGeolocationExceptionsView();
327 break;
328 }
329
330 case NotificationType::DESKTOP_NOTIFICATION_DEFAULT_CHANGED: {
331 UpdateSettingDefaultFromModel(CONTENT_SETTINGS_TYPE_NOTIFICATIONS);
332 break;
333 }
334
335 case NotificationType::DESKTOP_NOTIFICATION_SETTINGS_CHANGED: {
336 UpdateNotificationExceptionsView();
337 break;
338 }
339
340 default:
341 OptionsPageUIHandler::Observe(type, source, details);
342 }
343 }
344
UpdateSettingDefaultFromModel(ContentSettingsType type)345 void ContentSettingsHandler::UpdateSettingDefaultFromModel(
346 ContentSettingsType type) {
347 DictionaryValue filter_settings;
348 filter_settings.SetString(ContentSettingsTypeToGroupName(type) + ".value",
349 GetSettingDefaultFromModel(type));
350 filter_settings.SetBoolean(ContentSettingsTypeToGroupName(type) + ".managed",
351 GetDefaultSettingManagedFromModel(type));
352
353 web_ui_->CallJavascriptFunction(
354 "ContentSettings.setContentFilterSettingsValue", filter_settings);
355 }
356
GetSettingDefaultFromModel(ContentSettingsType type)357 std::string ContentSettingsHandler::GetSettingDefaultFromModel(
358 ContentSettingsType type) {
359 ContentSetting default_setting;
360 if (type == CONTENT_SETTINGS_TYPE_GEOLOCATION) {
361 default_setting = web_ui_->GetProfile()->
362 GetGeolocationContentSettingsMap()->GetDefaultContentSetting();
363 } else if (type == CONTENT_SETTINGS_TYPE_NOTIFICATIONS) {
364 default_setting = DesktopNotificationServiceFactory::GetForProfile(
365 web_ui_->GetProfile())->GetDefaultContentSetting();
366 } else {
367 default_setting = GetContentSettingsMap()->GetDefaultContentSetting(type);
368 }
369
370 return ContentSettingToString(default_setting);
371 }
372
GetDefaultSettingManagedFromModel(ContentSettingsType type)373 bool ContentSettingsHandler::GetDefaultSettingManagedFromModel(
374 ContentSettingsType type) {
375 if (type == CONTENT_SETTINGS_TYPE_GEOLOCATION) {
376 return web_ui_->GetProfile()->
377 GetGeolocationContentSettingsMap()->IsDefaultContentSettingManaged();
378 } else if (type == CONTENT_SETTINGS_TYPE_NOTIFICATIONS) {
379 return DesktopNotificationServiceFactory::GetForProfile(
380 web_ui_->GetProfile())->IsDefaultContentSettingManaged();
381 } else {
382 return GetContentSettingsMap()->IsDefaultContentSettingManaged(type);
383 }
384 }
385
UpdateAllExceptionsViewsFromModel()386 void ContentSettingsHandler::UpdateAllExceptionsViewsFromModel() {
387 for (int type = CONTENT_SETTINGS_TYPE_DEFAULT + 1;
388 type < CONTENT_SETTINGS_NUM_TYPES; ++type) {
389 UpdateExceptionsViewFromModel(static_cast<ContentSettingsType>(type));
390 }
391 }
392
UpdateAllOTRExceptionsViewsFromModel()393 void ContentSettingsHandler::UpdateAllOTRExceptionsViewsFromModel() {
394 for (int type = CONTENT_SETTINGS_TYPE_DEFAULT + 1;
395 type < CONTENT_SETTINGS_NUM_TYPES; ++type) {
396 UpdateOTRExceptionsViewFromModel(static_cast<ContentSettingsType>(type));
397 }
398 }
399
UpdateExceptionsViewFromModel(ContentSettingsType type)400 void ContentSettingsHandler::UpdateExceptionsViewFromModel(
401 ContentSettingsType type) {
402 switch (type) {
403 case CONTENT_SETTINGS_TYPE_GEOLOCATION:
404 UpdateGeolocationExceptionsView();
405 break;
406 case CONTENT_SETTINGS_TYPE_NOTIFICATIONS:
407 UpdateNotificationExceptionsView();
408 break;
409 case CONTENT_SETTINGS_TYPE_PRERENDER:
410 // Prerender is currently (02/24/2011) an experimental feature which is
411 // only turned on via about:flags. There is intentionally no UI in
412 // chrome://preferences for CONTENT_SETTINGS_TYPE_PRERENDER.
413 // TODO(cbentzel): Change once prerender moves out of about:flags.
414 break;
415 default:
416 UpdateExceptionsViewFromHostContentSettingsMap(type);
417 break;
418 }
419 }
420
UpdateOTRExceptionsViewFromModel(ContentSettingsType type)421 void ContentSettingsHandler::UpdateOTRExceptionsViewFromModel(
422 ContentSettingsType type) {
423 switch (type) {
424 case CONTENT_SETTINGS_TYPE_GEOLOCATION:
425 case CONTENT_SETTINGS_TYPE_NOTIFICATIONS:
426 case CONTENT_SETTINGS_TYPE_PRERENDER:
427 break;
428 default:
429 UpdateExceptionsViewFromOTRHostContentSettingsMap(type);
430 break;
431 }
432 }
433
UpdateGeolocationExceptionsView()434 void ContentSettingsHandler::UpdateGeolocationExceptionsView() {
435 GeolocationContentSettingsMap* map =
436 web_ui_->GetProfile()->GetGeolocationContentSettingsMap();
437 GeolocationContentSettingsMap::AllOriginsSettings all_settings =
438 map->GetAllOriginsSettings();
439 GeolocationContentSettingsMap::AllOriginsSettings::const_iterator i;
440
441 ListValue exceptions;
442 for (i = all_settings.begin(); i != all_settings.end(); ++i) {
443 const GURL& origin = i->first;
444 const GeolocationContentSettingsMap::OneOriginSettings& one_settings =
445 i->second;
446
447 GeolocationContentSettingsMap::OneOriginSettings::const_iterator parent =
448 one_settings.find(origin);
449
450 // Add the "parent" entry for the non-embedded setting.
451 ContentSetting parent_setting =
452 parent == one_settings.end() ? CONTENT_SETTING_DEFAULT : parent->second;
453 exceptions.Append(
454 GetGeolocationExceptionForPage(origin, origin, parent_setting));
455
456 // Add the "children" for any embedded settings.
457 GeolocationContentSettingsMap::OneOriginSettings::const_iterator j;
458 for (j = one_settings.begin(); j != one_settings.end(); ++j) {
459 // Skip the non-embedded setting which we already added above.
460 if (j == parent)
461 continue;
462
463 exceptions.Append(
464 GetGeolocationExceptionForPage(origin, j->first, j->second));
465 }
466 }
467
468 StringValue type_string(
469 ContentSettingsTypeToGroupName(CONTENT_SETTINGS_TYPE_GEOLOCATION));
470 web_ui_->CallJavascriptFunction("ContentSettings.setExceptions",
471 type_string, exceptions);
472
473 // This is mainly here to keep this function ideologically parallel to
474 // UpdateExceptionsViewFromHostContentSettingsMap().
475 UpdateSettingDefaultFromModel(CONTENT_SETTINGS_TYPE_GEOLOCATION);
476 }
477
UpdateNotificationExceptionsView()478 void ContentSettingsHandler::UpdateNotificationExceptionsView() {
479 DesktopNotificationService* service =
480 DesktopNotificationServiceFactory::GetForProfile(web_ui_->GetProfile());
481
482 std::vector<GURL> allowed(service->GetAllowedOrigins());
483 std::vector<GURL> blocked(service->GetBlockedOrigins());
484
485 ListValue exceptions;
486 for (size_t i = 0; i < allowed.size(); ++i) {
487 exceptions.Append(
488 GetNotificationExceptionForPage(allowed[i], CONTENT_SETTING_ALLOW));
489 }
490 for (size_t i = 0; i < blocked.size(); ++i) {
491 exceptions.Append(
492 GetNotificationExceptionForPage(blocked[i], CONTENT_SETTING_BLOCK));
493 }
494
495 StringValue type_string(
496 ContentSettingsTypeToGroupName(CONTENT_SETTINGS_TYPE_NOTIFICATIONS));
497 web_ui_->CallJavascriptFunction("ContentSettings.setExceptions",
498 type_string, exceptions);
499
500 // This is mainly here to keep this function ideologically parallel to
501 // UpdateExceptionsViewFromHostContentSettingsMap().
502 UpdateSettingDefaultFromModel(CONTENT_SETTINGS_TYPE_NOTIFICATIONS);
503 }
504
UpdateExceptionsViewFromHostContentSettingsMap(ContentSettingsType type)505 void ContentSettingsHandler::UpdateExceptionsViewFromHostContentSettingsMap(
506 ContentSettingsType type) {
507 HostContentSettingsMap::SettingsForOneType entries;
508 GetContentSettingsMap()->GetSettingsForOneType(type, "", &entries);
509
510 ListValue exceptions;
511 for (size_t i = 0; i < entries.size(); ++i) {
512 exceptions.Append(GetExceptionForPage(entries[i].first, entries[i].second));
513 }
514
515 StringValue type_string(ContentSettingsTypeToGroupName(type));
516 web_ui_->CallJavascriptFunction("ContentSettings.setExceptions", type_string,
517 exceptions);
518
519 UpdateExceptionsViewFromOTRHostContentSettingsMap(type);
520
521 // The default may also have changed (we won't get a separate notification).
522 // If it hasn't changed, this call will be harmless.
523 UpdateSettingDefaultFromModel(type);
524 }
525
UpdateExceptionsViewFromOTRHostContentSettingsMap(ContentSettingsType type)526 void ContentSettingsHandler::UpdateExceptionsViewFromOTRHostContentSettingsMap(
527 ContentSettingsType type) {
528 const HostContentSettingsMap* otr_settings_map = GetOTRContentSettingsMap();
529 if (!otr_settings_map)
530 return;
531
532 HostContentSettingsMap::SettingsForOneType otr_entries;
533 otr_settings_map->GetSettingsForOneType(type, "", &otr_entries);
534
535 ListValue otr_exceptions;
536 for (size_t i = 0; i < otr_entries.size(); ++i) {
537 otr_exceptions.Append(GetExceptionForPage(otr_entries[i].first,
538 otr_entries[i].second));
539 }
540
541 StringValue type_string(ContentSettingsTypeToGroupName(type));
542 web_ui_->CallJavascriptFunction("ContentSettings.setOTRExceptions",
543 type_string, otr_exceptions);
544 }
545
RegisterMessages()546 void ContentSettingsHandler::RegisterMessages() {
547 web_ui_->RegisterMessageCallback("setContentFilter",
548 NewCallback(this,
549 &ContentSettingsHandler::SetContentFilter));
550 web_ui_->RegisterMessageCallback("setAllowThirdPartyCookies",
551 NewCallback(this,
552 &ContentSettingsHandler::SetAllowThirdPartyCookies));
553 web_ui_->RegisterMessageCallback("removeException",
554 NewCallback(this,
555 &ContentSettingsHandler::RemoveException));
556 web_ui_->RegisterMessageCallback("setException",
557 NewCallback(this,
558 &ContentSettingsHandler::SetException));
559 web_ui_->RegisterMessageCallback("checkExceptionPatternValidity",
560 NewCallback(this,
561 &ContentSettingsHandler::CheckExceptionPatternValidity));
562 }
563
SetContentFilter(const ListValue * args)564 void ContentSettingsHandler::SetContentFilter(const ListValue* args) {
565 DCHECK_EQ(2U, args->GetSize());
566 std::string group, setting;
567 if (!(args->GetString(0, &group) &&
568 args->GetString(1, &setting))) {
569 NOTREACHED();
570 return;
571 }
572
573 ContentSetting default_setting = ContentSettingFromString(setting);
574 ContentSettingsType content_type = ContentSettingsTypeFromGroupName(group);
575 if (content_type == CONTENT_SETTINGS_TYPE_GEOLOCATION) {
576 web_ui_->GetProfile()->GetGeolocationContentSettingsMap()->
577 SetDefaultContentSetting(default_setting);
578 } else if (content_type == CONTENT_SETTINGS_TYPE_NOTIFICATIONS) {
579 DesktopNotificationServiceFactory::GetForProfile(web_ui_->GetProfile())->
580 SetDefaultContentSetting(default_setting);
581 } else {
582 GetContentSettingsMap()->
583 SetDefaultContentSetting(content_type, default_setting);
584 }
585 }
586
SetAllowThirdPartyCookies(const ListValue * args)587 void ContentSettingsHandler::SetAllowThirdPartyCookies(const ListValue* args) {
588 string16 allow = ExtractStringValue(args);
589
590 GetContentSettingsMap()->SetBlockThirdPartyCookies(
591 LowerCaseEqualsASCII(allow, "true"));
592 }
593
RemoveException(const ListValue * args)594 void ContentSettingsHandler::RemoveException(const ListValue* args) {
595 size_t arg_i = 0;
596 std::string type_string;
597 CHECK(args->GetString(arg_i++, &type_string));
598
599 ContentSettingsType type = ContentSettingsTypeFromGroupName(type_string);
600 if (type == CONTENT_SETTINGS_TYPE_GEOLOCATION) {
601 std::string origin;
602 std::string embedding_origin;
603 bool rv = args->GetString(arg_i++, &origin);
604 DCHECK(rv);
605 rv = args->GetString(arg_i++, &embedding_origin);
606 DCHECK(rv);
607
608 web_ui_->GetProfile()->GetGeolocationContentSettingsMap()->
609 SetContentSetting(GURL(origin),
610 GURL(embedding_origin),
611 CONTENT_SETTING_DEFAULT);
612 } else if (type == CONTENT_SETTINGS_TYPE_NOTIFICATIONS) {
613 std::string origin;
614 std::string setting;
615 bool rv = args->GetString(arg_i++, &origin);
616 DCHECK(rv);
617 rv = args->GetString(arg_i++, &setting);
618 DCHECK(rv);
619 ContentSetting content_setting = ContentSettingFromString(setting);
620 if (content_setting == CONTENT_SETTING_ALLOW) {
621 DesktopNotificationServiceFactory::GetForProfile(web_ui_->GetProfile())->
622 ResetAllowedOrigin(GURL(origin));
623 } else {
624 DCHECK_EQ(content_setting, CONTENT_SETTING_BLOCK);
625 DesktopNotificationServiceFactory::GetForProfile(web_ui_->GetProfile())->
626 ResetBlockedOrigin(GURL(origin));
627 }
628 } else {
629 std::string mode;
630 bool rv = args->GetString(arg_i++, &mode);
631 DCHECK(rv);
632
633 std::string pattern;
634 rv = args->GetString(arg_i++, &pattern);
635 DCHECK(rv);
636
637 HostContentSettingsMap* settings_map =
638 mode == "normal" ? GetContentSettingsMap() :
639 GetOTRContentSettingsMap();
640 // The settings map could be null if the mode was OTR but the OTR profile
641 // got destroyed before we received this message.
642 if (settings_map) {
643 settings_map->SetContentSetting(
644 ContentSettingsPattern(pattern),
645 ContentSettingsTypeFromGroupName(type_string),
646 "",
647 CONTENT_SETTING_DEFAULT);
648 }
649 }
650 }
651
SetException(const ListValue * args)652 void ContentSettingsHandler::SetException(const ListValue* args) {
653 size_t arg_i = 0;
654 std::string type_string;
655 CHECK(args->GetString(arg_i++, &type_string));
656 std::string mode;
657 CHECK(args->GetString(arg_i++, &mode));
658 std::string pattern;
659 CHECK(args->GetString(arg_i++, &pattern));
660 std::string setting;
661 CHECK(args->GetString(arg_i++, &setting));
662
663 ContentSettingsType type = ContentSettingsTypeFromGroupName(type_string);
664 if (type == CONTENT_SETTINGS_TYPE_GEOLOCATION ||
665 type == CONTENT_SETTINGS_TYPE_NOTIFICATIONS) {
666 NOTREACHED();
667 return;
668 }
669
670 HostContentSettingsMap* settings_map =
671 mode == "normal" ? GetContentSettingsMap() :
672 GetOTRContentSettingsMap();
673
674 // The settings map could be null if the mode was OTR but the OTR profile
675 // got destroyed before we received this message.
676 if (!settings_map)
677 return;
678
679 settings_map->SetContentSetting(ContentSettingsPattern(pattern),
680 type,
681 "",
682 ContentSettingFromString(setting));
683 }
684
CheckExceptionPatternValidity(const ListValue * args)685 void ContentSettingsHandler::CheckExceptionPatternValidity(
686 const ListValue* args) {
687 size_t arg_i = 0;
688 Value* type;
689 CHECK(args->Get(arg_i++, &type));
690 std::string mode_string;
691 CHECK(args->GetString(arg_i++, &mode_string));
692 std::string pattern_string;
693 CHECK(args->GetString(arg_i++, &pattern_string));
694
695 ContentSettingsPattern pattern(pattern_string);
696
697 scoped_ptr<Value> mode_value(Value::CreateStringValue(mode_string));
698 scoped_ptr<Value> pattern_value(Value::CreateStringValue(pattern_string));
699 scoped_ptr<Value> valid_value(Value::CreateBooleanValue(pattern.IsValid()));
700
701 web_ui_->CallJavascriptFunction(
702 "ContentSettings.patternValidityCheckComplete",
703 *type,
704 *mode_value.get(),
705 *pattern_value.get(),
706 *valid_value.get());
707 }
708
709 // static
ContentSettingsTypeToGroupName(ContentSettingsType type)710 std::string ContentSettingsHandler::ContentSettingsTypeToGroupName(
711 ContentSettingsType type) {
712 if (type < CONTENT_SETTINGS_TYPE_COOKIES ||
713 type >= CONTENT_SETTINGS_NUM_TYPES) {
714 NOTREACHED();
715 return "";
716 }
717 return kContentSettingsTypeGroupNames[type];
718 }
719
GetContentSettingsMap()720 HostContentSettingsMap* ContentSettingsHandler::GetContentSettingsMap() {
721 return web_ui_->GetProfile()->GetHostContentSettingsMap();
722 }
723
724 HostContentSettingsMap*
GetOTRContentSettingsMap()725 ContentSettingsHandler::GetOTRContentSettingsMap() {
726 Profile* profile = web_ui_->GetProfile();
727 if (profile->HasOffTheRecordProfile())
728 return profile->GetOffTheRecordProfile()->GetHostContentSettingsMap();
729 return NULL;
730 }
731