| 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/policy/app_pack_updater.h" | 5 #include "chrome/browser/policy/app_pack_updater.h" |
| 6 | 6 |
| 7 #include "base/bind.h" | 7 #include "base/bind.h" |
| 8 #include "base/bind_helpers.h" | 8 #include "base/bind_helpers.h" |
| 9 #include "base/file_util.h" | 9 #include "base/file_util.h" |
| 10 #include "base/location.h" | 10 #include "base/location.h" |
| (...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 95 weak_ptr_factory_.GetWeakPtr())); | 95 weak_ptr_factory_.GetWeakPtr())); |
| 96 } else { | 96 } else { |
| 97 // Linger until the device switches to DEVICE_MODE_KIOSK and the app pack | 97 // Linger until the device switches to DEVICE_MODE_KIOSK and the app pack |
| 98 // device setting appears. | 98 // device setting appears. |
| 99 } | 99 } |
| 100 } | 100 } |
| 101 | 101 |
| 102 AppPackUpdater::~AppPackUpdater() { | 102 AppPackUpdater::~AppPackUpdater() { |
| 103 chromeos::CrosSettings::Get()->RemoveSettingsObserver( | 103 chromeos::CrosSettings::Get()->RemoveSettingsObserver( |
| 104 chromeos::kAppPack, this); | 104 chromeos::kAppPack, this); |
| 105 net::NetworkChangeNotifier::RemoveIPAddressObserver(this); | |
| 106 } | 105 } |
| 107 | 106 |
| 108 extensions::ExternalLoader* AppPackUpdater::CreateExternalLoader() { | 107 extensions::ExternalLoader* AppPackUpdater::CreateExternalLoader() { |
| 109 if (created_extension_loader_) { | 108 if (created_extension_loader_) { |
| 110 NOTREACHED(); | 109 NOTREACHED(); |
| 111 return NULL; | 110 return NULL; |
| 112 } | 111 } |
| 113 created_extension_loader_ = true; | 112 created_extension_loader_ = true; |
| 114 AppPackExternalLoader* loader = new AppPackExternalLoader(); | 113 AppPackExternalLoader* loader = new AppPackExternalLoader(); |
| 115 extension_loader_ = loader->AsWeakPtr(); | 114 extension_loader_ = loader->AsWeakPtr(); |
| (...skipping 18 matching lines...) Expand all Loading... |
| 134 void AppPackUpdater::Init() { | 133 void AppPackUpdater::Init() { |
| 135 if (initialized_) | 134 if (initialized_) |
| 136 return; | 135 return; |
| 137 | 136 |
| 138 initialized_ = true; | 137 initialized_ = true; |
| 139 worker_pool_token_ = BrowserThread::GetBlockingPool()->GetSequenceToken(); | 138 worker_pool_token_ = BrowserThread::GetBlockingPool()->GetSequenceToken(); |
| 140 notification_registrar_.Add( | 139 notification_registrar_.Add( |
| 141 this, | 140 this, |
| 142 chrome::NOTIFICATION_EXTENSION_INSTALL_ERROR, | 141 chrome::NOTIFICATION_EXTENSION_INSTALL_ERROR, |
| 143 content::NotificationService::AllBrowserContextsAndSources()); | 142 content::NotificationService::AllBrowserContextsAndSources()); |
| 144 net::NetworkChangeNotifier::AddIPAddressObserver(this); | |
| 145 LoadPolicy(); | 143 LoadPolicy(); |
| 146 } | 144 } |
| 147 | 145 |
| 148 void AppPackUpdater::Observe(int type, | 146 void AppPackUpdater::Observe(int type, |
| 149 const content::NotificationSource& source, | 147 const content::NotificationSource& source, |
| 150 const content::NotificationDetails& details) { | 148 const content::NotificationDetails& details) { |
| 151 switch (type) { | 149 switch (type) { |
| 152 case chrome::NOTIFICATION_SYSTEM_SETTING_CHANGED: | 150 case chrome::NOTIFICATION_SYSTEM_SETTING_CHANGED: |
| 153 DCHECK_EQ(chromeos::kAppPack, | 151 DCHECK_EQ(chromeos::kAppPack, |
| 154 *content::Details<const std::string>(details).ptr()); | 152 *content::Details<const std::string>(details).ptr()); |
| (...skipping 10 matching lines...) Expand all Loading... |
| 165 content::Source<extensions::CrxInstaller>(source).ptr(); | 163 content::Source<extensions::CrxInstaller>(source).ptr(); |
| 166 OnDamagedFileDetected(installer->source_file()); | 164 OnDamagedFileDetected(installer->source_file()); |
| 167 break; | 165 break; |
| 168 } | 166 } |
| 169 | 167 |
| 170 default: | 168 default: |
| 171 NOTREACHED(); | 169 NOTREACHED(); |
| 172 } | 170 } |
| 173 } | 171 } |
| 174 | 172 |
| 175 void AppPackUpdater::OnIPAddressChanged() { | |
| 176 // Check if the AppPack has been fully downloaded whenever the network | |
| 177 // changes. This allows the AppPack to recover in case the network wasn't | |
| 178 // ready early during startup. | |
| 179 // To avoid performing too many update checks in case the network conditions | |
| 180 // change too often, an update is only triggered now if there are extensions | |
| 181 // configured via policy that haven't been checked for updates yet. | |
| 182 for (PolicyEntryMap::iterator it = app_pack_extensions_.begin(); | |
| 183 it != app_pack_extensions_.end(); ++it) { | |
| 184 if (!it->second.update_checked) { | |
| 185 // |id| is configured via policy, but hasn't been updated before. | |
| 186 // Drop any pending requests and start a full check now. | |
| 187 VLOG(1) << "Extension " << it->first << " hasn't been checked yet, " | |
| 188 << "new update triggered now by network change notification."; | |
| 189 downloader_.reset(); | |
| 190 weak_ptr_factory_.InvalidateWeakPtrs(); | |
| 191 LoadPolicy(); | |
| 192 break; | |
| 193 } | |
| 194 } | |
| 195 } | |
| 196 | |
| 197 void AppPackUpdater::LoadPolicy() { | 173 void AppPackUpdater::LoadPolicy() { |
| 198 chromeos::CrosSettings* settings = chromeos::CrosSettings::Get(); | 174 chromeos::CrosSettings* settings = chromeos::CrosSettings::Get(); |
| 199 if (chromeos::CrosSettingsProvider::TRUSTED != settings->PrepareTrustedValues( | 175 if (chromeos::CrosSettingsProvider::TRUSTED != settings->PrepareTrustedValues( |
| 200 base::Bind(&AppPackUpdater::LoadPolicy, | 176 base::Bind(&AppPackUpdater::LoadPolicy, |
| 201 weak_ptr_factory_.GetWeakPtr()))) { | 177 weak_ptr_factory_.GetWeakPtr()))) { |
| 202 return; | 178 return; |
| 203 } | 179 } |
| 204 | 180 |
| 205 app_pack_extensions_.clear(); | 181 app_pack_extensions_.clear(); |
| 206 const base::Value* value = settings->GetPref(chromeos::kAppPack); | 182 const base::Value* value = settings->GetPref(chromeos::kAppPack); |
| 207 const base::ListValue* list = NULL; | 183 const base::ListValue* list = NULL; |
| 208 if (value && value->GetAsList(&list)) { | 184 if (value && value->GetAsList(&list)) { |
| 209 for (base::ListValue::const_iterator it = list->begin(); | 185 for (base::ListValue::const_iterator it = list->begin(); |
| 210 it != list->end(); ++it) { | 186 it != list->end(); ++it) { |
| 211 base::DictionaryValue* dict = NULL; | 187 base::DictionaryValue* dict = NULL; |
| 212 if (!(*it)->GetAsDictionary(&dict)) { | 188 if (!(*it)->GetAsDictionary(&dict)) { |
| 213 LOG(WARNING) << "AppPack entry is not a dictionary, ignoring."; | 189 LOG(WARNING) << "AppPack entry is not a dictionary, ignoring."; |
| 214 continue; | 190 continue; |
| 215 } | 191 } |
| 216 std::string id; | 192 std::string id; |
| 217 std::string update_url; | 193 std::string update_url; |
| 218 if (dict->GetString(kExtensionId, &id) && | 194 if (dict->GetString(kExtensionId, &id) && |
| 219 dict->GetString(kUpdateUrl, &update_url)) { | 195 dict->GetString(kUpdateUrl, &update_url)) { |
| 220 app_pack_extensions_[id].update_url = update_url; | 196 app_pack_extensions_[id] = update_url; |
| 221 app_pack_extensions_[id].update_checked = false; | |
| 222 } else { | 197 } else { |
| 223 LOG(WARNING) << "Failed to read required fields for an AppPack entry, " | 198 LOG(WARNING) << "Failed to read required fields for an AppPack entry, " |
| 224 << "ignoring."; | 199 << "ignoring."; |
| 225 } | 200 } |
| 226 } | 201 } |
| 227 } | 202 } |
| 228 | 203 |
| 229 VLOG(1) << "Refreshed AppPack policy, got " << app_pack_extensions_.size() | 204 VLOG(1) << "Refreshed AppPack policy, got " << app_pack_extensions_.size() |
| 230 << " entries."; | 205 << " entries."; |
| 231 | 206 |
| (...skipping 166 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 398 base::DictionaryValue* dict = new base::DictionaryValue(); | 373 base::DictionaryValue* dict = new base::DictionaryValue(); |
| 399 dict->SetString(extensions::ExternalProviderImpl::kExternalCrx, | 374 dict->SetString(extensions::ExternalProviderImpl::kExternalCrx, |
| 400 it->second.path); | 375 it->second.path); |
| 401 dict->SetString(extensions::ExternalProviderImpl::kExternalVersion, | 376 dict->SetString(extensions::ExternalProviderImpl::kExternalVersion, |
| 402 it->second.cached_version); | 377 it->second.cached_version); |
| 403 | 378 |
| 404 // Include this optional flag if the extension's update url is the Webstore. | 379 // Include this optional flag if the extension's update url is the Webstore. |
| 405 PolicyEntryMap::iterator policy_entry = app_pack_extensions_.find(id); | 380 PolicyEntryMap::iterator policy_entry = app_pack_extensions_.find(id); |
| 406 if (policy_entry != app_pack_extensions_.end() && | 381 if (policy_entry != app_pack_extensions_.end() && |
| 407 extension_urls::IsWebstoreUpdateUrl( | 382 extension_urls::IsWebstoreUpdateUrl( |
| 408 GURL(policy_entry->second.update_url))) { | 383 GURL(policy_entry->second))) { |
| 409 dict->SetBoolean(extensions::ExternalProviderImpl::kIsFromWebstore, true); | 384 dict->SetBoolean(extensions::ExternalProviderImpl::kIsFromWebstore, true); |
| 410 } | 385 } |
| 411 | 386 |
| 412 prefs->Set(it->first, dict); | 387 prefs->Set(it->first, dict); |
| 413 | 388 |
| 414 VLOG(1) << "Updating AppPack extension loader, added " << it->second.path; | 389 VLOG(1) << "Updating AppPack extension loader, added " << it->second.path; |
| 415 } | 390 } |
| 416 | 391 |
| 417 extension_loader_->SetCurrentAppPackExtensions(prefs.Pass()); | 392 extension_loader_->SetCurrentAppPackExtensions(prefs.Pass()); |
| 418 } | 393 } |
| 419 | 394 |
| 420 void AppPackUpdater::DownloadMissingExtensions() { | 395 void AppPackUpdater::DownloadMissingExtensions() { |
| 421 // Check for updates for all extensions configured by the policy. Some of | 396 // Check for updates for all extensions configured by the policy. Some of |
| 422 // them may already be in the cache; only those with updated version will be | 397 // them may already be in the cache; only those with updated version will be |
| 423 // downloaded, in that case. | 398 // downloaded, in that case. |
| 424 if (!downloader_.get()) { | 399 if (!downloader_.get()) { |
| 425 downloader_.reset(new extensions::ExtensionDownloader(this, | 400 downloader_.reset(new extensions::ExtensionDownloader(this, |
| 426 request_context_)); | 401 request_context_)); |
| 427 } | 402 } |
| 428 for (PolicyEntryMap::iterator it = app_pack_extensions_.begin(); | 403 for (PolicyEntryMap::iterator it = app_pack_extensions_.begin(); |
| 429 it != app_pack_extensions_.end(); ++it) { | 404 it != app_pack_extensions_.end(); ++it) { |
| 430 downloader_->AddPendingExtension(it->first, GURL(it->second.update_url), 0); | 405 downloader_->AddPendingExtension(it->first, GURL(it->second), 0); |
| 431 } | 406 } |
| 432 VLOG(1) << "Downloading AppPack update manifest now"; | 407 VLOG(1) << "Downloading AppPack update manifest now"; |
| 433 downloader_->StartAllPending(); | 408 downloader_->StartAllPending(); |
| 434 } | 409 } |
| 435 | 410 |
| 436 void AppPackUpdater::OnExtensionDownloadFailed( | 411 void AppPackUpdater::OnExtensionDownloadFailed( |
| 437 const std::string& id, | 412 const std::string& id, |
| 438 extensions::ExtensionDownloaderDelegate::Error error, | 413 extensions::ExtensionDownloaderDelegate::Error error, |
| 439 const extensions::ExtensionDownloaderDelegate::PingResult& ping_result, | 414 const extensions::ExtensionDownloaderDelegate::PingResult& ping_result, |
| 440 const std::set<int>& request_ids) { | 415 const std::set<int>& request_ids) { |
| 441 if (error == NO_UPDATE_AVAILABLE) { | 416 if (error == NO_UPDATE_AVAILABLE) { |
| 442 if (!ContainsKey(cached_extensions_, id)) | 417 if (!ContainsKey(cached_extensions_, id)) |
| 443 LOG(ERROR) << "AppPack extension " << id << " not found on update server"; | 418 LOG(ERROR) << "AppPack extension " << id << " not found on update server"; |
| 444 SetUpdateChecked(id); | |
| 445 } else { | 419 } else { |
| 446 LOG(ERROR) << "AppPack failed to download extension " << id | 420 LOG(ERROR) << "AppPack failed to download extension " << id |
| 447 << ", error " << error; | 421 << ", error " << error; |
| 448 } | 422 } |
| 449 } | 423 } |
| 450 | 424 |
| 451 void AppPackUpdater::OnExtensionDownloadFinished( | 425 void AppPackUpdater::OnExtensionDownloadFinished( |
| 452 const std::string& id, | 426 const std::string& id, |
| 453 const FilePath& path, | 427 const FilePath& path, |
| 454 const GURL& download_url, | 428 const GURL& download_url, |
| 455 const std::string& version, | 429 const std::string& version, |
| 456 const extensions::ExtensionDownloaderDelegate::PingResult& ping_result, | 430 const extensions::ExtensionDownloaderDelegate::PingResult& ping_result, |
| 457 const std::set<int>& request_ids) { | 431 const std::set<int>& request_ids) { |
| 458 // Just downloaded the latest version, no need to do further update checks | |
| 459 // for this extension. | |
| 460 SetUpdateChecked(id); | |
| 461 | |
| 462 // The explicit copy ctors are to make sure that Bind() binds a copy and not | 432 // The explicit copy ctors are to make sure that Bind() binds a copy and not |
| 463 // a reference to the arguments. | 433 // a reference to the arguments. |
| 464 PostBlockingTask(FROM_HERE, | 434 PostBlockingTask(FROM_HERE, |
| 465 base::Bind(&AppPackUpdater::BlockingInstallCacheEntry, | 435 base::Bind(&AppPackUpdater::BlockingInstallCacheEntry, |
| 466 weak_ptr_factory_.GetWeakPtr(), | 436 weak_ptr_factory_.GetWeakPtr(), |
| 467 std::string(id), | 437 std::string(id), |
| 468 FilePath(path), | 438 FilePath(path), |
| 469 std::string(version))); | 439 std::string(version))); |
| 470 } | 440 } |
| 471 | 441 |
| (...skipping 120 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 592 | 562 |
| 593 void AppPackUpdater::SetScreenSaverPath(const FilePath& path) { | 563 void AppPackUpdater::SetScreenSaverPath(const FilePath& path) { |
| 594 // Don't invoke the callback if the path isn't changing. | 564 // Don't invoke the callback if the path isn't changing. |
| 595 if (path != screen_saver_path_) { | 565 if (path != screen_saver_path_) { |
| 596 screen_saver_path_ = path; | 566 screen_saver_path_ = path; |
| 597 if (!screen_saver_update_callback_.is_null()) | 567 if (!screen_saver_update_callback_.is_null()) |
| 598 screen_saver_update_callback_.Run(screen_saver_path_); | 568 screen_saver_update_callback_.Run(screen_saver_path_); |
| 599 } | 569 } |
| 600 } | 570 } |
| 601 | 571 |
| 602 void AppPackUpdater::SetUpdateChecked(const std::string& id) { | |
| 603 PolicyEntryMap::iterator entry = app_pack_extensions_.find(id); | |
| 604 if (entry != app_pack_extensions_.end()) | |
| 605 entry->second.update_checked = true; | |
| 606 } | |
| 607 | |
| 608 } // namespace policy | 572 } // namespace policy |
| OLD | NEW |