Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1615)

Unified Diff: chrome/browser/ui/webui/options/content_settings_handler.cc

Issue 1447813002: Add USB devices to the content settings page. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@get_all_objects
Patch Set: Created 5 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: chrome/browser/ui/webui/options/content_settings_handler.cc
diff --git a/chrome/browser/ui/webui/options/content_settings_handler.cc b/chrome/browser/ui/webui/options/content_settings_handler.cc
index 10ce23ade6398fb732c9c6706db094e7d62b3d22..f1c78c7b992d9c02ec620e42f799c418481de8fd 100644
--- a/chrome/browser/ui/webui/options/content_settings_handler.cc
+++ b/chrome/browser/ui/webui/options/content_settings_handler.cc
@@ -25,8 +25,11 @@
#include "chrome/browser/custom_handlers/protocol_handler_registry_factory.h"
#include "chrome/browser/extensions/extension_special_storage_policy.h"
#include "chrome/browser/notifications/desktop_notification_profile_util.h"
+#include "chrome/browser/permissions/chooser_context_base.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/ui/browser_list.h"
+#include "chrome/browser/usb/usb_chooser_context.h"
+#include "chrome/browser/usb/usb_chooser_context_factory.h"
#include "chrome/common/chrome_switches.h"
#include "chrome/common/extensions/manifest_handlers/app_launch_info.h"
#include "chrome/common/pref_names.h"
@@ -69,6 +72,13 @@ using content_settings::ContentSettingToString;
using content_settings::ContentSettingFromString;
using extensions::APIPermission;
+struct ChooserTypeNameEntry {
Bernhard Bauer 2015/11/16 12:53:30 Move this into the anonymous namespace? I also wou
Reilly Grant (use Gerrit) 2015/11/16 22:18:27 It is necessary to define this type outside of the
Bernhard Bauer 2015/11/17 13:36:53 Oh, right! In that case, can you move it into the
Reilly Grant (use Gerrit) 2015/11/18 00:30:09 Done.
+ ContentSettingsType type;
+ ChooserContextBase* (*get_context)(Profile*);
+ const char* name;
+ const char* ui_name_key;
+};
+
namespace {
struct ContentSettingWithExceptions {
@@ -92,6 +102,15 @@ typedef std::map<std::pair<ContentSettingsPattern, std::string>,
OnePatternSettings>
AllPatternsSettings;
+// Maps from the UI string to the object it represents (for sorting purposes).
+typedef std::multimap<std::string, const base::DictionaryValue*> SortedObjects;
+// Maps from a secondary URL to the set of objects it has permission to access.
+typedef std::map<GURL, SortedObjects> OneOriginObjects;
+// Maps from a primary URL/source pair to a OneOriginObjects. All the mappings
+// in OneOriginObjects share the given primary URL and source.
+typedef std::map<std::pair<GURL, std::string>, OneOriginObjects>
+ AllOriginObjects;
+
// The AppFilter is used in AddExceptionsGrantedByHostedApps() to choose
// extensions which should have their extent displayed.
typedef bool (*AppFilter)(const extensions::Extension& app,
@@ -109,6 +128,8 @@ const char kAppId[] = "appId";
const char kEmbeddingOrigin[] = "embeddingOrigin";
const char kPreferencesSource[] = "preference";
const char kZoom[] = "zoom";
+const char kObject[] = "object";
+const char kObjectName[] = "objectName";
const ContentSettingsTypeNameEntry kContentSettingsTypeGroupNames[] = {
{CONTENT_SETTINGS_TYPE_COOKIES, "cookies"},
@@ -134,6 +155,15 @@ const ContentSettingsTypeNameEntry kContentSettingsTypeGroupNames[] = {
#endif
};
+ChooserContextBase* GetUsbChooserContext(Profile* profile) {
+ return UsbChooserContextFactory::GetForProfile(profile);
+}
+
+const ChooserTypeNameEntry kChooserTypeGroupNames[] = {
+ {CONTENT_SETTINGS_TYPE_USB_CHOOSER_DATA, &GetUsbChooserContext,
+ "usb-devices", "name"},
+};
+
// 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";
@@ -247,6 +277,14 @@ ContentSettingsType ContentSettingsTypeFromGroupName(const std::string& name) {
return CONTENT_SETTINGS_TYPE_DEFAULT;
}
+const ChooserTypeNameEntry* ChooserTypeFromGroupName(const std::string& name) {
+ for (const ChooserTypeNameEntry& chooser_type : kChooserTypeGroupNames) {
+ if (chooser_type.name == name)
+ return &chooser_type;
+ }
+ return nullptr;
+}
+
// Create a DictionaryValue* that will act as a data source for a single row
// in a HostContentSettingsMap-controlled exceptions table (e.g., cookies).
scoped_ptr<base::DictionaryValue> GetExceptionForPage(
@@ -312,6 +350,31 @@ scoped_ptr<base::DictionaryValue> GetNotificationExceptionForPage(
return make_scoped_ptr(exception);
}
+// Create a DictionaryValue* that will act as a data source for a single row
+// in a chooser permission exceptions table.
+scoped_ptr<base::DictionaryValue> GetChooserExceptionForPage(
+ const GURL& requesting_origin,
+ const GURL& embedding_origin,
+ const std::string& provider_name,
+ const std::string& name,
+ const base::DictionaryValue* object) {
+ scoped_ptr<base::DictionaryValue> exception(new base::DictionaryValue());
+
+ std::string setting_string =
+ content_settings::ContentSettingToString(CONTENT_SETTING_DEFAULT);
+ DCHECK(!setting_string.empty());
+
+ exception->SetString(kSetting, setting_string);
+ exception->SetString(kOrigin, requesting_origin.spec());
+ exception->SetString(kEmbeddingOrigin, embedding_origin.spec());
+ exception->SetString(kSource, provider_name);
+ if (object) {
+ exception->SetString(kObjectName, name);
+ exception->Set(kObject, object->CreateDeepCopy());
+ }
+ return exception.Pass();
+}
+
// Returns true whenever the |extension| is hosted and has |permission|.
// Must have the AppFilter signature.
template <APIPermission::ID permission>
@@ -439,6 +502,7 @@ void ContentSettingsHandler::GetLocalizedValues(
{"manageHandlers", IDS_HANDLERS_MANAGE},
{"exceptionPatternHeader", IDS_EXCEPTIONS_PATTERN_HEADER},
{"exceptionBehaviorHeader", IDS_EXCEPTIONS_ACTION_HEADER},
+ {"exceptionUsbDeviceHeader", IDS_EXCEPTIONS_USB_DEVICE_HEADER},
{"exceptionZoomHeader", IDS_EXCEPTIONS_ZOOM_HEADER},
{"embeddedOnHost", IDS_EXCEPTIONS_GEOLOCATION_EMBEDDED_ON_HOST},
// Cookies filter.
@@ -550,6 +614,8 @@ void ContentSettingsHandler::GetLocalizedValues(
{"pushMessagingAllow", IDS_PUSH_MESSSAGING_ALLOW_RADIO},
{"pushMessagingAsk", IDS_PUSH_MESSSAGING_ASK_RADIO},
{"pushMessagingBlock", IDS_PUSH_MESSSAGING_BLOCK_RADIO},
+ {"usbDevicesHeader", IDS_USB_DEVICES_HEADER_AND_TAB_LABEL},
+ {"usbDevicesManage", IDS_USB_DEVICES_MANAGE_BUTTON},
{"zoomlevelsHeader", IDS_ZOOMLEVELS_HEADER_AND_TAB_LABEL},
{"zoomLevelsManage", IDS_ZOOMLEVELS_MANAGE_BUTTON},
};
@@ -604,6 +670,8 @@ void ContentSettingsHandler::GetLocalizedValues(
IDS_AUTOMATIC_DOWNLOADS_TAB_LABEL);
RegisterTitle(localized_strings, "midi-sysex",
IDS_MIDI_SYSEX_TAB_LABEL);
+ RegisterTitle(localized_strings, "usb-devices",
+ IDS_USB_DEVICES_HEADER_AND_TAB_LABEL);
RegisterTitle(localized_strings, "zoomlevels",
IDS_ZOOMLEVELS_HEADER_AND_TAB_LABEL);
@@ -699,6 +767,7 @@ void ContentSettingsHandler::InitializePage() {
UpdateHandlersEnabledRadios();
UpdateAllExceptionsViewsFromModel();
+ UpdateAllChooserExceptionsViewsFromModel();
UpdateProtectedContentExceptionsButton();
}
@@ -712,9 +781,16 @@ void ContentSettingsHandler::OnContentSettingChanged(
// TODO(estade): we pretend update_all() is always true.
if (details.update_all_types()) {
UpdateAllExceptionsViewsFromModel();
+ UpdateAllChooserExceptionsViewsFromModel();
} else {
if (ContainsKey(GetExceptionsInfoMap(), details.type()))
UpdateExceptionsViewFromModel(details.type());
+ for (const ChooserTypeNameEntry& chooser_type : kChooserTypeGroupNames) {
+ if (chooser_type.type == details.type()) {
+ UpdateChooserExceptionsViewFromModel(chooser_type);
+ break;
+ }
+ }
}
}
@@ -1032,6 +1108,114 @@ void ContentSettingsHandler::UpdateMIDISysExExceptionsView() {
CONTENT_SETTINGS_TYPE_MIDI_SYSEX);
}
+void ContentSettingsHandler::UpdateAllChooserExceptionsViewsFromModel() {
+ for (const ChooserTypeNameEntry& chooser_type : kChooserTypeGroupNames)
+ UpdateChooserExceptionsViewFromModel(chooser_type);
+}
+
+void ContentSettingsHandler::UpdateChooserExceptionsViewFromModel(
+ const ChooserTypeNameEntry& chooser_type) {
+ ChooserContextBase* chooser_context =
+ chooser_type.get_context(Profile::FromWebUI(web_ui()));
+ std::vector<scoped_ptr<ChosenObjectPattern>> objects =
+ chooser_context->GetAllGrantedObjects();
+ AllOriginObjects all_origin_objects;
+ for (const scoped_ptr<ChosenObjectPattern>& object : objects) {
+ std::string name;
+ bool found = object->object.GetString(chooser_type.ui_name_key, &name);
+ DCHECK(found);
+ // It is safe for this structure to hold references into |objects| because
+ // they are both destroyed at the end of this function.
+ all_origin_objects[make_pair(object->requesting_origin,
+ object->source)][object->embedding_origin]
+ .insert(make_pair(name, &object->object));
+ }
+
+ // Keep the exceptions sorted by provider so they will be displayed in
+ // precedence order.
+ ScopedVector<base::ListValue> all_provider_exceptions;
Bernhard Bauer 2015/11/16 12:53:31 I think there is some code here that is shared wit
Reilly Grant (use Gerrit) 2015/11/16 22:18:27 I've rewritten the code in both places to avoid th
+ all_provider_exceptions.resize(HostContentSettingsMap::NUM_PROVIDER_TYPES);
+ for (auto& one_provider_exceptions : all_provider_exceptions)
+ one_provider_exceptions = new base::ListValue();
+
+ for (const auto& all_origin_objects_entry : all_origin_objects) {
+ const GURL& requesting_origin = all_origin_objects_entry.first.first;
+ const std::string& source = all_origin_objects_entry.first.second;
+ const OneOriginObjects& one_origin_objects =
+ all_origin_objects_entry.second;
+
+ base::ListValue* this_provider_exceptions = all_provider_exceptions
+ [HostContentSettingsMap::GetProviderTypeFromSource(source)];
+
+ // Add entries for any non-embedded origins.
+ bool has_embedded_entries = false;
+ for (const auto& one_origin_objects_entry : one_origin_objects) {
+ const GURL& embedding_origin = one_origin_objects_entry.first;
+ const SortedObjects& sorted_objects = one_origin_objects_entry.second;
+
+ // Skip the embedded settings which will be added below.
+ if (requesting_origin != embedding_origin) {
+ has_embedded_entries = true;
+ continue;
+ }
+
+ for (const auto& sorted_objects_entry : sorted_objects) {
+ this_provider_exceptions->Append(GetChooserExceptionForPage(
+ requesting_origin, embedding_origin, source,
+ sorted_objects_entry.first, sorted_objects_entry.second));
+ }
+ }
+
+ if (has_embedded_entries) {
+ // Add a "parent" entry that simply acts as a heading for all entries
+ // where
+ // |requesting_origin| has been embedded.
+ this_provider_exceptions->Append(GetChooserExceptionForPage(
+ requesting_origin, requesting_origin, source, "", nullptr));
+
+ // Add the "children" for any embedded settings.
+ for (const auto& one_origin_objects_entry : one_origin_objects) {
+ const GURL& embedding_origin = one_origin_objects_entry.first;
+ const SortedObjects& sorted_objects = one_origin_objects_entry.second;
+
+ // Skip the non-embedded setting which we already added above.
+ if (requesting_origin == embedding_origin)
+ continue;
+
+ for (const auto& sorted_objects_entry : sorted_objects) {
+ this_provider_exceptions->Append(GetChooserExceptionForPage(
+ requesting_origin, embedding_origin, source,
+ sorted_objects_entry.first, sorted_objects_entry.second));
+ }
+ }
+ }
+ }
+
+ base::ListValue exceptions;
+ for (const auto& one_provider_exceptions : all_provider_exceptions) {
+ // Append |one_provider_exceptions| at the end of |exceptions|. ListValue
+ // does not support concatenation, so we must append one item at a time.
+ // Furthermore, ListValue::Remove is O(size) if we remove an item from the
+ // beginning, so we need to remove them in the reverse order.
+ ScopedVector<base::Value> reverse_helper;
Bernhard Bauer 2015/11/16 12:53:30 Also, this should use std::vector<scoped_ptr<>>. O
Reilly Grant (use Gerrit) 2015/11/16 22:18:27 Done.
+ while (!one_provider_exceptions->empty()) {
+ scoped_ptr<base::Value> exception;
+ one_provider_exceptions->Remove(one_provider_exceptions->GetSize() - 1,
+ &exception);
+ reverse_helper.push_back(exception.Pass());
+ }
+ while (!reverse_helper.empty()) {
+ ScopedVector<base::Value>::iterator back = reverse_helper.end() - 1;
+ exceptions.Append(make_scoped_ptr(*back));
+ reverse_helper.weak_erase(back);
+ }
+ }
+
+ base::StringValue type_string(chooser_type.name);
+ web_ui()->CallJavascriptFunction("ContentSettings.setExceptions", type_string,
+ exceptions);
+}
+
void ContentSettingsHandler::AdjustZoomLevelsListForSigninPageIfNecessary(
content::HostZoomMap::ZoomLevelVector* zoom_levels) {
if (switches::IsEnableWebviewBasedSignin())
@@ -1396,6 +1580,40 @@ void ContentSettingsHandler::RemoveZoomLevelException(
host_zoom_map->SetZoomLevelForHost(pattern, default_level);
}
+void ContentSettingsHandler::RemoveChooserException(
+ const ChooserTypeNameEntry* chooser_type,
+ const base::ListValue* args) {
+ std::string mode;
+ bool rv = args->GetString(1, &mode);
+ DCHECK(rv);
+
+ std::string requesting_origin_string;
+ rv = args->GetString(2, &requesting_origin_string);
+ DCHECK(rv);
+ GURL requesting_origin(requesting_origin_string);
+ DCHECK(requesting_origin.is_valid());
+
+ std::string embedding_origin_string;
+ rv = args->GetString(3, &embedding_origin_string);
+ DCHECK(rv);
+ GURL embedding_origin(embedding_origin_string);
+ DCHECK(embedding_origin.is_valid());
+
+ const base::DictionaryValue* object;
Bernhard Bauer 2015/11/16 12:53:30 Initialize this to null? Otherwise you might end u
Reilly Grant (use Gerrit) 2015/11/16 22:18:27 Done.
+ rv = args->GetDictionary(4, &object);
+ DCHECK(rv);
+
+ Profile* profile = Profile::FromWebUI(web_ui());
+ if (mode != "normal") {
Bernhard Bauer 2015/11/16 12:53:30 Braces are unnecessary.
Reilly Grant (use Gerrit) 2015/11/16 22:18:27 Done.
+ profile = profile->GetOffTheRecordProfile();
+ }
+
+ ChooserContextBase* chooser_context = chooser_type->get_context(profile);
+ chooser_context->RevokeObjectPermission(requesting_origin, embedding_origin,
+ *object);
+ // TODO(reillyg): Record this in UMA or something.
+}
+
void ContentSettingsHandler::RegisterMessages() {
web_ui()->RegisterMessageCallback("setContentFilter",
base::Bind(&ContentSettingsHandler::SetContentFilter,
@@ -1460,6 +1678,13 @@ void ContentSettingsHandler::RemoveException(const base::ListValue* args) {
return;
}
+ const ChooserTypeNameEntry* chooser_type =
+ ChooserTypeFromGroupName(type_string);
+ if (chooser_type) {
+ RemoveChooserException(chooser_type, args);
+ return;
+ }
+
ContentSettingsType type = ContentSettingsTypeFromGroupName(type_string);
RemoveExceptionFromHostContentSettingsMap(args, type);

Powered by Google App Engine
This is Rietveld 408576698