OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "chrome/browser/extensions/unpacked_installer.h" | 5 #include "chrome/browser/extensions/unpacked_installer.h" |
6 | 6 |
7 #include "base/bind.h" | 7 #include "base/bind.h" |
8 #include "base/callback.h" | 8 #include "base/callback.h" |
9 #include "base/file_util.h" | 9 #include "base/file_util.h" |
| 10 #include "base/string_util.h" |
10 #include "base/threading/thread_restrictions.h" | 11 #include "base/threading/thread_restrictions.h" |
11 #include "chrome/browser/extensions/extension_install_prompt.h" | 12 #include "chrome/browser/extensions/extension_install_prompt.h" |
12 #include "chrome/browser/extensions/extension_install_ui.h" | 13 #include "chrome/browser/extensions/extension_install_ui.h" |
13 #include "chrome/browser/extensions/extension_prefs.h" | 14 #include "chrome/browser/extensions/extension_prefs.h" |
14 #include "chrome/browser/extensions/extension_service.h" | 15 #include "chrome/browser/extensions/extension_service.h" |
15 #include "chrome/browser/extensions/permissions_updater.h" | 16 #include "chrome/browser/extensions/permissions_updater.h" |
| 17 #include "chrome/browser/extensions/requirements_checker.h" |
16 #include "chrome/common/extensions/extension.h" | 18 #include "chrome/common/extensions/extension.h" |
17 #include "chrome/common/extensions/extension_file_util.h" | 19 #include "chrome/common/extensions/extension_file_util.h" |
18 #include "chrome/common/string_ordinal.h" | 20 #include "chrome/common/string_ordinal.h" |
19 | 21 |
20 using content::BrowserThread; | 22 using content::BrowserThread; |
21 using extensions::Extension; | 23 using extensions::Extension; |
22 | 24 |
23 namespace { | 25 namespace { |
24 | 26 |
25 const char kUnpackedExtensionsBlacklistedError[] = | 27 const char kUnpackedExtensionsBlacklistedError[] = |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
60 | 62 |
61 void SimpleExtensionLoadPrompt::ShowPrompt() { | 63 void SimpleExtensionLoadPrompt::ShowPrompt() { |
62 install_ui_->ConfirmInstall(this, extension_); | 64 install_ui_->ConfirmInstall(this, extension_); |
63 } | 65 } |
64 | 66 |
65 void SimpleExtensionLoadPrompt::InstallUIProceed() { | 67 void SimpleExtensionLoadPrompt::InstallUIProceed() { |
66 if (service_weak_.get()) { | 68 if (service_weak_.get()) { |
67 extensions::PermissionsUpdater perms_updater(service_weak_->profile()); | 69 extensions::PermissionsUpdater perms_updater(service_weak_->profile()); |
68 perms_updater.GrantActivePermissions(extension_, false); | 70 perms_updater.GrantActivePermissions(extension_, false); |
69 service_weak_->OnExtensionInstalled( | 71 service_weak_->OnExtensionInstalled( |
70 extension_, false, StringOrdinal()); // Not from web store. | 72 extension_, |
| 73 false, // Not from web store. |
| 74 StringOrdinal(), |
| 75 false /* no requirement errors */); |
71 } | 76 } |
72 delete this; | 77 delete this; |
73 } | 78 } |
74 | 79 |
75 void SimpleExtensionLoadPrompt::InstallUIAbort(bool user_initiated) { | 80 void SimpleExtensionLoadPrompt::InstallUIAbort(bool user_initiated) { |
76 delete this; | 81 delete this; |
77 } | 82 } |
78 | 83 |
79 } // namespace | 84 } // namespace |
80 | 85 |
81 namespace extensions { | 86 namespace extensions { |
82 | 87 |
83 // static | 88 // static |
84 scoped_refptr<UnpackedInstaller> UnpackedInstaller::Create( | 89 scoped_refptr<UnpackedInstaller> UnpackedInstaller::Create( |
85 ExtensionService* extension_service) { | 90 ExtensionService* extension_service) { |
86 return scoped_refptr<UnpackedInstaller>( | 91 return scoped_refptr<UnpackedInstaller>( |
87 new UnpackedInstaller(extension_service)); | 92 new UnpackedInstaller(extension_service)); |
88 } | 93 } |
89 | 94 |
90 UnpackedInstaller::UnpackedInstaller(ExtensionService* extension_service) | 95 UnpackedInstaller::UnpackedInstaller(ExtensionService* extension_service) |
91 : service_weak_(extension_service->AsWeakPtr()), | 96 : service_weak_(extension_service->AsWeakPtr()), |
92 prompt_for_plugins_(true) { | 97 prompt_for_plugins_(true), |
| 98 requirements_checker_(new RequirementsChecker()) { |
93 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 99 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
94 } | 100 } |
95 | 101 |
96 UnpackedInstaller::~UnpackedInstaller() { | 102 UnpackedInstaller::~UnpackedInstaller() { |
97 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI) || | 103 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI) || |
98 BrowserThread::CurrentlyOn(BrowserThread::FILE)); | 104 BrowserThread::CurrentlyOn(BrowserThread::FILE)); |
99 } | 105 } |
100 | 106 |
101 void UnpackedInstaller::Load(const FilePath& path_in) { | 107 void UnpackedInstaller::Load(const FilePath& path_in) { |
102 extension_path_ = path_in; | 108 extension_path_ = path_in; |
103 BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE, | 109 BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE, |
104 base::Bind(&UnpackedInstaller::GetAbsolutePath, this)); | 110 base::Bind(&UnpackedInstaller::GetAbsolutePath, this)); |
105 } | 111 } |
106 | 112 |
107 void UnpackedInstaller::LoadFromCommandLine(const FilePath& path_in) { | 113 void UnpackedInstaller::LoadFromCommandLine(const FilePath& path_in) { |
| 114 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 115 |
108 if (!service_weak_.get()) | 116 if (!service_weak_.get()) |
109 return; | 117 return; |
110 // Load extensions from the command line synchronously to avoid a race | 118 // Load extensions from the command line synchronously to avoid a race |
111 // between extension loading and loading an URL from the command line. | 119 // between extension loading and loading an URL from the command line. |
112 base::ThreadRestrictions::ScopedAllowIO allow_io; | 120 base::ThreadRestrictions::ScopedAllowIO allow_io; |
113 | 121 |
114 extension_path_ = path_in; | 122 extension_path_ = path_in; |
115 file_util::AbsolutePath(&extension_path_); | 123 file_util::AbsolutePath(&extension_path_); |
116 | 124 |
117 if (!IsLoadingUnpackedAllowed()) { | 125 if (!IsLoadingUnpackedAllowed()) { |
118 ReportExtensionLoadError(kUnpackedExtensionsBlacklistedError); | 126 ReportExtensionLoadError(kUnpackedExtensionsBlacklistedError); |
119 return; | 127 return; |
120 } | 128 } |
121 | 129 |
122 std::string id = Extension::GenerateIdForPath(extension_path_); | 130 std::string id = Extension::GenerateIdForPath(extension_path_); |
123 bool allow_file_access = | 131 bool allow_file_access = |
124 Extension::ShouldAlwaysAllowFileAccess(Extension::LOAD); | 132 Extension::ShouldAlwaysAllowFileAccess(Extension::LOAD); |
125 if (service_weak_->extension_prefs()->HasAllowFileAccessSetting(id)) | 133 if (service_weak_->extension_prefs()->HasAllowFileAccessSetting(id)) |
126 allow_file_access = service_weak_->extension_prefs()->AllowFileAccess(id); | 134 allow_file_access = service_weak_->extension_prefs()->AllowFileAccess(id); |
127 | 135 |
128 int flags = Extension::REQUIRE_MODERN_MANIFEST_VERSION; | 136 int flags = Extension::REQUIRE_MODERN_MANIFEST_VERSION; |
129 if (allow_file_access) | 137 if (allow_file_access) |
130 flags |= Extension::ALLOW_FILE_ACCESS; | 138 flags |= Extension::ALLOW_FILE_ACCESS; |
131 | 139 |
132 std::string error; | 140 std::string error; |
133 scoped_refptr<const Extension> extension(extension_file_util::LoadExtension( | 141 extension_ = extension_file_util::LoadExtension( |
134 extension_path_, | 142 extension_path_, |
135 Extension::LOAD, | 143 Extension::LOAD, |
136 flags | Extension::FOLLOW_SYMLINKS_ANYWHERE, | 144 flags | Extension::FOLLOW_SYMLINKS_ANYWHERE, |
137 &error)); | 145 &error); |
138 | 146 |
139 if (!extension) { | 147 if (!extension_.get()) { |
140 ReportExtensionLoadError(error); | 148 ReportExtensionLoadError(error); |
141 return; | 149 return; |
142 } | 150 } |
143 | 151 |
144 OnLoaded(extension); | 152 CheckRequirements(); |
| 153 } |
| 154 |
| 155 void UnpackedInstaller::CheckRequirements() { |
| 156 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 157 requirements_checker_->Check( |
| 158 extension_, |
| 159 base::Bind(&UnpackedInstaller::RequirementsChecked, this)); |
| 160 } |
| 161 |
| 162 void UnpackedInstaller::RequirementsChecked(std::vector<std::string> errors) { |
| 163 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 164 |
| 165 if (!errors.empty()) { |
| 166 ReportExtensionLoadError(JoinString(errors, ' ')); |
| 167 return; |
| 168 } |
| 169 |
| 170 OnLoaded(); |
145 } | 171 } |
146 | 172 |
147 bool UnpackedInstaller::IsLoadingUnpackedAllowed() const { | 173 bool UnpackedInstaller::IsLoadingUnpackedAllowed() const { |
148 if (!service_weak_) | 174 if (!service_weak_) |
149 return true; | 175 return true; |
150 // If there is a "*" in the extension blacklist, then no extensions should be | 176 // If there is a "*" in the extension blacklist, then no extensions should be |
151 // allowed at all (except explicitly whitelisted extensions). | 177 // allowed at all (except explicitly whitelisted extensions). |
152 return !service_weak_->extension_prefs()->ExtensionsBlacklistedByDefault(); | 178 return !service_weak_->extension_prefs()->ExtensionsBlacklistedByDefault(); |
153 } | 179 } |
154 | 180 |
(...skipping 29 matching lines...) Expand all Loading... |
184 &UnpackedInstaller::LoadWithFileAccess, | 210 &UnpackedInstaller::LoadWithFileAccess, |
185 this, allow_file_access)); | 211 this, allow_file_access)); |
186 } | 212 } |
187 | 213 |
188 void UnpackedInstaller::LoadWithFileAccess(bool allow_file_access) { | 214 void UnpackedInstaller::LoadWithFileAccess(bool allow_file_access) { |
189 CHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); | 215 CHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); |
190 int flags = Extension::REQUIRE_MODERN_MANIFEST_VERSION; | 216 int flags = Extension::REQUIRE_MODERN_MANIFEST_VERSION; |
191 if (allow_file_access) | 217 if (allow_file_access) |
192 flags |= Extension::ALLOW_FILE_ACCESS; | 218 flags |= Extension::ALLOW_FILE_ACCESS; |
193 std::string error; | 219 std::string error; |
194 scoped_refptr<const Extension> extension(extension_file_util::LoadExtension( | 220 extension_ = extension_file_util::LoadExtension( |
195 extension_path_, | 221 extension_path_, |
196 Extension::LOAD, | 222 Extension::LOAD, |
197 flags | Extension::FOLLOW_SYMLINKS_ANYWHERE, | 223 flags | Extension::FOLLOW_SYMLINKS_ANYWHERE, |
198 &error)); | 224 &error); |
199 | 225 |
200 if (!extension) { | 226 if (!extension_.get()) { |
201 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, | 227 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, |
202 base::Bind( | 228 base::Bind( |
203 &UnpackedInstaller::ReportExtensionLoadError, | 229 &UnpackedInstaller::ReportExtensionLoadError, |
204 this, error)); | 230 this, error)); |
205 return; | 231 return; |
206 } | 232 } |
207 | 233 |
208 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, | 234 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, |
209 base::Bind( | 235 base::Bind(&UnpackedInstaller::CheckRequirements, this)); |
210 &UnpackedInstaller::OnLoaded, | |
211 this, extension)); | |
212 } | 236 } |
213 | 237 |
214 void UnpackedInstaller::ReportExtensionLoadError(const std::string &error) { | 238 void UnpackedInstaller::ReportExtensionLoadError(const std::string &error) { |
215 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 239 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
216 if (!service_weak_.get()) | 240 if (!service_weak_.get()) |
217 return; | 241 return; |
218 service_weak_->ReportExtensionLoadError(extension_path_, error, true); | 242 service_weak_->ReportExtensionLoadError(extension_path_, error, true); |
219 } | 243 } |
220 | 244 |
221 void UnpackedInstaller::OnLoaded( | 245 void UnpackedInstaller::OnLoaded() { |
222 const scoped_refptr<const Extension>& extension) { | |
223 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 246 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
224 if (!service_weak_.get()) | 247 if (!service_weak_.get()) |
225 return; | 248 return; |
226 const ExtensionSet* disabled_extensions = | 249 const ExtensionSet* disabled_extensions = |
227 service_weak_->disabled_extensions(); | 250 service_weak_->disabled_extensions(); |
228 if (service_weak_->show_extensions_prompts() && | 251 if (service_weak_->show_extensions_prompts() && |
229 prompt_for_plugins_ && | 252 prompt_for_plugins_ && |
230 !extension->plugins().empty() && | 253 !extension_->plugins().empty() && |
231 !disabled_extensions->Contains(extension->id())) { | 254 !disabled_extensions->Contains(extension_->id())) { |
232 SimpleExtensionLoadPrompt* prompt = new SimpleExtensionLoadPrompt( | 255 SimpleExtensionLoadPrompt* prompt = new SimpleExtensionLoadPrompt( |
233 service_weak_->profile(), | 256 service_weak_->profile(), |
234 service_weak_, | 257 service_weak_, |
235 extension); | 258 extension_); |
236 prompt->ShowPrompt(); | 259 prompt->ShowPrompt(); |
237 return; // continues in SimpleExtensionLoadPrompt::InstallPrompt* | 260 return; // continues in SimpleExtensionLoadPrompt::InstallPrompt* |
238 } | 261 } |
239 | 262 |
240 PermissionsUpdater perms_updater(service_weak_->profile()); | 263 PermissionsUpdater perms_updater(service_weak_->profile()); |
241 perms_updater.GrantActivePermissions(extension, false); | 264 perms_updater.GrantActivePermissions(extension_, false); |
242 service_weak_->OnExtensionInstalled(extension, | 265 service_weak_->OnExtensionInstalled(extension_, |
243 false, // Not from web store. | 266 false, // Not from web store. |
244 StringOrdinal()); | 267 StringOrdinal(), |
| 268 false /* no requirement errors */); |
245 } | 269 } |
246 | 270 |
247 } // namespace extensions | 271 } // namespace extensions |
OLD | NEW |