1 // Copyright (c) 2011 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.
5 #include "content/child/quota_dispatcher.h"
7 #include "base/basictypes.h"
8 #include "base/lazy_instance.h"
9 #include "base/threading/thread_local.h"
10 #include "content/child/child_thread.h"
11 #include "content/child/quota_message_filter.h"
12 #include "content/child/thread_safe_sender.h"
13 #include "content/common/quota_messages.h"
14 #include "third_party/WebKit/public/platform/WebStorageQuotaCallbacks.h"
15 #include "third_party/WebKit/public/platform/WebStorageQuotaType.h"
18 using quota::QuotaStatusCode;
19 using quota::StorageType;
21 using blink::WebStorageQuotaCallbacks;
22 using blink::WebStorageQuotaError;
23 using blink::WebStorageQuotaType;
25 using webkit_glue::WorkerTaskRunner;
29 static base::LazyInstance<base::ThreadLocalPointer<QuotaDispatcher> >::Leaky
30 g_quota_dispatcher_tls = LAZY_INSTANCE_INITIALIZER;
34 // QuotaDispatcher::Callback implementation for WebStorageQuotaCallbacks.
35 class WebStorageQuotaDispatcherCallback : public QuotaDispatcher::Callback {
37 explicit WebStorageQuotaDispatcherCallback(
38 blink::WebStorageQuotaCallbacks callback)
39 : callbacks_(callback) {}
40 virtual ~WebStorageQuotaDispatcherCallback() {}
42 virtual void DidQueryStorageUsageAndQuota(int64 usage, int64 quota) OVERRIDE {
43 callbacks_.didQueryStorageUsageAndQuota(usage, quota);
45 virtual void DidGrantStorageQuota(int64 usage, int64 granted_quota) OVERRIDE {
46 callbacks_.didGrantStorageQuota(usage, granted_quota);
48 virtual void DidFail(quota::QuotaStatusCode error) OVERRIDE {
49 callbacks_.didFail(static_cast<WebStorageQuotaError>(error));
53 blink::WebStorageQuotaCallbacks callbacks_;
55 DISALLOW_COPY_AND_ASSIGN(WebStorageQuotaDispatcherCallback);
58 int CurrentWorkerId() {
59 return WorkerTaskRunner::Instance()->CurrentWorkerId();
64 QuotaDispatcher::QuotaDispatcher(ThreadSafeSender* thread_safe_sender,
65 QuotaMessageFilter* quota_message_filter)
66 : thread_safe_sender_(thread_safe_sender),
67 quota_message_filter_(quota_message_filter) {
68 g_quota_dispatcher_tls.Pointer()->Set(this);
71 QuotaDispatcher::~QuotaDispatcher() {
72 IDMap<Callback, IDMapOwnPointer>::iterator iter(&pending_quota_callbacks_);
73 while (!iter.IsAtEnd()) {
74 iter.GetCurrentValue()->DidFail(quota::kQuotaErrorAbort);
78 g_quota_dispatcher_tls.Pointer()->Set(NULL);
81 QuotaDispatcher* QuotaDispatcher::ThreadSpecificInstance(
82 ThreadSafeSender* thread_safe_sender,
83 QuotaMessageFilter* quota_message_filter) {
84 if (g_quota_dispatcher_tls.Pointer()->Get())
85 return g_quota_dispatcher_tls.Pointer()->Get();
87 QuotaDispatcher* dispatcher = new QuotaDispatcher(
88 thread_safe_sender, quota_message_filter);
89 if (WorkerTaskRunner::Instance()->CurrentWorkerId())
90 WorkerTaskRunner::Instance()->AddStopObserver(dispatcher);
94 void QuotaDispatcher::OnWorkerRunLoopStopped() {
98 void QuotaDispatcher::OnMessageReceived(const IPC::Message& msg) {
100 IPC_BEGIN_MESSAGE_MAP(QuotaDispatcher, msg)
101 IPC_MESSAGE_HANDLER(QuotaMsg_DidGrantStorageQuota,
102 DidGrantStorageQuota)
103 IPC_MESSAGE_HANDLER(QuotaMsg_DidQueryStorageUsageAndQuota,
104 DidQueryStorageUsageAndQuota);
105 IPC_MESSAGE_HANDLER(QuotaMsg_DidFail, DidFail);
106 IPC_MESSAGE_UNHANDLED(handled = false)
107 IPC_END_MESSAGE_MAP()
108 DCHECK(handled) << "Unhandled message:" << msg.type();
111 void QuotaDispatcher::QueryStorageUsageAndQuota(
112 const GURL& origin_url,
114 Callback* callback) {
116 int request_id = quota_message_filter_->GenerateRequestID(CurrentWorkerId());
117 pending_quota_callbacks_.AddWithID(callback, request_id);
118 thread_safe_sender_->Send(new QuotaHostMsg_QueryStorageUsageAndQuota(
119 request_id, origin_url, type));
122 void QuotaDispatcher::RequestStorageQuota(
124 const GURL& origin_url,
126 uint64 requested_size,
127 Callback* callback) {
129 DCHECK(CurrentWorkerId() == 0);
130 int request_id = quota_message_filter_->GenerateRequestID(CurrentWorkerId());
131 pending_quota_callbacks_.AddWithID(callback, request_id);
132 thread_safe_sender_->Send(new QuotaHostMsg_RequestStorageQuota(
133 render_view_id, request_id, origin_url, type, requested_size));
137 QuotaDispatcher::Callback*
138 QuotaDispatcher::CreateWebStorageQuotaCallbacksWrapper(
139 blink::WebStorageQuotaCallbacks callbacks) {
140 return new WebStorageQuotaDispatcherCallback(callbacks);
143 void QuotaDispatcher::DidGrantStorageQuota(
146 int64 granted_quota) {
147 Callback* callback = pending_quota_callbacks_.Lookup(request_id);
149 callback->DidGrantStorageQuota(current_usage, granted_quota);
150 pending_quota_callbacks_.Remove(request_id);
153 void QuotaDispatcher::DidQueryStorageUsageAndQuota(
156 int64 current_quota) {
157 Callback* callback = pending_quota_callbacks_.Lookup(request_id);
159 callback->DidQueryStorageUsageAndQuota(current_usage, current_quota);
160 pending_quota_callbacks_.Remove(request_id);
163 void QuotaDispatcher::DidFail(
165 QuotaStatusCode error) {
166 Callback* callback = pending_quota_callbacks_.Lookup(request_id);
168 callback->DidFail(error);
169 pending_quota_callbacks_.Remove(request_id);
172 COMPILE_ASSERT(int(blink::WebStorageQuotaTypeTemporary) == \
173 int(quota::kStorageTypeTemporary), mismatching_enums);
174 COMPILE_ASSERT(int(blink::WebStorageQuotaTypePersistent) == \
175 int(quota::kStorageTypePersistent), mismatching_enums);
177 COMPILE_ASSERT(int(blink::WebStorageQuotaErrorNotSupported) == \
178 int(quota::kQuotaErrorNotSupported), mismatching_enums);
179 COMPILE_ASSERT(int(blink::WebStorageQuotaErrorAbort) == \
180 int(quota::kQuotaErrorAbort), mismatching_enums);
182 } // namespace content