state_store.cc revision 5f1c94371a64b3196d4be9466099bb892df9b88e
1116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch// 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) 5116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "extensions/browser/state_store.h" 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 72a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/bind.h" 8ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch#include "base/message_loop/message_loop.h" 9116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "content/public/browser/browser_context.h" 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/notification_service.h" 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/notification_types.h" 12f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#include "extensions/browser/extension_registry.h" 13f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "extensions/common/extension.h" 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace { 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Delay, in seconds, before we should open the State Store database. We 182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// defer it to avoid slowing down startup. See http://crbug.com/161848 192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const int kInitDelaySeconds = 1; 202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)std::string GetFullKey(const std::string& extension_id, 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& key) { 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return extension_id + "." + key; 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace extensions { 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Helper class to delay tasks until we're ready to start executing them. 312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)class StateStore::DelayedTaskQueue { 322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) public: 332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DelayedTaskQueue() : ready_(false) {} 342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ~DelayedTaskQueue() {} 352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Queues up a task for invoking once we're ready. Invokes immediately if 372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // we're already ready. 382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) void InvokeWhenReady(base::Closure task); 392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Marks us ready, and invokes all pending tasks. 412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) void SetReady(); 422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 43a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // Return whether or not the DelayedTaskQueue is |ready_|. 44a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) bool ready() const { return ready_; } 45a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) private: 472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) bool ready_; 482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) std::vector<base::Closure> pending_tasks_; 492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}; 502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void StateStore::DelayedTaskQueue::InvokeWhenReady(base::Closure task) { 522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (ready_) { 532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) task.Run(); 542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } else { 552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) pending_tasks_.push_back(task); 562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void StateStore::DelayedTaskQueue::SetReady() { 602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ready_ = true; 612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) for (size_t i = 0; i < pending_tasks_.size(); ++i) 632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) pending_tasks_[i].Run(); 642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) pending_tasks_.clear(); 652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 67116680a4aac90f2aa7413d9095a592090648e557Ben MurdochStateStore::StateStore(content::BrowserContext* context, 682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const base::FilePath& db_path, 692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) bool deferred_load) 70f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) : db_path_(db_path), 71f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) task_queue_(new DelayedTaskQueue()), 72f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) extension_registry_observer_(this) { 73116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch extension_registry_observer_.Add(ExtensionRegistry::Get(context)); 742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (deferred_load) { 765f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // Don't Init() until the first page is loaded or the embedder explicitly 775f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // requests it. 78116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch registrar_.Add( 79116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch this, 80116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch content::NOTIFICATION_LOAD_COMPLETED_MAIN_FRAME, 81116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch content::NotificationService::AllBrowserContextsAndSources()); 822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } else { 832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) Init(); 842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 87116680a4aac90f2aa7413d9095a592090648e557Ben MurdochStateStore::StateStore(content::BrowserContext* context, 88116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch scoped_ptr<ValueStore> value_store) 89f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) : store_(value_store.Pass()), 90f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) task_queue_(new DelayedTaskQueue()), 91f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) extension_registry_observer_(this) { 92116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch extension_registry_observer_.Add(ExtensionRegistry::Get(context)); 932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // This constructor is for testing. No need to delay Init. 952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) Init(); 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)StateStore::~StateStore() { 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1015f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)void StateStore::RequestInitAfterDelay() { 1025f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) InitAfterDelay(); 1035f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)} 1045f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void StateStore::RegisterKey(const std::string& key) { 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) registered_keys_.insert(key); 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void StateStore::GetExtensionValue(const std::string& extension_id, 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& key, 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ReadCallback callback) { 112116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch task_queue_->InvokeWhenReady(base::Bind(&ValueStoreFrontend::Get, 113116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch base::Unretained(&store_), 114116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch GetFullKey(extension_id, key), 115116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch callback)); 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 118116680a4aac90f2aa7413d9095a592090648e557Ben Murdochvoid StateStore::SetExtensionValue(const std::string& extension_id, 119116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch const std::string& key, 120116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch scoped_ptr<base::Value> value) { 121116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch task_queue_->InvokeWhenReady(base::Bind(&ValueStoreFrontend::Set, 122116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch base::Unretained(&store_), 123116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch GetFullKey(extension_id, key), 124116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch base::Passed(&value))); 1252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 1262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void StateStore::RemoveExtensionValue(const std::string& extension_id, 1282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const std::string& key) { 129116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch task_queue_->InvokeWhenReady(base::Bind(&ValueStoreFrontend::Remove, 130116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch base::Unretained(&store_), 131116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch GetFullKey(extension_id, key))); 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 134116680a4aac90f2aa7413d9095a592090648e557Ben Murdochbool StateStore::IsInitialized() const { 135116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch return task_queue_->ready(); 136116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch} 137a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void StateStore::Observe(int type, 1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const content::NotificationSource& source, 1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const content::NotificationDetails& details) { 1415f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) DCHECK_EQ(type, content::NOTIFICATION_LOAD_COMPLETED_MAIN_FRAME); 142f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) registrar_.RemoveAll(); 1435f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) InitAfterDelay(); 144f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)} 145f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 146f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)void StateStore::OnExtensionWillBeInstalled( 147f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) content::BrowserContext* browser_context, 148f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) const Extension* extension, 149f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) bool is_update, 150f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) bool from_ephemeral, 151f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) const std::string& old_name) { 152f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) RemoveKeysForExtension(extension->id()); 153f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)} 154f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 155f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)void StateStore::OnExtensionUninstalled( 156f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) content::BrowserContext* browser_context, 1575f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) const Extension* extension, 1585f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) extensions::UninstallReason reason) { 159f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) RemoveKeysForExtension(extension->id()); 1602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 1612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void StateStore::Init() { 1635f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // Could be called twice if InitAfterDelay() is requested explicitly by the 1645f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // embedder in addition to internally after first page load. 1655f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if (IsInitialized()) 1665f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return; 1675f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 1682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!db_path_.empty()) 1692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) store_.Init(db_path_); 1702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) task_queue_->SetReady(); 1712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1735f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)void StateStore::InitAfterDelay() { 1745f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if (IsInitialized()) 1755f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return; 1765f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 1775f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) base::MessageLoop::current()->PostDelayedTask( 1785f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) FROM_HERE, 1795f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) base::Bind(&StateStore::Init, AsWeakPtr()), 1805f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) base::TimeDelta::FromSeconds(kInitDelaySeconds)); 1815f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)} 1825f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 1832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void StateStore::RemoveKeysForExtension(const std::string& extension_id) { 1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (std::set<std::string>::iterator key = registered_keys_.begin(); 185116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch key != registered_keys_.end(); 186116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch ++key) { 187116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch task_queue_->InvokeWhenReady(base::Bind(&ValueStoreFrontend::Remove, 188116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch base::Unretained(&store_), 189116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch GetFullKey(extension_id, *key))); 1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace extensions 194