• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright (c) 2013 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/content_settings/content_settings_internal_extension_provider.h"
6 
7 #include "chrome/browser/chrome_notification_types.h"
8 #include "chrome/browser/content_settings/content_settings_rule.h"
9 #include "chrome/browser/extensions/extension_host.h"
10 #include "chrome/browser/extensions/extension_service.h"
11 #include "chrome/common/chrome_content_client.h"
12 #include "chrome/common/content_settings.h"
13 #include "chrome/common/content_settings_pattern.h"
14 #include "chrome/common/extensions/api/plugins/plugins_handler.h"
15 #include "chrome/common/extensions/extension_set.h"
16 #include "chrome/common/extensions/features/simple_feature.h"
17 #include "content/public/browser/browser_thread.h"
18 #include "content/public/browser/notification_details.h"
19 #include "content/public/browser/notification_service.h"
20 #include "extensions/common/constants.h"
21 #include "extensions/common/extension.h"
22 
23 using extensions::UnloadedExtensionInfo;
24 
25 namespace content_settings {
26 
InternalExtensionProvider(ExtensionService * extension_service)27 InternalExtensionProvider::InternalExtensionProvider(
28     ExtensionService* extension_service)
29     : registrar_(new content::NotificationRegistrar) {
30   // Whitelist all extensions loaded so far.
31   const ExtensionSet* extensions = extension_service->extensions();
32   for (ExtensionSet::const_iterator it = extensions->begin();
33        it != extensions->end(); ++it) {
34     if (extensions::PluginInfo::HasPlugins(it->get()))
35       SetContentSettingForExtension(it->get(), CONTENT_SETTING_ALLOW);
36   }
37   Profile* profile = extension_service->profile();
38   registrar_->Add(this, chrome::NOTIFICATION_EXTENSION_HOST_CREATED,
39                   content::Source<Profile>(profile));
40   registrar_->Add(this, chrome::NOTIFICATION_EXTENSION_LOADED,
41                   content::Source<Profile>(profile));
42   registrar_->Add(this, chrome::NOTIFICATION_EXTENSION_UNLOADED,
43                   content::Source<Profile>(profile));
44 }
45 
~InternalExtensionProvider()46 InternalExtensionProvider::~InternalExtensionProvider() {
47   DCHECK(!registrar_.get());
48 }
49 
GetRuleIterator(ContentSettingsType content_type,const ResourceIdentifier & resource_identifier,bool incognito) const50 RuleIterator* InternalExtensionProvider::GetRuleIterator(
51     ContentSettingsType content_type,
52     const ResourceIdentifier& resource_identifier,
53     bool incognito) const {
54   return value_map_.GetRuleIterator(content_type, resource_identifier, &lock_);
55 }
56 
SetWebsiteSetting(const ContentSettingsPattern & primary_pattern,const ContentSettingsPattern & secondary_pattern,ContentSettingsType content_type,const ResourceIdentifier & resource_identifier,Value * value)57 bool InternalExtensionProvider::SetWebsiteSetting(
58     const ContentSettingsPattern& primary_pattern,
59     const ContentSettingsPattern& secondary_pattern,
60     ContentSettingsType content_type,
61     const ResourceIdentifier& resource_identifier,
62     Value* value) {
63   return false;
64 }
65 
ClearAllContentSettingsRules(ContentSettingsType content_type)66 void InternalExtensionProvider::ClearAllContentSettingsRules(
67     ContentSettingsType content_type) {}
68 
Observe(int type,const content::NotificationSource & source,const content::NotificationDetails & details)69 void InternalExtensionProvider::Observe(int type,
70                                   const content::NotificationSource& source,
71                                   const content::NotificationDetails& details) {
72   switch (type) {
73     case chrome::NOTIFICATION_EXTENSION_HOST_CREATED: {
74       const extensions::ExtensionHost* host =
75           content::Details<extensions::ExtensionHost>(details).ptr();
76       if (host->extension()->is_platform_app()) {
77         SetContentSettingForExtension(host->extension(), CONTENT_SETTING_BLOCK);
78 
79         // White-list CRD's v2 app, until crbug.com/134216 is complete.
80         const char* kAppWhitelist[] = {
81           "2775E568AC98F9578791F1EAB65A1BF5F8CEF414",
82           "4AA3C5D69A4AECBD236CAD7884502209F0F5C169",
83           "97B23E01B2AA064E8332EE43A7A85C628AADC3F2",
84           "9E930B2B5EABA6243AE6C710F126E54688E8FAF6",
85           "C449A798C495E6CF7D6AF10162113D564E67AD12",
86           "E410CDAB2C6E6DD408D731016CECF2444000A912",
87           "EBA908206905323CECE6DC4B276A58A0F4AC573F"
88         };
89         if (extensions::SimpleFeature::IsIdInWhitelist(
90                 host->extension()->id(),
91                 std::set<std::string>(
92                     kAppWhitelist, kAppWhitelist + arraysize(kAppWhitelist)))) {
93           SetContentSettingForExtensionAndResource(
94               host->extension(),
95               ChromeContentClient::kRemotingViewerPluginPath,
96               CONTENT_SETTING_ALLOW);
97         }
98       }
99 
100       break;
101     }
102     case chrome::NOTIFICATION_EXTENSION_LOADED: {
103       const extensions::Extension* extension =
104           content::Details<extensions::Extension>(details).ptr();
105       if (extensions::PluginInfo::HasPlugins(extension))
106         SetContentSettingForExtension(extension, CONTENT_SETTING_ALLOW);
107       break;
108     }
109     case chrome::NOTIFICATION_EXTENSION_UNLOADED: {
110       const UnloadedExtensionInfo& info =
111           *(content::Details<UnloadedExtensionInfo>(details).ptr());
112       if (extensions::PluginInfo::HasPlugins(info.extension))
113         SetContentSettingForExtension(info.extension, CONTENT_SETTING_DEFAULT);
114       break;
115     }
116     default:
117       NOTREACHED();
118   }
119 }
120 
ShutdownOnUIThread()121 void InternalExtensionProvider::ShutdownOnUIThread() {
122   DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
123   RemoveAllObservers();
124   registrar_.reset();
125 }
126 
SetContentSettingForExtension(const extensions::Extension * extension,ContentSetting setting)127 void InternalExtensionProvider::SetContentSettingForExtension(
128     const extensions::Extension* extension,
129     ContentSetting setting) {
130   SetContentSettingForExtensionAndResource(
131       extension, ResourceIdentifier(), setting);
132 }
133 
SetContentSettingForExtensionAndResource(const extensions::Extension * extension,const ResourceIdentifier & resource,ContentSetting setting)134 void InternalExtensionProvider::SetContentSettingForExtensionAndResource(
135     const extensions::Extension* extension,
136     const ResourceIdentifier& resource,
137     ContentSetting setting) {
138   scoped_ptr<ContentSettingsPattern::BuilderInterface> pattern_builder(
139       ContentSettingsPattern::CreateBuilder(false));
140   pattern_builder->WithScheme(extensions::kExtensionScheme);
141   pattern_builder->WithHost(extension->id());
142   pattern_builder->WithPathWildcard();
143 
144   ContentSettingsPattern primary_pattern = pattern_builder->Build();
145   ContentSettingsPattern secondary_pattern = ContentSettingsPattern::Wildcard();
146   {
147     base::AutoLock lock(lock_);
148     if (setting == CONTENT_SETTING_DEFAULT) {
149       value_map_.DeleteValue(primary_pattern,
150                              secondary_pattern,
151                              CONTENT_SETTINGS_TYPE_PLUGINS,
152                              resource);
153     } else {
154       value_map_.SetValue(primary_pattern,
155                           secondary_pattern,
156                           CONTENT_SETTINGS_TYPE_PLUGINS,
157                           resource,
158                           Value::CreateIntegerValue(setting));
159     }
160   }
161   NotifyObservers(primary_pattern,
162                   secondary_pattern,
163                   CONTENT_SETTINGS_TYPE_PLUGINS,
164                   resource);
165 }
166 
167 }  // namespace content_settings
168