Update To 11.40.268.0
[platform/framework/web/crosswalk.git] / src / extensions / browser / quota_service.cc
1 // Copyright 2013 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 "extensions/browser/quota_service.h"
6
7 #include "base/message_loop/message_loop.h"
8 #include "base/stl_util.h"
9 #include "extensions/browser/extension_function.h"
10 #include "extensions/common/error_utils.h"
11
12 namespace {
13
14 // If the browser stays open long enough, we reset state once a day.
15 // Whatever this value is, it should be an order of magnitude longer than
16 // the longest interval in any of the QuotaLimitHeuristics in use.
17 const int kPurgeIntervalInDays = 1;
18
19 const char kOverQuotaError[] = "This request exceeds the * quota.";
20
21 }  // namespace
22
23 namespace extensions {
24
25 QuotaService::QuotaService() {
26   if (base::MessageLoop::current() != NULL) {  // Null in unit tests.
27     purge_timer_.Start(FROM_HERE,
28                        base::TimeDelta::FromDays(kPurgeIntervalInDays),
29                        this,
30                        &QuotaService::Purge);
31   }
32 }
33
34 QuotaService::~QuotaService() {
35   DCHECK(CalledOnValidThread());
36   purge_timer_.Stop();
37   Purge();
38 }
39
40 std::string QuotaService::Assess(const std::string& extension_id,
41                                  ExtensionFunction* function,
42                                  const base::ListValue* args,
43                                  const base::TimeTicks& event_time) {
44   DCHECK(CalledOnValidThread());
45
46   if (function->ShouldSkipQuotaLimiting())
47     return std::string();
48
49   // Lookup function list for extension.
50   FunctionHeuristicsMap& functions = function_heuristics_[extension_id];
51
52   // Lookup heuristics for function, create if necessary.
53   QuotaLimitHeuristics& heuristics = functions[function->name()];
54   if (heuristics.empty())
55     function->GetQuotaLimitHeuristics(&heuristics);
56
57   if (heuristics.empty())
58     return std::string();  // No heuristic implies no limit.
59
60   QuotaLimitHeuristic* failed_heuristic = NULL;
61   for (QuotaLimitHeuristics::iterator heuristic = heuristics.begin();
62        heuristic != heuristics.end();
63        ++heuristic) {
64     // Apply heuristic to each item (bucket).
65     if (!(*heuristic)->ApplyToArgs(args, event_time)) {
66       failed_heuristic = *heuristic;
67       break;
68     }
69   }
70
71   if (!failed_heuristic)
72     return std::string();
73
74   std::string error = failed_heuristic->GetError();
75   DCHECK_GT(error.length(), 0u);
76   return error;
77 }
78
79 void QuotaService::PurgeFunctionHeuristicsMap(FunctionHeuristicsMap* map) {
80   FunctionHeuristicsMap::iterator heuristics = map->begin();
81   while (heuristics != map->end()) {
82     STLDeleteElements(&heuristics->second);
83     map->erase(heuristics++);
84   }
85 }
86
87 void QuotaService::Purge() {
88   DCHECK(CalledOnValidThread());
89   std::map<std::string, FunctionHeuristicsMap>::iterator it =
90       function_heuristics_.begin();
91   for (; it != function_heuristics_.end(); function_heuristics_.erase(it++))
92     PurgeFunctionHeuristicsMap(&it->second);
93 }
94
95 void QuotaLimitHeuristic::Bucket::Reset(const Config& config,
96                                         const base::TimeTicks& start) {
97   num_tokens_ = config.refill_token_count;
98   expiration_ = start + config.refill_interval;
99 }
100
101 void QuotaLimitHeuristic::SingletonBucketMapper::GetBucketsForArgs(
102     const base::ListValue* args,
103     BucketList* buckets) {
104   buckets->push_back(&bucket_);
105 }
106
107 QuotaLimitHeuristic::QuotaLimitHeuristic(const Config& config,
108                                          BucketMapper* map,
109                                          const std::string& name)
110     : config_(config), bucket_mapper_(map), name_(name) {}
111
112 QuotaLimitHeuristic::~QuotaLimitHeuristic() {}
113
114 bool QuotaLimitHeuristic::ApplyToArgs(const base::ListValue* args,
115                                       const base::TimeTicks& event_time) {
116   BucketList buckets;
117   bucket_mapper_->GetBucketsForArgs(args, &buckets);
118   for (BucketList::iterator i = buckets.begin(); i != buckets.end(); ++i) {
119     if ((*i)->expiration().is_null())  // A brand new bucket.
120       (*i)->Reset(config_, event_time);
121     if (!Apply(*i, event_time))
122       return false;  // It only takes one to spoil it for everyone.
123   }
124   return true;
125 }
126
127 std::string QuotaLimitHeuristic::GetError() const {
128   return extensions::ErrorUtils::FormatErrorMessage(kOverQuotaError, name_);
129 }
130
131 bool QuotaService::TimedLimit::Apply(Bucket* bucket,
132                                      const base::TimeTicks& event_time) {
133   if (event_time > bucket->expiration())
134     bucket->Reset(config(), event_time);
135
136   return bucket->DeductToken();
137 }
138
139 }  // namespace extensions