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