summaryrefslogtreecommitdiffstats
path: root/net/sdch/sdch_owner.h
blob: 3d6b59b76618a819943914759ddb04d8bb382eaa (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef NET_SDCH_SDCH_OWNER_H_
#define NET_SDCH_SDCH_OWNER_H_

#include <map>
#include <string>

#include "base/memory/memory_pressure_listener.h"
#include "base/memory/ref_counted.h"
#include "base/prefs/pref_store.h"
#include "net/base/sdch_observer.h"
#include "net/url_request/sdch_dictionary_fetcher.h"

class GURL;
class PersistentPrefStore;
class ValueMapPrefStore;
class WriteablePrefStore;

namespace base {
class Clock;
}

namespace net {
class SdchManager;
class URLRequestContext;

// This class owns the SDCH objects not owned as part of URLRequestContext, and
// exposes interface for setting SDCH policy.  It should be instantiated by
// the net/ embedder.
// TODO(rdsmith): Implement dictionary prioritization.
class NET_EXPORT SdchOwner : public SdchObserver, public PrefStore::Observer {
 public:
  static const size_t kMaxTotalDictionarySize;
  static const size_t kMinSpaceForDictionaryFetch;

  // Consumer must guarantee that |sdch_manager| and |context| outlive
  // this object.
  SdchOwner(SdchManager* sdch_manager, URLRequestContext* context);
  ~SdchOwner() override;

  // Enables use of pref persistence.  Note that |pref_store| is owned
  // by the caller, but must be guaranteed to outlive SdchOwner.  The
  // actual mechanisms by which the PersistentPrefStore are persisted
  // are the responsibility of the caller.  This routine may only be
  // called once per SdchOwner instance.
  void EnablePersistentStorage(PersistentPrefStore* pref_store);

  // Defaults to kMaxTotalDictionarySize.
  void SetMaxTotalDictionarySize(size_t max_total_dictionary_size);

  // Defaults to kMinSpaceForDictionaryFetch.
  void SetMinSpaceForDictionaryFetch(size_t min_space_for_dictionary_fetch);

  // SdchObserver implementation.
  void OnDictionaryAdded(const GURL& dictionary_url,
                         const std::string& server_hash) override;
  void OnDictionaryRemoved(const std::string& server_hash) override;
  void OnDictionaryUsed(const std::string& server_hash) override;
  void OnGetDictionary(const GURL& request_url,
                       const GURL& dictionary_url) override;
  void OnClearDictionaries() override;

  // PrefStore::Observer implementation.
  void OnPrefValueChanged(const std::string& key) override;
  void OnInitializationCompleted(bool succeeded) override;

  // Implementation detail--this is the function callback by the callback passed
  // to the fetcher through which the fetcher informs the SdchOwner that it's
  // gotten the dictionary.  The first two arguments are bound locally.
  // Public for testing.
  void OnDictionaryFetched(base::Time last_used,
                           int use_count,
                           const std::string& dictionary_text,
                           const GURL& dictionary_url,
                           const BoundNetLog& net_log,
                           bool was_from_cache);

  void SetClockForTesting(scoped_ptr<base::Clock> clock);

  // Returns the total number of dictionaries loaded.
  int GetDictionaryCountForTesting() const;

  // Returns whether this SdchOwner has dictionary from |url| loaded.
  bool HasDictionaryFromURLForTesting(const GURL& url) const;

  void SetFetcherForTesting(scoped_ptr<SdchDictionaryFetcher> fetcher);

 private:
  // For each active dictionary, stores local info.
  // Indexed by the server hash of the dictionary.
  struct DictionaryInfo {
    base::Time last_used;
    int use_count;
    size_t size;

    DictionaryInfo() : use_count(0), size(0) {}
    DictionaryInfo(const base::Time& last_used, size_t size)
        : last_used(last_used), use_count(0), size(size) {}
    DictionaryInfo(const DictionaryInfo& rhs) = default;
    DictionaryInfo& operator=(const DictionaryInfo& rhs) = default;
  };

  void OnMemoryPressure(
      base::MemoryPressureListener::MemoryPressureLevel level);

  // Schedule loading of all dictionaries described in |persisted_info|.
  // Returns false and does not schedule a load if |persisted_info| has an
  // unsupported version or no dictionaries key. Skips any dictionaries that are
  // malformed in |persisted_info|.
  bool SchedulePersistedDictionaryLoads(
      const base::DictionaryValue& persisted_info);

  bool IsPersistingDictionaries() const;

  enum DictionaryFate {
    // A Get-Dictionary header wasn't acted on.
    DICTIONARY_FATE_GET_IGNORED = 1,

    // A fetch was attempted, but failed.
    // TODO(rdsmith): Actually record this case.
    DICTIONARY_FATE_FETCH_FAILED = 2,

    // A successful fetch was dropped on the floor, no space.
    DICTIONARY_FATE_FETCH_IGNORED_NO_SPACE = 3,

    // A successful fetch was refused by the SdchManager.
    DICTIONARY_FATE_FETCH_MANAGER_REFUSED = 4,

    // A dictionary was successfully added based on
    // a Get-Dictionary header in a response.
    DICTIONARY_FATE_ADD_RESPONSE_TRIGGERED = 5,

    // A dictionary was evicted by an incoming dict.
    DICTIONARY_FATE_EVICT_FOR_DICT = 6,

    // A dictionary was evicted by memory pressure.
    DICTIONARY_FATE_EVICT_FOR_MEMORY = 7,

    // A dictionary was evicted on destruction.
    DICTIONARY_FATE_EVICT_FOR_DESTRUCTION = 8,

    // A dictionary was successfully added based on
    // persistence from a previous browser revision.
    DICTIONARY_FATE_ADD_PERSISTENCE_TRIGGERED = 9,

    // A dictionary was unloaded on destruction, but is still present on disk.
    DICTIONARY_FATE_UNLOAD_FOR_DESTRUCTION = 10,

    DICTIONARY_FATE_MAX = 11
  };

  void RecordDictionaryFate(DictionaryFate fate);

  // Record the lifetime memory use of a specified dictionary, identified by
  // server hash.
  void RecordDictionaryEvictionOrUnload(
      const std::string& server_hash,
      size_t size,
      int use_count, DictionaryFate fate);

  net::SdchManager* manager_;
  scoped_ptr<net::SdchDictionaryFetcher> fetcher_;

  size_t total_dictionary_bytes_;

  scoped_ptr<base::Clock> clock_;

  size_t max_total_dictionary_size_;
  size_t min_space_for_dictionary_fetch_;

  base::MemoryPressureListener memory_pressure_listener_;

  // Dictionary persistence machinery.
  // * |in_memory_pref_store_| is created on construction and used in
  //   the absence of any call to EnablePersistentStorage().
  // * |external_pref_store_| holds the preference store specified
  //   by EnablePersistentStorage() (if any), while it is being read in.
  //   A non-null value here signals that the SdchOwner is observing
  //   the pref store; when read-in completes and observation is no longer
  //   needed, the pointer is set to null.  This is to avoid lots of
  //   extra irrelevant function calls; the only observer interface this
  //   class is interested in is OnInitializationCompleted().
  // * |pref_store_| holds an unowned pointer to the currently
  //   active pref store (one of the preceding two).
  scoped_refptr<ValueMapPrefStore> in_memory_pref_store_;
  PersistentPrefStore* external_pref_store_;

  WriteablePrefStore* pref_store_;

  // The use counts of dictionaries when they were loaded from the persistent
  // store, keyed by server hash. These are stored to avoid generating
  // misleading ever-increasing use counts for dictionaries that are persisted,
  // since the UMA histogram for use counts is only supposed to be since last
  // load.
  std::map<std::string, int> use_counts_at_load_;

  // Load times for loaded dictionaries, keyed by server hash. These are used to
  // track the durations that dictionaries are in memory.
  std::map<std::string, base::Time> load_times_;

  // Byte-seconds consumed by dictionaries that have been unloaded. These are
  // stored for later uploading in the SdchOwner destructor.
  std::vector<int64> consumed_byte_seconds_;

  // Creation time for this SdchOwner object, used for reporting temporal memory
  // pressure.
  base::Time creation_time_;

  DISALLOW_COPY_AND_ASSIGN(SdchOwner);
};

}  // namespace net

#endif  // NET_SDCH_SDCH_OWNER_H_