• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.
4 
5 #include "content/child/quota_dispatcher.h"
6 
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"
16 #include "url/gurl.h"
17 
18 using quota::QuotaStatusCode;
19 using quota::StorageType;
20 
21 using blink::WebStorageQuotaCallbacks;
22 using blink::WebStorageQuotaError;
23 using blink::WebStorageQuotaType;
24 
25 using webkit_glue::WorkerTaskRunner;
26 
27 namespace content {
28 
29 static base::LazyInstance<base::ThreadLocalPointer<QuotaDispatcher> >::Leaky
30     g_quota_dispatcher_tls = LAZY_INSTANCE_INITIALIZER;
31 
32 namespace {
33 
34 // QuotaDispatcher::Callback implementation for WebStorageQuotaCallbacks.
35 class WebStorageQuotaDispatcherCallback : public QuotaDispatcher::Callback {
36  public:
WebStorageQuotaDispatcherCallback(blink::WebStorageQuotaCallbacks * callback)37   WebStorageQuotaDispatcherCallback(blink::WebStorageQuotaCallbacks* callback)
38       : callbacks_(callback) {
39     DCHECK(callbacks_);
40   }
~WebStorageQuotaDispatcherCallback()41   virtual ~WebStorageQuotaDispatcherCallback() {}
DidQueryStorageUsageAndQuota(int64 usage,int64 quota)42   virtual void DidQueryStorageUsageAndQuota(int64 usage, int64 quota) OVERRIDE {
43     callbacks_->didQueryStorageUsageAndQuota(usage, quota);
44   }
DidGrantStorageQuota(int64 granted_quota)45   virtual void DidGrantStorageQuota(int64 granted_quota) OVERRIDE {
46     callbacks_->didGrantStorageQuota(granted_quota);
47   }
DidFail(quota::QuotaStatusCode error)48   virtual void DidFail(quota::QuotaStatusCode error) OVERRIDE {
49     callbacks_->didFail(static_cast<WebStorageQuotaError>(error));
50   }
51 
52  private:
53   // Not owned (self-destructed).
54   blink::WebStorageQuotaCallbacks* callbacks_;
55 };
56 
CurrentWorkerId()57 int CurrentWorkerId() {
58   return WorkerTaskRunner::Instance()->CurrentWorkerId();
59 }
60 
61 }  // namespace
62 
QuotaDispatcher(ThreadSafeSender * thread_safe_sender,QuotaMessageFilter * quota_message_filter)63 QuotaDispatcher::QuotaDispatcher(ThreadSafeSender* thread_safe_sender,
64                                  QuotaMessageFilter* quota_message_filter)
65     : thread_safe_sender_(thread_safe_sender),
66       quota_message_filter_(quota_message_filter) {
67   g_quota_dispatcher_tls.Pointer()->Set(this);
68 }
69 
~QuotaDispatcher()70 QuotaDispatcher::~QuotaDispatcher() {
71   IDMap<Callback, IDMapOwnPointer>::iterator iter(&pending_quota_callbacks_);
72   while (!iter.IsAtEnd()) {
73     iter.GetCurrentValue()->DidFail(quota::kQuotaErrorAbort);
74     iter.Advance();
75   }
76 
77   g_quota_dispatcher_tls.Pointer()->Set(NULL);
78 }
79 
ThreadSpecificInstance(ThreadSafeSender * thread_safe_sender,QuotaMessageFilter * quota_message_filter)80 QuotaDispatcher* QuotaDispatcher::ThreadSpecificInstance(
81     ThreadSafeSender* thread_safe_sender,
82     QuotaMessageFilter* quota_message_filter) {
83   if (g_quota_dispatcher_tls.Pointer()->Get())
84     return g_quota_dispatcher_tls.Pointer()->Get();
85 
86   QuotaDispatcher* dispatcher = new QuotaDispatcher(
87       thread_safe_sender, quota_message_filter);
88   if (WorkerTaskRunner::Instance()->CurrentWorkerId())
89     WorkerTaskRunner::Instance()->AddStopObserver(dispatcher);
90   return dispatcher;
91 }
92 
OnWorkerRunLoopStopped()93 void QuotaDispatcher::OnWorkerRunLoopStopped() {
94   delete this;
95 }
96 
OnMessageReceived(const IPC::Message & msg)97 void QuotaDispatcher::OnMessageReceived(const IPC::Message& msg) {
98   bool handled = true;
99   IPC_BEGIN_MESSAGE_MAP(QuotaDispatcher, msg)
100     IPC_MESSAGE_HANDLER(QuotaMsg_DidGrantStorageQuota,
101                         DidGrantStorageQuota)
102     IPC_MESSAGE_HANDLER(QuotaMsg_DidQueryStorageUsageAndQuota,
103                         DidQueryStorageUsageAndQuota);
104     IPC_MESSAGE_HANDLER(QuotaMsg_DidFail, DidFail);
105     IPC_MESSAGE_UNHANDLED(handled = false)
106   IPC_END_MESSAGE_MAP()
107   DCHECK(handled) << "Unhandled message:" << msg.type();
108 }
109 
QueryStorageUsageAndQuota(const GURL & origin_url,StorageType type,Callback * callback)110 void QuotaDispatcher::QueryStorageUsageAndQuota(
111     const GURL& origin_url,
112     StorageType type,
113     Callback* callback) {
114   DCHECK(callback);
115   int request_id = quota_message_filter_->GenerateRequestID(CurrentWorkerId());
116   pending_quota_callbacks_.AddWithID(callback, request_id);
117   thread_safe_sender_->Send(new QuotaHostMsg_QueryStorageUsageAndQuota(
118       request_id, origin_url, type));
119 }
120 
RequestStorageQuota(int render_view_id,const GURL & origin_url,StorageType type,int64 requested_size,Callback * callback)121 void QuotaDispatcher::RequestStorageQuota(
122     int render_view_id,
123     const GURL& origin_url,
124     StorageType type,
125     int64 requested_size,
126     Callback* callback) {
127   DCHECK(callback);
128   DCHECK(CurrentWorkerId() == 0);
129   int request_id = quota_message_filter_->GenerateRequestID(CurrentWorkerId());
130   pending_quota_callbacks_.AddWithID(callback, request_id);
131   thread_safe_sender_->Send(new QuotaHostMsg_RequestStorageQuota(
132       render_view_id, request_id, origin_url, type, requested_size));
133 }
134 
135 // static
136 QuotaDispatcher::Callback*
CreateWebStorageQuotaCallbacksWrapper(blink::WebStorageQuotaCallbacks * callbacks)137 QuotaDispatcher::CreateWebStorageQuotaCallbacksWrapper(
138     blink::WebStorageQuotaCallbacks* callbacks) {
139   return new WebStorageQuotaDispatcherCallback(callbacks);
140 }
141 
DidGrantStorageQuota(int request_id,int64 granted_quota)142 void QuotaDispatcher::DidGrantStorageQuota(
143     int request_id,
144     int64 granted_quota) {
145   Callback* callback = pending_quota_callbacks_.Lookup(request_id);
146   DCHECK(callback);
147   callback->DidGrantStorageQuota(granted_quota);
148   pending_quota_callbacks_.Remove(request_id);
149 }
150 
DidQueryStorageUsageAndQuota(int request_id,int64 current_usage,int64 current_quota)151 void QuotaDispatcher::DidQueryStorageUsageAndQuota(
152     int request_id,
153     int64 current_usage,
154     int64 current_quota) {
155   Callback* callback = pending_quota_callbacks_.Lookup(request_id);
156   DCHECK(callback);
157   callback->DidQueryStorageUsageAndQuota(current_usage, current_quota);
158   pending_quota_callbacks_.Remove(request_id);
159 }
160 
DidFail(int request_id,QuotaStatusCode error)161 void QuotaDispatcher::DidFail(
162     int request_id,
163     QuotaStatusCode error) {
164   Callback* callback = pending_quota_callbacks_.Lookup(request_id);
165   DCHECK(callback);
166   callback->DidFail(error);
167   pending_quota_callbacks_.Remove(request_id);
168 }
169 
170 COMPILE_ASSERT(int(blink::WebStorageQuotaTypeTemporary) == \
171                int(quota::kStorageTypeTemporary), mismatching_enums);
172 COMPILE_ASSERT(int(blink::WebStorageQuotaTypePersistent) == \
173                int(quota::kStorageTypePersistent), mismatching_enums);
174 
175 COMPILE_ASSERT(int(blink::WebStorageQuotaErrorNotSupported) == \
176                int(quota::kQuotaErrorNotSupported), mismatching_enums);
177 COMPILE_ASSERT(int(blink::WebStorageQuotaErrorAbort) == \
178                int(quota::kQuotaErrorAbort), mismatching_enums);
179 
180 }  // namespace content
181