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