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 3 // found in the LICENSE file. 4 5 #ifndef CHROME_BROWSER_EXTENSIONS_USER_SCRIPT_LISTENER_H_ 6 #define CHROME_BROWSER_EXTENSIONS_USER_SCRIPT_LISTENER_H_ 7 8 #include <list> 9 #include <map> 10 11 #include "base/compiler_specific.h" 12 #include "base/containers/circular_deque.h" 13 #include "base/macros.h" 14 #include "base/memory/weak_ptr.h" 15 #include "base/scoped_observer.h" 16 #include "content/public/browser/notification_observer.h" 17 #include "content/public/browser/notification_registrar.h" 18 #include "extensions/browser/extension_registry.h" 19 #include "extensions/browser/extension_registry_observer.h" 20 #include "extensions/browser/user_script_loader.h" 21 22 class GURL; 23 class URLPattern; 24 25 namespace content { 26 class BrowserContext; 27 class NavigationHandle; 28 class NavigationThrottle; 29 } 30 31 namespace extensions { 32 class Extension; 33 34 // This class handles delaying of resource loads that depend on unloaded user 35 // scripts. For each request that comes in, we check if it depends on a user 36 // script, and if so, whether that user script is ready; if not, we delay the 37 // request. 38 // 39 // This class lives on the UI thread. 40 class UserScriptListener : public content::NotificationObserver, 41 public ExtensionRegistryObserver, 42 public UserScriptLoader::Observer { 43 public: 44 UserScriptListener(); 45 ~UserScriptListener() override; 46 47 // Constructs a NavigationThrottle if the UserScriptListener needs to delay 48 // the given navigation. Otherwise, this method returns NULL. 49 std::unique_ptr<content::NavigationThrottle> CreateNavigationThrottle( 50 content::NavigationHandle* navigation_handle); 51 52 void SetUserScriptsNotReadyForTesting(content::BrowserContext* context); 53 void TriggerUserScriptsReadyForTesting(content::BrowserContext* context); 54 55 private: 56 using URLPatterns = std::list<URLPattern>; 57 58 bool ShouldDelayRequest(const GURL& url); 59 void StartDelayedRequests(); 60 61 // Update user_scripts_ready_ based on the status of all profiles. On a 62 // transition from false to true, we resume all delayed requests. 63 void CheckIfAllUserScriptsReady(); 64 65 // Resume any requests that we delayed in order to wait for user scripts. 66 void UserScriptsReady(content::BrowserContext* context); 67 68 // Clean up per-profile information related to the given profile. 69 void ProfileDestroyed(content::BrowserContext* context); 70 71 // Appends new url patterns to our list, also setting user_scripts_ready_ 72 // to false. 73 void AppendNewURLPatterns(content::BrowserContext* context, 74 const URLPatterns& new_patterns); 75 76 // Replaces our url pattern list. This is only used when patterns have been 77 // deleted, so user_scripts_ready_ remains unchanged. 78 void ReplaceURLPatterns(content::BrowserContext* context, 79 const URLPatterns& patterns); 80 81 // True if all user scripts from all profiles are ready. 82 bool user_scripts_ready_ = false; 83 84 // Stores a throttle per URL request that we have delayed. 85 class Throttle; 86 using WeakThrottle = base::WeakPtr<Throttle>; 87 using WeakThrottleList = base::circular_deque<WeakThrottle>; 88 WeakThrottleList throttles_; 89 90 // Per-profile bookkeeping so we know when all user scripts are ready. 91 struct ProfileData; 92 using ProfileDataMap = std::map<content::BrowserContext*, ProfileData>; 93 ProfileDataMap profile_data_; 94 95 // --- UI thread: 96 97 // Helper to collect the extension's user script URL patterns in a list and 98 // return it. 99 void CollectURLPatterns(const Extension* extension, 100 URLPatterns* patterns); 101 102 // content::NotificationObserver 103 void Observe(int type, 104 const content::NotificationSource& source, 105 const content::NotificationDetails& details) override; 106 107 // ExtensionRegistryObserver: 108 void OnExtensionLoaded(content::BrowserContext* browser_context, 109 const Extension* extension) override; 110 void OnExtensionUnloaded(content::BrowserContext* browser_context, 111 const Extension* extension, 112 UnloadedExtensionReason reason) override; 113 void OnShutdown(ExtensionRegistry* registry) override; 114 115 // UserScriptLoader::Observer: 116 void OnScriptsLoaded(UserScriptLoader* loader, 117 content::BrowserContext* browser_context) override; 118 void OnUserScriptLoaderDestroyed(UserScriptLoader* loader) override; 119 120 ScopedObserver<extensions::ExtensionRegistry, 121 extensions::ExtensionRegistryObserver> 122 extension_registry_observer_{this}; 123 ScopedObserver<extensions::UserScriptLoader, 124 extensions::UserScriptLoader::Observer> 125 user_script_loader_observer_{this}; 126 127 content::NotificationRegistrar registrar_; 128 129 DISALLOW_COPY_AND_ASSIGN(UserScriptListener); 130 }; 131 132 } // namespace extensions 133 134 #endif // CHROME_BROWSER_EXTENSIONS_USER_SCRIPT_LISTENER_H_ 135