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 #ifndef CHROME_BROWSER_CHROMEOS_EXTENSIONS_INSTALL_LIMITER_H_ 6 #define CHROME_BROWSER_CHROMEOS_EXTENSIONS_INSTALL_LIMITER_H_ 7 8 #include <stdint.h> 9 10 #include <set> 11 12 #include "base/compiler_specific.h" 13 #include "base/containers/queue.h" 14 #include "base/files/file_path.h" 15 #include "base/macros.h" 16 #include "base/memory/ref_counted.h" 17 #include "base/memory/weak_ptr.h" 18 #include "base/timer/timer.h" 19 #include "chrome/browser/extensions/crx_installer.h" 20 #include "components/keyed_service/core/keyed_service.h" 21 #include "content/public/browser/notification_observer.h" 22 #include "content/public/browser/notification_registrar.h" 23 24 namespace extensions { 25 26 // TODO(hendrich, https://crbug.com/1046302) 27 // Add a test for the InstallLimiter, which checks that small extensions are 28 // installed before large extensions and that we don't have to wait the entire 29 // 5s when the OnAllExternalProvidersReady() signal was called. 30 31 // InstallLimiter defers big app installs after all small app installs and then 32 // runs big app installs one by one. This improves first-time login experience. 33 // See http://crbug.com/166296 34 class InstallLimiter : public KeyedService, 35 public content::NotificationObserver, 36 public base::SupportsWeakPtr<InstallLimiter> { 37 public: 38 static InstallLimiter* Get(Profile* profile); 39 40 // Install should be deferred if the size is larger than 1MB and the app is 41 // not the screensaver in demo mode (which requires instant installation to 42 // avoid visual delay). 43 static bool ShouldDeferInstall(int64_t app_size, const std::string& app_id); 44 45 InstallLimiter(); 46 ~InstallLimiter() override; 47 48 void DisableForTest(); 49 50 void Add(const scoped_refptr<CrxInstaller>& installer, 51 const CRXFileInfo& file_info); 52 53 // Triggers installation of deferred installations if all file sizes for 54 // added installations have been determined. 55 void OnAllExternalProvidersReady(); 56 57 private: 58 // DeferredInstall holds info to run a CrxInstaller later. 59 struct DeferredInstall { 60 DeferredInstall(const scoped_refptr<CrxInstaller>& installer, 61 const CRXFileInfo& file_info); 62 DeferredInstall(const DeferredInstall& other); 63 ~DeferredInstall(); 64 65 const scoped_refptr<CrxInstaller> installer; 66 const CRXFileInfo file_info; 67 }; 68 69 using DeferredInstallList = base::queue<DeferredInstall>; 70 using CrxInstallerSet = std::set<scoped_refptr<CrxInstaller>>; 71 72 // Adds install info with size. If |size| is greater than a certain threshold, 73 // it stores the install info into |deferred_installs_| to run it later. 74 // Otherwise, it just runs the installer. 75 void AddWithSize(const scoped_refptr<CrxInstaller>& installer, 76 const CRXFileInfo& file_info, 77 int64_t size); 78 79 // Checks and runs deferred big app installs when appropriate. 80 void CheckAndRunDeferrredInstalls(); 81 82 // Starts install using passed-in info and observes |installer|'s done 83 // notification. 84 void RunInstall(const scoped_refptr<CrxInstaller>& installer, 85 const CRXFileInfo& file_info); 86 87 // content::NotificationObserver overrides: 88 void Observe(int type, 89 const content::NotificationSource& source, 90 const content::NotificationDetails& details) override; 91 92 // Checks that OnAllExternalProvidersReady() has been called and all file 93 // sizes for added installations are determined. If this method returns true, 94 // we can directly continue installing all remaining extensions, since there 95 // will be no more added installations coming. 96 bool AllInstallsQueuedWithFileSize() const; 97 98 content::NotificationRegistrar registrar_; 99 100 DeferredInstallList deferred_installs_; 101 CrxInstallerSet running_installers_; 102 103 // A timer to wait before running deferred big app install. 104 base::OneShotTimer wait_timer_; 105 106 bool disabled_for_test_; 107 108 bool all_external_providers_ready_ = false; 109 int num_installs_waiting_for_file_size_ = 0; 110 111 DISALLOW_COPY_AND_ASSIGN(InstallLimiter); 112 }; 113 114 } // namespace extensions 115 116 #endif // CHROME_BROWSER_CHROMEOS_EXTENSIONS_INSTALL_LIMITER_H_ 117