Home | History | Annotate | Download | only in child
      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 quota::QuotaStatusCode;
     23 using quota::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(quota::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(quota::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(quota::kStorageTypeTemporary), mismatching_enums);
    180 COMPILE_ASSERT(int(blink::WebStorageQuotaTypePersistent) == \
    181                int(quota::kStorageTypePersistent), mismatching_enums);
    182 
    183 COMPILE_ASSERT(int(blink::WebStorageQuotaErrorNotSupported) == \
    184                int(quota::kQuotaErrorNotSupported), mismatching_enums);
    185 COMPILE_ASSERT(int(blink::WebStorageQuotaErrorAbort) == \
    186                int(quota::kQuotaErrorAbort), mismatching_enums);
    187 
    188 }  // namespace content
    189