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

Unified 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, 4 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 side-by-side diff with in-line comments
Download patch
Index: chrome/browser/extensions/shell_window_geometry_cache.cc
diff --git a/chrome/browser/extensions/shell_window_geometry_cache.cc b/chrome/browser/extensions/shell_window_geometry_cache.cc
new file mode 100644
index 0000000000000000000000000000000000000000..5dd653d241ebf3fdc4c73338c6390ee5d80bfb22
--- /dev/null
+++ b/chrome/browser/extensions/shell_window_geometry_cache.cc
@@ -0,0 +1,175 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/extensions/shell_window_geometry_cache.h"
+
+#include "base/bind.h"
+#include "chrome/browser/extensions/state_store.h"
+#include "chrome/common/chrome_notification_types.h"
+#include "chrome/common/extensions/extension.h"
+#include "content/public/browser/notification_service.h"
+#include "content/public/browser/notification_types.h"
+
+namespace {
+
+// Keys for serialization to and from Value to store in the preferences.
+const char kWindowGeometryKey[] = "window_geometry";
+
+// The timeout in milliseconds before we'll persist window geometry to the
+// StateStore.
+const int kSyncTimeoutMilliseconds = 1000;
+
+} // namespace
+
+namespace extensions {
+
+ShellWindowGeometryCache::ShellWindowGeometryCache(Profile* profile,
+ StateStore* state_store)
+ : store_(state_store) {
+ registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_LOADED,
+ content::Source<Profile>(profile));
+ registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_UNLOADED,
+ content::Source<Profile>(profile));
+
+ store_->RegisterKey(kWindowGeometryKey);
+}
+
+ShellWindowGeometryCache::~ShellWindowGeometryCache() {
+ SyncToStorage();
+}
+
+void ShellWindowGeometryCache::SaveGeometry(
+ const std::string& extension_id,
+ const std::string& window_id,
+ const gfx::Rect& bounds) {
+ std::map<std::string, gfx::Rect>& geometry = cache_[extension_id];
+ geometry[window_id] = bounds;
+
+ unsynced_extensions_.insert(extension_id);
+
+ // We don't use Reset() because the timer may not yet be running.
+ // (In that case Stop() is a no-op.)
+ sync_timer_.Stop();
+ sync_timer_.Start(FROM_HERE,
+ base::TimeDelta::FromMilliseconds(kSyncTimeoutMilliseconds), this,
+ &ShellWindowGeometryCache::SyncToStorage);
+}
+
+void ShellWindowGeometryCache::SyncToStorage() {
+ std::set<std::string> tosync;
+ tosync.swap(unsynced_extensions_);
+ for (std::set<std::string>::const_iterator it = tosync.begin(),
+ eit = tosync.end(); it != eit; ++it) {
+ const std::string& extension_id = *it;
+ const std::map<std::string, gfx::Rect>& geometry = cache_[extension_id];
+
+ scoped_ptr<base::DictionaryValue> dict(new base::DictionaryValue);
+ for (std::map<std::string, gfx::Rect>::const_iterator it =
+ geometry.begin(), eit = geometry.end(); it != eit; ++it) {
+ base::DictionaryValue* value = new base::DictionaryValue;
+ const gfx::Rect& bounds = it->second;
+ value->SetInteger("x", bounds.x());
+ value->SetInteger("y", bounds.y());
+ value->SetInteger("w", bounds.width());
+ value->SetInteger("h", bounds.height());
+ dict->SetWithoutPathExpansion(it->first, value);
+ }
+ store_->SetExtensionValue(extension_id, kWindowGeometryKey,
+ scoped_ptr<base::Value>(dict.release()));
+ }
+}
+
+bool ShellWindowGeometryCache::GetGeometry(
+ const std::string& extension_id,
+ const std::string& window_id,
+ gfx::Rect* bounds) const {
+
+ std::map<std::string, std::map<std::string, gfx::Rect> >::const_iterator
+ ext = cache_.find(extension_id);
+
+ // Not in the map means loading data for the extension didn't finish yet.
+ if (ext == cache_.end())
+ return false;
+
+ std::map<std::string, gfx::Rect>::const_iterator win = ext->second.find(
+ window_id);
+
+ if (win == ext->second.end())
+ return false;
+
+ *bounds = win->second;
+ return true;
+}
+
+void ShellWindowGeometryCache::Observe(
+ int type, const content::NotificationSource& source,
+ const content::NotificationDetails& details) {
+ switch (type) {
+ case chrome::NOTIFICATION_EXTENSION_LOADED: {
+ std::string extension_id =
+ content::Details<const Extension>(details).ptr()->id();
+ OnExtensionLoaded(extension_id);
+ break;
+ }
+ case chrome::NOTIFICATION_EXTENSION_UNLOADED: {
+ std::string extension_id =
+ content::Details<const UnloadedExtensionInfo>(details).
+ ptr()->extension->id();
+ OnExtensionUnloaded(extension_id);
+ break;
+ }
+ default:
+ NOTREACHED();
+ return;
+ }
+}
+
+void ShellWindowGeometryCache::OnExtensionLoaded(
+ const std::string& extension_id)
+{
+ store_->GetExtensionValue(extension_id, kWindowGeometryKey,
+ base::Bind(&ShellWindowGeometryCache::GeometryFromStorage,
+ AsWeakPtr(), extension_id));
+}
+
+void ShellWindowGeometryCache::OnExtensionUnloaded(
+ const std::string& extension_id)
+{
+ SyncToStorage();
+ cache_.erase(extension_id);
+}
+
+void ShellWindowGeometryCache::GeometryFromStorage(
+ const std::string& extension_id, scoped_ptr<base::Value> value) {
+ // TODO(mek): What should happen if an extension is already unloaded by the
+ // time this code is executed.
+ std::map<std::string, gfx::Rect>& geometry = cache_[extension_id];
+
+ base::DictionaryValue* dict;
+ if (value.get() && value->GetAsDictionary(&dict)) {
+ for (base::DictionaryValue::Iterator it(*dict); it.HasNext();
+ it.Advance()) {
+ // If the cache already contains geometry for this window, don't
+ // overwrite that information since it is probably the result of an
+ // application starting up very quickly.
+ std::map<std::string, gfx::Rect>::iterator geomIt =
+ geometry.find(it.key());
+ if (geomIt == geometry.end()) {
+ const base::DictionaryValue* geom;
+ if (it.value().GetAsDictionary(&geom)) {
+ gfx::Rect& bounds = geometry[it.key()];
+
+ int i;
+ if (geom->GetInteger("x", &i)) bounds.set_x(i);
+ if (geom->GetInteger("y", &i)) bounds.set_y(i);
+ if (geom->GetInteger("w", &i)) bounds.set_width(i);
+ if (geom->GetInteger("h", &i)) bounds.set_height(i);
+ }
+ }
+ }
+ }
+}
+
+
+} // namespace extensions

Powered by Google App Engine
This is Rietveld 408576698