OLD | NEW |
| (Empty) |
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/content_settings_handler.h" | |
6 | |
7 #include <map> | |
8 #include <string> | |
9 #include <vector> | |
10 | |
11 #include "base/bind.h" | |
12 #include "base/bind_helpers.h" | |
13 #include "base/command_line.h" | |
14 #include "base/utf_string_conversions.h" | |
15 #include "base/values.h" | |
16 #include "chrome/browser/browser_process.h" | |
17 #include "chrome/browser/content_settings/content_settings_details.h" | |
18 #include "chrome/browser/content_settings/content_settings_utils.h" | |
19 #include "chrome/browser/content_settings/host_content_settings_map.h" | |
20 #include "chrome/browser/custom_handlers/protocol_handler_registry.h" | |
21 #include "chrome/browser/intents/web_intents_util.h" | |
22 #include "chrome/browser/notifications/desktop_notification_service.h" | |
23 #include "chrome/browser/notifications/desktop_notification_service_factory.h" | |
24 #include "chrome/browser/prefs/pref_service.h" | |
25 #include "chrome/browser/profiles/profile.h" | |
26 #include "chrome/browser/ui/browser_list.h" | |
27 #include "chrome/common/chrome_notification_types.h" | |
28 #include "chrome/common/chrome_switches.h" | |
29 #include "chrome/common/content_settings.h" | |
30 #include "chrome/common/content_settings_pattern.h" | |
31 #include "chrome/common/pref_names.h" | |
32 #include "chrome/common/url_constants.h" | |
33 #include "content/public/browser/notification_service.h" | |
34 #include "content/public/browser/notification_source.h" | |
35 #include "content/public/browser/notification_types.h" | |
36 #include "content/public/browser/user_metrics.h" | |
37 #include "content/public/browser/web_ui.h" | |
38 #include "content/public/common/content_switches.h" | |
39 #include "grit/generated_resources.h" | |
40 #include "grit/locale_settings.h" | |
41 #include "ui/base/l10n/l10n_util.h" | |
42 | |
43 using content::UserMetricsAction; | |
44 | |
45 namespace { | |
46 | |
47 struct ContentSettingsTypeNameEntry { | |
48 ContentSettingsType type; | |
49 const char* name; | |
50 }; | |
51 | |
52 typedef std::map<ContentSettingsPattern, ContentSetting> OnePatternSettings; | |
53 typedef std::map<ContentSettingsPattern, OnePatternSettings> | |
54 AllPatternsSettings; | |
55 | |
56 const char* kDisplayPattern = "displayPattern"; | |
57 const char* kSetting = "setting"; | |
58 const char* kOrigin = "origin"; | |
59 const char* kSource = "source"; | |
60 const char* kEmbeddingOrigin = "embeddingOrigin"; | |
61 | |
62 const ContentSettingsTypeNameEntry kContentSettingsTypeGroupNames[] = { | |
63 {CONTENT_SETTINGS_TYPE_COOKIES, "cookies"}, | |
64 {CONTENT_SETTINGS_TYPE_IMAGES, "images"}, | |
65 {CONTENT_SETTINGS_TYPE_JAVASCRIPT, "javascript"}, | |
66 {CONTENT_SETTINGS_TYPE_PLUGINS, "plugins"}, | |
67 {CONTENT_SETTINGS_TYPE_POPUPS, "popups"}, | |
68 {CONTENT_SETTINGS_TYPE_GEOLOCATION, "location"}, | |
69 {CONTENT_SETTINGS_TYPE_NOTIFICATIONS, "notifications"}, | |
70 {CONTENT_SETTINGS_TYPE_INTENTS, "intents"}, | |
71 {CONTENT_SETTINGS_TYPE_AUTO_SELECT_CERTIFICATE, "auto-select-certificate"}, | |
72 {CONTENT_SETTINGS_TYPE_FULLSCREEN, "fullscreen"}, | |
73 {CONTENT_SETTINGS_TYPE_MOUSELOCK, "mouselock"}, | |
74 }; | |
75 COMPILE_ASSERT(arraysize(kContentSettingsTypeGroupNames) == | |
76 CONTENT_SETTINGS_NUM_TYPES, | |
77 MISSING_CONTENT_SETTINGS_TYPE); | |
78 | |
79 ContentSettingsType ContentSettingsTypeFromGroupName(const std::string& name) { | |
80 for (size_t i = 0; i < arraysize(kContentSettingsTypeGroupNames); ++i) { | |
81 if (name == kContentSettingsTypeGroupNames[i].name) | |
82 return kContentSettingsTypeGroupNames[i].type; | |
83 } | |
84 | |
85 NOTREACHED() << name << " is not a recognized content settings type."; | |
86 return CONTENT_SETTINGS_TYPE_DEFAULT; | |
87 } | |
88 | |
89 std::string ContentSettingToString(ContentSetting setting) { | |
90 switch (setting) { | |
91 case CONTENT_SETTING_ALLOW: | |
92 return "allow"; | |
93 case CONTENT_SETTING_ASK: | |
94 return "ask"; | |
95 case CONTENT_SETTING_BLOCK: | |
96 return "block"; | |
97 case CONTENT_SETTING_SESSION_ONLY: | |
98 return "session"; | |
99 case CONTENT_SETTING_DEFAULT: | |
100 return "default"; | |
101 case CONTENT_SETTING_NUM_SETTINGS: | |
102 NOTREACHED(); | |
103 } | |
104 | |
105 return ""; | |
106 } | |
107 | |
108 ContentSetting ContentSettingFromString(const std::string& name) { | |
109 if (name == "allow") | |
110 return CONTENT_SETTING_ALLOW; | |
111 if (name == "ask") | |
112 return CONTENT_SETTING_ASK; | |
113 if (name == "block") | |
114 return CONTENT_SETTING_BLOCK; | |
115 if (name == "session") | |
116 return CONTENT_SETTING_SESSION_ONLY; | |
117 | |
118 NOTREACHED() << name << " is not a recognized content setting."; | |
119 return CONTENT_SETTING_DEFAULT; | |
120 } | |
121 | |
122 std::string GeolocationExceptionToString( | |
123 const ContentSettingsPattern& origin, | |
124 const ContentSettingsPattern& embedding_origin) { | |
125 if (origin == embedding_origin) | |
126 return origin.ToString(); | |
127 | |
128 // TODO(estade): the page needs to use CSS to indent the string. | |
129 std::string indent(" "); | |
130 | |
131 if (embedding_origin == ContentSettingsPattern::Wildcard()) { | |
132 // NOTE: As long as the user cannot add/edit entries from the exceptions | |
133 // dialog, it's impossible to actually have a non-default setting for some | |
134 // origin "embedded on any other site", so this row will never appear. If | |
135 // we add the ability to add/edit exceptions, we'll need to decide when to | |
136 // display this and how "removing" it will function. | |
137 return indent + | |
138 l10n_util::GetStringUTF8(IDS_EXCEPTIONS_GEOLOCATION_EMBEDDED_ANY_OTHER); | |
139 } | |
140 | |
141 return indent + l10n_util::GetStringFUTF8( | |
142 IDS_EXCEPTIONS_GEOLOCATION_EMBEDDED_ON_HOST, | |
143 UTF8ToUTF16(embedding_origin.ToString())); | |
144 } | |
145 | |
146 // Create a DictionaryValue* that will act as a data source for a single row | |
147 // in a HostContentSettingsMap-controlled exceptions table (e.g., cookies). | |
148 // Ownership of the pointer is passed to the caller. | |
149 DictionaryValue* GetExceptionForPage( | |
150 const ContentSettingsPattern& pattern, | |
151 const ContentSetting& setting, | |
152 const std::string& provider_name) { | |
153 DictionaryValue* exception = new DictionaryValue(); | |
154 exception->SetString(kDisplayPattern, pattern.ToString()); | |
155 exception->SetString(kSetting, ContentSettingToString(setting)); | |
156 exception->SetString(kSource, provider_name); | |
157 return exception; | |
158 } | |
159 | |
160 // Create a DictionaryValue* that will act as a data source for a single row | |
161 // in the Geolocation exceptions table. Ownership of the pointer is passed to | |
162 // the caller. | |
163 DictionaryValue* GetGeolocationExceptionForPage( | |
164 const ContentSettingsPattern& origin, | |
165 const ContentSettingsPattern& embedding_origin, | |
166 ContentSetting setting) { | |
167 DictionaryValue* exception = new DictionaryValue(); | |
168 exception->SetString(kDisplayPattern, | |
169 GeolocationExceptionToString(origin, embedding_origin)); | |
170 exception->SetString(kSetting, ContentSettingToString(setting)); | |
171 exception->SetString(kOrigin, origin.ToString()); | |
172 exception->SetString(kEmbeddingOrigin, embedding_origin.ToString()); | |
173 return exception; | |
174 } | |
175 | |
176 // Create a DictionaryValue* that will act as a data source for a single row | |
177 // in the desktop notifications exceptions table. Ownership of the pointer is | |
178 // passed to the caller. | |
179 DictionaryValue* GetNotificationExceptionForPage( | |
180 const ContentSettingsPattern& pattern, | |
181 ContentSetting setting, | |
182 const std::string& provider_name) { | |
183 DictionaryValue* exception = new DictionaryValue(); | |
184 exception->SetString(kDisplayPattern, pattern.ToString()); | |
185 exception->SetString(kSetting, ContentSettingToString(setting)); | |
186 exception->SetString(kOrigin, pattern.ToString()); | |
187 exception->SetString(kSource, provider_name); | |
188 return exception; | |
189 } | |
190 | |
191 } // namespace | |
192 | |
193 ContentSettingsHandler::ContentSettingsHandler() { | |
194 } | |
195 | |
196 ContentSettingsHandler::~ContentSettingsHandler() { | |
197 } | |
198 | |
199 void ContentSettingsHandler::GetLocalizedValues( | |
200 DictionaryValue* localized_strings) { | |
201 DCHECK(localized_strings); | |
202 | |
203 static OptionsStringResource resources[] = { | |
204 { "content_exceptions", IDS_COOKIES_EXCEPTIONS_BUTTON }, | |
205 { "allowException", IDS_EXCEPTIONS_ALLOW_BUTTON }, | |
206 { "blockException", IDS_EXCEPTIONS_BLOCK_BUTTON }, | |
207 { "sessionException", IDS_EXCEPTIONS_SESSION_ONLY_BUTTON }, | |
208 { "askException", IDS_EXCEPTIONS_ASK_BUTTON }, | |
209 { "addExceptionRow", IDS_EXCEPTIONS_ADD_BUTTON }, | |
210 { "removeExceptionRow", IDS_EXCEPTIONS_REMOVE_BUTTON }, | |
211 { "editExceptionRow", IDS_EXCEPTIONS_EDIT_BUTTON }, | |
212 { "otr_exceptions_explanation", IDS_EXCEPTIONS_OTR_LABEL }, | |
213 { "examplePattern", IDS_EXCEPTIONS_PATTERN_EXAMPLE }, | |
214 { "addNewExceptionInstructions", IDS_EXCEPTIONS_ADD_NEW_INSTRUCTIONS }, | |
215 { "manage_exceptions", IDS_EXCEPTIONS_MANAGE }, | |
216 { "manage_handlers", IDS_HANDLERS_MANAGE }, | |
217 { "exceptionPatternHeader", IDS_EXCEPTIONS_PATTERN_HEADER }, | |
218 { "exceptionBehaviorHeader", IDS_EXCEPTIONS_ACTION_HEADER }, | |
219 // Cookies filter. | |
220 { "cookies_tab_label", IDS_COOKIES_TAB_LABEL }, | |
221 { "cookies_header", IDS_COOKIES_HEADER }, | |
222 { "cookies_allow", IDS_COOKIES_ALLOW_RADIO }, | |
223 { "cookies_block", IDS_COOKIES_BLOCK_RADIO }, | |
224 { "cookies_session_only", IDS_COOKIES_SESSION_ONLY_RADIO }, | |
225 { "cookies_block_3rd_party", IDS_COOKIES_BLOCK_3RDPARTY_CHKBOX }, | |
226 { "cookies_clear_when_close", IDS_COOKIES_CLEAR_WHEN_CLOSE_CHKBOX }, | |
227 { "cookies_lso_clear_when_close", IDS_COOKIES_LSO_CLEAR_WHEN_CLOSE_CHKBOX }, | |
228 { "cookies_show_cookies", IDS_COOKIES_SHOW_COOKIES_BUTTON }, | |
229 { "flash_storage_settings", IDS_FLASH_STORAGE_SETTINGS }, | |
230 { "flash_storage_url", IDS_FLASH_STORAGE_URL }, | |
231 // Image filter. | |
232 { "images_tab_label", IDS_IMAGES_TAB_LABEL }, | |
233 { "images_header", IDS_IMAGES_HEADER }, | |
234 { "images_allow", IDS_IMAGES_LOAD_RADIO }, | |
235 { "images_block", IDS_IMAGES_NOLOAD_RADIO }, | |
236 // JavaScript filter. | |
237 { "javascript_tab_label", IDS_JAVASCRIPT_TAB_LABEL }, | |
238 { "javascript_header", IDS_JAVASCRIPT_HEADER }, | |
239 { "javascript_allow", IDS_JS_ALLOW_RADIO }, | |
240 { "javascript_block", IDS_JS_DONOTALLOW_RADIO }, | |
241 // Plug-ins filter. | |
242 { "plugins_tab_label", IDS_PLUGIN_TAB_LABEL }, | |
243 { "plugins_header", IDS_PLUGIN_HEADER }, | |
244 { "plugins_ask", IDS_PLUGIN_ASK_RADIO }, | |
245 { "plugins_allow", IDS_PLUGIN_LOAD_RADIO }, | |
246 { "plugins_block", IDS_PLUGIN_NOLOAD_RADIO }, | |
247 { "disableIndividualPlugins", IDS_PLUGIN_SELECTIVE_DISABLE }, | |
248 // Pop-ups filter. | |
249 { "popups_tab_label", IDS_POPUP_TAB_LABEL }, | |
250 { "popups_header", IDS_POPUP_HEADER }, | |
251 { "popups_allow", IDS_POPUP_ALLOW_RADIO }, | |
252 { "popups_block", IDS_POPUP_BLOCK_RADIO }, | |
253 // Location filter. | |
254 { "location_tab_label", IDS_GEOLOCATION_TAB_LABEL }, | |
255 { "location_header", IDS_GEOLOCATION_HEADER }, | |
256 { "location_allow", IDS_GEOLOCATION_ALLOW_RADIO }, | |
257 { "location_ask", IDS_GEOLOCATION_ASK_RADIO }, | |
258 { "location_block", IDS_GEOLOCATION_BLOCK_RADIO }, | |
259 // Notifications filter. | |
260 { "notifications_tab_label", IDS_NOTIFICATIONS_TAB_LABEL }, | |
261 { "notifications_header", IDS_NOTIFICATIONS_HEADER }, | |
262 { "notifications_allow", IDS_NOTIFICATIONS_ALLOW_RADIO }, | |
263 { "notifications_ask", IDS_NOTIFICATIONS_ASK_RADIO }, | |
264 { "notifications_block", IDS_NOTIFICATIONS_BLOCK_RADIO }, | |
265 // Intents filter. | |
266 { "webIntentsTabLabel", IDS_WEB_INTENTS_TAB_LABEL }, | |
267 { "allowWebIntents", IDS_ALLOW_WEB_INTENTS }, | |
268 // Fullscreen filter. | |
269 { "fullscreen_tab_label", IDS_FULLSCREEN_TAB_LABEL }, | |
270 { "fullscreen_header", IDS_FULLSCREEN_HEADER }, | |
271 // Mouse Lock filter. | |
272 { "mouselock_tab_label", IDS_MOUSE_LOCK_TAB_LABEL }, | |
273 { "mouselock_header", IDS_MOUSE_LOCK_HEADER }, | |
274 { "mouselock_allow", IDS_MOUSE_LOCK_ALLOW_RADIO }, | |
275 { "mouselock_ask", IDS_MOUSE_LOCK_ASK_RADIO }, | |
276 { "mouselock_block", IDS_MOUSE_LOCK_BLOCK_RADIO }, | |
277 }; | |
278 | |
279 RegisterStrings(localized_strings, resources, arraysize(resources)); | |
280 RegisterTitle(localized_strings, "contentSettingsPage", | |
281 IDS_CONTENT_SETTINGS_TITLE); | |
282 localized_strings->SetBoolean("enable_web_intents", | |
283 web_intents::IsWebIntentsEnabled()); | |
284 } | |
285 | |
286 void ContentSettingsHandler::InitializeHandler() { | |
287 notification_registrar_.Add( | |
288 this, chrome::NOTIFICATION_PROFILE_CREATED, | |
289 content::NotificationService::AllSources()); | |
290 notification_registrar_.Add( | |
291 this, chrome::NOTIFICATION_PROFILE_DESTROYED, | |
292 content::NotificationService::AllSources()); | |
293 | |
294 UpdateHandlersEnabledRadios(); | |
295 UpdateAllExceptionsViewsFromModel(); | |
296 notification_registrar_.Add( | |
297 this, chrome::NOTIFICATION_CONTENT_SETTINGS_CHANGED, | |
298 content::NotificationService::AllSources()); | |
299 notification_registrar_.Add( | |
300 this, chrome::NOTIFICATION_DESKTOP_NOTIFICATION_SETTINGS_CHANGED, | |
301 content::NotificationService::AllSources()); | |
302 Profile* profile = Profile::FromWebUI(web_ui()); | |
303 notification_registrar_.Add( | |
304 this, chrome::NOTIFICATION_PROTOCOL_HANDLER_REGISTRY_CHANGED, | |
305 content::Source<Profile>(profile)); | |
306 | |
307 PrefService* prefs = profile->GetPrefs(); | |
308 pref_change_registrar_.Init(prefs); | |
309 pref_change_registrar_.Add(prefs::kGeolocationContentSettings, this); | |
310 } | |
311 | |
312 void ContentSettingsHandler::Observe( | |
313 int type, | |
314 const content::NotificationSource& source, | |
315 const content::NotificationDetails& details) { | |
316 switch (type) { | |
317 case chrome::NOTIFICATION_PROFILE_DESTROYED: { | |
318 if (content::Source<Profile>(source).ptr()->IsOffTheRecord()) { | |
319 web_ui()->CallJavascriptFunction( | |
320 "ContentSettingsExceptionsArea.OTRProfileDestroyed"); | |
321 } | |
322 break; | |
323 } | |
324 | |
325 case chrome::NOTIFICATION_PROFILE_CREATED: { | |
326 if (content::Source<Profile>(source).ptr()->IsOffTheRecord()) | |
327 UpdateAllOTRExceptionsViewsFromModel(); | |
328 break; | |
329 } | |
330 | |
331 case chrome::NOTIFICATION_CONTENT_SETTINGS_CHANGED: { | |
332 // Filter out notifications from other profiles. | |
333 HostContentSettingsMap* map = | |
334 content::Source<HostContentSettingsMap>(source).ptr(); | |
335 if (map != GetContentSettingsMap() && | |
336 map != GetOTRContentSettingsMap()) | |
337 break; | |
338 | |
339 const ContentSettingsDetails* settings_details = | |
340 content::Details<const ContentSettingsDetails>(details).ptr(); | |
341 | |
342 // TODO(estade): we pretend update_all() is always true. | |
343 if (settings_details->update_all_types()) | |
344 UpdateAllExceptionsViewsFromModel(); | |
345 else | |
346 UpdateExceptionsViewFromModel(settings_details->type()); | |
347 break; | |
348 } | |
349 | |
350 case chrome::NOTIFICATION_PREF_CHANGED: { | |
351 const std::string& pref_name = | |
352 *content::Details<std::string>(details).ptr(); | |
353 if (pref_name == prefs::kGeolocationContentSettings) | |
354 UpdateGeolocationExceptionsView(); | |
355 break; | |
356 } | |
357 | |
358 case chrome::NOTIFICATION_DESKTOP_NOTIFICATION_SETTINGS_CHANGED: { | |
359 UpdateNotificationExceptionsView(); | |
360 break; | |
361 } | |
362 | |
363 case chrome::NOTIFICATION_PROTOCOL_HANDLER_REGISTRY_CHANGED: { | |
364 UpdateHandlersEnabledRadios(); | |
365 break; | |
366 } | |
367 | |
368 default: | |
369 OptionsPageUIHandler::Observe(type, source, details); | |
370 } | |
371 } | |
372 | |
373 void ContentSettingsHandler::UpdateSettingDefaultFromModel( | |
374 ContentSettingsType type) { | |
375 DictionaryValue filter_settings; | |
376 std::string provider_id; | |
377 filter_settings.SetString(ContentSettingsTypeToGroupName(type) + ".value", | |
378 GetSettingDefaultFromModel(type, &provider_id)); | |
379 filter_settings.SetString( | |
380 ContentSettingsTypeToGroupName(type) + ".managedBy", | |
381 provider_id); | |
382 | |
383 web_ui()->CallJavascriptFunction( | |
384 "ContentSettings.setContentFilterSettingsValue", filter_settings); | |
385 } | |
386 | |
387 std::string ContentSettingsHandler::GetSettingDefaultFromModel( | |
388 ContentSettingsType type, std::string* provider_id) { | |
389 Profile* profile = Profile::FromWebUI(web_ui()); | |
390 ContentSetting default_setting; | |
391 if (type == CONTENT_SETTINGS_TYPE_NOTIFICATIONS) { | |
392 default_setting = | |
393 DesktopNotificationServiceFactory::GetForProfile(profile)-> | |
394 GetDefaultContentSetting(provider_id); | |
395 } else { | |
396 default_setting = | |
397 profile->GetHostContentSettingsMap()-> | |
398 GetDefaultContentSetting(type, provider_id); | |
399 } | |
400 | |
401 return ContentSettingToString(default_setting); | |
402 } | |
403 | |
404 void ContentSettingsHandler::UpdateHandlersEnabledRadios() { | |
405 #if defined(ENABLE_REGISTER_PROTOCOL_HANDLER) | |
406 base::FundamentalValue handlers_enabled( | |
407 GetProtocolHandlerRegistry()->enabled()); | |
408 | |
409 web_ui()->CallJavascriptFunction( | |
410 "ContentSettings.updateHandlersEnabledRadios", | |
411 handlers_enabled); | |
412 #endif // defined(ENABLE_REGISTER_PROTOCOL_HANDLER) | |
413 } | |
414 | |
415 void ContentSettingsHandler::UpdateAllExceptionsViewsFromModel() { | |
416 for (int type = CONTENT_SETTINGS_TYPE_DEFAULT + 1; | |
417 type < CONTENT_SETTINGS_NUM_TYPES; ++type) { | |
418 // The content settings type CONTENT_SETTINGS_TYPE_AUTO_SELECT_CERTIFICATE | |
419 // is supposed to be set by policy only. Hence there is no user facing UI | |
420 // for this content type and we skip it here. | |
421 if (type == CONTENT_SETTINGS_TYPE_AUTO_SELECT_CERTIFICATE) | |
422 continue; | |
423 UpdateExceptionsViewFromModel(static_cast<ContentSettingsType>(type)); | |
424 } | |
425 } | |
426 | |
427 void ContentSettingsHandler::UpdateAllOTRExceptionsViewsFromModel() { | |
428 for (int type = CONTENT_SETTINGS_TYPE_DEFAULT + 1; | |
429 type < CONTENT_SETTINGS_NUM_TYPES; ++type) { | |
430 UpdateOTRExceptionsViewFromModel(static_cast<ContentSettingsType>(type)); | |
431 } | |
432 } | |
433 | |
434 void ContentSettingsHandler::UpdateExceptionsViewFromModel( | |
435 ContentSettingsType type) { | |
436 // Don't update intents settings at this point. | |
437 // Turn on when enable_web_intents_tag is enabled. | |
438 if (type == CONTENT_SETTINGS_TYPE_INTENTS) | |
439 return; | |
440 | |
441 switch (type) { | |
442 case CONTENT_SETTINGS_TYPE_GEOLOCATION: | |
443 UpdateGeolocationExceptionsView(); | |
444 break; | |
445 case CONTENT_SETTINGS_TYPE_NOTIFICATIONS: | |
446 UpdateNotificationExceptionsView(); | |
447 break; | |
448 default: | |
449 UpdateExceptionsViewFromHostContentSettingsMap(type); | |
450 break; | |
451 } | |
452 } | |
453 | |
454 void ContentSettingsHandler::UpdateOTRExceptionsViewFromModel( | |
455 ContentSettingsType type) { | |
456 switch (type) { | |
457 case CONTENT_SETTINGS_TYPE_GEOLOCATION: | |
458 case CONTENT_SETTINGS_TYPE_NOTIFICATIONS: | |
459 case CONTENT_SETTINGS_TYPE_INTENTS: | |
460 case CONTENT_SETTINGS_TYPE_AUTO_SELECT_CERTIFICATE: | |
461 break; | |
462 default: | |
463 UpdateExceptionsViewFromOTRHostContentSettingsMap(type); | |
464 break; | |
465 } | |
466 } | |
467 | |
468 void ContentSettingsHandler::UpdateGeolocationExceptionsView() { | |
469 Profile* profile = Profile::FromWebUI(web_ui()); | |
470 HostContentSettingsMap* map = profile->GetHostContentSettingsMap(); | |
471 | |
472 ContentSettingsForOneType all_settings; | |
473 map->GetSettingsForOneType( | |
474 CONTENT_SETTINGS_TYPE_GEOLOCATION, | |
475 std::string(), | |
476 &all_settings); | |
477 | |
478 // Group geolocation settings by primary_pattern. | |
479 AllPatternsSettings all_patterns_settings; | |
480 for (ContentSettingsForOneType::iterator i = | |
481 all_settings.begin(); | |
482 i != all_settings.end(); | |
483 ++i) { | |
484 // Don't add default settings. | |
485 if (i->primary_pattern == ContentSettingsPattern::Wildcard() && | |
486 i->secondary_pattern == ContentSettingsPattern::Wildcard() && | |
487 i->source != "preferences") { | |
488 continue; | |
489 } | |
490 all_patterns_settings[i->primary_pattern][i->secondary_pattern] = | |
491 i->setting; | |
492 } | |
493 | |
494 ListValue exceptions; | |
495 for (AllPatternsSettings::iterator i = all_patterns_settings.begin(); | |
496 i != all_patterns_settings.end(); | |
497 ++i) { | |
498 const ContentSettingsPattern& primary_pattern = i->first; | |
499 const OnePatternSettings& one_settings = i->second; | |
500 | |
501 OnePatternSettings::const_iterator parent = | |
502 one_settings.find(primary_pattern); | |
503 | |
504 // Add the "parent" entry for the non-embedded setting. | |
505 ContentSetting parent_setting = | |
506 parent == one_settings.end() ? CONTENT_SETTING_DEFAULT : parent->second; | |
507 exceptions.Append(GetGeolocationExceptionForPage(primary_pattern, | |
508 primary_pattern, | |
509 parent_setting)); | |
510 | |
511 // Add the "children" for any embedded settings. | |
512 for (OnePatternSettings::const_iterator j = one_settings.begin(); | |
513 j != one_settings.end(); | |
514 ++j) { | |
515 // Skip the non-embedded setting which we already added above. | |
516 if (j == parent) | |
517 continue; | |
518 | |
519 exceptions.Append( | |
520 GetGeolocationExceptionForPage(primary_pattern, j->first, j->second)); | |
521 } | |
522 } | |
523 | |
524 StringValue type_string( | |
525 ContentSettingsTypeToGroupName(CONTENT_SETTINGS_TYPE_GEOLOCATION)); | |
526 web_ui()->CallJavascriptFunction("ContentSettings.setExceptions", | |
527 type_string, exceptions); | |
528 | |
529 // This is mainly here to keep this function ideologically parallel to | |
530 // UpdateExceptionsViewFromHostContentSettingsMap(). | |
531 UpdateSettingDefaultFromModel(CONTENT_SETTINGS_TYPE_GEOLOCATION); | |
532 } | |
533 | |
534 void ContentSettingsHandler::UpdateNotificationExceptionsView() { | |
535 Profile* profile = Profile::FromWebUI(web_ui()); | |
536 DesktopNotificationService* service = | |
537 DesktopNotificationServiceFactory::GetForProfile(profile); | |
538 | |
539 ContentSettingsForOneType settings; | |
540 service->GetNotificationsSettings(&settings); | |
541 | |
542 ListValue exceptions; | |
543 for (ContentSettingsForOneType::const_iterator i = | |
544 settings.begin(); | |
545 i != settings.end(); | |
546 ++i) { | |
547 // Don't add default settings. | |
548 if (i->primary_pattern == ContentSettingsPattern::Wildcard() && | |
549 i->secondary_pattern == ContentSettingsPattern::Wildcard() && | |
550 i->source != "preferences") { | |
551 continue; | |
552 } | |
553 | |
554 exceptions.Append( | |
555 GetNotificationExceptionForPage(i->primary_pattern, i->setting, | |
556 i->source)); | |
557 } | |
558 | |
559 StringValue type_string( | |
560 ContentSettingsTypeToGroupName(CONTENT_SETTINGS_TYPE_NOTIFICATIONS)); | |
561 web_ui()->CallJavascriptFunction("ContentSettings.setExceptions", | |
562 type_string, exceptions); | |
563 | |
564 // This is mainly here to keep this function ideologically parallel to | |
565 // UpdateExceptionsViewFromHostContentSettingsMap(). | |
566 UpdateSettingDefaultFromModel(CONTENT_SETTINGS_TYPE_NOTIFICATIONS); | |
567 } | |
568 | |
569 void ContentSettingsHandler::UpdateExceptionsViewFromHostContentSettingsMap( | |
570 ContentSettingsType type) { | |
571 ContentSettingsForOneType entries; | |
572 GetContentSettingsMap()->GetSettingsForOneType(type, "", &entries); | |
573 | |
574 ListValue exceptions; | |
575 for (size_t i = 0; i < entries.size(); ++i) { | |
576 // Skip default settings from extensions and policy, and the default content | |
577 // settings; all of them will affect the default setting UI. | |
578 if (entries[i].primary_pattern == ContentSettingsPattern::Wildcard() && | |
579 entries[i].secondary_pattern == ContentSettingsPattern::Wildcard() && | |
580 entries[i].source != "preference") { | |
581 continue; | |
582 } | |
583 // The content settings UI does not support secondary content settings | |
584 // pattern yet. For content settings set through the content settings UI the | |
585 // secondary pattern is by default a wildcard pattern. Hence users are not | |
586 // able to modify content settings with a secondary pattern other than the | |
587 // wildcard pattern. So only show settings that the user is able to modify. | |
588 // TODO(bauerb): Support a read-only view for those patterns. | |
589 if (entries[i].secondary_pattern == ContentSettingsPattern::Wildcard()) { | |
590 exceptions.Append( | |
591 GetExceptionForPage(entries[i].primary_pattern, entries[i].setting, | |
592 entries[i].source)); | |
593 } else { | |
594 LOG(ERROR) << "Secondary content settings patterns are not " | |
595 << "supported by the content settings UI"; | |
596 } | |
597 } | |
598 | |
599 StringValue type_string(ContentSettingsTypeToGroupName(type)); | |
600 web_ui()->CallJavascriptFunction("ContentSettings.setExceptions", type_string, | |
601 exceptions); | |
602 | |
603 UpdateExceptionsViewFromOTRHostContentSettingsMap(type); | |
604 | |
605 // TODO(koz): The default for fullscreen is always 'ask'. | |
606 // http://crbug.com/104683 | |
607 if (type == CONTENT_SETTINGS_TYPE_FULLSCREEN) | |
608 return; | |
609 | |
610 // The default may also have changed (we won't get a separate notification). | |
611 // If it hasn't changed, this call will be harmless. | |
612 UpdateSettingDefaultFromModel(type); | |
613 } | |
614 | |
615 void ContentSettingsHandler::UpdateExceptionsViewFromOTRHostContentSettingsMap( | |
616 ContentSettingsType type) { | |
617 const HostContentSettingsMap* otr_settings_map = GetOTRContentSettingsMap(); | |
618 if (!otr_settings_map) | |
619 return; | |
620 | |
621 ContentSettingsForOneType otr_entries; | |
622 otr_settings_map->GetSettingsForOneType(type, "", &otr_entries); | |
623 | |
624 ListValue otr_exceptions; | |
625 for (size_t i = 0; i < otr_entries.size(); ++i) { | |
626 // Off-the-record HostContentSettingsMap contains incognito content settings | |
627 // as well as normal content settings. Here, we use the incongnito settings | |
628 // only. | |
629 if (!otr_entries[i].incognito) | |
630 continue; | |
631 // The content settings UI does not support secondary content settings | |
632 // pattern yet. For content settings set through the content settings UI the | |
633 // secondary pattern is by default a wildcard pattern. Hence users are not | |
634 // able to modify content settings with a secondary pattern other than the | |
635 // wildcard pattern. So only show settings that the user is able to modify. | |
636 // TODO(bauerb): Support a read-only view for those patterns. | |
637 if (otr_entries[i].secondary_pattern == | |
638 ContentSettingsPattern::Wildcard()) { | |
639 otr_exceptions.Append( | |
640 GetExceptionForPage(otr_entries[i].primary_pattern, | |
641 otr_entries[i].setting, | |
642 otr_entries[i].source)); | |
643 } else { | |
644 LOG(ERROR) << "Secondary content settings patterns are not " | |
645 << "supported by the content settings UI"; | |
646 } | |
647 } | |
648 | |
649 StringValue type_string(ContentSettingsTypeToGroupName(type)); | |
650 web_ui()->CallJavascriptFunction("ContentSettings.setOTRExceptions", | |
651 type_string, otr_exceptions); | |
652 } | |
653 | |
654 void ContentSettingsHandler::RegisterMessages() { | |
655 web_ui()->RegisterMessageCallback("setContentFilter", | |
656 base::Bind(&ContentSettingsHandler::SetContentFilter, | |
657 base::Unretained(this))); | |
658 web_ui()->RegisterMessageCallback("removeException", | |
659 base::Bind(&ContentSettingsHandler::RemoveException, | |
660 base::Unretained(this))); | |
661 web_ui()->RegisterMessageCallback("setException", | |
662 base::Bind(&ContentSettingsHandler::SetException, | |
663 base::Unretained(this))); | |
664 web_ui()->RegisterMessageCallback("checkExceptionPatternValidity", | |
665 base::Bind(&ContentSettingsHandler::CheckExceptionPatternValidity, | |
666 base::Unretained(this))); | |
667 } | |
668 | |
669 void ContentSettingsHandler::ApplyWhitelist(ContentSettingsType content_type, | |
670 ContentSetting default_setting) { | |
671 Profile* profile = Profile::FromWebUI(web_ui()); | |
672 HostContentSettingsMap* map = GetContentSettingsMap(); | |
673 if (content_type != CONTENT_SETTINGS_TYPE_PLUGINS) | |
674 return; | |
675 const int kDefaultWhitelistVersion = 1; | |
676 PrefService* prefs = profile->GetPrefs(); | |
677 int version = prefs->GetInteger( | |
678 prefs::kContentSettingsDefaultWhitelistVersion); | |
679 if (version >= kDefaultWhitelistVersion) | |
680 return; | |
681 ContentSetting old_setting = | |
682 map->GetDefaultContentSetting(CONTENT_SETTINGS_TYPE_PLUGINS, NULL); | |
683 if (old_setting == CONTENT_SETTING_ALLOW && | |
684 default_setting == CONTENT_SETTING_ASK) { | |
685 map->SetWebsiteSetting( | |
686 ContentSettingsPattern::Wildcard(), | |
687 ContentSettingsPattern::Wildcard(), | |
688 CONTENT_SETTINGS_TYPE_PLUGINS, | |
689 "google-talk", | |
690 Value::CreateIntegerValue(CONTENT_SETTING_ALLOW)); | |
691 } | |
692 prefs->SetInteger(prefs::kContentSettingsDefaultWhitelistVersion, | |
693 kDefaultWhitelistVersion); | |
694 } | |
695 | |
696 void ContentSettingsHandler::SetContentFilter(const ListValue* args) { | |
697 DCHECK_EQ(2U, args->GetSize()); | |
698 std::string group, setting; | |
699 if (!(args->GetString(0, &group) && | |
700 args->GetString(1, &setting))) { | |
701 NOTREACHED(); | |
702 return; | |
703 } | |
704 | |
705 ContentSetting default_setting = ContentSettingFromString(setting); | |
706 ContentSettingsType content_type = ContentSettingsTypeFromGroupName(group); | |
707 Profile* profile = Profile::FromWebUI(web_ui()); | |
708 if (content_type == CONTENT_SETTINGS_TYPE_NOTIFICATIONS) { | |
709 DesktopNotificationServiceFactory::GetForProfile(profile)-> | |
710 SetDefaultContentSetting(default_setting); | |
711 } else { | |
712 HostContentSettingsMap* map = GetContentSettingsMap(); | |
713 ApplyWhitelist(content_type, default_setting); | |
714 map->SetDefaultContentSetting(content_type, default_setting); | |
715 } | |
716 switch (content_type) { | |
717 case CONTENT_SETTINGS_TYPE_COOKIES: | |
718 content::RecordAction( | |
719 UserMetricsAction("Options_DefaultCookieSettingChanged")); | |
720 break; | |
721 case CONTENT_SETTINGS_TYPE_IMAGES: | |
722 content::RecordAction( | |
723 UserMetricsAction("Options_DefaultImagesSettingChanged")); | |
724 break; | |
725 case CONTENT_SETTINGS_TYPE_JAVASCRIPT: | |
726 content::RecordAction( | |
727 UserMetricsAction("Options_DefaultJavaScriptSettingChanged")); | |
728 break; | |
729 case CONTENT_SETTINGS_TYPE_PLUGINS: | |
730 content::RecordAction( | |
731 UserMetricsAction("Options_DefaultPluginsSettingChanged")); | |
732 break; | |
733 case CONTENT_SETTINGS_TYPE_POPUPS: | |
734 content::RecordAction( | |
735 UserMetricsAction("Options_DefaultPopupsSettingChanged")); | |
736 break; | |
737 case CONTENT_SETTINGS_TYPE_NOTIFICATIONS: | |
738 content::RecordAction( | |
739 UserMetricsAction("Options_DefaultNotificationsSettingChanged")); | |
740 break; | |
741 case CONTENT_SETTINGS_TYPE_GEOLOCATION: | |
742 content::RecordAction( | |
743 UserMetricsAction("Options_DefaultGeolocationSettingChanged")); | |
744 break; | |
745 case CONTENT_SETTINGS_TYPE_INTENTS: | |
746 content::RecordAction( | |
747 UserMetricsAction("Options_DefaultHandlersSettingChanged")); | |
748 break; | |
749 case CONTENT_SETTINGS_TYPE_MOUSELOCK: | |
750 content::RecordAction( | |
751 UserMetricsAction("Options_DefaultMouseLockSettingChanged")); | |
752 break; | |
753 default: | |
754 break; | |
755 } | |
756 } | |
757 | |
758 void ContentSettingsHandler::RemoveException(const ListValue* args) { | |
759 size_t arg_i = 0; | |
760 std::string type_string; | |
761 CHECK(args->GetString(arg_i++, &type_string)); | |
762 | |
763 Profile* profile = Profile::FromWebUI(web_ui()); | |
764 ContentSettingsType type = ContentSettingsTypeFromGroupName(type_string); | |
765 if (type == CONTENT_SETTINGS_TYPE_GEOLOCATION) { | |
766 std::string origin; | |
767 std::string embedding_origin; | |
768 bool rv = args->GetString(arg_i++, &origin); | |
769 DCHECK(rv); | |
770 rv = args->GetString(arg_i++, &embedding_origin); | |
771 DCHECK(rv); | |
772 | |
773 profile->GetHostContentSettingsMap()-> | |
774 SetContentSetting(ContentSettingsPattern::FromString(origin), | |
775 ContentSettingsPattern::FromString(embedding_origin), | |
776 CONTENT_SETTINGS_TYPE_GEOLOCATION, | |
777 std::string(), | |
778 CONTENT_SETTING_DEFAULT); | |
779 } else if (type == CONTENT_SETTINGS_TYPE_NOTIFICATIONS) { | |
780 std::string origin; | |
781 std::string setting; | |
782 bool rv = args->GetString(arg_i++, &origin); | |
783 DCHECK(rv); | |
784 rv = args->GetString(arg_i++, &setting); | |
785 DCHECK(rv); | |
786 ContentSetting content_setting = ContentSettingFromString(setting); | |
787 | |
788 DCHECK(content_setting == CONTENT_SETTING_ALLOW || | |
789 content_setting == CONTENT_SETTING_BLOCK); | |
790 DesktopNotificationServiceFactory::GetForProfile(profile)-> | |
791 ClearSetting(ContentSettingsPattern::FromString(origin)); | |
792 } else { | |
793 std::string mode; | |
794 bool rv = args->GetString(arg_i++, &mode); | |
795 DCHECK(rv); | |
796 | |
797 std::string pattern; | |
798 rv = args->GetString(arg_i++, &pattern); | |
799 DCHECK(rv); | |
800 | |
801 HostContentSettingsMap* settings_map = | |
802 mode == "normal" ? GetContentSettingsMap() : | |
803 GetOTRContentSettingsMap(); | |
804 // The settings map could be null if the mode was OTR but the OTR profile | |
805 // got destroyed before we received this message. | |
806 if (settings_map) { | |
807 settings_map->SetContentSetting( | |
808 ContentSettingsPattern::FromString(pattern), | |
809 ContentSettingsPattern::Wildcard(), | |
810 ContentSettingsTypeFromGroupName(type_string), | |
811 "", | |
812 CONTENT_SETTING_DEFAULT); | |
813 } | |
814 } | |
815 } | |
816 | |
817 void ContentSettingsHandler::SetException(const ListValue* args) { | |
818 size_t arg_i = 0; | |
819 std::string type_string; | |
820 CHECK(args->GetString(arg_i++, &type_string)); | |
821 std::string mode; | |
822 CHECK(args->GetString(arg_i++, &mode)); | |
823 std::string pattern; | |
824 CHECK(args->GetString(arg_i++, &pattern)); | |
825 std::string setting; | |
826 CHECK(args->GetString(arg_i++, &setting)); | |
827 | |
828 ContentSettingsType type = ContentSettingsTypeFromGroupName(type_string); | |
829 if (type == CONTENT_SETTINGS_TYPE_GEOLOCATION || | |
830 type == CONTENT_SETTINGS_TYPE_NOTIFICATIONS) { | |
831 NOTREACHED(); | |
832 return; | |
833 } | |
834 | |
835 HostContentSettingsMap* settings_map = | |
836 mode == "normal" ? GetContentSettingsMap() : | |
837 GetOTRContentSettingsMap(); | |
838 | |
839 // The settings map could be null if the mode was OTR but the OTR profile | |
840 // got destroyed before we received this message. | |
841 if (!settings_map) | |
842 return; | |
843 settings_map->SetContentSetting(ContentSettingsPattern::FromString(pattern), | |
844 ContentSettingsPattern::Wildcard(), | |
845 type, | |
846 "", | |
847 ContentSettingFromString(setting)); | |
848 } | |
849 | |
850 void ContentSettingsHandler::CheckExceptionPatternValidity( | |
851 const ListValue* args) { | |
852 size_t arg_i = 0; | |
853 Value* type; | |
854 CHECK(args->Get(arg_i++, &type)); | |
855 std::string mode_string; | |
856 CHECK(args->GetString(arg_i++, &mode_string)); | |
857 std::string pattern_string; | |
858 CHECK(args->GetString(arg_i++, &pattern_string)); | |
859 | |
860 ContentSettingsPattern pattern = | |
861 ContentSettingsPattern::FromString(pattern_string); | |
862 | |
863 scoped_ptr<Value> mode_value(Value::CreateStringValue(mode_string)); | |
864 scoped_ptr<Value> pattern_value(Value::CreateStringValue(pattern_string)); | |
865 scoped_ptr<Value> valid_value(Value::CreateBooleanValue(pattern.IsValid())); | |
866 | |
867 web_ui()->CallJavascriptFunction( | |
868 "ContentSettings.patternValidityCheckComplete", | |
869 *type, | |
870 *mode_value.get(), | |
871 *pattern_value.get(), | |
872 *valid_value.get()); | |
873 } | |
874 | |
875 // static | |
876 std::string ContentSettingsHandler::ContentSettingsTypeToGroupName( | |
877 ContentSettingsType type) { | |
878 for (size_t i = 0; i < arraysize(kContentSettingsTypeGroupNames); ++i) { | |
879 if (type == kContentSettingsTypeGroupNames[i].type) | |
880 return kContentSettingsTypeGroupNames[i].name; | |
881 } | |
882 | |
883 NOTREACHED(); | |
884 return std::string(); | |
885 } | |
886 | |
887 HostContentSettingsMap* ContentSettingsHandler::GetContentSettingsMap() { | |
888 return Profile::FromWebUI(web_ui())->GetHostContentSettingsMap(); | |
889 } | |
890 | |
891 ProtocolHandlerRegistry* ContentSettingsHandler::GetProtocolHandlerRegistry() { | |
892 return Profile::FromWebUI(web_ui())->GetProtocolHandlerRegistry(); | |
893 } | |
894 | |
895 HostContentSettingsMap* | |
896 ContentSettingsHandler::GetOTRContentSettingsMap() { | |
897 Profile* profile = Profile::FromWebUI(web_ui()); | |
898 if (profile->HasOffTheRecordProfile()) | |
899 return profile->GetOffTheRecordProfile()->GetHostContentSettingsMap(); | |
900 return NULL; | |
901 } | |
OLD | NEW |