Commit 1fbf113b authored by finnur's avatar finnur Committed by Commit bot

Site Settings Desktop: Implement Zoom Levels category.

BUG=635846, 614277
CQ_INCLUDE_TRYBOTS=master.tryserver.chromium.linux:closure_compilation

Review-Url: https://codereview.chromium.org/2323693002
Cr-Commit-Position: refs/heads/master@{#417554}
parent 24cc79a3
...@@ -1563,6 +1563,9 @@ ...@@ -1563,6 +1563,9 @@
<message name="IDS_SETTINGS_SITE_SETTINGS_FULLSCREEN" desc="Label for the fullscreen site settings."> <message name="IDS_SETTINGS_SITE_SETTINGS_FULLSCREEN" desc="Label for the fullscreen site settings.">
Fullscreen Fullscreen
</message> </message>
<message name="IDS_SETTINGS_SITE_SETTINGS_ZOOM_LEVELS" desc="Label for the Zoom levels category in site settings.">
Zoom levels
</message>
<message name="IDS_SETTINGS_SITE_SETTINGS_MAY_SAVE_COOKIES" desc="Label for the cookies option description site settings."> <message name="IDS_SETTINGS_SITE_SETTINGS_MAY_SAVE_COOKIES" desc="Label for the cookies option description site settings.">
Sites can save and read cookie data Sites can save and read cookie data
</message> </message>
...@@ -1761,6 +1764,9 @@ ...@@ -1761,6 +1764,9 @@
<message name="IDS_SETTINGS_SITE_SETTINGS_INCOGNITO_EMBEDDED" desc="A label for a site rule that specifies an embedded origin and only applies to the current incognito session."> <message name="IDS_SETTINGS_SITE_SETTINGS_INCOGNITO_EMBEDDED" desc="A label for a site rule that specifies an embedded origin and only applies to the current incognito session.">
Current incognito session (<ph name="EMBEDDING">$1<ex>embedded on google.com</ex></ph>) Current incognito session (<ph name="EMBEDDING">$1<ex>embedded on google.com</ex></ph>)
</message> </message>
<message name="IDS_SETTINGS_SITE_SETTINGS_NO_ZOOMED_SITES" desc="A label explaining that no sites have a configured zoom in/out value.">
No sites have been zoomed in or out.
</message>
<!-- Sync / People Page --> <!-- Sync / People Page -->
<message name="IDS_SETTINGS_PEOPLE" desc="Name of the settings page which manages Chrome's signed-in Google profile."> <message name="IDS_SETTINGS_PEOPLE" desc="Name of the settings page which manages Chrome's signed-in Google profile.">
......
...@@ -16,6 +16,7 @@ ...@@ -16,6 +16,7 @@
<link rel="import" href="/site_settings/protocol_handlers.html"> <link rel="import" href="/site_settings/protocol_handlers.html">
<link rel="import" href="/site_settings/usb_devices.html"> <link rel="import" href="/site_settings/usb_devices.html">
<link rel="import" href="/site_settings/site_data.html"> <link rel="import" href="/site_settings/site_data.html">
<link rel="import" href="/site_settings/zoom_levels.html">
<link rel="import" href="/site_settings_page/site_settings_page.html"> <link rel="import" href="/site_settings_page/site_settings_page.html">
<if expr="use_nss_certs"> <if expr="use_nss_certs">
...@@ -230,6 +231,11 @@ ...@@ -230,6 +231,11 @@
<protocol-handlers></protocol-handlers> <protocol-handlers></protocol-handlers>
</settings-subpage> </settings-subpage>
</template> </template>
<template is="dom-if" route-path="/siteSettings/zoomLevels" no-search>
<settings-subpage page-title="$i18n{siteSettingsCategoryZoomLevels}">
<zoom-levels></zoom-levels>
</settings-subpage>
</template>
<template is="dom-if" route-path="/siteSettings/javascript" no-search> <template is="dom-if" route-path="/siteSettings/javascript" no-search>
<settings-subpage page-title="$i18n{siteSettingsCategoryJavascript}"> <settings-subpage page-title="$i18n{siteSettingsCategoryJavascript}">
<site-settings-category <site-settings-category
......
...@@ -158,6 +158,7 @@ cr.define('settings', function() { ...@@ -158,6 +158,7 @@ cr.define('settings', function() {
r.SITE_SETTINGS_UNSANDBOXED_PLUGINS = r.SITE_SETTINGS_UNSANDBOXED_PLUGINS =
r.SITE_SETTINGS.createChild('unsandboxedPlugins'); r.SITE_SETTINGS.createChild('unsandboxedPlugins');
r.SITE_SETTINGS_USB_DEVICES = r.SITE_SETTINGS.createChild('usbDevices'); r.SITE_SETTINGS_USB_DEVICES = r.SITE_SETTINGS.createChild('usbDevices');
r.SITE_SETTINGS_ZOOM_LEVELS = r.SITE_SETTINGS.createChild('zoomLevels');
<if expr="chromeos"> <if expr="chromeos">
r.DATETIME = r.ADVANCED.createSection('/dateTime', 'dateTime'); r.DATETIME = r.ADVANCED.createSection('/dateTime', 'dateTime');
......
...@@ -907,6 +907,12 @@ ...@@ -907,6 +907,12 @@
<structure name="IDR_SETTINGS_WEBSITE_USAGE_PRIVATE_API_JS" <structure name="IDR_SETTINGS_WEBSITE_USAGE_PRIVATE_API_JS"
file="site_settings/website_usage_private_api.js" file="site_settings/website_usage_private_api.js"
type="chrome_html" /> type="chrome_html" />
<structure name="IDR_SETTINGS_ZOOM_LEVELS_HTML"
file="site_settings/zoom_levels.html"
type="chrome_html" />
<structure name="IDR_SETTINGS_ZOOM_LEVELS_JS"
file="site_settings/zoom_levels.js"
type="chrome_html" />
<if expr="chromeos"> <if expr="chromeos">
<structure name="IDR_SETTINGS_BLUETOOTH_DEVICE_DIALOG_HTML" <structure name="IDR_SETTINGS_BLUETOOTH_DEVICE_DIALOG_HTML"
file="bluetooth_page/bluetooth_device_dialog.html" file="bluetooth_page/bluetooth_device_dialog.html"
......
...@@ -170,5 +170,13 @@ ...@@ -170,5 +170,13 @@
], ],
'includes': ['../../../../../third_party/closure_compiler/compile_js2.gypi'], 'includes': ['../../../../../third_party/closure_compiler/compile_js2.gypi'],
}, },
{
'target_name': 'zoom_levels',
'dependencies': [
'<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:web_ui_listener_behavior',
'site_settings_behavior',
],
'includes': ['../../../../../third_party/closure_compiler/compile_js2.gypi'],
},
], ],
} }
...@@ -28,6 +28,7 @@ cr.define('settings', function() { ...@@ -28,6 +28,7 @@ cr.define('settings', function() {
KEYGEN: 'keygen', KEYGEN: 'keygen',
BACKGROUND_SYNC: 'background-sync', BACKGROUND_SYNC: 'background-sync',
USB_DEVICES: 'usb-chooser-data', USB_DEVICES: 'usb-chooser-data',
ZOOM_LEVELS: 'zoom-levels',
}; };
/** /**
......
...@@ -281,9 +281,10 @@ Polymer({ ...@@ -281,9 +281,10 @@ Polymer({
if (settings.ContentSettingsTypes[type] == if (settings.ContentSettingsTypes[type] ==
settings.ContentSettingsTypes.PROTOCOL_HANDLERS || settings.ContentSettingsTypes.PROTOCOL_HANDLERS ||
settings.ContentSettingsTypes[type] == settings.ContentSettingsTypes[type] ==
settings.ContentSettingsTypes.USB_DEVICES) { settings.ContentSettingsTypes.USB_DEVICES ||
// Protocol handlers and USB devices don't have data stored the way all settings.ContentSettingsTypes[type] ==
// the other categories do. settings.ContentSettingsTypes.ZOOM_LEVELS) {
// Some categories store their data in a custom way.
continue; continue;
} }
......
...@@ -71,6 +71,8 @@ var SiteSettingsBehaviorImpl = { ...@@ -71,6 +71,8 @@ var SiteSettingsBehaviorImpl = {
return 'unsandboxed-plugins'; return 'unsandboxed-plugins';
case settings.ContentSettingsTypes.USB_DEVICES: case settings.ContentSettingsTypes.USB_DEVICES:
return 'usb-devices'; return 'usb-devices';
case settings.ContentSettingsTypes.ZOOM_LEVELS:
return 'zoom-levels';
default: default:
return ''; return '';
} }
...@@ -114,6 +116,8 @@ var SiteSettingsBehaviorImpl = { ...@@ -114,6 +116,8 @@ var SiteSettingsBehaviorImpl = {
return settings.Route.SITE_SETTINGS_UNSANDBOXED_PLUGINS; return settings.Route.SITE_SETTINGS_UNSANDBOXED_PLUGINS;
case settings.ContentSettingsTypes.USB_DEVICES: case settings.ContentSettingsTypes.USB_DEVICES:
return settings.Route.SITE_SETTINGS_USB_DEVICES; return settings.Route.SITE_SETTINGS_USB_DEVICES;
case settings.ContentSettingsTypes.ZOOM_LEVELS:
return settings.Route.SITE_SETTINGS_ZOOM_LEVELS;
} }
assertNotReached(); assertNotReached();
}, },
...@@ -160,6 +164,8 @@ var SiteSettingsBehaviorImpl = { ...@@ -160,6 +164,8 @@ var SiteSettingsBehaviorImpl = {
return 'cr:extension'; return 'cr:extension';
case settings.ContentSettingsTypes.USB_DEVICES: case settings.ContentSettingsTypes.USB_DEVICES:
return 'settings:usb'; return 'settings:usb';
case settings.ContentSettingsTypes.ZOOM_LEVELS:
return 'settings:zoom-in';
default: default:
assertNotReached('Invalid category: ' + category); assertNotReached('Invalid category: ' + category);
return ''; return '';
...@@ -208,6 +214,8 @@ var SiteSettingsBehaviorImpl = { ...@@ -208,6 +214,8 @@ var SiteSettingsBehaviorImpl = {
return loadTimeData.getString('siteSettingsUnsandboxedPlugins'); return loadTimeData.getString('siteSettingsUnsandboxedPlugins');
case settings.ContentSettingsTypes.USB_DEVICES: case settings.ContentSettingsTypes.USB_DEVICES:
return loadTimeData.getString('siteSettingsUsbDevices'); return loadTimeData.getString('siteSettingsUsbDevices');
case settings.ContentSettingsTypes.ZOOM_LEVELS:
return loadTimeData.getString('siteSettingsZoomLevels');
default: default:
assertNotReached('Invalid category: ' + category); assertNotReached('Invalid category: ' + category);
return ''; return '';
...@@ -327,7 +335,7 @@ var SiteSettingsBehaviorImpl = { ...@@ -327,7 +335,7 @@ var SiteSettingsBehaviorImpl = {
'siteSettingsUnsandboxedPluginsAskRecommended') : 'siteSettingsUnsandboxedPluginsAskRecommended') :
loadTimeData.getString('siteSettingsUnsandboxedPluginsAsk'); loadTimeData.getString('siteSettingsUnsandboxedPluginsAsk');
default: default:
assertNotReached(); assertNotReached('Invalid category: ' + category);
return ''; return '';
} }
}, },
......
...@@ -66,6 +66,14 @@ var UsbDeviceDetails; ...@@ -66,6 +66,14 @@ var UsbDeviceDetails;
*/ */
var UsbDeviceEntry; var UsbDeviceEntry;
/**
* @typedef {{origin: string,
* setting: string,
* source: string,
* zoom: string}}
*/
var ZoomLevelEntry;
cr.define('settings', function() { cr.define('settings', function() {
/** @interface */ /** @interface */
function SiteSettingsPrefsBrowserProxy() {} function SiteSettingsPrefsBrowserProxy() {}
...@@ -216,6 +224,18 @@ cr.define('settings', function() { ...@@ -216,6 +224,18 @@ cr.define('settings', function() {
* profile exists). Returns the results via onIncognitoStatusChanged. * profile exists). Returns the results via onIncognitoStatusChanged.
*/ */
updateIncognitoStatus: function() {}, updateIncognitoStatus: function() {},
/**
* Fetches the currently defined zoom levels for sites. Returns the results
* via onZoomLevelsChanged.
*/
fetchZoomLevels: function() {},
/**
* Removes a zoom levels for a given host.
* @param {string} host The host to remove zoom levels for.
*/
removeZoomLevel: function(host) {},
}; };
/** /**
...@@ -326,6 +346,16 @@ cr.define('settings', function() { ...@@ -326,6 +346,16 @@ cr.define('settings', function() {
updateIncognitoStatus: function() { updateIncognitoStatus: function() {
chrome.send('updateIncognitoStatus'); chrome.send('updateIncognitoStatus');
}, },
/** @override */
fetchZoomLevels: function() {
chrome.send('fetchZoomLevels');
},
/** @override */
removeZoomLevel: function(host) {
chrome.send('removeZoomLevel', [host]);
},
}; };
return { return {
......
<link rel="import" href="chrome://resources/html/polymer.html">
<link rel="import" href="chrome://resources/cr_elements/icons.html">
<link rel="import" href="chrome://resources/polymer/v1_0/paper-icon-button/paper-icon-button.html">
<link rel="import" href="chrome://resources/html/web_ui_listener_behavior.html">
<link rel="import" href="/i18n_setup.html">
<link rel="import" href="/settings_shared_css.html">
<link rel="import" href="/site_settings/site_settings_behavior.html">
<link rel="import" href="/site_settings/site_settings_prefs_browser_proxy.html">
<dom-module id="zoom-levels">
<template>
<style include="settings-shared">
:host {
display: block;
}
.empty-message {
margin-top: 15px;
}
</style>
<div class="list-frame vertical-list" id="listContainer">
<template is="dom-repeat" items="[[sites_]]" id="list"
rendered-item-count="{{renderedCount}}">
<div class="list-item">
<div class="favicon-image"
style$="[[computeSiteIcon(item.origin)]]">
</div>
<div class="middle">
<div>[[item.origin]]</div>
</div>
<div>[[item.zoom]]</div>
<div>
<paper-icon-button icon="settings:delete"
on-tap="removeZoomLevel_">
</div>
</div>
</template>
<template is="dom-if" if="{{!renderedCount}}">
<div class="empty-message" id="empty">
$i18n{siteSettingsNoZoomedSites}
</div>
</template>
</div>
</template>
<script src="zoom_levels.js"></script>
</dom-module>
// Copyright 2016 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
/**
* @fileoverview
* 'zoom-levels' is the polymer element for showing the sites that are zoomed in
* or out.
*/
Polymer({
is: 'zoom-levels',
behaviors: [SiteSettingsBehavior, WebUIListenerBehavior],
properties: {
/**
* Array of sites that are zoomed in or out.
* @type {!Array<ZoomLevelEntry>}
*/
sites_: Array,
},
ready: function() {
this.addWebUIListener('onZoomLevelsChanged',
this.onZoomLevelsChanged_.bind(this));
this.browserProxy.fetchZoomLevels();
},
/**
* A handler for when zoom levels change.
* @param {!Array<ZoomLevelEntry>} sites The up to date list of sites and
* their zoom levels.
*/
onZoomLevelsChanged_: function(sites) {
this.sites_ = sites;
},
/**
* A handler for when a zoom level for a site is deleted.
* @param {!{model: !{index: number}}} event
* @private
*/
removeZoomLevel_: function(event) {
var site = this.sites_[event.model.index];
this.browserProxy.removeZoomLevel(site.origin);
},
});
...@@ -159,6 +159,14 @@ ...@@ -159,6 +159,14 @@
<div id="handlers" class="secondary"></div> <div id="handlers" class="secondary"></div>
</div> </div>
</div> </div>
<div class="settings-box" category$="[[ContentSettingsTypes.ZOOM_LEVELS]]"
on-tap="onTapCategory">
<iron-icon icon="[[computeIconForContentCategory(
ContentSettingsTypes.ZOOM_LEVELS)]]"></iron-icon>
<div class="middle">
[[computeTitleForContentCategory(ContentSettingsTypes.ZOOM_LEVELS)]]
</div>
</div>
<div class="settings-box" category$="[[ContentSettingsTypes.USB_DEVICES]]" <div class="settings-box" category$="[[ContentSettingsTypes.USB_DEVICES]]"
on-tap="onTapCategory"> on-tap="onTapCategory">
<iron-icon icon="[[computeIconForContentCategory( <iron-icon icon="[[computeIconForContentCategory(
......
...@@ -1268,6 +1268,8 @@ void AddSiteSettingsStrings(content::WebUIDataSource* html_source) { ...@@ -1268,6 +1268,8 @@ void AddSiteSettingsStrings(content::WebUIDataSource* html_source) {
{"siteSettingsCategoryNotifications", {"siteSettingsCategoryNotifications",
IDS_SETTINGS_SITE_SETTINGS_NOTIFICATIONS}, IDS_SETTINGS_SITE_SETTINGS_NOTIFICATIONS},
{"siteSettingsCategoryPopups", IDS_SETTINGS_SITE_SETTINGS_POPUPS}, {"siteSettingsCategoryPopups", IDS_SETTINGS_SITE_SETTINGS_POPUPS},
{"siteSettingsCategoryZoomLevels",
IDS_SETTINGS_SITE_SETTINGS_ZOOM_LEVELS},
{"siteSettingsAllSites", IDS_SETTINGS_SITE_SETTINGS_ALL_SITES}, {"siteSettingsAllSites", IDS_SETTINGS_SITE_SETTINGS_ALL_SITES},
{"siteSettingsAutomaticDownloads", {"siteSettingsAutomaticDownloads",
IDS_SETTINGS_SITE_SETTINGS_AUTOMATIC_DOWNLOADS}, IDS_SETTINGS_SITE_SETTINGS_AUTOMATIC_DOWNLOADS},
...@@ -1288,6 +1290,8 @@ void AddSiteSettingsStrings(content::WebUIDataSource* html_source) { ...@@ -1288,6 +1290,8 @@ void AddSiteSettingsStrings(content::WebUIDataSource* html_source) {
IDS_SETTINGS_SITE_SETTINGS_UNSANDBOXED_PLUGINS}, IDS_SETTINGS_SITE_SETTINGS_UNSANDBOXED_PLUGINS},
{"siteSettingsUsbDevices", IDS_SETTINGS_SITE_SETTINGS_USB_DEVICES}, {"siteSettingsUsbDevices", IDS_SETTINGS_SITE_SETTINGS_USB_DEVICES},
{"siteSettingsFullscreen", IDS_SETTINGS_SITE_SETTINGS_FULLSCREEN}, {"siteSettingsFullscreen", IDS_SETTINGS_SITE_SETTINGS_FULLSCREEN},
{"siteSettingsZoomLevels", IDS_SETTINGS_SITE_SETTINGS_ZOOM_LEVELS},
{"siteSettingsNoZoomedSites", IDS_SETTINGS_SITE_SETTINGS_NO_ZOOMED_SITES},
{"siteSettingsMaySaveCookies", {"siteSettingsMaySaveCookies",
IDS_SETTINGS_SITE_SETTINGS_MAY_SAVE_COOKIES}, IDS_SETTINGS_SITE_SETTINGS_MAY_SAVE_COOKIES},
{"siteSettingsAskFirst", IDS_SETTINGS_SITE_SETTINGS_ASK_FIRST}, {"siteSettingsAskFirst", IDS_SETTINGS_SITE_SETTINGS_ASK_FIRST},
......
...@@ -9,6 +9,7 @@ ...@@ -9,6 +9,7 @@
#include <utility> #include <utility>
#include "base/bind.h" #include "base/bind.h"
#include "base/i18n/number_formatting.h"
#include "base/macros.h" #include "base/macros.h"
#include "base/values.h" #include "base/values.h"
#include "chrome/browser/browsing_data/browsing_data_local_storage_helper.h" #include "chrome/browser/browsing_data/browsing_data_local_storage_helper.h"
...@@ -18,16 +19,20 @@ ...@@ -18,16 +19,20 @@
#include "chrome/browser/profiles/profile.h" #include "chrome/browser/profiles/profile.h"
#include "chrome/browser/ui/webui/site_settings_helper.h" #include "chrome/browser/ui/webui/site_settings_helper.h"
#include "chrome/common/extensions/manifest_handlers/app_launch_info.h" #include "chrome/common/extensions/manifest_handlers/app_launch_info.h"
#include "chrome/grit/generated_resources.h"
#include "components/content_settings/core/browser/host_content_settings_map.h" #include "components/content_settings/core/browser/host_content_settings_map.h"
#include "components/content_settings/core/common/content_settings_types.h" #include "components/content_settings/core/common/content_settings_types.h"
#include "content/public/browser/browser_thread.h" #include "content/public/browser/browser_thread.h"
#include "content/public/browser/notification_service.h" #include "content/public/browser/notification_service.h"
#include "content/public/browser/web_ui.h" #include "content/public/browser/web_ui.h"
#include "content/public/common/page_zoom.h"
#include "content/public/common/url_constants.h"
#include "extensions/browser/extension_registry.h" #include "extensions/browser/extension_registry.h"
#include "extensions/common/permissions/api_permission.h" #include "extensions/common/permissions/api_permission.h"
#include "extensions/common/permissions/permissions_data.h" #include "extensions/common/permissions/permissions_data.h"
#include "storage/browser/quota/quota_manager.h" #include "storage/browser/quota/quota_manager.h"
#include "storage/common/quota/quota_status_code.h" #include "storage/common/quota/quota_status_code.h"
#include "ui/base/l10n/l10n_util.h"
#include "ui/base/text/bytes_formatting.h" #include "ui/base/text/bytes_formatting.h"
namespace settings { namespace settings {
...@@ -36,6 +41,7 @@ namespace { ...@@ -36,6 +41,7 @@ namespace {
const char kAppName[] = "appName"; const char kAppName[] = "appName";
const char kAppId[] = "appId"; const char kAppId[] = "appId";
const char kZoom[] = "zoom";
// Return an appropriate API Permission ID for the given string name. // Return an appropriate API Permission ID for the given string name.
extensions::APIPermission::APIPermission::ID APIPermissionFromGroupName( extensions::APIPermission::APIPermission::ID APIPermissionFromGroupName(
...@@ -158,6 +164,14 @@ void SiteSettingsHandler::RegisterMessages() { ...@@ -158,6 +164,14 @@ void SiteSettingsHandler::RegisterMessages() {
"updateIncognitoStatus", "updateIncognitoStatus",
base::Bind(&SiteSettingsHandler::HandleUpdateIncognitoStatus, base::Bind(&SiteSettingsHandler::HandleUpdateIncognitoStatus,
base::Unretained(this))); base::Unretained(this)));
web_ui()->RegisterMessageCallback(
"fetchZoomLevels",
base::Bind(&SiteSettingsHandler::HandleFetchZoomLevels,
base::Unretained(this)));
web_ui()->RegisterMessageCallback(
"removeZoomLevel",
base::Bind(&SiteSettingsHandler::HandleRemoveZoomLevel,
base::Unretained(this)));
} }
void SiteSettingsHandler::OnJavascriptAllowed() { void SiteSettingsHandler::OnJavascriptAllowed() {
...@@ -175,11 +189,22 @@ void SiteSettingsHandler::OnJavascriptAllowed() { ...@@ -175,11 +189,22 @@ void SiteSettingsHandler::OnJavascriptAllowed() {
notification_registrar_.Add( notification_registrar_.Add(
this, chrome::NOTIFICATION_PROFILE_DESTROYED, this, chrome::NOTIFICATION_PROFILE_DESTROYED,
content::NotificationService::AllSources()); content::NotificationService::AllSources());
// Here we only subscribe to the HostZoomMap for the default storage partition
// since we don't allow the user to manage the zoom levels for apps.
// We're only interested in zoom-levels that are persisted, since the user
// is given the opportunity to view/delete these in the content-settings page.
host_zoom_map_subscription_ =
content::HostZoomMap::GetDefaultForBrowserContext(profile_)
->AddZoomLevelChangedCallback(
base::Bind(&SiteSettingsHandler::OnZoomLevelChanged,
base::Unretained(this)));
} }
void SiteSettingsHandler::OnJavascriptDisallowed() { void SiteSettingsHandler::OnJavascriptDisallowed() {
observer_.RemoveAll(); observer_.RemoveAll();
notification_registrar_.RemoveAll(); notification_registrar_.RemoveAll();
host_zoom_map_subscription_.reset();
} }
void SiteSettingsHandler::OnGetUsageInfo( void SiteSettingsHandler::OnGetUsageInfo(
...@@ -265,6 +290,11 @@ void SiteSettingsHandler::Observe( ...@@ -265,6 +290,11 @@ void SiteSettingsHandler::Observe(
} }
} }
void SiteSettingsHandler::OnZoomLevelChanged(
const content::HostZoomMap::ZoomLevelChange& change) {
SendZoomLevels();
}
void SiteSettingsHandler::HandleFetchUsageTotal( void SiteSettingsHandler::HandleFetchUsageTotal(
const base::ListValue* args) { const base::ListValue* args) {
AllowJavascript(); AllowJavascript();
...@@ -528,4 +558,92 @@ void SiteSettingsHandler::SendIncognitoStatus( ...@@ -528,4 +558,92 @@ void SiteSettingsHandler::SendIncognitoStatus(
base::FundamentalValue(incognito_enabled)); base::FundamentalValue(incognito_enabled));
} }
void SiteSettingsHandler::HandleFetchZoomLevels(const base::ListValue* args) {
AllowJavascript();
SendZoomLevels();
}
void SiteSettingsHandler::SendZoomLevels() {
if (!IsJavascriptAllowed())
return;
base::ListValue zoom_levels_exceptions;
content::HostZoomMap* host_zoom_map =
content::HostZoomMap::GetDefaultForBrowserContext(profile_);
content::HostZoomMap::ZoomLevelVector zoom_levels(
host_zoom_map->GetAllZoomLevels());
// Sort ZoomLevelChanges by host and scheme
// (a.com < http://a.com < https://a.com < b.com).
std::sort(zoom_levels.begin(), zoom_levels.end(),
[](const content::HostZoomMap::ZoomLevelChange& a,
const content::HostZoomMap::ZoomLevelChange& b) {
return a.host == b.host ? a.scheme < b.scheme : a.host < b.host;
});
for (content::HostZoomMap::ZoomLevelVector::const_iterator i =
zoom_levels.begin();
i != zoom_levels.end();
++i) {
std::unique_ptr<base::DictionaryValue> exception(new base::DictionaryValue);
switch (i->mode) {
case content::HostZoomMap::ZOOM_CHANGED_FOR_HOST: {
std::string host = i->host;
if (host == content::kUnreachableWebDataURL) {
host =
l10n_util::GetStringUTF8(IDS_ZOOMLEVELS_CHROME_ERROR_PAGES_LABEL);
}
exception->SetString(site_settings::kOrigin, 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.
continue;
case content::HostZoomMap::PAGE_SCALE_IS_ONE_CHANGED:
continue;
case content::HostZoomMap::ZOOM_CHANGED_TEMPORARY_ZOOM:
NOTREACHED();
}
std::string setting_string =
content_settings::ContentSettingToString(CONTENT_SETTING_DEFAULT);
DCHECK(!setting_string.empty());
exception->SetString(site_settings::kSetting, setting_string);
// 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, base::FormatPercent(zoom_percent));
exception->SetString(
site_settings::kSource, site_settings::kPreferencesSource);
// Append the new entry to the list and map.
zoom_levels_exceptions.Append(std::move(exception));
}
CallJavascriptFunction("cr.webUIListenerCallback",
base::StringValue("onZoomLevelsChanged"),
zoom_levels_exceptions);
}
void SiteSettingsHandler::HandleRemoveZoomLevel(const base::ListValue* args) {
CHECK_EQ(1U, args->GetSize());
std::string origin;
CHECK(args->GetString(0, &origin));
if (origin ==
l10n_util::GetStringUTF8(IDS_ZOOMLEVELS_CHROME_ERROR_PAGES_LABEL)) {
origin = content::kUnreachableWebDataURL;
}
content::HostZoomMap* host_zoom_map;
host_zoom_map = content::HostZoomMap::GetDefaultForBrowserContext(profile_);
double default_level = host_zoom_map->GetDefaultZoomLevel();
host_zoom_map->SetZoomLevelForHost(origin, default_level);
}
} // namespace settings } // namespace settings
...@@ -11,6 +11,7 @@ ...@@ -11,6 +11,7 @@
#include "chrome/browser/storage/storage_info_fetcher.h" #include "chrome/browser/storage/storage_info_fetcher.h"
#include "chrome/browser/ui/webui/settings/settings_page_ui_handler.h" #include "chrome/browser/ui/webui/settings/settings_page_ui_handler.h"
#include "components/content_settings/core/browser/content_settings_observer.h" #include "components/content_settings/core/browser/content_settings_observer.h"
#include "content/public/browser/host_zoom_map.h"
#include "content/public/browser/notification_observer.h" #include "content/public/browser/notification_observer.h"
#include "content/public/browser/notification_registrar.h" #include "content/public/browser/notification_registrar.h"
...@@ -26,7 +27,7 @@ namespace settings { ...@@ -26,7 +27,7 @@ namespace settings {
// Chrome "ContentSettings" settings page UI handler. // Chrome "ContentSettings" settings page UI handler.
class SiteSettingsHandler : public SettingsPageUIHandler, class SiteSettingsHandler : public SettingsPageUIHandler,
public content_settings::Observer, public content_settings::Observer,
public content::NotificationObserver { public content::NotificationObserver {
public: public:
explicit SiteSettingsHandler(Profile* profile); explicit SiteSettingsHandler(Profile* profile);
~SiteSettingsHandler() override; ~SiteSettingsHandler() override;
...@@ -51,12 +52,16 @@ class SiteSettingsHandler : public SettingsPageUIHandler, ...@@ -51,12 +52,16 @@ class SiteSettingsHandler : public SettingsPageUIHandler,
const content::NotificationSource& source, const content::NotificationSource& source,
const content::NotificationDetails& details) override; const content::NotificationDetails& details) override;
// content::HostZoomMap subscription.
void OnZoomLevelChanged(const content::HostZoomMap::ZoomLevelChange& change);
private: private:
friend class SiteSettingsHandlerTest; friend class SiteSettingsHandlerTest;
FRIEND_TEST_ALL_PREFIXES(SiteSettingsHandlerTest, GetAndSetDefault); FRIEND_TEST_ALL_PREFIXES(SiteSettingsHandlerTest, GetAndSetDefault);
FRIEND_TEST_ALL_PREFIXES(SiteSettingsHandlerTest, Origins); FRIEND_TEST_ALL_PREFIXES(SiteSettingsHandlerTest, Origins);
FRIEND_TEST_ALL_PREFIXES(SiteSettingsHandlerTest, Patterns); FRIEND_TEST_ALL_PREFIXES(SiteSettingsHandlerTest, Patterns);
FRIEND_TEST_ALL_PREFIXES(SiteSettingsHandlerTest, Incognito); FRIEND_TEST_ALL_PREFIXES(SiteSettingsHandlerTest, Incognito);
FRIEND_TEST_ALL_PREFIXES(SiteSettingsHandlerTest, ZoomLevels);
// Asynchronously fetches the usage for a given origin. Replies back with // Asynchronously fetches the usage for a given origin. Replies back with
// OnGetUsageInfo above. // OnGetUsageInfo above.
...@@ -91,10 +96,23 @@ class SiteSettingsHandler : public SettingsPageUIHandler, ...@@ -91,10 +96,23 @@ class SiteSettingsHandler : public SettingsPageUIHandler,
// Notifies the JS side whether incognito is enabled. // Notifies the JS side whether incognito is enabled.
void SendIncognitoStatus(Profile* profile, bool was_destroyed); void SendIncognitoStatus(Profile* profile, bool was_destroyed);
// Handles the request for a list of all zoom levels.
void HandleFetchZoomLevels(const base::ListValue* args);
// Sends the zoom level list down to the web ui.
void SendZoomLevels();
// Removes a particular zoom level for a given host.
void HandleRemoveZoomLevel(const base::ListValue* args);
Profile* profile_; Profile* profile_;
content::NotificationRegistrar notification_registrar_; content::NotificationRegistrar notification_registrar_;
// Keeps track of events related to zooming.
std::unique_ptr<content::HostZoomMap::Subscription>
host_zoom_map_subscription_;
// The host for which to fetch usage. // The host for which to fetch usage.
std::string usage_host_; std::string usage_host_;
......
...@@ -148,6 +148,37 @@ class SiteSettingsHandlerTest : public testing::Test { ...@@ -148,6 +148,37 @@ class SiteSettingsHandlerTest : public testing::Test {
EXPECT_EQ(expected_incognito, incognito); EXPECT_EQ(expected_incognito, incognito);
} }
void ValidateZoom(const std::string& expected_host,
const std::string& expected_zoom, size_t expected_total_calls) {
EXPECT_EQ(expected_total_calls, web_ui()->call_data().size());
const content::TestWebUI::CallData& data = *web_ui()->call_data().back();
EXPECT_EQ("cr.webUIListenerCallback", data.function_name());
std::string callback_id;
ASSERT_TRUE(data.arg1()->GetAsString(&callback_id));
EXPECT_EQ("onZoomLevelsChanged", callback_id);
const base::ListValue* exceptions;
ASSERT_TRUE(data.arg2()->GetAsList(&exceptions));
if (expected_host.empty()) {
EXPECT_EQ(0U, exceptions->GetSize());
} else {
EXPECT_EQ(1U, exceptions->GetSize());
const base::DictionaryValue* exception;
ASSERT_TRUE(exceptions->GetDictionary(0, &exception));
std::string host;
ASSERT_TRUE(exception->GetString("origin", &host));
ASSERT_EQ(expected_host, host);
std::string zoom;
ASSERT_TRUE(exception->GetString("zoom", &zoom));
ASSERT_EQ(expected_zoom, zoom);
}
}
void CreateIncognitoProfile() { void CreateIncognitoProfile() {
incognito_profile_ = TestingProfile::Builder().BuildIncognito(&profile_); incognito_profile_ = TestingProfile::Builder().BuildIncognito(&profile_);
} }
...@@ -253,4 +284,26 @@ TEST_F(SiteSettingsHandlerTest, Incognito) { ...@@ -253,4 +284,26 @@ TEST_F(SiteSettingsHandlerTest, Incognito) {
ValidateIncognitoExists(false, 3U); ValidateIncognitoExists(false, 3U);
} }
TEST_F(SiteSettingsHandlerTest, ZoomLevels) {
std::string host("http://www.google.com");
double zoom_level = 1.1;
content::HostZoomMap* host_zoom_map =
content::HostZoomMap::GetDefaultForBrowserContext(profile());
host_zoom_map->SetZoomLevelForHost(host, zoom_level);
ValidateZoom(host, "122%", 1U);
base::ListValue args;
handler()->HandleFetchZoomLevels(&args);
ValidateZoom(host, "122%", 2U);
args.AppendString("http://www.google.com");
handler()->HandleRemoveZoomLevel(&args);
ValidateZoom("", "", 3U);
double default_level = host_zoom_map->GetDefaultZoomLevel();
double level = host_zoom_map->GetZoomLevelForHostAndScheme("http", host);
EXPECT_EQ(default_level, level);
}
} // namespace settings } // namespace settings
...@@ -497,6 +497,7 @@ CrSettingsSiteSettingsTest.prototype = { ...@@ -497,6 +497,7 @@ CrSettingsSiteSettingsTest.prototype = {
'site_settings_category_tests.js', 'site_settings_category_tests.js',
'test_browser_proxy.js', 'test_browser_proxy.js',
'test_site_settings_prefs_browser_proxy.js', 'test_site_settings_prefs_browser_proxy.js',
'zoom_levels_tests.js',
]), ]),
}; };
...@@ -505,6 +506,7 @@ TEST_F('CrSettingsSiteSettingsTest', 'SiteSettings', function() { ...@@ -505,6 +506,7 @@ TEST_F('CrSettingsSiteSettingsTest', 'SiteSettings', function() {
site_details_permission.registerTests(); site_details_permission.registerTests();
site_list.registerTests(); site_list.registerTests();
site_settings_category.registerTests(); site_settings_category.registerTests();
zoom_levels.registerTests();
mocha.run(); mocha.run();
}); });
......
...@@ -144,7 +144,8 @@ cr.define('site_settings_category', function() { ...@@ -144,7 +144,8 @@ cr.define('site_settings_category', function() {
// Test category text ids and descriptions for those categories that // Test category text ids and descriptions for those categories that
// have those. // have those.
if (category != settings.ContentSettingsTypes.FULLSCREEN && if (category != settings.ContentSettingsTypes.FULLSCREEN &&
category != settings.ContentSettingsTypes.USB_DEVICES) { category != settings.ContentSettingsTypes.USB_DEVICES &&
category != settings.ContentSettingsTypes.ZOOM_LEVELS) {
assertNotEquals('', testElement.computeCategoryTextId(category)); assertNotEquals('', testElement.computeCategoryTextId(category));
assertNotEquals('', testElement.computeCategoryDesc( assertNotEquals('', testElement.computeCategoryDesc(
......
...@@ -50,8 +50,10 @@ var prefsEmpty = { ...@@ -50,8 +50,10 @@ var prefsEmpty = {
*/ */
var TestSiteSettingsPrefsBrowserProxy = function() { var TestSiteSettingsPrefsBrowserProxy = function() {
settings.TestBrowserProxy.call(this, [ settings.TestBrowserProxy.call(this, [
'fetchZoomLevels',
'getDefaultValueForContentType', 'getDefaultValueForContentType',
'getExceptionList', 'getExceptionList',
'removeZoomLevel',
'resetCategoryPermissionForOrigin', 'resetCategoryPermissionForOrigin',
'setCategoryPermissionForOrigin', 'setCategoryPermissionForOrigin',
'setDefaultValueForContentType', 'setDefaultValueForContentType',
...@@ -59,10 +61,11 @@ var TestSiteSettingsPrefsBrowserProxy = function() { ...@@ -59,10 +61,11 @@ var TestSiteSettingsPrefsBrowserProxy = function() {
/** @private {!SiteSettingsPref} */ /** @private {!SiteSettingsPref} */
this.prefs_ = prefsEmpty; this.prefs_ = prefsEmpty;
/** @private {!Array<ZoomLevelEntry>} */
this.zoomList_ = [];
}; };
// TODO(finnur): Modify the tests so that most of the code this class implements
// can be ripped out.
TestSiteSettingsPrefsBrowserProxy.prototype = { TestSiteSettingsPrefsBrowserProxy.prototype = {
__proto__: settings.TestBrowserProxy.prototype, __proto__: settings.TestBrowserProxy.prototype,
...@@ -82,6 +85,14 @@ TestSiteSettingsPrefsBrowserProxy.prototype = { ...@@ -82,6 +85,14 @@ TestSiteSettingsPrefsBrowserProxy.prototype = {
} }
}, },
/**
* Sets the prefs to use when testing.
* @param !Array<ZoomLevelEntry> list The zoom list to set.
*/
setZoomList: function(list) {
this.zoomList_ = list;
},
/** @override */ /** @override */
setDefaultValueForContentType: function(contentType, defaultValue) { setDefaultValueForContentType: function(contentType, defaultValue) {
this.methodCalled( this.methodCalled(
...@@ -185,4 +196,15 @@ TestSiteSettingsPrefsBrowserProxy.prototype = { ...@@ -185,4 +196,15 @@ TestSiteSettingsPrefsBrowserProxy.prototype = {
[primaryPattern, secondaryPattern, contentType, value]); [primaryPattern, secondaryPattern, contentType, value]);
return Promise.resolve(); return Promise.resolve();
}, },
/** @override */
fetchZoomLevels: function() {
cr.webUIListenerCallback('onZoomLevelsChanged', this.zoomList_);
this.methodCalled('fetchZoomLevels');
},
/** @override */
removeZoomLevel: function(host) {
this.methodCalled('removeZoomLevel', [host]);
},
}; };
// Copyright 2016 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
/** @fileoverview Suite of tests for zoom-levels. */
cr.define('zoom_levels', function() {
function registerTests() {
suite('ZoomLevels', function() {
/**
* A zoom levels category created before each test.
* @type {ZoomLevels}
*/
var testElement;
/**
* The mock proxy object to use during test.
* @type {TestSiteSettingsPrefsBrowserProxy}
*/
var browserProxy = null;
/**
* An example zoom list.
* @type {!Array<ZoomLevelEntry>}
*/
var zoomList = [
{
origin: 'http://www.google.com',
setting: '',
source: '',
zoom: '125%',
},
{
origin: 'http://www.chromium.org',
setting: '',
source: '',
zoom: '125%',
},
];
// Import necessary html before running suite.
suiteSetup(function() {
return PolymerTest.importHtml(
'chrome://md-settings/site_settings/zoom_levels.html');
});
setup(function() {
browserProxy = new TestSiteSettingsPrefsBrowserProxy();
settings.SiteSettingsPrefsBrowserProxyImpl.instance_ = browserProxy;
return initPage();
});
teardown(function() {
testElement.remove();
testElement = null;
});
/** @return {!Promise} */
function initPage() {
browserProxy.reset();
PolymerTest.clearBody();
testElement = document.createElement('zoom-levels');
document.body.appendChild(testElement);
return browserProxy.whenCalled('fetchZoomLevels');
}
/**
* Fetch the remove button from the list.
* @param {!HTMLElement} listContainer The list to use for the lookup.
* @param {number} index The index of the child element (which site) to
* fetch.
*/
function getRemoveButton(listContainer, index) {
return listContainer.children[index].querySelector('paper-icon-button');
}
test('empty zoom state', function() {
var list = testElement.$.list;
assertTrue(!!list);
assertEquals(0, list.items.length);
});
test('non-empty zoom state', function() {
browserProxy.setZoomList(zoomList);
return initPage().then(function() {
var list = testElement.$.list;
assertTrue(!!list);
assertEquals(2, list.items.length);
var removeButton =
getRemoveButton(testElement.$.listContainer, 0);
assert(!!removeButton);
MockInteractions.tap(removeButton);
return browserProxy.whenCalled('removeZoomLevel');
}).then(function(arguments) {
assertEquals("http://www.google.com", arguments[0]);
});
});
});
}
return {
registerTests: registerTests,
};
});
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment