Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(93)

Side by Side Diff: chrome/browser/extensions/shell_window_geometry_cache.cc

Issue 10871086: First part of remembering platform app window geometry. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: actually make it compile Created 8 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
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 #include "chrome/browser/extensions/shell_window_geometry_cache.h"
6
7 #include "base/bind.h"
8 #include "chrome/browser/extensions/state_store.h"
9 #include "chrome/common/chrome_notification_types.h"
10 #include "chrome/common/extensions/extension.h"
11 #include "content/public/browser/notification_service.h"
12 #include "content/public/browser/notification_types.h"
13
14 namespace {
15
16 // Keys for serialization to and from Value to store in the preferences.
17 const char kWindowGeometryKey[] = "window_geometry";
18
19 // The timeout in milliseconds before we'll persist window geometry to the
20 // StateStore.
21 const int kSyncTimeoutMilliseconds = 1000;
22
23 } // namespace
24
25 namespace extensions {
26
27 ShellWindowGeometryCache::ShellWindowGeometryCache(Profile* profile,
28 StateStore* state_store)
29 : store_(state_store) {
30 registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_LOADED,
31 content::Source<Profile>(profile));
32 registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_UNLOADED,
33 content::Source<Profile>(profile));
34
35 store_->RegisterKey(kWindowGeometryKey);
36 }
37
38 ShellWindowGeometryCache::~ShellWindowGeometryCache() {
39 SyncToStorage();
40 }
41
42 void ShellWindowGeometryCache::SaveGeometry(
43 const std::string& extension_id,
44 const std::string& window_id,
45 const gfx::Rect& bounds) {
46 std::map<std::string, gfx::Rect>& geometry = cache_[extension_id];
47 geometry[window_id] = bounds;
48
49 unsynced_extensions_.insert(extension_id);
50
51 // We don't use Reset() because the timer may not yet be running.
52 // (In that case Stop() is a no-op.)
53 sync_timer_.Stop();
54 sync_timer_.Start(FROM_HERE,
55 base::TimeDelta::FromMilliseconds(kSyncTimeoutMilliseconds), this,
56 &ShellWindowGeometryCache::SyncToStorage);
57 }
58
59 void ShellWindowGeometryCache::SyncToStorage() {
60 std::set<std::string> tosync;
61 tosync.swap(unsynced_extensions_);
62 for (std::set<std::string>::const_iterator it = tosync.begin(),
63 eit = tosync.end(); it != eit; ++it) {
64 const std::string& extension_id = *it;
65 const std::map<std::string, gfx::Rect>& geometry = cache_[extension_id];
66
67 scoped_ptr<base::DictionaryValue> dict(new base::DictionaryValue);
68 for (std::map<std::string, gfx::Rect>::const_iterator it =
69 geometry.begin(), eit = geometry.end(); it != eit; ++it) {
70 base::DictionaryValue* value = new base::DictionaryValue;
71 const gfx::Rect& bounds = it->second;
72 value->SetInteger("x", bounds.x());
73 value->SetInteger("y", bounds.y());
74 value->SetInteger("w", bounds.width());
75 value->SetInteger("h", bounds.height());
76 dict->SetWithoutPathExpansion(it->first, value);
77 }
78 store_->SetExtensionValue(extension_id, kWindowGeometryKey,
79 scoped_ptr<base::Value>(dict.release()));
80 }
81 }
82
83 bool ShellWindowGeometryCache::GetGeometry(
84 const std::string& extension_id,
85 const std::string& window_id,
86 gfx::Rect* bounds) const {
87
88 std::map<std::string, std::map<std::string, gfx::Rect> >::const_iterator
89 ext = cache_.find(extension_id);
90
91 // Not in the map means loading data for the extension didn't finish yet.
92 if (ext == cache_.end())
93 return false;
94
95 std::map<std::string, gfx::Rect>::const_iterator win = ext->second.find(
96 window_id);
97
98 if (win == ext->second.end())
99 return false;
100
101 *bounds = win->second;
102 return true;
103 }
104
105 void ShellWindowGeometryCache::Observe(
106 int type, const content::NotificationSource& source,
107 const content::NotificationDetails& details) {
108 switch (type) {
109 case chrome::NOTIFICATION_EXTENSION_LOADED: {
110 std::string extension_id =
111 content::Details<const Extension>(details).ptr()->id();
112 OnExtensionLoaded(extension_id);
113 break;
114 }
115 case chrome::NOTIFICATION_EXTENSION_UNLOADED: {
116 std::string extension_id =
117 content::Details<const UnloadedExtensionInfo>(details).
118 ptr()->extension->id();
119 OnExtensionUnloaded(extension_id);
120 break;
121 }
122 default:
123 NOTREACHED();
124 return;
125 }
126 }
127
128 void ShellWindowGeometryCache::OnExtensionLoaded(
129 const std::string& extension_id)
130 {
131 store_->GetExtensionValue(extension_id, kWindowGeometryKey,
132 base::Bind(&ShellWindowGeometryCache::GeometryFromStorage,
133 AsWeakPtr(), extension_id));
134 }
135
136 void ShellWindowGeometryCache::OnExtensionUnloaded(
137 const std::string& extension_id)
138 {
139 SyncToStorage();
140 cache_.erase(extension_id);
141 }
142
143 void ShellWindowGeometryCache::GeometryFromStorage(
144 const std::string& extension_id, scoped_ptr<base::Value> value) {
145 // TODO(mek): What should happen if an extension is already unloaded by the
146 // time this code is executed.
147 std::map<std::string, gfx::Rect>& geometry = cache_[extension_id];
148
149 base::DictionaryValue* dict;
150 if (value.get() && value->GetAsDictionary(&dict)) {
151 for (base::DictionaryValue::Iterator it(*dict); it.HasNext();
152 it.Advance()) {
153 // If the cache already contains geometry for this window, don't
154 // overwrite that information since it is probably the result of an
155 // application starting up very quickly.
156 std::map<std::string, gfx::Rect>::iterator geomIt =
157 geometry.find(it.key());
158 if (geomIt == geometry.end()) {
159 const base::DictionaryValue* geom;
160 if (it.value().GetAsDictionary(&geom)) {
161 gfx::Rect& bounds = geometry[it.key()];
162
163 int i;
164 if (geom->GetInteger("x", &i)) bounds.set_x(i);
165 if (geom->GetInteger("y", &i)) bounds.set_y(i);
166 if (geom->GetInteger("w", &i)) bounds.set_width(i);
167 if (geom->GetInteger("h", &i)) bounds.set_height(i);
168 }
169 }
170 }
171 }
172 }
173
174
175 } // namespace extensions
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698