Upstream version 7.35.139.0
[platform/framework/web/crosswalk.git] / src / chrome / browser / ui / webui / options / content_settings_handler.cc
index 226e930..49e936e 100644 (file)
@@ -4,6 +4,7 @@
 
 #include "chrome/browser/ui/webui/options/content_settings_handler.h"
 
+#include <algorithm>
 #include <map>
 #include <vector>
 
@@ -11,6 +12,7 @@
 #include "base/bind_helpers.h"
 #include "base/command_line.h"
 #include "base/prefs/pref_service.h"
+#include "base/strings/string_number_conversions.h"
 #include "base/strings/utf_string_conversions.h"
 #include "base/values.h"
 #include "chrome/browser/browser_process.h"
@@ -30,7 +32,6 @@
 #include "chrome/common/chrome_switches.h"
 #include "chrome/common/content_settings.h"
 #include "chrome/common/content_settings_pattern.h"
-#include "chrome/common/extensions/extension_set.h"
 #include "chrome/common/extensions/manifest_handlers/app_launch_info.h"
 #include "chrome/common/pref_names.h"
 #include "chrome/common/url_constants.h"
@@ -40,6 +41,8 @@
 #include "content/public/browser/user_metrics.h"
 #include "content/public/browser/web_ui.h"
 #include "content/public/common/content_switches.h"
+#include "content/public/common/page_zoom.h"
+#include "extensions/common/extension_set.h"
 #include "extensions/common/permissions/api_permission.h"
 #include "grit/generated_resources.h"
 #include "grit/locale_settings.h"
@@ -49,7 +52,7 @@
 #include "chrome/browser/chromeos/login/user_manager.h"
 #endif
 
