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

Side by Side Diff: chrome/browser/extensions/component_loader.cc

Issue 2504333003: Fix DictionaryValue leak in component_loader.cc (Closed)
Patch Set: address comments + rewrite all loops Created 4 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 unified diff | Download patch
OLDNEW
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/component_loader.h" 5 #include "chrome/browser/extensions/component_loader.h"
6 6
7 #include <string> 7 #include <string>
8 8
9 #include "base/command_line.h" 9 #include "base/command_line.h"
10 #include "base/files/file_util.h" 10 #include "base/files/file_util.h"
(...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after
104 return !base::CommandLine::ForCurrentProcess()->HasSwitch( 104 return !base::CommandLine::ForCurrentProcess()->HasSwitch(
105 chromeos::switches::kGuestSession) && 105 chromeos::switches::kGuestSession) &&
106 user_manager::UserManager::IsInitialized() && 106 user_manager::UserManager::IsInitialized() &&
107 user_manager::UserManager::Get()->IsUserLoggedIn(); 107 user_manager::UserManager::Get()->IsUserLoggedIn();
108 } 108 }
109 #endif // defined(OS_CHROMEOS) 109 #endif // defined(OS_CHROMEOS)
110 110
111 } // namespace 111 } // namespace
112 112
113 ComponentLoader::ComponentExtensionInfo::ComponentExtensionInfo( 113 ComponentLoader::ComponentExtensionInfo::ComponentExtensionInfo(
114 const base::DictionaryValue* manifest, const base::FilePath& directory) 114 std::unique_ptr<base::DictionaryValue> manifest_param,
115 : manifest(manifest), 115 const base::FilePath& directory)
116 root_directory(directory) { 116 : manifest(std::move(manifest_param)), root_directory(directory) {
117 if (!root_directory.IsAbsolute()) { 117 if (!root_directory.IsAbsolute()) {
118 CHECK(PathService::Get(chrome::DIR_RESOURCES, &root_directory)); 118 CHECK(PathService::Get(chrome::DIR_RESOURCES, &root_directory));
119 root_directory = root_directory.Append(directory); 119 root_directory = root_directory.Append(directory);
120 } 120 }
121 extension_id = GenerateId(manifest, root_directory); 121 extension_id = GenerateId(manifest.get(), root_directory);
122 } 122 }
123 123
124 ComponentLoader::ComponentExtensionInfo::ComponentExtensionInfo(
125 ComponentExtensionInfo&& other)
126 : manifest(std::move(other.manifest)),
127 root_directory(std::move(other.root_directory)),
128 extension_id(std::move(other.extension_id)) {}
129
130 ComponentLoader::ComponentExtensionInfo&
131 ComponentLoader::ComponentExtensionInfo::operator=(
132 ComponentExtensionInfo&& other) {
133 manifest = std::move(other.manifest);
134 root_directory = std::move(other.root_directory);
135 extension_id = std::move(other.extension_id);
136 return *this;
137 }
138
139 ComponentLoader::ComponentExtensionInfo::~ComponentExtensionInfo() {}
140
124 ComponentLoader::ComponentLoader(ExtensionServiceInterface* extension_service, 141 ComponentLoader::ComponentLoader(ExtensionServiceInterface* extension_service,
125 PrefService* profile_prefs, 142 PrefService* profile_prefs,
126 PrefService* local_state, 143 PrefService* local_state,
127 Profile* profile) 144 Profile* profile)
128 : profile_prefs_(profile_prefs), 145 : profile_prefs_(profile_prefs),
129 local_state_(local_state), 146 local_state_(local_state),
130 profile_(profile), 147 profile_(profile),
131 extension_service_(extension_service), 148 extension_service_(extension_service),
132 ignore_whitelist_for_testing_(false), 149 ignore_whitelist_for_testing_(false),
133 weak_factory_(this) {} 150 weak_factory_(this) {}
134 151
135 ComponentLoader::~ComponentLoader() { 152 ComponentLoader::~ComponentLoader() {
136 ClearAllRegistered();
137 } 153 }
138 154
139 void ComponentLoader::LoadAll() { 155 void ComponentLoader::LoadAll() {
140 TRACE_EVENT0("browser,startup", "ComponentLoader::LoadAll"); 156 TRACE_EVENT0("browser,startup", "ComponentLoader::LoadAll");
141 SCOPED_UMA_HISTOGRAM_TIMER("Extensions.LoadAllComponentTime"); 157 SCOPED_UMA_HISTOGRAM_TIMER("Extensions.LoadAllComponentTime");
142 158
143 for (RegisteredComponentExtensions::iterator it = 159 for (const auto& component_extension : component_extensions_)
144 component_extensions_.begin(); 160 Load(component_extension);
145 it != component_extensions_.end(); ++it) {
146 Load(*it);
147 }
148 } 161 }
149 162
150 base::DictionaryValue* ComponentLoader::ParseManifest( 163 std::unique_ptr<base::DictionaryValue> ComponentLoader::ParseManifest(
151 base::StringPiece manifest_contents) const { 164 base::StringPiece manifest_contents) const {
152 JSONStringValueDeserializer deserializer(manifest_contents); 165 JSONStringValueDeserializer deserializer(manifest_contents);
153 std::unique_ptr<base::Value> manifest = deserializer.Deserialize(NULL, NULL); 166 std::unique_ptr<base::Value> manifest = deserializer.Deserialize(NULL, NULL);
154 167
155 if (!manifest.get() || !manifest->IsType(base::Value::TYPE_DICTIONARY)) { 168 if (!manifest.get() || !manifest->IsType(base::Value::TYPE_DICTIONARY)) {
156 LOG(ERROR) << "Failed to parse extension manifest."; 169 LOG(ERROR) << "Failed to parse extension manifest.";
157 return NULL; 170 return std::unique_ptr<base::DictionaryValue>();
158 } 171 }
159 // Transfer ownership to the caller. 172 return base::DictionaryValue::From(std::move(manifest));
160 return static_cast<base::DictionaryValue*>(manifest.release());
161 }
162
163 void ComponentLoader::ClearAllRegistered() {
164 for (RegisteredComponentExtensions::iterator it =
165 component_extensions_.begin();
166 it != component_extensions_.end(); ++it) {
167 delete it->manifest;
168 }
169
170 component_extensions_.clear();
171 }
172
173 std::string ComponentLoader::GetExtensionID(
174 int manifest_resource_id,
175 const base::FilePath& root_directory) {
176 base::DictionaryValue* manifest =
177 ParseManifest(ResourceBundle::GetSharedInstance().GetRawDataResource(
178 manifest_resource_id));
179 if (!manifest)
180 return std::string();
181
182 ComponentExtensionInfo info(manifest, root_directory);
183 return info.extension_id;
184 } 173 }
185 174
186 std::string ComponentLoader::Add(int manifest_resource_id, 175 std::string ComponentLoader::Add(int manifest_resource_id,
187 const base::FilePath& root_directory) { 176 const base::FilePath& root_directory) {
188 if (!ignore_whitelist_for_testing_ && 177 if (!ignore_whitelist_for_testing_ &&
189 !IsComponentExtensionWhitelisted(manifest_resource_id)) 178 !IsComponentExtensionWhitelisted(manifest_resource_id))
190 return std::string(); 179 return std::string();
191 180
192 base::StringPiece manifest_contents = 181 base::StringPiece manifest_contents =
193 ResourceBundle::GetSharedInstance().GetRawDataResource( 182 ResourceBundle::GetSharedInstance().GetRawDataResource(
194 manifest_resource_id); 183 manifest_resource_id);
195 return Add(manifest_contents, root_directory, true); 184 return Add(manifest_contents, root_directory, true);
196 } 185 }
197 186
198 std::string ComponentLoader::Add(const base::StringPiece& manifest_contents, 187 std::string ComponentLoader::Add(const base::StringPiece& manifest_contents,
199 const base::FilePath& root_directory) { 188 const base::FilePath& root_directory) {
200 return Add(manifest_contents, root_directory, false); 189 return Add(manifest_contents, root_directory, false);
201 } 190 }
202 191
203 std::string ComponentLoader::Add(const base::StringPiece& manifest_contents, 192 std::string ComponentLoader::Add(const base::StringPiece& manifest_contents,
204 const base::FilePath& root_directory, 193 const base::FilePath& root_directory,
205 bool skip_whitelist) { 194 bool skip_whitelist) {
206 // The Value is kept for the lifetime of the ComponentLoader. This is 195 // The Value is kept for the lifetime of the ComponentLoader. This is
207 // required in case LoadAll() is called again. 196 // required in case LoadAll() is called again.
208 base::DictionaryValue* manifest = ParseManifest(manifest_contents); 197 std::unique_ptr<base::DictionaryValue> manifest =
198 ParseManifest(manifest_contents);
209 if (manifest) 199 if (manifest)
210 return Add(manifest, root_directory, skip_whitelist); 200 return Add(std::move(manifest), root_directory, skip_whitelist);
211 return std::string(); 201 return std::string();
212 } 202 }
213 203
214 std::string ComponentLoader::Add(const base::DictionaryValue* parsed_manifest, 204 std::string ComponentLoader::Add(
215 const base::FilePath& root_directory, 205 std::unique_ptr<base::DictionaryValue> parsed_manifest,
216 bool skip_whitelist) { 206 const base::FilePath& root_directory,
217 ComponentExtensionInfo info(parsed_manifest, root_directory); 207 bool skip_whitelist) {
208 ComponentExtensionInfo info(std::move(parsed_manifest), root_directory);
218 if (!ignore_whitelist_for_testing_ && 209 if (!ignore_whitelist_for_testing_ &&
219 !skip_whitelist && 210 !skip_whitelist &&
220 !IsComponentExtensionWhitelisted(info.extension_id)) 211 !IsComponentExtensionWhitelisted(info.extension_id))
221 return std::string(); 212 return std::string();
222 213
223 component_extensions_.push_back(info); 214 component_extensions_.push_back(std::move(info));
215 ComponentExtensionInfo& added_info = component_extensions_.back();
224 if (extension_service_->is_ready()) 216 if (extension_service_->is_ready())
225 Load(info); 217 Load(added_info);
226 return info.extension_id; 218 return added_info.extension_id;
227 } 219 }
228 220
229 std::string ComponentLoader::AddOrReplace(const base::FilePath& path) { 221 std::string ComponentLoader::AddOrReplace(const base::FilePath& path) {
230 base::FilePath absolute_path = base::MakeAbsoluteFilePath(path); 222 base::FilePath absolute_path = base::MakeAbsoluteFilePath(path);
231 std::string error; 223 std::string error;
232 std::unique_ptr<base::DictionaryValue> manifest( 224 std::unique_ptr<base::DictionaryValue> manifest(
233 file_util::LoadManifest(absolute_path, &error)); 225 file_util::LoadManifest(absolute_path, &error));
234 if (!manifest) { 226 if (!manifest) {
235 LOG(ERROR) << "Could not load extension from '" << 227 LOG(ERROR) << "Could not load extension from '" <<
236 absolute_path.value() << "'. " << error; 228 absolute_path.value() << "'. " << error;
237 return std::string(); 229 return std::string();
238 } 230 }
239 Remove(GenerateId(manifest.get(), absolute_path)); 231 Remove(GenerateId(manifest.get(), absolute_path));
240 232
241 // We don't check component extensions loaded by path because this is only 233 // We don't check component extensions loaded by path because this is only
242 // used by developers for testing. 234 // used by developers for testing.
243 return Add(manifest.release(), absolute_path, true); 235 return Add(std::move(manifest), absolute_path, true);
244 } 236 }
245 237
246 void ComponentLoader::Reload(const std::string& extension_id) { 238 void ComponentLoader::Reload(const std::string& extension_id) {
247 for (RegisteredComponentExtensions::iterator it = 239 for (const auto& component_extension : component_extensions_) {
248 component_extensions_.begin(); it != component_extensions_.end(); 240 if (component_extension.extension_id == extension_id) {
249 ++it) { 241 Load(component_extension);
250 if (it->extension_id == extension_id) {
251 Load(*it);
252 break; 242 break;
253 } 243 }
254 } 244 }
255 } 245 }
256 246
257 void ComponentLoader::Load(const ComponentExtensionInfo& info) { 247 void ComponentLoader::Load(const ComponentExtensionInfo& info) {
258 std::string error; 248 std::string error;
259 scoped_refptr<const Extension> extension(CreateExtension(info, &error)); 249 scoped_refptr<const Extension> extension(CreateExtension(info, &error));
260 if (!extension.get()) { 250 if (!extension.get()) {
261 LOG(ERROR) << error; 251 LOG(ERROR) << error;
262 return; 252 return;
263 } 253 }
264 254
265 CHECK_EQ(info.extension_id, extension->id()) << extension->name(); 255 CHECK_EQ(info.extension_id, extension->id()) << extension->name();
266 extension_service_->AddComponentExtension(extension.get()); 256 extension_service_->AddComponentExtension(extension.get());
267 } 257 }
268 258
269 void ComponentLoader::Remove(const base::FilePath& root_directory) { 259 void ComponentLoader::Remove(const base::FilePath& root_directory) {
270 // Find the ComponentExtensionInfo for the extension. 260 // Find the ComponentExtensionInfo for the extension.
271 RegisteredComponentExtensions::iterator it = component_extensions_.begin(); 261 for (const auto& component_extension : component_extensions_) {
272 for (; it != component_extensions_.end(); ++it) { 262 if (component_extension.root_directory == root_directory) {
273 if (it->root_directory == root_directory) { 263 Remove(GenerateId(component_extension.manifest.get(), root_directory));
274 Remove(GenerateId(it->manifest, root_directory));
275 break; 264 break;
276 } 265 }
277 } 266 }
278 } 267 }
279 268
280 void ComponentLoader::Remove(const std::string& id) { 269 void ComponentLoader::Remove(const std::string& id) {
281 RegisteredComponentExtensions::iterator it = component_extensions_.begin(); 270 for (RegisteredComponentExtensions::iterator it =
282 for (; it != component_extensions_.end(); ++it) { 271 component_extensions_.begin();
272 it != component_extensions_.end(); ++it) {
283 if (it->extension_id == id) { 273 if (it->extension_id == id) {
284 UnloadComponent(&(*it)); 274 UnloadComponent(&(*it));
285 it = component_extensions_.erase(it); 275 component_extensions_.erase(it);
286 break; 276 break;
287 } 277 }
288 } 278 }
289 } 279 }
290 280
291 bool ComponentLoader::Exists(const std::string& id) const { 281 bool ComponentLoader::Exists(const std::string& id) const {
292 RegisteredComponentExtensions::const_iterator it = 282 for (const auto& component_extension : component_extensions_) {
293 component_extensions_.begin(); 283 if (component_extension.extension_id == id)
294 for (; it != component_extensions_.end(); ++it)
295 if (it->extension_id == id)
296 return true; 284 return true;
285 }
297 return false; 286 return false;
298 } 287 }
299 288
300 void ComponentLoader::AddFileManagerExtension() { 289 void ComponentLoader::AddFileManagerExtension() {
301 #if defined(OS_CHROMEOS) 290 #if defined(OS_CHROMEOS)
302 AddWithNameAndDescription( 291 AddWithNameAndDescription(
303 IDR_FILEMANAGER_MANIFEST, 292 IDR_FILEMANAGER_MANIFEST,
304 base::FilePath(FILE_PATH_LITERAL("file_manager")), 293 base::FilePath(FILE_PATH_LITERAL("file_manager")),
305 l10n_util::GetStringUTF8(IDS_FILEMANAGER_APP_NAME), 294 l10n_util::GetStringUTF8(IDS_FILEMANAGER_APP_NAME),
306 l10n_util::GetStringUTF8(IDS_FILEMANAGER_APP_DESCRIPTION)); 295 l10n_util::GetStringUTF8(IDS_FILEMANAGER_APP_DESCRIPTION));
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after
393 if (!ignore_whitelist_for_testing_ && 382 if (!ignore_whitelist_for_testing_ &&
394 !IsComponentExtensionWhitelisted(manifest_resource_id)) 383 !IsComponentExtensionWhitelisted(manifest_resource_id))
395 return; 384 return;
396 385
397 base::StringPiece manifest_contents = 386 base::StringPiece manifest_contents =
398 ResourceBundle::GetSharedInstance().GetRawDataResource( 387 ResourceBundle::GetSharedInstance().GetRawDataResource(
399 manifest_resource_id); 388 manifest_resource_id);
400 389
401 // The Value is kept for the lifetime of the ComponentLoader. This is 390 // The Value is kept for the lifetime of the ComponentLoader. This is
402 // required in case LoadAll() is called again. 391 // required in case LoadAll() is called again.
403 base::DictionaryValue* manifest = ParseManifest(manifest_contents); 392 std::unique_ptr<base::DictionaryValue> manifest =
393 ParseManifest(manifest_contents);
404 394
405 if (manifest) { 395 if (manifest) {
406 manifest->SetString(manifest_keys::kName, name_string); 396 manifest->SetString(manifest_keys::kName, name_string);
407 manifest->SetString(manifest_keys::kDescription, description_string); 397 manifest->SetString(manifest_keys::kDescription, description_string);
408 Add(manifest, root_directory, true); 398 Add(std::move(manifest), root_directory, true);
409 } 399 }
410 } 400 }
411 401
412 void ComponentLoader::AddChromeApp() { 402 void ComponentLoader::AddChromeApp() {
413 #if BUILDFLAG(ENABLE_APP_LIST) 403 #if BUILDFLAG(ENABLE_APP_LIST)
414 AddWithNameAndDescription( 404 AddWithNameAndDescription(
415 IDR_CHROME_APP_MANIFEST, base::FilePath(FILE_PATH_LITERAL("chrome_app")), 405 IDR_CHROME_APP_MANIFEST, base::FilePath(FILE_PATH_LITERAL("chrome_app")),
416 l10n_util::GetStringUTF8(IDS_SHORT_PRODUCT_NAME), 406 l10n_util::GetStringUTF8(IDS_SHORT_PRODUCT_NAME),
417 l10n_util::GetStringUTF8(IDS_CHROME_SHORTCUT_DESCRIPTION)); 407 l10n_util::GetStringUTF8(IDS_CHROME_SHORTCUT_DESCRIPTION));
418 #endif 408 #endif
(...skipping 212 matching lines...) Expand 10 before | Expand all | Expand 10 after
631 (command_line->HasSwitch(switches::kTestType) || 621 (command_line->HasSwitch(switches::kTestType) ||
632 command_line->HasSwitch( 622 command_line->HasSwitch(
633 switches::kDisableComponentExtensionsWithBackgroundPages))) { 623 switches::kDisableComponentExtensionsWithBackgroundPages))) {
634 return; 624 return;
635 } 625 }
636 626
637 AddHangoutServicesExtension(); 627 AddHangoutServicesExtension();
638 } 628 }
639 629
640 void ComponentLoader::UnloadComponent(ComponentExtensionInfo* component) { 630 void ComponentLoader::UnloadComponent(ComponentExtensionInfo* component) {
641 delete component->manifest;
642 if (extension_service_->is_ready()) { 631 if (extension_service_->is_ready()) {
643 extension_service_-> 632 extension_service_->
644 RemoveComponentExtension(component->extension_id); 633 RemoveComponentExtension(component->extension_id);
645 } 634 }
646 } 635 }
647 636
648 void ComponentLoader::EnableFileSystemInGuestMode(const std::string& id) { 637 void ComponentLoader::EnableFileSystemInGuestMode(const std::string& id) {
649 #if defined(OS_CHROMEOS) 638 #if defined(OS_CHROMEOS)
650 if (!IsNormalSession()) { 639 if (!IsNormalSession()) {
651 // TODO(dpolukhin): Hack to enable HTML5 temporary file system for 640 // TODO(dpolukhin): Hack to enable HTML5 temporary file system for
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
685 } 674 }
686 675
687 void ComponentLoader::FinishAddComponentFromDir( 676 void ComponentLoader::FinishAddComponentFromDir(
688 const base::FilePath& root_directory, 677 const base::FilePath& root_directory,
689 const char* extension_id, 678 const char* extension_id,
690 const base::Closure& done_cb, 679 const base::Closure& done_cb,
691 std::unique_ptr<base::DictionaryValue> manifest) { 680 std::unique_ptr<base::DictionaryValue> manifest) {
692 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); 681 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
693 if (!manifest) 682 if (!manifest)
694 return; // Error already logged. 683 return; // Error already logged.
695 std::string actual_extension_id = Add( 684 std::string actual_extension_id =
696 manifest.release(), 685 Add(std::move(manifest), root_directory, false);
697 root_directory,
698 false);
699 CHECK_EQ(extension_id, actual_extension_id); 686 CHECK_EQ(extension_id, actual_extension_id);
700 if (!done_cb.is_null()) 687 if (!done_cb.is_null())
701 done_cb.Run(); 688 done_cb.Run();
702 } 689 }
703 #endif 690 #endif
704 691
705 } // namespace extensions 692 } // namespace extensions
OLDNEW
« no previous file with comments | « chrome/browser/extensions/component_loader.h ('k') | chrome/browser/extensions/component_loader_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698