15d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Copyright 2014 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)#ifndef EXTENSIONS_BROWSER_APP_WINDOW_APP_WINDOW_GEOMETRY_CACHE_H_ 603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)#define EXTENSIONS_BROWSER_APP_WINDOW_APP_WINDOW_GEOMETRY_CACHE_H_ 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <map> 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <set> 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <string> 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/memory/scoped_ptr.h" 1390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "base/memory/singleton.h" 14a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "base/observer_list.h" 15cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "base/scoped_observer.h" 16eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "base/time/time.h" 17eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "base/timer/timer.h" 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/values.h" 19a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "components/keyed_service/content/browser_context_keyed_service_factory.h" 20a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "components/keyed_service/core/keyed_service.h" 21cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "extensions/browser/extension_registry_observer.h" 22b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)#include "ui/base/ui_base_types.h" 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/gfx/rect.h" 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace extensions { 2603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)class ExtensionPrefs; 28cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)class ExtensionRegistry; 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// A cache for persisted geometry of app windows, both to not have to wait 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// for IO when creating a new window, and to not cause IO on every window 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// geometry change. 33a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)class AppWindowGeometryCache : public KeyedService, 3403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) public ExtensionRegistryObserver { 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public: 3690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) class Factory : public BrowserContextKeyedServiceFactory { 3790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) public: 385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) static AppWindowGeometryCache* GetForContext( 3990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) content::BrowserContext* context, 4090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) bool create); 4190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 4290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) static Factory* GetInstance(); 435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 4490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) private: 4590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) friend struct DefaultSingletonTraits<Factory>; 4690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 4790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) Factory(); 4890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) virtual ~Factory(); 4990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 5090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // BrowserContextKeyedServiceFactory 51a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) virtual KeyedService* BuildServiceInstanceFor( 5290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) content::BrowserContext* context) const OVERRIDE; 5390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) virtual bool ServiceIsNULLWhileTesting() const OVERRIDE; 5490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) virtual content::BrowserContext* GetBrowserContextToUse( 5590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) content::BrowserContext* context) const OVERRIDE; 5690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) }; 5790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 58a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) class Observer { 59a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) public: 60a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) virtual void OnGeometryCacheChanged(const std::string& extension_id, 61a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) const std::string& window_id, 62a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) const gfx::Rect& bounds) = 0; 63a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 64a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) protected: 655c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu virtual ~Observer() {} 66a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) }; 67a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 686e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) AppWindowGeometryCache(content::BrowserContext* context, 6903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) ExtensionPrefs* prefs); 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) virtual ~AppWindowGeometryCache(); 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // Returns the instance for the given browsing context. 745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) static AppWindowGeometryCache* Get(content::BrowserContext* context); 7590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 76b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) // Save the geometry and state associated with |extension_id| and |window_id|. 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void SaveGeometry(const std::string& extension_id, 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& window_id, 79b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) const gfx::Rect& bounds, 80eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch const gfx::Rect& screen_bounds, 81b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) ui::WindowShowState state); 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 83b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) // Get any saved geometry and state associated with |extension_id| and 84a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) // |window_id|. If saved data exists, sets |bounds|, |screen_bounds| and 85a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) // |state| if not NULL and returns true. 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool GetGeometry(const std::string& extension_id, 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& window_id, 88b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) gfx::Rect* bounds, 89eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch gfx::Rect* screen_bounds, 907d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) ui::WindowShowState* state); 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 92a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // KeyedService 9390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) virtual void Shutdown() OVERRIDE; 9490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 95a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) void AddObserver(Observer* observer); 96a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) void RemoveObserver(Observer* observer); 97a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Maximum number of windows we'll cache the geometry for per app. 992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) static const size_t kMaxCachedWindows = 100; 1002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) protected: 1025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) friend class AppWindowGeometryCacheTest; 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // For tests, this modifies the timeout delay for saving changes from calls 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // to SaveGeometry. (Note that even if this is set to 0, you still need to 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // run the message loop to see the results of any SyncToStorage call). 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void SetSyncDelayForTests(int timeout_ms); 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private: 1102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Data stored for each window. 1112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) struct WindowData { 112eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch WindowData(); 113eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch ~WindowData(); 1142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) gfx::Rect bounds; 115eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch gfx::Rect screen_bounds; 116b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) ui::WindowShowState window_state; 1172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::Time last_change; 1182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) }; 1192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Data stored for each extension. 1212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) typedef std::map<std::string, WindowData> ExtensionData; 1222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 123cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // ExtensionRegistryObserver implementation. 12403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) virtual void OnExtensionLoaded(content::BrowserContext* browser_context, 12503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) const Extension* extension) OVERRIDE; 126cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) virtual void OnExtensionUnloaded( 127cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) content::BrowserContext* browser_context, 12803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) const Extension* extension, 12903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) UnloadedExtensionInfo::Reason reason) OVERRIDE; 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1317d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) void LoadGeometryFromStorage(const std::string& extension_id); 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void SyncToStorage(); 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Preferences storage. 13503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) ExtensionPrefs* prefs_; 1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 137cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // Cached data. 1382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) std::map<std::string, ExtensionData> cache_; 1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 140cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // Data that still needs saving. 1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::set<std::string> unsynced_extensions_; 1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 143cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // The timer used to save the data. 1445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::OneShotTimer<AppWindowGeometryCache> sync_timer_; 1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The timeout value we'll use for |sync_timer_|. 1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::TimeDelta sync_delay_; 1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 149cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // Listen to extension load, unloaded notifications. 15003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) ScopedObserver<ExtensionRegistry, ExtensionRegistryObserver> 151cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) extension_registry_observer_; 152cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 153a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) ObserverList<Observer> observers_; 1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 15603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)} // namespace extensions 1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 15803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)#endif // EXTENSIONS_BROWSER_APP_WINDOW_APP_WINDOW_GEOMETRY_CACHE_H_ 159