-using content::UserMetricsAction;
+using base::UserMetricsAction;
 using extensions::APIPermission;
 
 namespace {
@@ -83,6 +86,7 @@ const char* kAppId = "appId";
 const char* kEmbeddingOrigin = "embeddingOrigin";
 const char* kPreferencesSource = "preference";
 const char* kVideoSetting = "video";
+const char* kZoom = "zoom";
 
 const ContentSettingsTypeNameEntry kContentSettingsTypeGroupNames[] = {
   {CONTENT_SETTINGS_TYPE_COOKIES, "cookies"},
@@ -102,12 +106,15 @@ const ContentSettingsTypeNameEntry kContentSettingsTypeGroupNames[] = {
   {CONTENT_SETTINGS_TYPE_PPAPI_BROKER, "ppapi-broker"},
   {CONTENT_SETTINGS_TYPE_AUTOMATIC_DOWNLOADS, "multiple-automatic-downloads"},
   {CONTENT_SETTINGS_TYPE_MIDI_SYSEX, "midi-sysex"},
-  {CONTENT_SETTINGS_TYPE_SAVE_PASSWORD, "save-password"},
 #if defined(OS_CHROMEOS)
   {CONTENT_SETTINGS_TYPE_PROTECTED_MEDIA_IDENTIFIER, "protectedContent"},
 #endif
 };
 
+// A pseudo content type. We use it to display data like a content setting even
+// though it is not a real content setting.
+const char* kZoomContentType = "zoomlevels";
+
 ContentSettingsType ContentSettingsTypeFromGroupName(const std::string& name) {
   for (size_t i = 0; i < arraysize(kContentSettingsTypeGroupNames); ++i) {
     if (name == kContentSettingsTypeGroupNames[i].name)
@@ -154,12 +161,12 @@ ContentSetting ContentSettingFromString(const std::string& name) {
 // Create a DictionaryValue* that will act as a data source for a single row
 // in a HostContentSettingsMap-controlled exceptions table (e.g., cookies).
 // Ownership of the pointer is passed to the caller.
-DictionaryValue* GetExceptionForPage(
+base::DictionaryValue* GetExceptionForPage(
     const ContentSettingsPattern& pattern,
     const ContentSettingsPattern& secondary_pattern,
     const ContentSetting& setting,
     const std::string& provider_name) {
-  DictionaryValue* exception = new DictionaryValue();
+  base::DictionaryValue* exception = new base::DictionaryValue();
   exception->SetString(kOrigin, pattern.ToString());
   exception->SetString(kEmbeddingOrigin,
                        secondary_pattern == ContentSettingsPattern::Wildcard()
@@ -173,11 +180,11 @@ DictionaryValue* GetExceptionForPage(
 // Create a DictionaryValue* that will act as a data source for a single row
 // in the Geolocation exceptions table. Ownership of the pointer is passed to
 // the caller.
-DictionaryValue* GetGeolocationExceptionForPage(
+base::DictionaryValue* GetGeolocationExceptionForPage(
     const ContentSettingsPattern& origin,
     const ContentSettingsPattern& embedding_origin,
     ContentSetting setting) {
-  DictionaryValue* exception = new DictionaryValue();
+  base::DictionaryValue* exception = new base::DictionaryValue();
   exception->SetString(kSetting, ContentSettingToString(setting));
   exception->SetString(kOrigin, origin.ToString());
   exception->SetString(kEmbeddingOrigin, embedding_origin.ToString());
@@ -187,11 +194,11 @@ DictionaryValue* GetGeolocationExceptionForPage(
 // Create a DictionaryValue* that will act as a data source for a single row
 // in the desktop notifications exceptions table. Ownership of the pointer is
 // passed to the caller.
-DictionaryValue* GetNotificationExceptionForPage(
+base::DictionaryValue* GetNotificationExceptionForPage(
     const ContentSettingsPattern& pattern,
     ContentSetting setting,
     const std::string& provider_name) {
-  DictionaryValue* exception = new DictionaryValue();
+  base::DictionaryValue* exception = new base::DictionaryValue();
   exception->SetString(kSetting, ContentSettingToString(setting));
   exception->SetString(kOrigin, pattern.ToString());
   exception->SetString(kSource, provider_name);
@@ -209,8 +216,8 @@ bool HostedAppHasPermission(
 // Add an "Allow"-entry to the list of |exceptions| for a |url_pattern| from
 // the web extent of a hosted |app|.
 void AddExceptionForHostedApp(const std::string& url_pattern,
-    const extensions::Extension& app, ListValue* exceptions) {
-  DictionaryValue* exception = new DictionaryValue();
+    const extensions::Extension& app, base::ListValue* exceptions) {
+  base::DictionaryValue* exception = new base::DictionaryValue();
   exception->SetString(kSetting, ContentSettingToString(CONTENT_SETTING_ALLOW));
   exception->SetString(kOrigin, url_pattern);
   exception->SetString(kEmbeddingOrigin, url_pattern);
@@ -223,13 +230,13 @@ void AddExceptionForHostedApp(const std::string& url_pattern,
 // Asks the |profile| for hosted apps which have the |permission| set, and
 // adds their web extent and launch URL to the |exceptions| list.
 void AddExceptionsGrantedByHostedApps(
-    Profile* profile, AppFilter app_filter, ListValue* exceptions) {
+    Profile* profile, AppFilter app_filter, base::ListValue* exceptions) {
   const ExtensionService* extension_service = profile->GetExtensionService();
   // After ExtensionSystem::Init has been called at the browser's start,
   // GetExtensionService() should not return NULL, so this is safe:
-  const ExtensionSet* extensions = extension_service->extensions();
+  const extensions::ExtensionSet* extensions = extension_service->extensions();
 
-  for (ExtensionSet::const_iterator extension = extensions->begin();
+  for (extensions::ExtensionSet::const_iterator extension = extensions->begin();
        extension != extensions->end(); ++extension) {
     if (!app_filter(*extension->get(), profile))
       continue;
@@ -251,6 +258,13 @@ void AddExceptionsGrantedByHostedApps(
   }
 }
 
+// Sort ZoomLevelChanges by host and scheme
+// (a.com < http://a.com < https://a.com < b.com).
+bool HostZoomSort(const content::HostZoomMap::ZoomLevelChange& a,
+                  const content::HostZoomMap::ZoomLevelChange& b) {
+  return a.host == b.host ? a.scheme < b.scheme : a.host < b.host;
+}
+
 }  // namespace
 
 namespace options {
@@ -278,7 +292,7 @@ ContentSettingsHandler::~ContentSettingsHandler() {
 }
 
 void ContentSettingsHandler::GetLocalizedValues(
-    DictionaryValue* localized_strings) {
+    base::DictionaryValue* localized_strings) {
   DCHECK(localized_strings);
 
   static OptionsStringResource resources[] = {
@@ -292,6 +306,7 @@ void ContentSettingsHandler::GetLocalizedValues(
     { "manage_handlers", IDS_HANDLERS_MANAGE },
     { "exceptionPatternHeader", IDS_EXCEPTIONS_PATTERN_HEADER },
     { "exceptionBehaviorHeader", IDS_EXCEPTIONS_ACTION_HEADER },
+    { "exceptionZoomHeader", IDS_EXCEPTIONS_ZOOM_HEADER },
     { "embeddedOnHost", IDS_EXCEPTIONS_GEOLOCATION_EMBEDDED_ON_HOST },
     // Cookies filter.
     { "cookies_tab_label", IDS_COOKIES_TAB_LABEL },
@@ -401,6 +416,8 @@ void ContentSettingsHandler::GetLocalizedValues(
     { "midiSysExAllow", IDS_MIDI_SYSEX_ALLOW_RADIO },
     { "midiSysExAsk", IDS_MIDI_SYSEX_ASK_RADIO },
     { "midiSysExBlock", IDS_MIDI_SYSEX_BLOCK_RADIO },
+    { "zoomlevels_header", IDS_ZOOMLEVELS_HEADER_AND_TAB_LABEL },
+    { "zoomLevelsManage", IDS_ZOOMLEVELS_MANAGE_BUTTON },
   };
 
   RegisterStrings(localized_strings, resources, arraysize(resources));
@@ -439,9 +456,9 @@ void ContentSettingsHandler::GetLocalizedValues(
                 IDS_AUTOMATIC_DOWNLOADS_TAB_LABEL);
   RegisterTitle(localized_strings, "midi-sysex",
                 IDS_MIDI_SYSEX_TAB_LABEL);
+  RegisterTitle(localized_strings, "zoomlevels",
+                IDS_ZOOMLEVELS_HEADER_AND_TAB_LABEL);
 
-  localized_strings->SetBoolean("newContentSettings",
-      CommandLine::ForCurrentProcess()->HasSwitch(switches::kContentSettings2));
   localized_strings->SetString(
       "exceptionsLearnMoreUrl",
       google_util::StringAppendGoogleLocaleParam(
@@ -481,6 +498,18 @@ void ContentSettingsHandler::InitializeHandler() {
       prefs::kVideoCaptureAllowed,
       base::Bind(&ContentSettingsHandler::UpdateMediaSettingsView,
                  base::Unretained(this)));
+  pref_change_registrar_.Add(
+      prefs::kEnableDRM,
+      base::Bind(
+          &ContentSettingsHandler::UpdateProtectedContentExceptionsButton,
+          base::Unretained(this)));
+
+  content::HostZoomMap* host_zoom_map =
+      content::HostZoomMap::GetForBrowserContext(profile);
+  host_zoom_map_subscription_ =
+      host_zoom_map->AddZoomLevelChangedCallback(
+          base::Bind(&ContentSettingsHandler::OnZoomLevelChanged,
+                     base::Unretained(this)));
 
   flash_settings_manager_.reset(new PepperFlashSettingsManager(this, profile));
 }
@@ -491,6 +520,7 @@ void ContentSettingsHandler::InitializePage() {
 
   UpdateHandlersEnabledRadios();
   UpdateAllExceptionsViewsFromModel();
+  UpdateProtectedContentExceptionsButton();
 }
 
 void ContentSettingsHandler::Observe(
@@ -540,9 +570,6 @@ void ContentSettingsHandler::Observe(
       UpdateHandlersEnabledRadios();
       break;
     }
-
-    default:
-      OptionsPageUIHandler::Observe(type, source, details);
   }
 }
 
@@ -567,7 +594,7 @@ void ContentSettingsHandler::OnGetPermissionSettingsCompleted(
 
 void ContentSettingsHandler::UpdateSettingDefaultFromModel(
     ContentSettingsType type) {
-  DictionaryValue filter_settings;
+  base::DictionaryValue filter_settings;
   std::string provider_id;
   filter_settings.SetString(ContentSettingsTypeToGroupName(type) + ".value",
                             GetSettingDefaultFromModel(type, &provider_id));
@@ -593,7 +620,7 @@ void ContentSettingsHandler::UpdateMediaSettingsView() {
   media_settings_.default_setting_initialized = true;
   UpdateFlashMediaLinksVisibility();
 
-  DictionaryValue media_ui_settings;
+  base::DictionaryValue media_ui_settings;
   media_ui_settings.SetBoolean("cameraDisabled", video_disabled);
   media_ui_settings.SetBoolean("micDisabled", audio_disabled);
 
@@ -611,7 +638,7 @@ void ContentSettingsHandler::UpdateMediaSettingsView() {
 
   // In case only audio is enabled change the text appropriately.
   if (video_disabled && !audio_disabled) {
-    DictionaryValue media_ui_settings;
+    base::DictionaryValue media_ui_settings;
     media_ui_settings.SetString("askText", "mediaStreamAudioAsk");
     media_ui_settings.SetString("blockText", "mediaStreamAudioBlock");
     media_ui_settings.SetBoolean("showBubble", true);
@@ -625,7 +652,7 @@ void ContentSettingsHandler::UpdateMediaSettingsView() {
   if (audio_disabled && video_disabled) {
     // Fake policy controlled default because the user can not change anything
     // until both audio and video are blocked.
-    DictionaryValue filter_settings;
+    base::DictionaryValue filter_settings;
     std::string group_name =
         ContentSettingsTypeToGroupName(CONTENT_SETTINGS_TYPE_MEDIASTREAM);
     filter_settings.SetString(group_name + ".value",
@@ -675,6 +702,9 @@ void ContentSettingsHandler::UpdateAllExceptionsViewsFromModel() {
        type < CONTENT_SETTINGS_NUM_TYPES; ++type) {
     UpdateExceptionsViewFromModel(static_cast<ContentSettingsType>(type));
   }
+  // Zoom levels are not actually a content type so we need to handle them
+  // separately.
+  UpdateZoomLevelsExceptionsView();
 }
 
 void ContentSettingsHandler::UpdateAllOTRExceptionsViewsFromModel() {
@@ -711,9 +741,6 @@ void ContentSettingsHandler::UpdateExceptionsViewFromModel(
     case CONTENT_SETTINGS_TYPE_PROTOCOL_HANDLERS:
       // The RPH settings are retrieved separately.
       break;
-    case CONTENT_SETTINGS_TYPE_SAVE_PASSWORD:
-      // There is no user facing UI for this content type and we skip it here.
-      break;
     case CONTENT_SETTINGS_TYPE_MIDI_SYSEX:
       UpdateMIDISysExExceptionsView();
       break;
@@ -774,7 +801,7 @@ void ContentSettingsHandler::UpdateGeolocationExceptionsView() {
         [i->secondary_pattern] = i->setting;
   }
 
-  ListValue exceptions;
+  base::ListValue exceptions;
   AddExceptionsGrantedByHostedApps(
       profile,
       HostedAppHasPermission<APIPermission::kGeolocation>,
@@ -808,7 +835,7 @@ void ContentSettingsHandler::UpdateGeolocationExceptionsView() {
     }
   }
 
-  StringValue type_string(
+  base::StringValue type_string(
       ContentSettingsTypeToGroupName(CONTENT_SETTINGS_TYPE_GEOLOCATION));
   web_ui()->CallJavascriptFunction("ContentSettings.setExceptions",
                                    type_string, exceptions);
@@ -826,7 +853,7 @@ void ContentSettingsHandler::UpdateNotificationExceptionsView() {
   ContentSettingsForOneType settings;
   service->GetNotificationsSettings(&settings);
 
-  ListValue exceptions;
+  base::ListValue exceptions;
   AddExceptionsGrantedByHostedApps(profile,
       HostedAppHasPermission<APIPermission::kNotification>,
       &exceptions);
@@ -847,7 +874,7 @@ void ContentSettingsHandler::UpdateNotificationExceptionsView() {
                                         i->source));
   }
 
-  StringValue type_string(
+  base::StringValue type_string(
       ContentSettingsTypeToGroupName(CONTENT_SETTINGS_TYPE_NOTIFICATIONS));
   web_ui()->CallJavascriptFunction("ContentSettings.setExceptions",
                                    type_string, exceptions);
@@ -858,13 +885,13 @@ void ContentSettingsHandler::UpdateNotificationExceptionsView() {
 }
 
 void ContentSettingsHandler::UpdateMediaExceptionsView() {
-  ListValue media_exceptions;
+  base::ListValue media_exceptions;
   GetExceptionsFromHostContentSettingsMap(
       GetContentSettingsMap(),
       CONTENT_SETTINGS_TYPE_MEDIASTREAM_MIC,
       &media_exceptions);
 
-  ListValue video_exceptions;
+  base::ListValue video_exceptions;
   GetExceptionsFromHostContentSettingsMap(
       GetContentSettingsMap(),
       CONTENT_SETTINGS_TYPE_MEDIASTREAM_CAMERA,
@@ -872,9 +899,9 @@ void ContentSettingsHandler::UpdateMediaExceptionsView() {
 
   // Merge the |video_exceptions| list to |media_exceptions| list.
   std::map<std::string, base::DictionaryValue*> entries_map;
-  for (ListValue::const_iterator media_entry(media_exceptions.begin());
+  for (base::ListValue::const_iterator media_entry(media_exceptions.begin());
        media_entry != media_exceptions.end(); ++media_entry) {
-    DictionaryValue* media_dict = NULL;
+    base::DictionaryValue* media_dict = NULL;
     if (!(*media_entry)->GetAsDictionary(&media_dict))
       NOTREACHED();
 
@@ -886,9 +913,9 @@ void ContentSettingsHandler::UpdateMediaExceptionsView() {
     entries_map[media_origin] = media_dict;
   }
 
-  for (ListValue::iterator video_entry = video_exceptions.begin();
+  for (base::ListValue::iterator video_entry = video_exceptions.begin();
        video_entry != video_exceptions.end(); ++video_entry) {
-    DictionaryValue* video_dict = NULL;
+    base::DictionaryValue* video_dict = NULL;
     if (!(*video_entry)->GetAsDictionary(&video_dict))
       NOTREACHED();
 
@@ -900,7 +927,7 @@ void ContentSettingsHandler::UpdateMediaExceptionsView() {
     std::map<std::string, base::DictionaryValue*>::iterator iter =
         entries_map.find(video_origin);
     if (iter == entries_map.end()) {
-      DictionaryValue* exception = new DictionaryValue();
+      base::DictionaryValue* exception = new base::DictionaryValue();
       exception->SetString(kOrigin, video_origin);
       exception->SetString(kSetting,
                            ContentSettingToString(CONTENT_SETTING_ASK));
@@ -917,9 +944,9 @@ void ContentSettingsHandler::UpdateMediaExceptionsView() {
   }
 
   media_settings_.exceptions.clear();
-  for (ListValue::const_iterator media_entry = media_exceptions.begin();
+  for (base::ListValue::const_iterator media_entry = media_exceptions.begin();
        media_entry != media_exceptions.end(); ++media_entry) {
-    DictionaryValue* media_dict = NULL;
+    base::DictionaryValue* media_dict = NULL;
     bool result = (*media_entry)->GetAsDictionary(&media_dict);
     DCHECK(result);
 
@@ -939,7 +966,7 @@ void ContentSettingsHandler::UpdateMediaExceptionsView() {
   media_settings_.exceptions_initialized = true;
   UpdateFlashMediaLinksVisibility();
 
-  StringValue type_string(
+  base::StringValue type_string(
        ContentSettingsTypeToGroupName(CONTENT_SETTINGS_TYPE_MEDIASTREAM));
   web_ui()->CallJavascriptFunction("ContentSettings.setExceptions",
                                    type_string, media_exceptions);
@@ -959,12 +986,58 @@ void ContentSettingsHandler::UpdateMIDISysExExceptionsView() {
       CONTENT_SETTINGS_TYPE_MIDI_SYSEX);
 }
 
+void ContentSettingsHandler::UpdateZoomLevelsExceptionsView() {
+  base::ListValue zoom_levels_exceptions;
+
+  content::HostZoomMap* host_zoom_map =
+      content::HostZoomMap::GetForBrowserContext(Profile::FromWebUI(web_ui()));
+  content::HostZoomMap::ZoomLevelVector zoom_levels(
+      host_zoom_map->GetAllZoomLevels());
+  std::sort(zoom_levels.begin(), zoom_levels.end(), HostZoomSort);
+
+  for (content::HostZoomMap::ZoomLevelVector::const_iterator i =
+           zoom_levels.begin();
+       i != zoom_levels.end();
+       ++i) {
+    scoped_ptr<base::DictionaryValue> exception(new base::DictionaryValue);
+    switch (i->mode) {
+      case content::HostZoomMap::ZOOM_CHANGED_FOR_HOST:
+        exception->SetString(kOrigin, i->host);
+        break;
+      case content::HostZoomMap::ZOOM_CHANGED_FOR_SCHEME_AND_HOST:
+        // These are not stored in preferences and get cleared on next browser
+        // start. Therefore, we don't care for them.
+        break;
+      case content::HostZoomMap::ZOOM_CHANGED_TEMPORARY_ZOOM:
+        NOTREACHED();
+    }
+    exception->SetString(kSetting,
+                         ContentSettingToString(CONTENT_SETTING_DEFAULT));
+
+    // Calculate the zoom percent from the factor. Round up to the nearest whole
+    // number.
+    int zoom_percent = static_cast<int>(
+        content::ZoomLevelToZoomFactor(i->zoom_level) * 100 + 0.5);
+    exception->SetString(
+        kZoom,
+        l10n_util::GetStringFUTF16(IDS_ZOOM_PERCENT,
+                                   base::IntToString16(zoom_percent)));
+    exception->SetString(kSource, kPreferencesSource);
+    // Append the new entry to the list and map.
+    zoom_levels_exceptions.Append(exception.release());
+  }
+
+  base::StringValue type_string(kZoomContentType);
+  web_ui()->CallJavascriptFunction("ContentSettings.setExceptions",
+                                   type_string, zoom_levels_exceptions);
+}
+
 void ContentSettingsHandler::UpdateExceptionsViewFromHostContentSettingsMap(
     ContentSettingsType type) {
-  ListValue exceptions;
+  base::ListValue exceptions;
   GetExceptionsFromHostContentSettingsMap(
       GetContentSettingsMap(), type, &exceptions);
-  StringValue type_string(ContentSettingsTypeToGroupName(type));
+  base::StringValue type_string(ContentSettingsTypeToGroupName(type));
   web_ui()->CallJavascriptFunction("ContentSettings.setExceptions", type_string,
                                    exceptions);
 
@@ -991,9 +1064,9 @@ void ContentSettingsHandler::UpdateExceptionsViewFromOTRHostContentSettingsMap(
   const HostContentSettingsMap* otr_settings_map = GetOTRContentSettingsMap();
   if (!otr_settings_map)
     return;
-  ListValue exceptions;
+  base::ListValue exceptions;
   GetExceptionsFromHostContentSettingsMap(otr_settings_map, type, &exceptions);
-  StringValue type_string(ContentSettingsTypeToGroupName(type));
+  base::StringValue type_string(ContentSettingsTypeToGroupName(type));
   web_ui()->CallJavascriptFunction("ContentSettings.setOTRExceptions",
                                    type_string, exceptions);
 }
@@ -1001,7 +1074,7 @@ void ContentSettingsHandler::UpdateExceptionsViewFromOTRHostContentSettingsMap(
 void ContentSettingsHandler::GetExceptionsFromHostContentSettingsMap(
     const HostContentSettingsMap* map,
     ContentSettingsType type,
-    ListValue* exceptions) {
+    base::ListValue* exceptions) {
   ContentSettingsForOneType entries;
   map->GetSettingsForOneType(type, std::string(), &entries);
   // Group settings by primary_pattern.
@@ -1027,7 +1100,7 @@ void ContentSettingsHandler::GetExceptionsFromHostContentSettingsMap(
 
   // Keep the exceptions sorted by provider so they will be displayed in
   // precedence order.
-  std::vector<std::vector<Value*> > all_provider_exceptions;
+  std::vector<std::vector<base::Value*> > all_provider_exceptions;
   all_provider_exceptions.resize(HostContentSettingsMap::NUM_PROVIDER_TYPES);
 
   for (AllPatternsSettings::iterator i = all_patterns_settings.begin();
@@ -1045,8 +1118,9 @@ void ContentSettingsHandler::GetExceptionsFromHostContentSettingsMap(
       parent = one_settings.find(ContentSettingsPattern::Wildcard());
 
     const std::string& source = i->first.second;
-    std::vector<Value*>* this_provider_exceptions = &all_provider_exceptions.at(
-        HostContentSettingsMap::GetProviderTypeFromSource(source));
+    std::vector<base::Value*>* this_provider_exceptions =
+        &all_provider_exceptions.at(
+            HostContentSettingsMap::GetProviderTypeFromSource(source));
 
     // Add the "parent" entry for the non-embedded setting.
     ContentSetting parent_setting =
@@ -1082,13 +1156,13 @@ void ContentSettingsHandler::GetExceptionsFromHostContentSettingsMap(
 }
 
 void ContentSettingsHandler::RemoveNotificationException(
-    const ListValue* args, size_t arg_index) {
+    const base::ListValue* args) {
   Profile* profile = Profile::FromWebUI(web_ui());
   std::string origin;
   std::string setting;
-  bool rv = args->GetString(arg_index++, &origin);
+  bool rv = args->GetString(1, &origin);
   DCHECK(rv);
-  rv = args->GetString(arg_index++, &setting);
+  rv = args->GetString(2, &setting);
   DCHECK(rv);
   ContentSetting content_setting = ContentSettingFromString(setting);
 
@@ -1098,14 +1172,13 @@ void ContentSettingsHandler::RemoveNotificationException(
       ClearSetting(ContentSettingsPattern::FromString(origin));
 }
 
-void ContentSettingsHandler::RemoveMediaException(
-    const ListValue* args, size_t arg_index) {
+void ContentSettingsHandler::RemoveMediaException(const base::ListValue* args) {
   std::string mode;
-  bool rv = args->GetString(arg_index++, &mode);
+  bool rv = args->GetString(1, &mode);
   DCHECK(rv);
 
   std::string pattern;
-  rv = args->GetString(arg_index++, &pattern);
+  rv = args->GetString(2, &pattern);
   DCHECK(rv);
 
   HostContentSettingsMap* settings_map =
@@ -1126,18 +1199,18 @@ void ContentSettingsHandler::RemoveMediaException(
 }
 
 void ContentSettingsHandler::RemoveExceptionFromHostContentSettingsMap(
-    const ListValue* args, size_t arg_index,
+    const base::ListValue* args,
     ContentSettingsType type) {
   std::string mode;
-  bool rv = args->GetString(arg_index++, &mode);
+  bool rv = args->GetString(1, &mode);
   DCHECK(rv);
 
   std::string pattern;
-  rv = args->GetString(arg_index++, &pattern);
+  rv = args->GetString(2, &pattern);
   DCHECK(rv);
 
   std::string secondary_pattern;
-  rv = args->GetString(arg_index++, &secondary_pattern);
+  rv = args->GetString(3, &secondary_pattern);
   DCHECK(rv);
 
   HostContentSettingsMap* settings_map =
@@ -1155,6 +1228,22 @@ void ContentSettingsHandler::RemoveExceptionFromHostContentSettingsMap(
   }
 }
 
+void ContentSettingsHandler::RemoveZoomLevelException(
+    const base::ListValue* args) {
+  std::string mode;
+  bool rv = args->GetString(1, &mode);
+  DCHECK(rv);
+
+  std::string pattern;
+  rv = args->GetString(2, &pattern);
+  DCHECK(rv);
+
+  content::HostZoomMap* host_zoom_map =
+      content::HostZoomMap::GetForBrowserContext(Profile::FromWebUI(web_ui()));
+  double default_level = host_zoom_map->GetDefaultZoomLevel();
+  host_zoom_map->SetZoomLevelForHost(pattern, default_level);
+}
+
 void ContentSettingsHandler::RegisterMessages() {
   web_ui()->RegisterMessageCallback("setContentFilter",
       base::Bind(&ContentSettingsHandler::SetContentFilter,
@@ -1199,7 +1288,7 @@ void ContentSettingsHandler::ApplyWhitelist(ContentSettingsType content_type,
                     kDefaultWhitelistVersion);
 }
 
-void ContentSettingsHandler::SetContentFilter(const ListValue* args) {
+void ContentSettingsHandler::SetContentFilter(const base::ListValue* args) {
   DCHECK_EQ(2U, args->GetSize());
   std::string group, setting;
   if (!(args->GetString(0, &group) &&
@@ -1265,8 +1354,8 @@ void ContentSettingsHandler::SetContentFilter(const ListValue* args) {
           UserMetricsAction("Options_DefaultMediaStreamMicSettingChanged"));
       break;
     case CONTENT_SETTINGS_TYPE_AUTOMATIC_DOWNLOADS:
-      content::RecordAction(UserMetricsAction(
-          "Options_DefaultMultipleAutomaticDownloadsSettingChanged"));
+      content::RecordAction(
+          UserMetricsAction("Options_DefaultMultipleAutomaticDLSettingChange"));
       break;
     case CONTENT_SETTINGS_TYPE_MIDI_SYSEX:
       content::RecordAction(
@@ -1277,35 +1366,41 @@ void ContentSettingsHandler::SetContentFilter(const ListValue* args) {
   }
 }
 
-void ContentSettingsHandler::RemoveException(const ListValue* args) {
-  size_t arg_i = 0;
+void ContentSettingsHandler::RemoveException(const base::ListValue* args) {
   std::string type_string;
-  CHECK(args->GetString(arg_i++, &type_string));
+  CHECK(args->GetString(0, &type_string));
+
+  // Zoom levels are no actual content type so we need to handle them
+  // separately. They would not be recognized by
+  // ContentSettingsTypeFromGroupName.
+  if (type_string == kZoomContentType) {
+    RemoveZoomLevelException(args);
+    return;
+  }
 
   ContentSettingsType type = ContentSettingsTypeFromGroupName(type_string);
   switch (type) {
     case CONTENT_SETTINGS_TYPE_NOTIFICATIONS:
-      RemoveNotificationException(args, arg_i);
+      RemoveNotificationException(args);
       break;
     case CONTENT_SETTINGS_TYPE_MEDIASTREAM:
-      RemoveMediaException(args, arg_i);
+      RemoveMediaException(args);
       break;
     default:
-      RemoveExceptionFromHostContentSettingsMap(args, arg_i, type);
+      RemoveExceptionFromHostContentSettingsMap(args, type);
       break;
   }
 }
 
-void ContentSettingsHandler::SetException(const ListValue* args) {
-  size_t arg_i = 0;
+void ContentSettingsHandler::SetException(const base::ListValue* args) {
   std::string type_string;
-  CHECK(args->GetString(arg_i++, &type_string));
+  CHECK(args->GetString(0, &type_string));
   std::string mode;
-  CHECK(args->GetString(arg_i++, &mode));
+  CHECK(args->GetString(1, &mode));
   std::string pattern;
-  CHECK(args->GetString(arg_i++, &pattern));
+  CHECK(args->GetString(2, &pattern));
   std::string setting;
-  CHECK(args->GetString(arg_i++, &setting));
+  CHECK(args->GetString(3, &setting));
 
   ContentSettingsType type = ContentSettingsTypeFromGroupName(type_string);
   if (type == CONTENT_SETTINGS_TYPE_GEOLOCATION ||
@@ -1332,14 +1427,13 @@ void ContentSettingsHandler::SetException(const ListValue* args) {
 }
 
 void ContentSettingsHandler::CheckExceptionPatternValidity(
-    const ListValue* args) {
-  size_t arg_i = 0;
+    const base::ListValue* args) {
   std::string type_string;
-  CHECK(args->GetString(arg_i++, &type_string));
+  CHECK(args->GetString(0, &type_string));
   std::string mode_string;
-  CHECK(args->GetString(arg_i++, &mode_string));
+  CHECK(args->GetString(1, &mode_string));
   std::string pattern_string;
-  CHECK(args->GetString(arg_i++, &pattern_string));
+  CHECK(args->GetString(2, &pattern_string));
 
   ContentSettingsPattern pattern =
       ContentSettingsPattern::FromString(pattern_string);
@@ -1400,6 +1494,11 @@ void ContentSettingsHandler::OnPepperFlashPrefChanged() {
     media_settings_.flash_settings_initialized = false;
 }
 
+void ContentSettingsHandler::OnZoomLevelChanged(
+    const content::HostZoomMap::ZoomLevelChange& change) {
+  UpdateZoomLevelsExceptionsView();
+}
+
 void ContentSettingsHandler::ShowFlashMediaLink(LinkType link_type, bool show) {
   bool& show_link = link_type == DEFAULT_SETTING ?
       media_settings_.show_flash_default_link :
@@ -1459,4 +1558,13 @@ void ContentSettingsHandler::UpdateFlashMediaLinksVisibility() {
   }
 }
 
+void ContentSettingsHandler::UpdateProtectedContentExceptionsButton() {
+  PrefService* prefs = Profile::FromWebUI(web_ui())->GetPrefs();
+  // Exceptions apply only when the feature is enabled.
+  bool enable_exceptions = prefs->GetBoolean(prefs::kEnableDRM);
+  web_ui()->CallJavascriptFunction(
+      "ContentSettings.enableProtectedContentExceptions",
+      base::FundamentalValue(enable_exceptions));
+}
+
 }  // namespace options