summaryrefslogtreecommitdiffstats
path: root/chromium/content/browser/appcache/appcache_backfillers.cc
blob: fbe0b5de0a32dd664eae7d500bcdde095e5716c7 (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
// Copyright 2019 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.

#include "content/browser/appcache/appcache_backfillers.h"

#include "content/browser/appcache/appcache_update_job.h"
#include "net/http/http_request_headers.h"
#include "sql/statement.h"
#include "storage/common/quota/padding_key.h"
#include "url/gurl.h"

namespace content {

namespace {

int64_t ComputeEntryPaddingSize(std::string response_url,
                                std::string manifest_url) {
  if (GURL(response_url).GetOrigin() == GURL(manifest_url).GetOrigin())
    return 0;
  return storage::ComputeRandomResponsePadding();
}

// Iterates over each Cache record; execute |callable| on each iteration.
//
// ForEachCallable: (int64_t cache_id, int64_t group_id) -> bool.
//
// Returns whether the database queries succeeded.
template <typename ForEachCallable>
bool ForEachCache(sql::Database* db, const ForEachCallable& callable) {
  static const char kSql[] = "SELECT cache_id, group_id FROM Caches";
  sql::Statement statement(db->GetUniqueStatement(kSql));
  while (statement.Step()) {
    int64_t cache_id = statement.ColumnInt64(0);
    int64_t group_id = statement.ColumnInt64(1);
    if (!callable(cache_id, group_id))
      return false;
  }
  return true;
}

}  // namespace

// AppCacheBackfillerVersion8

bool AppCacheBackfillerVersion8::BackfillPaddingSizes() {
  return ForEachCache(db_, [&](int64_t cache_id, int64_t group_id) -> bool {
    base::Optional<std::string> manifest_url = GetManifestUrlForGroup(group_id);
    if (!manifest_url.has_value())
      return false;

    int64_t cache_padding_size = 0;
    if (!ForEachEntry(
            cache_id,
            [&](std::string response_url, int64_t response_id) -> bool {
              int64_t entry_padding_size =
                  ComputeEntryPaddingSize(response_url, manifest_url.value());
              cache_padding_size += entry_padding_size;
              return UpdateEntryPaddingSize(response_id, entry_padding_size);
            })) {
      return false;
    }

    return UpdateCachePaddingSize(cache_id, cache_padding_size);
  });
}

template <typename ForEachCallable>
bool AppCacheBackfillerVersion8::ForEachEntry(int64_t cache_id,
                                              const ForEachCallable& callable) {
  static const char kSql[] =
      "SELECT url, response_id, cache_id FROM Entries WHERE cache_id = ?";
  sql::Statement statement(db_->GetUniqueStatement(kSql));
  statement.BindInt64(0, cache_id);
  while (statement.Step()) {
    std::string url = statement.ColumnString(0);
    int64_t response_id = statement.ColumnInt64(1);
    if (!callable(url, response_id))
      return false;
  }
  return true;
}

base::Optional<std::string> AppCacheBackfillerVersion8::GetManifestUrlForGroup(
    int64_t group_id) {
  static const char kSql[] =
      "SELECT manifest_url, group_id FROM Groups WHERE group_id = ?";
  sql::Statement statement(db_->GetUniqueStatement(kSql));
  statement.BindInt64(0, group_id);
  if (!statement.Step())
    return base::nullopt;
  return statement.ColumnString(0);
}

bool AppCacheBackfillerVersion8::UpdateEntryPaddingSize(int64_t response_id,
                                                        int64_t padding_size) {
  static const char kSql[] =
      "UPDATE Entries SET padding_size = ? WHERE response_id = ?";
  sql::Statement statement(db_->GetCachedStatement(SQL_FROM_HERE, kSql));
  statement.BindInt64(0, padding_size);
  statement.BindInt64(1, response_id);
  return statement.Run();
}

bool AppCacheBackfillerVersion8::UpdateCachePaddingSize(int64_t cache_id,
                                                        int64_t padding_size) {
  static const char kSql[] =
      "UPDATE Caches SET padding_size = ? WHERE cache_id = ?";
  sql::Statement statement(db_->GetCachedStatement(SQL_FROM_HERE, kSql));
  statement.BindInt64(0, padding_size);
  statement.BindInt64(1, cache_id);
  return statement.Run();
}

// AppCacheBackfillerVersion9

bool AppCacheBackfillerVersion9::BackfillManifestParserVersionAndScope() {
  return ForEachCache(db_, [&](int64_t cache_id, int64_t group_id) -> bool {
    base::Optional<std::string> manifest_url = GetManifestUrlForGroup(group_id);
    if (!manifest_url.has_value())
      return false;

    // |manifest_parser_version| should be set to 0 to recognize that scope
    // checking wasn't enabled when this group record was written.
    int64_t manifest_parser_version = 0;
    if (!UpdateCacheManifestParserVersion(cache_id, manifest_parser_version))
      return false;

    // This is where pre-version 9 DBs will end up with a manifest scope
    // that previously didn't have one.  Update using the entire origin for a
    // scope.  Will end up getting "fixed" on the next update from version 0 to
    // version 1 once manifest scoping is enabled.
    std::string manifest_scope = "/";
    return UpdateCacheManifestScope(cache_id, manifest_scope);
  });
}

bool AppCacheBackfillerVersion9::UpdateCacheManifestParserVersion(
    int64_t cache_id,
    int64_t manifest_parser_version) {
  static const char kSql[] =
      "UPDATE Caches SET manifest_parser_version = ? WHERE"
      " cache_id = ?";
  sql::Statement statement(db_->GetCachedStatement(SQL_FROM_HERE, kSql));
  statement.BindInt64(0, manifest_parser_version);
  statement.BindInt64(1, cache_id);
  return statement.Run();
}

bool AppCacheBackfillerVersion9::UpdateCacheManifestScope(
    int64_t cache_id,
    const std::string& manifest_scope) {
  static const char kSql[] =
      "UPDATE Caches SET manifest_scope = ? WHERE"
      " cache_id = ?";
  sql::Statement statement(db_->GetCachedStatement(SQL_FROM_HERE, kSql));
  statement.BindString(0, manifest_scope);
  statement.BindInt64(1, cache_id);
  return statement.Run();
}

base::Optional<std::string> AppCacheBackfillerVersion9::GetManifestUrlForGroup(
    int64_t group_id) {
  static const char kSql[] =
      "SELECT manifest_url, group_id FROM Groups WHERE group_id = ?";
  sql::Statement statement(db_->GetUniqueStatement(kSql));
  statement.BindInt64(0, group_id);
  if (!statement.Step())
    return base::nullopt;
  return statement.ColumnString(0);
}

}  // namespace content