1// Copyright 2014 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 EXTENSIONS_BROWSER_APP_WINDOW_APP_WINDOW_GEOMETRY_CACHE_H_ 6#define EXTENSIONS_BROWSER_APP_WINDOW_APP_WINDOW_GEOMETRY_CACHE_H_ 7 8#include <map> 9#include <set> 10#include <string> 11 12#include "base/memory/scoped_ptr.h" 13#include "base/memory/singleton.h" 14#include "base/observer_list.h" 15#include "base/scoped_observer.h" 16#include "base/time/time.h" 17#include "base/timer/timer.h" 18#include "base/values.h" 19#include "components/keyed_service/content/browser_context_keyed_service_factory.h" 20#include "components/keyed_service/core/keyed_service.h" 21#include "extensions/browser/extension_registry_observer.h" 22#include "ui/base/ui_base_types.h" 23#include "ui/gfx/rect.h" 24 25namespace extensions { 26 27class ExtensionPrefs; 28class ExtensionRegistry; 29 30// A cache for persisted geometry of app windows, both to not have to wait 31// for IO when creating a new window, and to not cause IO on every window 32// geometry change. 33class AppWindowGeometryCache : public KeyedService, 34 public ExtensionRegistryObserver { 35 public: 36 class Factory : public BrowserContextKeyedServiceFactory { 37 public: 38 static AppWindowGeometryCache* GetForContext( 39 content::BrowserContext* context, 40 bool create); 41 42 static Factory* GetInstance(); 43 44 private: 45 friend struct DefaultSingletonTraits<Factory>; 46 47 Factory(); 48 virtual ~Factory(); 49 50 // BrowserContextKeyedServiceFactory 51 virtual KeyedService* BuildServiceInstanceFor( 52 content::BrowserContext* context) const OVERRIDE; 53 virtual bool ServiceIsNULLWhileTesting() const OVERRIDE; 54 virtual content::BrowserContext* GetBrowserContextToUse( 55 content::BrowserContext* context) const OVERRIDE; 56 }; 57 58 class Observer { 59 public: 60 virtual void OnGeometryCacheChanged(const std::string& extension_id, 61 const std::string& window_id, 62 const gfx::Rect& bounds) = 0; 63 64 protected: 65 virtual ~Observer() {} 66 }; 67 68 AppWindowGeometryCache(content::BrowserContext* context, 69 ExtensionPrefs* prefs); 70 71 virtual ~AppWindowGeometryCache(); 72 73 // Returns the instance for the given browsing context. 74 static AppWindowGeometryCache* Get(content::BrowserContext* context); 75 76 // Save the geometry and state associated with |extension_id| and |window_id|. 77 void SaveGeometry(const std::string& extension_id, 78 const std::string& window_id, 79 const gfx::Rect& bounds, 80 const gfx::Rect& screen_bounds, 81 ui::WindowShowState state); 82 83 // Get any saved geometry and state associated with |extension_id| and 84 // |window_id|. If saved data exists, sets |bounds|, |screen_bounds| and 85 // |state| if not NULL and returns true. 86 bool GetGeometry(const std::string& extension_id, 87 const std::string& window_id, 88 gfx::Rect* bounds, 89 gfx::Rect* screen_bounds, 90 ui::WindowShowState* state); 91 92 // KeyedService 93 virtual void Shutdown() OVERRIDE; 94 95 void AddObserver(Observer* observer); 96 void RemoveObserver(Observer* observer); 97 98 // Maximum number of windows we'll cache the geometry for per app. 99 static const size_t kMaxCachedWindows = 100; 100 101 protected: 102 friend class AppWindowGeometryCacheTest; 103 104 // For tests, this modifies the timeout delay for saving changes from calls 105 // to SaveGeometry. (Note that even if this is set to 0, you still need to 106 // run the message loop to see the results of any SyncToStorage call). 107 void SetSyncDelayForTests(int timeout_ms); 108 109 private: 110 // Data stored for each window. 111 struct WindowData { 112 WindowData(); 113 ~WindowData(); 114 gfx::Rect bounds; 115 gfx::Rect screen_bounds; 116 ui::WindowShowState window_state; 117 base::Time last_change; 118 }; 119 120 // Data stored for each extension. 121 typedef std::map<std::string, WindowData> ExtensionData; 122 123 // ExtensionRegistryObserver implementation. 124 virtual void OnExtensionLoaded(content::BrowserContext* browser_context, 125 const Extension* extension) OVERRIDE; 126 virtual void OnExtensionUnloaded( 127 content::BrowserContext* browser_context, 128 const Extension* extension, 129 UnloadedExtensionInfo::Reason reason) OVERRIDE; 130 131 void LoadGeometryFromStorage(const std::string& extension_id); 132 void SyncToStorage(); 133 134 // Preferences storage. 135 ExtensionPrefs* prefs_; 136 137 // Cached data. 138 std::map<std::string, ExtensionData> cache_; 139 140 // Data that still needs saving. 141 std::set<std::string> unsynced_extensions_; 142 143 // The timer used to save the data. 144 base::OneShotTimer<AppWindowGeometryCache> sync_timer_; 145 146 // The timeout value we'll use for |sync_timer_|. 147 base::TimeDelta sync_delay_; 148 149 // Listen to extension load, unloaded notifications. 150 ScopedObserver<ExtensionRegistry, ExtensionRegistryObserver> 151 extension_registry_observer_; 152 153 ObserverList<Observer> observers_; 154}; 155 156} // namespace extensions 157 158#endif // EXTENSIONS_BROWSER_APP_WINDOW_APP_WINDOW_GEOMETRY_CACHE_H_ 159