1*6777b538SAndroid Build Coastguard Worker // Copyright 2016 The Chromium Authors
2*6777b538SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be
3*6777b538SAndroid Build Coastguard Worker // found in the LICENSE file.
4*6777b538SAndroid Build Coastguard Worker
5*6777b538SAndroid Build Coastguard Worker #include <iostream>
6*6777b538SAndroid Build Coastguard Worker #include <memory>
7*6777b538SAndroid Build Coastguard Worker #include <string_view>
8*6777b538SAndroid Build Coastguard Worker #include <unordered_map>
9*6777b538SAndroid Build Coastguard Worker
10*6777b538SAndroid Build Coastguard Worker #include "base/at_exit.h"
11*6777b538SAndroid Build Coastguard Worker #include "base/command_line.h"
12*6777b538SAndroid Build Coastguard Worker #include "base/files/file_path.h"
13*6777b538SAndroid Build Coastguard Worker #include "base/format_macros.h"
14*6777b538SAndroid Build Coastguard Worker #include "base/hash/md5.h"
15*6777b538SAndroid Build Coastguard Worker #include "base/logging.h"
16*6777b538SAndroid Build Coastguard Worker #include "base/message_loop/message_pump_type.h"
17*6777b538SAndroid Build Coastguard Worker #include "base/run_loop.h"
18*6777b538SAndroid Build Coastguard Worker #include "base/strings/string_number_conversions.h"
19*6777b538SAndroid Build Coastguard Worker #include "base/strings/stringprintf.h"
20*6777b538SAndroid Build Coastguard Worker #include "base/task/single_thread_task_executor.h"
21*6777b538SAndroid Build Coastguard Worker #include "base/task/thread_pool/thread_pool_instance.h"
22*6777b538SAndroid Build Coastguard Worker #include "net/base/io_buffer.h"
23*6777b538SAndroid Build Coastguard Worker #include "net/base/test_completion_callback.h"
24*6777b538SAndroid Build Coastguard Worker #include "net/disk_cache/disk_cache.h"
25*6777b538SAndroid Build Coastguard Worker #include "net/disk_cache/disk_cache_test_util.h"
26*6777b538SAndroid Build Coastguard Worker #include "net/http/http_cache.h"
27*6777b538SAndroid Build Coastguard Worker #include "net/http/http_response_headers.h"
28*6777b538SAndroid Build Coastguard Worker #include "net/http/http_response_info.h"
29*6777b538SAndroid Build Coastguard Worker #include "net/http/http_util.h"
30*6777b538SAndroid Build Coastguard Worker
31*6777b538SAndroid Build Coastguard Worker using disk_cache::Backend;
32*6777b538SAndroid Build Coastguard Worker using disk_cache::BackendResult;
33*6777b538SAndroid Build Coastguard Worker using disk_cache::Entry;
34*6777b538SAndroid Build Coastguard Worker using disk_cache::EntryResult;
35*6777b538SAndroid Build Coastguard Worker
36*6777b538SAndroid Build Coastguard Worker namespace {
37*6777b538SAndroid Build Coastguard Worker
38*6777b538SAndroid Build Coastguard Worker struct EntryData {
39*6777b538SAndroid Build Coastguard Worker std::string url;
40*6777b538SAndroid Build Coastguard Worker std::string mime_type;
41*6777b538SAndroid Build Coastguard Worker int size;
42*6777b538SAndroid Build Coastguard Worker };
43*6777b538SAndroid Build Coastguard Worker
44*6777b538SAndroid Build Coastguard Worker constexpr int kResponseInfoIndex = 0;
45*6777b538SAndroid Build Coastguard Worker constexpr int kResponseContentIndex = 1;
46*6777b538SAndroid Build Coastguard Worker
47*6777b538SAndroid Build Coastguard Worker const char* const kCommandNames[] = {
48*6777b538SAndroid Build Coastguard Worker "stop", "get_size", "list_keys", "get_stream",
49*6777b538SAndroid Build Coastguard Worker "delete_stream", "delete_key", "update_raw_headers", "list_dups",
50*6777b538SAndroid Build Coastguard Worker "set_header"};
51*6777b538SAndroid Build Coastguard Worker
52*6777b538SAndroid Build Coastguard Worker // Prints the command line help.
PrintHelp()53*6777b538SAndroid Build Coastguard Worker void PrintHelp() {
54*6777b538SAndroid Build Coastguard Worker std::cout << "cachetool <cache_path> <cache_backend_type> <subcommand> "
55*6777b538SAndroid Build Coastguard Worker << std::endl
56*6777b538SAndroid Build Coastguard Worker << std::endl;
57*6777b538SAndroid Build Coastguard Worker std::cout << "Available cache backend types: simple, blockfile" << std::endl;
58*6777b538SAndroid Build Coastguard Worker std::cout << "Available subcommands:" << std::endl;
59*6777b538SAndroid Build Coastguard Worker std::cout << " batch: Starts cachetool to process serialized commands "
60*6777b538SAndroid Build Coastguard Worker << "passed down by the standard input and return commands output "
61*6777b538SAndroid Build Coastguard Worker << "in the stdout until the stop command is received." << std::endl;
62*6777b538SAndroid Build Coastguard Worker std::cout << " delete_key <key>: Delete key from cache." << std::endl;
63*6777b538SAndroid Build Coastguard Worker std::cout << " delete_stream <key> <index>: Delete a particular stream of a"
64*6777b538SAndroid Build Coastguard Worker << " given key." << std::endl;
65*6777b538SAndroid Build Coastguard Worker std::cout << " get_size: Calculate the total size of the cache in bytes."
66*6777b538SAndroid Build Coastguard Worker << std::endl;
67*6777b538SAndroid Build Coastguard Worker std::cout << " get_stream <key> <index>: Print a particular stream for a"
68*6777b538SAndroid Build Coastguard Worker << " given key." << std::endl;
69*6777b538SAndroid Build Coastguard Worker std::cout << " list_keys: List all keys in the cache." << std::endl;
70*6777b538SAndroid Build Coastguard Worker std::cout << " list_dups: List all resources with duplicate bodies in the "
71*6777b538SAndroid Build Coastguard Worker << "cache." << std::endl;
72*6777b538SAndroid Build Coastguard Worker std::cout << " update_raw_headers <key>: Update stdin as the key's raw "
73*6777b538SAndroid Build Coastguard Worker << "response headers." << std::endl;
74*6777b538SAndroid Build Coastguard Worker std::cout << " set_header <key> <name> <value>: Set one of key's raw "
75*6777b538SAndroid Build Coastguard Worker << "response headers." << std::endl;
76*6777b538SAndroid Build Coastguard Worker std::cout << " stop: Verify that the cache can be opened and return, "
77*6777b538SAndroid Build Coastguard Worker << "confirming the cache exists and is of the right type."
78*6777b538SAndroid Build Coastguard Worker << std::endl;
79*6777b538SAndroid Build Coastguard Worker std::cout << "Expected values of <index> are:" << std::endl;
80*6777b538SAndroid Build Coastguard Worker std::cout << " 0 (HTTP response headers)" << std::endl;
81*6777b538SAndroid Build Coastguard Worker std::cout << " 1 (transport encoded content)" << std::endl;
82*6777b538SAndroid Build Coastguard Worker std::cout << " 2 (compiled content)" << std::endl;
83*6777b538SAndroid Build Coastguard Worker }
84*6777b538SAndroid Build Coastguard Worker
85*6777b538SAndroid Build Coastguard Worker // Generic command input/output.
86*6777b538SAndroid Build Coastguard Worker class CommandMarshal {
87*6777b538SAndroid Build Coastguard Worker public:
CommandMarshal(Backend * cache_backend)88*6777b538SAndroid Build Coastguard Worker explicit CommandMarshal(Backend* cache_backend)
89*6777b538SAndroid Build Coastguard Worker : cache_backend_(cache_backend) {}
90*6777b538SAndroid Build Coastguard Worker virtual ~CommandMarshal() = default;
91*6777b538SAndroid Build Coastguard Worker
92*6777b538SAndroid Build Coastguard Worker // Reads the next command's name to execute.
93*6777b538SAndroid Build Coastguard Worker virtual std::string ReadCommandName() = 0;
94*6777b538SAndroid Build Coastguard Worker
95*6777b538SAndroid Build Coastguard Worker // Reads the next parameter as an integer.
96*6777b538SAndroid Build Coastguard Worker virtual int ReadInt() = 0;
97*6777b538SAndroid Build Coastguard Worker
98*6777b538SAndroid Build Coastguard Worker // Reads the next parameter as stream index.
ReadStreamIndex()99*6777b538SAndroid Build Coastguard Worker int ReadStreamIndex() {
100*6777b538SAndroid Build Coastguard Worker if (has_failed())
101*6777b538SAndroid Build Coastguard Worker return -1;
102*6777b538SAndroid Build Coastguard Worker int index = ReadInt();
103*6777b538SAndroid Build Coastguard Worker if (index < 0 || index > 2) {
104*6777b538SAndroid Build Coastguard Worker ReturnFailure("Invalid stream index.");
105*6777b538SAndroid Build Coastguard Worker return -1;
106*6777b538SAndroid Build Coastguard Worker }
107*6777b538SAndroid Build Coastguard Worker return index;
108*6777b538SAndroid Build Coastguard Worker }
109*6777b538SAndroid Build Coastguard Worker
110*6777b538SAndroid Build Coastguard Worker // Reads the next parameter as a string.
111*6777b538SAndroid Build Coastguard Worker virtual std::string ReadString() = 0;
112*6777b538SAndroid Build Coastguard Worker
113*6777b538SAndroid Build Coastguard Worker // Reads the next parameter from stdin as string.
114*6777b538SAndroid Build Coastguard Worker virtual std::string ReadBufferedString() = 0;
115*6777b538SAndroid Build Coastguard Worker
116*6777b538SAndroid Build Coastguard Worker // Communicates back an integer.
117*6777b538SAndroid Build Coastguard Worker virtual void ReturnInt(int integer) = 0;
118*6777b538SAndroid Build Coastguard Worker
119*6777b538SAndroid Build Coastguard Worker // Communicates back a 64-bit integer.
120*6777b538SAndroid Build Coastguard Worker virtual void ReturnInt64(int64_t integer) = 0;
121*6777b538SAndroid Build Coastguard Worker
122*6777b538SAndroid Build Coastguard Worker // Communicates back a string.
123*6777b538SAndroid Build Coastguard Worker virtual void ReturnString(const std::string& string) = 0;
124*6777b538SAndroid Build Coastguard Worker
125*6777b538SAndroid Build Coastguard Worker // Communicates back a buffer.
126*6777b538SAndroid Build Coastguard Worker virtual void ReturnBuffer(net::GrowableIOBuffer* buffer) = 0;
127*6777b538SAndroid Build Coastguard Worker
128*6777b538SAndroid Build Coastguard Worker // Communicates back command failure.
129*6777b538SAndroid Build Coastguard Worker virtual void ReturnFailure(const std::string& error_msg) = 0;
130*6777b538SAndroid Build Coastguard Worker
131*6777b538SAndroid Build Coastguard Worker // Communicates back command success.
ReturnSuccess()132*6777b538SAndroid Build Coastguard Worker virtual void ReturnSuccess() { DCHECK(!command_failed_); }
133*6777b538SAndroid Build Coastguard Worker
134*6777b538SAndroid Build Coastguard Worker // Returns whether the command has failed.
has_failed()135*6777b538SAndroid Build Coastguard Worker inline bool has_failed() { return command_failed_; }
136*6777b538SAndroid Build Coastguard Worker
137*6777b538SAndroid Build Coastguard Worker // Returns the opened cache backend.
cache_backend()138*6777b538SAndroid Build Coastguard Worker Backend* cache_backend() { return cache_backend_; }
139*6777b538SAndroid Build Coastguard Worker
140*6777b538SAndroid Build Coastguard Worker protected:
141*6777b538SAndroid Build Coastguard Worker bool command_failed_ = false;
142*6777b538SAndroid Build Coastguard Worker Backend* const cache_backend_;
143*6777b538SAndroid Build Coastguard Worker };
144*6777b538SAndroid Build Coastguard Worker
145*6777b538SAndroid Build Coastguard Worker // Command line input/output that is user readable.
146*6777b538SAndroid Build Coastguard Worker class ProgramArgumentCommandMarshal final : public CommandMarshal {
147*6777b538SAndroid Build Coastguard Worker public:
ProgramArgumentCommandMarshal(Backend * cache_backend,base::CommandLine::StringVector args)148*6777b538SAndroid Build Coastguard Worker ProgramArgumentCommandMarshal(Backend* cache_backend,
149*6777b538SAndroid Build Coastguard Worker base::CommandLine::StringVector args)
150*6777b538SAndroid Build Coastguard Worker : CommandMarshal(cache_backend), command_line_args_(args) {}
151*6777b538SAndroid Build Coastguard Worker
152*6777b538SAndroid Build Coastguard Worker // Implements CommandMarshal.
ReadCommandName()153*6777b538SAndroid Build Coastguard Worker std::string ReadCommandName() override {
154*6777b538SAndroid Build Coastguard Worker if (args_id_ == 0)
155*6777b538SAndroid Build Coastguard Worker return ReadString();
156*6777b538SAndroid Build Coastguard Worker else if (args_id_ == command_line_args_.size())
157*6777b538SAndroid Build Coastguard Worker return "stop";
158*6777b538SAndroid Build Coastguard Worker else if (!has_failed())
159*6777b538SAndroid Build Coastguard Worker ReturnFailure("Command line arguments too long.");
160*6777b538SAndroid Build Coastguard Worker return "";
161*6777b538SAndroid Build Coastguard Worker }
162*6777b538SAndroid Build Coastguard Worker
163*6777b538SAndroid Build Coastguard Worker // Implements CommandMarshal.
ReadInt()164*6777b538SAndroid Build Coastguard Worker int ReadInt() override {
165*6777b538SAndroid Build Coastguard Worker std::string integer_str = ReadString();
166*6777b538SAndroid Build Coastguard Worker int integer = -1;
167*6777b538SAndroid Build Coastguard Worker if (!base::StringToInt(integer_str, &integer)) {
168*6777b538SAndroid Build Coastguard Worker ReturnFailure("Couldn't parse integer.");
169*6777b538SAndroid Build Coastguard Worker return 0;
170*6777b538SAndroid Build Coastguard Worker }
171*6777b538SAndroid Build Coastguard Worker return integer;
172*6777b538SAndroid Build Coastguard Worker }
173*6777b538SAndroid Build Coastguard Worker
174*6777b538SAndroid Build Coastguard Worker // Implements CommandMarshal.
ReadString()175*6777b538SAndroid Build Coastguard Worker std::string ReadString() override {
176*6777b538SAndroid Build Coastguard Worker if (args_id_ < command_line_args_.size())
177*6777b538SAndroid Build Coastguard Worker return command_line_args_[args_id_++];
178*6777b538SAndroid Build Coastguard Worker if (!has_failed())
179*6777b538SAndroid Build Coastguard Worker ReturnFailure("Command line arguments too short.");
180*6777b538SAndroid Build Coastguard Worker return "";
181*6777b538SAndroid Build Coastguard Worker }
182*6777b538SAndroid Build Coastguard Worker
183*6777b538SAndroid Build Coastguard Worker // Implements CommandMarshal.
ReadBufferedString()184*6777b538SAndroid Build Coastguard Worker std::string ReadBufferedString() override {
185*6777b538SAndroid Build Coastguard Worker std::ostringstream raw_headers_stream;
186*6777b538SAndroid Build Coastguard Worker for (std::string line; std::getline(std::cin, line);)
187*6777b538SAndroid Build Coastguard Worker raw_headers_stream << line << std::endl;
188*6777b538SAndroid Build Coastguard Worker return raw_headers_stream.str();
189*6777b538SAndroid Build Coastguard Worker }
190*6777b538SAndroid Build Coastguard Worker
191*6777b538SAndroid Build Coastguard Worker // Implements CommandMarshal.
ReturnInt(int integer)192*6777b538SAndroid Build Coastguard Worker void ReturnInt(int integer) override {
193*6777b538SAndroid Build Coastguard Worker DCHECK(!has_failed());
194*6777b538SAndroid Build Coastguard Worker std::cout << integer << std::endl;
195*6777b538SAndroid Build Coastguard Worker }
196*6777b538SAndroid Build Coastguard Worker
197*6777b538SAndroid Build Coastguard Worker // Implements CommandMarshal.
ReturnInt64(int64_t integer)198*6777b538SAndroid Build Coastguard Worker void ReturnInt64(int64_t integer) override {
199*6777b538SAndroid Build Coastguard Worker DCHECK(!has_failed());
200*6777b538SAndroid Build Coastguard Worker std::cout << integer << std::endl;
201*6777b538SAndroid Build Coastguard Worker }
202*6777b538SAndroid Build Coastguard Worker
203*6777b538SAndroid Build Coastguard Worker // Implements CommandMarshal.
ReturnString(const std::string & string)204*6777b538SAndroid Build Coastguard Worker void ReturnString(const std::string& string) override {
205*6777b538SAndroid Build Coastguard Worker DCHECK(!has_failed());
206*6777b538SAndroid Build Coastguard Worker std::cout << string << std::endl;
207*6777b538SAndroid Build Coastguard Worker }
208*6777b538SAndroid Build Coastguard Worker
209*6777b538SAndroid Build Coastguard Worker // Implements CommandMarshal.
ReturnBuffer(net::GrowableIOBuffer * buffer)210*6777b538SAndroid Build Coastguard Worker void ReturnBuffer(net::GrowableIOBuffer* buffer) override {
211*6777b538SAndroid Build Coastguard Worker DCHECK(!has_failed());
212*6777b538SAndroid Build Coastguard Worker std::cout.write(buffer->StartOfBuffer(), buffer->offset());
213*6777b538SAndroid Build Coastguard Worker }
214*6777b538SAndroid Build Coastguard Worker
215*6777b538SAndroid Build Coastguard Worker // Implements CommandMarshal.
ReturnFailure(const std::string & error_msg)216*6777b538SAndroid Build Coastguard Worker void ReturnFailure(const std::string& error_msg) override {
217*6777b538SAndroid Build Coastguard Worker DCHECK(!has_failed());
218*6777b538SAndroid Build Coastguard Worker std::cerr << error_msg << std::endl;
219*6777b538SAndroid Build Coastguard Worker command_failed_ = true;
220*6777b538SAndroid Build Coastguard Worker }
221*6777b538SAndroid Build Coastguard Worker
222*6777b538SAndroid Build Coastguard Worker private:
223*6777b538SAndroid Build Coastguard Worker const base::CommandLine::StringVector command_line_args_;
224*6777b538SAndroid Build Coastguard Worker size_t args_id_ = 0;
225*6777b538SAndroid Build Coastguard Worker };
226*6777b538SAndroid Build Coastguard Worker
227*6777b538SAndroid Build Coastguard Worker // Online command input/output that receives pickled commands from stdin and
228*6777b538SAndroid Build Coastguard Worker // returns their results back in stdout. Send the stop command to properly exit
229*6777b538SAndroid Build Coastguard Worker // cachetool's main loop.
230*6777b538SAndroid Build Coastguard Worker class StreamCommandMarshal final : public CommandMarshal {
231*6777b538SAndroid Build Coastguard Worker public:
StreamCommandMarshal(Backend * cache_backend)232*6777b538SAndroid Build Coastguard Worker explicit StreamCommandMarshal(Backend* cache_backend)
233*6777b538SAndroid Build Coastguard Worker : CommandMarshal(cache_backend) {}
234*6777b538SAndroid Build Coastguard Worker
235*6777b538SAndroid Build Coastguard Worker // Implements CommandMarshal.
ReadCommandName()236*6777b538SAndroid Build Coastguard Worker std::string ReadCommandName() override {
237*6777b538SAndroid Build Coastguard Worker if (has_failed())
238*6777b538SAndroid Build Coastguard Worker return "";
239*6777b538SAndroid Build Coastguard Worker std::cout.flush();
240*6777b538SAndroid Build Coastguard Worker size_t command_id = static_cast<size_t>(std::cin.get());
241*6777b538SAndroid Build Coastguard Worker if (command_id >= std::size(kCommandNames)) {
242*6777b538SAndroid Build Coastguard Worker ReturnFailure("Unknown command.");
243*6777b538SAndroid Build Coastguard Worker return "";
244*6777b538SAndroid Build Coastguard Worker }
245*6777b538SAndroid Build Coastguard Worker return kCommandNames[command_id];
246*6777b538SAndroid Build Coastguard Worker }
247*6777b538SAndroid Build Coastguard Worker
248*6777b538SAndroid Build Coastguard Worker // Implements CommandMarshal.
ReadInt()249*6777b538SAndroid Build Coastguard Worker int ReadInt() override {
250*6777b538SAndroid Build Coastguard Worker if (has_failed())
251*6777b538SAndroid Build Coastguard Worker return -1;
252*6777b538SAndroid Build Coastguard Worker int integer = -1;
253*6777b538SAndroid Build Coastguard Worker std::cin.read(reinterpret_cast<char*>(&integer), sizeof(integer));
254*6777b538SAndroid Build Coastguard Worker return integer;
255*6777b538SAndroid Build Coastguard Worker }
256*6777b538SAndroid Build Coastguard Worker
257*6777b538SAndroid Build Coastguard Worker // Implements CommandMarshal.
ReadString()258*6777b538SAndroid Build Coastguard Worker std::string ReadString() override {
259*6777b538SAndroid Build Coastguard Worker if (has_failed())
260*6777b538SAndroid Build Coastguard Worker return "";
261*6777b538SAndroid Build Coastguard Worker int string_size = ReadInt();
262*6777b538SAndroid Build Coastguard Worker if (string_size <= 0) {
263*6777b538SAndroid Build Coastguard Worker if (string_size < 0)
264*6777b538SAndroid Build Coastguard Worker ReturnFailure("Size of string is negative.");
265*6777b538SAndroid Build Coastguard Worker return "";
266*6777b538SAndroid Build Coastguard Worker }
267*6777b538SAndroid Build Coastguard Worker std::vector<char> tmp_buffer(string_size + 1);
268*6777b538SAndroid Build Coastguard Worker std::cin.read(tmp_buffer.data(), string_size);
269*6777b538SAndroid Build Coastguard Worker tmp_buffer[string_size] = 0;
270*6777b538SAndroid Build Coastguard Worker return std::string(tmp_buffer.data(), string_size);
271*6777b538SAndroid Build Coastguard Worker }
272*6777b538SAndroid Build Coastguard Worker
273*6777b538SAndroid Build Coastguard Worker // Implements CommandMarshal.
ReadBufferedString()274*6777b538SAndroid Build Coastguard Worker std::string ReadBufferedString() override { return ReadString(); }
275*6777b538SAndroid Build Coastguard Worker
276*6777b538SAndroid Build Coastguard Worker // Implements CommandMarshal.
ReturnInt(int integer)277*6777b538SAndroid Build Coastguard Worker void ReturnInt(int integer) override {
278*6777b538SAndroid Build Coastguard Worker DCHECK(!command_failed_);
279*6777b538SAndroid Build Coastguard Worker std::cout.write(reinterpret_cast<char*>(&integer), sizeof(integer));
280*6777b538SAndroid Build Coastguard Worker }
281*6777b538SAndroid Build Coastguard Worker
282*6777b538SAndroid Build Coastguard Worker // Implements CommandMarshal.
ReturnInt64(int64_t integer)283*6777b538SAndroid Build Coastguard Worker void ReturnInt64(int64_t integer) override {
284*6777b538SAndroid Build Coastguard Worker DCHECK(!has_failed());
285*6777b538SAndroid Build Coastguard Worker std::cout.write(reinterpret_cast<char*>(&integer), sizeof(integer));
286*6777b538SAndroid Build Coastguard Worker }
287*6777b538SAndroid Build Coastguard Worker
288*6777b538SAndroid Build Coastguard Worker // Implements CommandMarshal.
ReturnString(const std::string & string)289*6777b538SAndroid Build Coastguard Worker void ReturnString(const std::string& string) override {
290*6777b538SAndroid Build Coastguard Worker ReturnInt(string.size());
291*6777b538SAndroid Build Coastguard Worker std::cout.write(string.c_str(), string.size());
292*6777b538SAndroid Build Coastguard Worker }
293*6777b538SAndroid Build Coastguard Worker
294*6777b538SAndroid Build Coastguard Worker // Implements CommandMarshal.
ReturnBuffer(net::GrowableIOBuffer * buffer)295*6777b538SAndroid Build Coastguard Worker void ReturnBuffer(net::GrowableIOBuffer* buffer) override {
296*6777b538SAndroid Build Coastguard Worker ReturnInt(buffer->offset());
297*6777b538SAndroid Build Coastguard Worker std::cout.write(buffer->StartOfBuffer(), buffer->offset());
298*6777b538SAndroid Build Coastguard Worker }
299*6777b538SAndroid Build Coastguard Worker
300*6777b538SAndroid Build Coastguard Worker // Implements CommandMarshal.
ReturnFailure(const std::string & error_msg)301*6777b538SAndroid Build Coastguard Worker void ReturnFailure(const std::string& error_msg) override {
302*6777b538SAndroid Build Coastguard Worker ReturnString(error_msg);
303*6777b538SAndroid Build Coastguard Worker command_failed_ = true;
304*6777b538SAndroid Build Coastguard Worker }
305*6777b538SAndroid Build Coastguard Worker
306*6777b538SAndroid Build Coastguard Worker // Implements CommandMarshal.
ReturnSuccess()307*6777b538SAndroid Build Coastguard Worker void ReturnSuccess() override { ReturnInt(0); }
308*6777b538SAndroid Build Coastguard Worker };
309*6777b538SAndroid Build Coastguard Worker
310*6777b538SAndroid Build Coastguard Worker // Gets the cache's size.
GetSize(CommandMarshal * command_marshal)311*6777b538SAndroid Build Coastguard Worker void GetSize(CommandMarshal* command_marshal) {
312*6777b538SAndroid Build Coastguard Worker net::TestInt64CompletionCallback cb;
313*6777b538SAndroid Build Coastguard Worker int64_t rv = command_marshal->cache_backend()->CalculateSizeOfAllEntries(
314*6777b538SAndroid Build Coastguard Worker cb.callback());
315*6777b538SAndroid Build Coastguard Worker rv = cb.GetResult(rv);
316*6777b538SAndroid Build Coastguard Worker if (rv < 0)
317*6777b538SAndroid Build Coastguard Worker return command_marshal->ReturnFailure("Couldn't get cache size.");
318*6777b538SAndroid Build Coastguard Worker command_marshal->ReturnSuccess();
319*6777b538SAndroid Build Coastguard Worker command_marshal->ReturnInt64(rv);
320*6777b538SAndroid Build Coastguard Worker }
321*6777b538SAndroid Build Coastguard Worker
322*6777b538SAndroid Build Coastguard Worker // Prints all of a cache's keys to stdout.
ListKeys(CommandMarshal * command_marshal)323*6777b538SAndroid Build Coastguard Worker bool ListKeys(CommandMarshal* command_marshal) {
324*6777b538SAndroid Build Coastguard Worker std::unique_ptr<Backend::Iterator> entry_iterator =
325*6777b538SAndroid Build Coastguard Worker command_marshal->cache_backend()->CreateIterator();
326*6777b538SAndroid Build Coastguard Worker TestEntryResultCompletionCallback cb;
327*6777b538SAndroid Build Coastguard Worker EntryResult result = entry_iterator->OpenNextEntry(cb.callback());
328*6777b538SAndroid Build Coastguard Worker command_marshal->ReturnSuccess();
329*6777b538SAndroid Build Coastguard Worker while ((result = cb.GetResult(std::move(result))).net_error() == net::OK) {
330*6777b538SAndroid Build Coastguard Worker Entry* entry = result.ReleaseEntry();
331*6777b538SAndroid Build Coastguard Worker std::string url = entry->GetKey();
332*6777b538SAndroid Build Coastguard Worker command_marshal->ReturnString(url);
333*6777b538SAndroid Build Coastguard Worker entry->Close();
334*6777b538SAndroid Build Coastguard Worker result = entry_iterator->OpenNextEntry(cb.callback());
335*6777b538SAndroid Build Coastguard Worker }
336*6777b538SAndroid Build Coastguard Worker command_marshal->ReturnString("");
337*6777b538SAndroid Build Coastguard Worker return true;
338*6777b538SAndroid Build Coastguard Worker }
339*6777b538SAndroid Build Coastguard Worker
GetResponseInfoForEntry(disk_cache::Entry * entry,net::HttpResponseInfo * response_info)340*6777b538SAndroid Build Coastguard Worker bool GetResponseInfoForEntry(disk_cache::Entry* entry,
341*6777b538SAndroid Build Coastguard Worker net::HttpResponseInfo* response_info) {
342*6777b538SAndroid Build Coastguard Worker int size = entry->GetDataSize(kResponseInfoIndex);
343*6777b538SAndroid Build Coastguard Worker if (size == 0)
344*6777b538SAndroid Build Coastguard Worker return false;
345*6777b538SAndroid Build Coastguard Worker scoped_refptr<net::IOBuffer> buffer =
346*6777b538SAndroid Build Coastguard Worker base::MakeRefCounted<net::IOBufferWithSize>(size);
347*6777b538SAndroid Build Coastguard Worker net::TestCompletionCallback cb;
348*6777b538SAndroid Build Coastguard Worker
349*6777b538SAndroid Build Coastguard Worker int bytes_read = 0;
350*6777b538SAndroid Build Coastguard Worker while (true) {
351*6777b538SAndroid Build Coastguard Worker int rv = entry->ReadData(kResponseInfoIndex, bytes_read, buffer.get(), size,
352*6777b538SAndroid Build Coastguard Worker cb.callback());
353*6777b538SAndroid Build Coastguard Worker rv = cb.GetResult(rv);
354*6777b538SAndroid Build Coastguard Worker if (rv < 0) {
355*6777b538SAndroid Build Coastguard Worker entry->Close();
356*6777b538SAndroid Build Coastguard Worker return false;
357*6777b538SAndroid Build Coastguard Worker }
358*6777b538SAndroid Build Coastguard Worker
359*6777b538SAndroid Build Coastguard Worker if (rv == 0) {
360*6777b538SAndroid Build Coastguard Worker bool truncated_response_info = false;
361*6777b538SAndroid Build Coastguard Worker if (!net::HttpCache::ParseResponseInfo(
362*6777b538SAndroid Build Coastguard Worker buffer->data(), size, response_info, &truncated_response_info)) {
363*6777b538SAndroid Build Coastguard Worker return false;
364*6777b538SAndroid Build Coastguard Worker }
365*6777b538SAndroid Build Coastguard Worker return !truncated_response_info;
366*6777b538SAndroid Build Coastguard Worker }
367*6777b538SAndroid Build Coastguard Worker
368*6777b538SAndroid Build Coastguard Worker bytes_read += rv;
369*6777b538SAndroid Build Coastguard Worker }
370*6777b538SAndroid Build Coastguard Worker
371*6777b538SAndroid Build Coastguard Worker NOTREACHED();
372*6777b538SAndroid Build Coastguard Worker return false;
373*6777b538SAndroid Build Coastguard Worker }
374*6777b538SAndroid Build Coastguard Worker
GetMD5ForResponseBody(disk_cache::Entry * entry)375*6777b538SAndroid Build Coastguard Worker std::string GetMD5ForResponseBody(disk_cache::Entry* entry) {
376*6777b538SAndroid Build Coastguard Worker if (entry->GetDataSize(kResponseContentIndex) == 0)
377*6777b538SAndroid Build Coastguard Worker return "";
378*6777b538SAndroid Build Coastguard Worker
379*6777b538SAndroid Build Coastguard Worker const int kInitBufferSize = 80 * 1024;
380*6777b538SAndroid Build Coastguard Worker scoped_refptr<net::IOBuffer> buffer =
381*6777b538SAndroid Build Coastguard Worker base::MakeRefCounted<net::IOBufferWithSize>(kInitBufferSize);
382*6777b538SAndroid Build Coastguard Worker net::TestCompletionCallback cb;
383*6777b538SAndroid Build Coastguard Worker
384*6777b538SAndroid Build Coastguard Worker base::MD5Context ctx;
385*6777b538SAndroid Build Coastguard Worker base::MD5Init(&ctx);
386*6777b538SAndroid Build Coastguard Worker
387*6777b538SAndroid Build Coastguard Worker int bytes_read = 0;
388*6777b538SAndroid Build Coastguard Worker while (true) {
389*6777b538SAndroid Build Coastguard Worker int rv = entry->ReadData(kResponseContentIndex, bytes_read, buffer.get(),
390*6777b538SAndroid Build Coastguard Worker kInitBufferSize, cb.callback());
391*6777b538SAndroid Build Coastguard Worker rv = cb.GetResult(rv);
392*6777b538SAndroid Build Coastguard Worker if (rv < 0) {
393*6777b538SAndroid Build Coastguard Worker entry->Close();
394*6777b538SAndroid Build Coastguard Worker return "";
395*6777b538SAndroid Build Coastguard Worker }
396*6777b538SAndroid Build Coastguard Worker
397*6777b538SAndroid Build Coastguard Worker if (rv == 0) {
398*6777b538SAndroid Build Coastguard Worker base::MD5Digest digest;
399*6777b538SAndroid Build Coastguard Worker base::MD5Final(&digest, &ctx);
400*6777b538SAndroid Build Coastguard Worker return base::MD5DigestToBase16(digest);
401*6777b538SAndroid Build Coastguard Worker }
402*6777b538SAndroid Build Coastguard Worker
403*6777b538SAndroid Build Coastguard Worker bytes_read += rv;
404*6777b538SAndroid Build Coastguard Worker base::MD5Update(&ctx, std::string_view(buffer->data(), rv));
405*6777b538SAndroid Build Coastguard Worker }
406*6777b538SAndroid Build Coastguard Worker
407*6777b538SAndroid Build Coastguard Worker NOTREACHED();
408*6777b538SAndroid Build Coastguard Worker return "";
409*6777b538SAndroid Build Coastguard Worker }
410*6777b538SAndroid Build Coastguard Worker
PersistResponseInfo(CommandMarshal * command_marshal,const std::string & key,const net::HttpResponseInfo & response_info)411*6777b538SAndroid Build Coastguard Worker void PersistResponseInfo(CommandMarshal* command_marshal,
412*6777b538SAndroid Build Coastguard Worker const std::string& key,
413*6777b538SAndroid Build Coastguard Worker const net::HttpResponseInfo& response_info) {
414*6777b538SAndroid Build Coastguard Worker scoped_refptr<net::PickledIOBuffer> data =
415*6777b538SAndroid Build Coastguard Worker base::MakeRefCounted<net::PickledIOBuffer>();
416*6777b538SAndroid Build Coastguard Worker response_info.Persist(data->pickle(), false, false);
417*6777b538SAndroid Build Coastguard Worker data->Done();
418*6777b538SAndroid Build Coastguard Worker
419*6777b538SAndroid Build Coastguard Worker TestEntryResultCompletionCallback cb_open;
420*6777b538SAndroid Build Coastguard Worker EntryResult result = command_marshal->cache_backend()->OpenEntry(
421*6777b538SAndroid Build Coastguard Worker key, net::HIGHEST, cb_open.callback());
422*6777b538SAndroid Build Coastguard Worker result = cb_open.GetResult(std::move(result));
423*6777b538SAndroid Build Coastguard Worker CHECK_EQ(result.net_error(), net::OK);
424*6777b538SAndroid Build Coastguard Worker Entry* cache_entry = result.ReleaseEntry();
425*6777b538SAndroid Build Coastguard Worker
426*6777b538SAndroid Build Coastguard Worker int data_len = data->pickle()->size();
427*6777b538SAndroid Build Coastguard Worker net::TestCompletionCallback cb;
428*6777b538SAndroid Build Coastguard Worker int rv = cache_entry->WriteData(kResponseInfoIndex, 0, data.get(), data_len,
429*6777b538SAndroid Build Coastguard Worker cb.callback(), true);
430*6777b538SAndroid Build Coastguard Worker if (cb.GetResult(rv) != data_len)
431*6777b538SAndroid Build Coastguard Worker return command_marshal->ReturnFailure("Couldn't write headers.");
432*6777b538SAndroid Build Coastguard Worker command_marshal->ReturnSuccess();
433*6777b538SAndroid Build Coastguard Worker cache_entry->Close();
434*6777b538SAndroid Build Coastguard Worker }
435*6777b538SAndroid Build Coastguard Worker
ListDups(CommandMarshal * command_marshal)436*6777b538SAndroid Build Coastguard Worker void ListDups(CommandMarshal* command_marshal) {
437*6777b538SAndroid Build Coastguard Worker std::unique_ptr<Backend::Iterator> entry_iterator =
438*6777b538SAndroid Build Coastguard Worker command_marshal->cache_backend()->CreateIterator();
439*6777b538SAndroid Build Coastguard Worker TestEntryResultCompletionCallback cb;
440*6777b538SAndroid Build Coastguard Worker disk_cache::EntryResult result = entry_iterator->OpenNextEntry(cb.callback());
441*6777b538SAndroid Build Coastguard Worker command_marshal->ReturnSuccess();
442*6777b538SAndroid Build Coastguard Worker
443*6777b538SAndroid Build Coastguard Worker std::unordered_map<std::string, std::vector<EntryData>> md5_entries;
444*6777b538SAndroid Build Coastguard Worker
445*6777b538SAndroid Build Coastguard Worker int total_entries = 0;
446*6777b538SAndroid Build Coastguard Worker
447*6777b538SAndroid Build Coastguard Worker while ((result = cb.GetResult(std::move(result))).net_error() == net::OK) {
448*6777b538SAndroid Build Coastguard Worker Entry* entry = result.ReleaseEntry();
449*6777b538SAndroid Build Coastguard Worker total_entries += 1;
450*6777b538SAndroid Build Coastguard Worker net::HttpResponseInfo response_info;
451*6777b538SAndroid Build Coastguard Worker if (!GetResponseInfoForEntry(entry, &response_info)) {
452*6777b538SAndroid Build Coastguard Worker entry->Close();
453*6777b538SAndroid Build Coastguard Worker entry = nullptr;
454*6777b538SAndroid Build Coastguard Worker result = entry_iterator->OpenNextEntry(cb.callback());
455*6777b538SAndroid Build Coastguard Worker continue;
456*6777b538SAndroid Build Coastguard Worker }
457*6777b538SAndroid Build Coastguard Worker
458*6777b538SAndroid Build Coastguard Worker std::string hash = GetMD5ForResponseBody(entry);
459*6777b538SAndroid Build Coastguard Worker if (hash.empty()) {
460*6777b538SAndroid Build Coastguard Worker // Sparse entries and empty bodies are skipped.
461*6777b538SAndroid Build Coastguard Worker entry->Close();
462*6777b538SAndroid Build Coastguard Worker entry = nullptr;
463*6777b538SAndroid Build Coastguard Worker result = entry_iterator->OpenNextEntry(cb.callback());
464*6777b538SAndroid Build Coastguard Worker continue;
465*6777b538SAndroid Build Coastguard Worker }
466*6777b538SAndroid Build Coastguard Worker
467*6777b538SAndroid Build Coastguard Worker EntryData entry_data;
468*6777b538SAndroid Build Coastguard Worker
469*6777b538SAndroid Build Coastguard Worker entry_data.url = entry->GetKey();
470*6777b538SAndroid Build Coastguard Worker entry_data.size = entry->GetDataSize(kResponseContentIndex);
471*6777b538SAndroid Build Coastguard Worker if (response_info.headers)
472*6777b538SAndroid Build Coastguard Worker response_info.headers->GetMimeType(&entry_data.mime_type);
473*6777b538SAndroid Build Coastguard Worker
474*6777b538SAndroid Build Coastguard Worker auto iter = md5_entries.find(hash);
475*6777b538SAndroid Build Coastguard Worker if (iter == md5_entries.end()) {
476*6777b538SAndroid Build Coastguard Worker md5_entries.emplace(hash, std::vector<EntryData>{entry_data});
477*6777b538SAndroid Build Coastguard Worker } else {
478*6777b538SAndroid Build Coastguard Worker iter->second.push_back(entry_data);
479*6777b538SAndroid Build Coastguard Worker }
480*6777b538SAndroid Build Coastguard Worker
481*6777b538SAndroid Build Coastguard Worker entry->Close();
482*6777b538SAndroid Build Coastguard Worker entry = nullptr;
483*6777b538SAndroid Build Coastguard Worker result = entry_iterator->OpenNextEntry(cb.callback());
484*6777b538SAndroid Build Coastguard Worker }
485*6777b538SAndroid Build Coastguard Worker
486*6777b538SAndroid Build Coastguard Worker // Print the duplicates and collect stats.
487*6777b538SAndroid Build Coastguard Worker int total_duped_entries = 0;
488*6777b538SAndroid Build Coastguard Worker int64_t total_duped_bytes = 0u;
489*6777b538SAndroid Build Coastguard Worker for (const auto& hash_and_entries : md5_entries) {
490*6777b538SAndroid Build Coastguard Worker if (hash_and_entries.second.size() == 1)
491*6777b538SAndroid Build Coastguard Worker continue;
492*6777b538SAndroid Build Coastguard Worker
493*6777b538SAndroid Build Coastguard Worker int dups = hash_and_entries.second.size() - 1;
494*6777b538SAndroid Build Coastguard Worker total_duped_entries += dups;
495*6777b538SAndroid Build Coastguard Worker total_duped_bytes += hash_and_entries.second[0].size * dups;
496*6777b538SAndroid Build Coastguard Worker
497*6777b538SAndroid Build Coastguard Worker for (const auto& entry : hash_and_entries.second) {
498*6777b538SAndroid Build Coastguard Worker std::string out = base::StringPrintf(
499*6777b538SAndroid Build Coastguard Worker "%d, %s, %s", entry.size, entry.url.c_str(), entry.mime_type.c_str());
500*6777b538SAndroid Build Coastguard Worker command_marshal->ReturnString(out);
501*6777b538SAndroid Build Coastguard Worker }
502*6777b538SAndroid Build Coastguard Worker }
503*6777b538SAndroid Build Coastguard Worker
504*6777b538SAndroid Build Coastguard Worker // Print the stats.
505*6777b538SAndroid Build Coastguard Worker net::TestInt64CompletionCallback size_cb;
506*6777b538SAndroid Build Coastguard Worker int64_t rv = command_marshal->cache_backend()->CalculateSizeOfAllEntries(
507*6777b538SAndroid Build Coastguard Worker size_cb.callback());
508*6777b538SAndroid Build Coastguard Worker rv = size_cb.GetResult(rv);
509*6777b538SAndroid Build Coastguard Worker LOG(ERROR) << "Wasted bytes = " << total_duped_bytes;
510*6777b538SAndroid Build Coastguard Worker LOG(ERROR) << "Wasted entries = " << total_duped_entries;
511*6777b538SAndroid Build Coastguard Worker LOG(ERROR) << "Total entries = " << total_entries;
512*6777b538SAndroid Build Coastguard Worker LOG(ERROR) << "Cache size = " << rv;
513*6777b538SAndroid Build Coastguard Worker LOG(ERROR) << "Percentage of cache wasted = " << total_duped_bytes * 100 / rv;
514*6777b538SAndroid Build Coastguard Worker }
515*6777b538SAndroid Build Coastguard Worker
516*6777b538SAndroid Build Coastguard Worker // Gets a key's stream to a buffer.
GetStreamForKeyBuffer(CommandMarshal * command_marshal,const std::string & key,int index)517*6777b538SAndroid Build Coastguard Worker scoped_refptr<net::GrowableIOBuffer> GetStreamForKeyBuffer(
518*6777b538SAndroid Build Coastguard Worker CommandMarshal* command_marshal,
519*6777b538SAndroid Build Coastguard Worker const std::string& key,
520*6777b538SAndroid Build Coastguard Worker int index) {
521*6777b538SAndroid Build Coastguard Worker DCHECK(!command_marshal->has_failed());
522*6777b538SAndroid Build Coastguard Worker
523*6777b538SAndroid Build Coastguard Worker TestEntryResultCompletionCallback cb_open;
524*6777b538SAndroid Build Coastguard Worker EntryResult result = command_marshal->cache_backend()->OpenEntry(
525*6777b538SAndroid Build Coastguard Worker key, net::HIGHEST, cb_open.callback());
526*6777b538SAndroid Build Coastguard Worker result = cb_open.GetResult(std::move(result));
527*6777b538SAndroid Build Coastguard Worker if (result.net_error() != net::OK) {
528*6777b538SAndroid Build Coastguard Worker command_marshal->ReturnFailure("Couldn't find key's entry.");
529*6777b538SAndroid Build Coastguard Worker return nullptr;
530*6777b538SAndroid Build Coastguard Worker }
531*6777b538SAndroid Build Coastguard Worker Entry* cache_entry = result.ReleaseEntry();
532*6777b538SAndroid Build Coastguard Worker
533*6777b538SAndroid Build Coastguard Worker const int kInitBufferSize = 8192;
534*6777b538SAndroid Build Coastguard Worker scoped_refptr<net::GrowableIOBuffer> buffer =
535*6777b538SAndroid Build Coastguard Worker base::MakeRefCounted<net::GrowableIOBuffer>();
536*6777b538SAndroid Build Coastguard Worker buffer->SetCapacity(kInitBufferSize);
537*6777b538SAndroid Build Coastguard Worker net::TestCompletionCallback cb;
538*6777b538SAndroid Build Coastguard Worker while (true) {
539*6777b538SAndroid Build Coastguard Worker int rv = cache_entry->ReadData(index, buffer->offset(), buffer.get(),
540*6777b538SAndroid Build Coastguard Worker buffer->capacity() - buffer->offset(),
541*6777b538SAndroid Build Coastguard Worker cb.callback());
542*6777b538SAndroid Build Coastguard Worker rv = cb.GetResult(rv);
543*6777b538SAndroid Build Coastguard Worker if (rv < 0) {
544*6777b538SAndroid Build Coastguard Worker cache_entry->Close();
545*6777b538SAndroid Build Coastguard Worker command_marshal->ReturnFailure("Stream read error.");
546*6777b538SAndroid Build Coastguard Worker return nullptr;
547*6777b538SAndroid Build Coastguard Worker }
548*6777b538SAndroid Build Coastguard Worker buffer->set_offset(buffer->offset() + rv);
549*6777b538SAndroid Build Coastguard Worker if (rv == 0)
550*6777b538SAndroid Build Coastguard Worker break;
551*6777b538SAndroid Build Coastguard Worker buffer->SetCapacity(buffer->offset() * 2);
552*6777b538SAndroid Build Coastguard Worker }
553*6777b538SAndroid Build Coastguard Worker cache_entry->Close();
554*6777b538SAndroid Build Coastguard Worker return buffer;
555*6777b538SAndroid Build Coastguard Worker }
556*6777b538SAndroid Build Coastguard Worker
557*6777b538SAndroid Build Coastguard Worker // Prints a key's stream to stdout.
GetStreamForKey(CommandMarshal * command_marshal)558*6777b538SAndroid Build Coastguard Worker void GetStreamForKey(CommandMarshal* command_marshal) {
559*6777b538SAndroid Build Coastguard Worker std::string key = command_marshal->ReadString();
560*6777b538SAndroid Build Coastguard Worker int index = command_marshal->ReadInt();
561*6777b538SAndroid Build Coastguard Worker if (command_marshal->has_failed())
562*6777b538SAndroid Build Coastguard Worker return;
563*6777b538SAndroid Build Coastguard Worker scoped_refptr<net::GrowableIOBuffer> buffer(
564*6777b538SAndroid Build Coastguard Worker GetStreamForKeyBuffer(command_marshal, key, index));
565*6777b538SAndroid Build Coastguard Worker if (command_marshal->has_failed())
566*6777b538SAndroid Build Coastguard Worker return;
567*6777b538SAndroid Build Coastguard Worker if (index == kResponseInfoIndex) {
568*6777b538SAndroid Build Coastguard Worker net::HttpResponseInfo response_info;
569*6777b538SAndroid Build Coastguard Worker bool truncated_response_info = false;
570*6777b538SAndroid Build Coastguard Worker if (!net::HttpCache::ParseResponseInfo(buffer->StartOfBuffer(),
571*6777b538SAndroid Build Coastguard Worker buffer->offset(), &response_info,
572*6777b538SAndroid Build Coastguard Worker &truncated_response_info)) {
573*6777b538SAndroid Build Coastguard Worker // This can happen when reading data stored by content::CacheStorage.
574*6777b538SAndroid Build Coastguard Worker std::cerr << "WARNING: Returning empty response info for key: " << key
575*6777b538SAndroid Build Coastguard Worker << std::endl;
576*6777b538SAndroid Build Coastguard Worker command_marshal->ReturnSuccess();
577*6777b538SAndroid Build Coastguard Worker return command_marshal->ReturnString("");
578*6777b538SAndroid Build Coastguard Worker }
579*6777b538SAndroid Build Coastguard Worker if (truncated_response_info)
580*6777b538SAndroid Build Coastguard Worker std::cerr << "WARNING: Truncated HTTP response." << std::endl;
581*6777b538SAndroid Build Coastguard Worker command_marshal->ReturnSuccess();
582*6777b538SAndroid Build Coastguard Worker command_marshal->ReturnString(
583*6777b538SAndroid Build Coastguard Worker net::HttpUtil::ConvertHeadersBackToHTTPResponse(
584*6777b538SAndroid Build Coastguard Worker response_info.headers->raw_headers()));
585*6777b538SAndroid Build Coastguard Worker } else {
586*6777b538SAndroid Build Coastguard Worker command_marshal->ReturnSuccess();
587*6777b538SAndroid Build Coastguard Worker command_marshal->ReturnBuffer(buffer.get());
588*6777b538SAndroid Build Coastguard Worker }
589*6777b538SAndroid Build Coastguard Worker }
590*6777b538SAndroid Build Coastguard Worker
591*6777b538SAndroid Build Coastguard Worker // Sets stdin as the key's raw response headers.
UpdateRawResponseHeaders(CommandMarshal * command_marshal)592*6777b538SAndroid Build Coastguard Worker void UpdateRawResponseHeaders(CommandMarshal* command_marshal) {
593*6777b538SAndroid Build Coastguard Worker std::string key = command_marshal->ReadString();
594*6777b538SAndroid Build Coastguard Worker std::string raw_headers = command_marshal->ReadBufferedString();
595*6777b538SAndroid Build Coastguard Worker if (command_marshal->has_failed())
596*6777b538SAndroid Build Coastguard Worker return;
597*6777b538SAndroid Build Coastguard Worker scoped_refptr<net::GrowableIOBuffer> buffer(
598*6777b538SAndroid Build Coastguard Worker GetStreamForKeyBuffer(command_marshal, key, kResponseInfoIndex));
599*6777b538SAndroid Build Coastguard Worker if (command_marshal->has_failed())
600*6777b538SAndroid Build Coastguard Worker return;
601*6777b538SAndroid Build Coastguard Worker net::HttpResponseInfo response_info;
602*6777b538SAndroid Build Coastguard Worker bool truncated_response_info = false;
603*6777b538SAndroid Build Coastguard Worker net::HttpCache::ParseResponseInfo(buffer->StartOfBuffer(), buffer->offset(),
604*6777b538SAndroid Build Coastguard Worker &response_info, &truncated_response_info);
605*6777b538SAndroid Build Coastguard Worker if (truncated_response_info)
606*6777b538SAndroid Build Coastguard Worker std::cerr << "WARNING: Truncated HTTP response." << std::endl;
607*6777b538SAndroid Build Coastguard Worker
608*6777b538SAndroid Build Coastguard Worker response_info.headers =
609*6777b538SAndroid Build Coastguard Worker base::MakeRefCounted<net::HttpResponseHeaders>(raw_headers);
610*6777b538SAndroid Build Coastguard Worker PersistResponseInfo(command_marshal, key, response_info);
611*6777b538SAndroid Build Coastguard Worker }
612*6777b538SAndroid Build Coastguard Worker
613*6777b538SAndroid Build Coastguard Worker // Sets a response header for a key.
SetHeader(CommandMarshal * command_marshal)614*6777b538SAndroid Build Coastguard Worker void SetHeader(CommandMarshal* command_marshal) {
615*6777b538SAndroid Build Coastguard Worker std::string key = command_marshal->ReadString();
616*6777b538SAndroid Build Coastguard Worker std::string header_name = command_marshal->ReadString();
617*6777b538SAndroid Build Coastguard Worker std::string header_value = command_marshal->ReadString();
618*6777b538SAndroid Build Coastguard Worker if (command_marshal->has_failed())
619*6777b538SAndroid Build Coastguard Worker return;
620*6777b538SAndroid Build Coastguard Worker
621*6777b538SAndroid Build Coastguard Worker // Open the existing entry.
622*6777b538SAndroid Build Coastguard Worker scoped_refptr<net::GrowableIOBuffer> buffer(
623*6777b538SAndroid Build Coastguard Worker GetStreamForKeyBuffer(command_marshal, key, kResponseInfoIndex));
624*6777b538SAndroid Build Coastguard Worker if (command_marshal->has_failed())
625*6777b538SAndroid Build Coastguard Worker return;
626*6777b538SAndroid Build Coastguard Worker
627*6777b538SAndroid Build Coastguard Worker // Read the entry into |response_info|.
628*6777b538SAndroid Build Coastguard Worker net::HttpResponseInfo response_info;
629*6777b538SAndroid Build Coastguard Worker bool truncated_response_info = false;
630*6777b538SAndroid Build Coastguard Worker if (!net::HttpCache::ParseResponseInfo(buffer->StartOfBuffer(),
631*6777b538SAndroid Build Coastguard Worker buffer->offset(), &response_info,
632*6777b538SAndroid Build Coastguard Worker &truncated_response_info)) {
633*6777b538SAndroid Build Coastguard Worker command_marshal->ReturnFailure("Couldn't read response info");
634*6777b538SAndroid Build Coastguard Worker return;
635*6777b538SAndroid Build Coastguard Worker }
636*6777b538SAndroid Build Coastguard Worker if (truncated_response_info)
637*6777b538SAndroid Build Coastguard Worker std::cerr << "WARNING: Truncated HTTP response." << std::endl;
638*6777b538SAndroid Build Coastguard Worker
639*6777b538SAndroid Build Coastguard Worker // Update the header.
640*6777b538SAndroid Build Coastguard Worker response_info.headers->SetHeader(header_name, header_value);
641*6777b538SAndroid Build Coastguard Worker
642*6777b538SAndroid Build Coastguard Worker // Write the entry.
643*6777b538SAndroid Build Coastguard Worker PersistResponseInfo(command_marshal, key, response_info);
644*6777b538SAndroid Build Coastguard Worker }
645*6777b538SAndroid Build Coastguard Worker
646*6777b538SAndroid Build Coastguard Worker // Deletes a specified key stream from the cache.
DeleteStreamForKey(CommandMarshal * command_marshal)647*6777b538SAndroid Build Coastguard Worker void DeleteStreamForKey(CommandMarshal* command_marshal) {
648*6777b538SAndroid Build Coastguard Worker std::string key = command_marshal->ReadString();
649*6777b538SAndroid Build Coastguard Worker int index = command_marshal->ReadInt();
650*6777b538SAndroid Build Coastguard Worker if (command_marshal->has_failed())
651*6777b538SAndroid Build Coastguard Worker return;
652*6777b538SAndroid Build Coastguard Worker
653*6777b538SAndroid Build Coastguard Worker TestEntryResultCompletionCallback cb_open;
654*6777b538SAndroid Build Coastguard Worker EntryResult result = command_marshal->cache_backend()->OpenEntry(
655*6777b538SAndroid Build Coastguard Worker key, net::HIGHEST, cb_open.callback());
656*6777b538SAndroid Build Coastguard Worker result = cb_open.GetResult(std::move(result));
657*6777b538SAndroid Build Coastguard Worker if (result.net_error() != net::OK)
658*6777b538SAndroid Build Coastguard Worker return command_marshal->ReturnFailure("Couldn't find key's entry.");
659*6777b538SAndroid Build Coastguard Worker Entry* cache_entry = result.ReleaseEntry();
660*6777b538SAndroid Build Coastguard Worker
661*6777b538SAndroid Build Coastguard Worker net::TestCompletionCallback cb;
662*6777b538SAndroid Build Coastguard Worker scoped_refptr<net::StringIOBuffer> buffer =
663*6777b538SAndroid Build Coastguard Worker base::MakeRefCounted<net::StringIOBuffer>("");
664*6777b538SAndroid Build Coastguard Worker int rv =
665*6777b538SAndroid Build Coastguard Worker cache_entry->WriteData(index, 0, buffer.get(), 0, cb.callback(), true);
666*6777b538SAndroid Build Coastguard Worker if (cb.GetResult(rv) != net::OK)
667*6777b538SAndroid Build Coastguard Worker return command_marshal->ReturnFailure("Couldn't delete key stream.");
668*6777b538SAndroid Build Coastguard Worker command_marshal->ReturnSuccess();
669*6777b538SAndroid Build Coastguard Worker cache_entry->Close();
670*6777b538SAndroid Build Coastguard Worker }
671*6777b538SAndroid Build Coastguard Worker
672*6777b538SAndroid Build Coastguard Worker // Deletes a specified key from the cache.
DeleteKey(CommandMarshal * command_marshal)673*6777b538SAndroid Build Coastguard Worker void DeleteKey(CommandMarshal* command_marshal) {
674*6777b538SAndroid Build Coastguard Worker std::string key = command_marshal->ReadString();
675*6777b538SAndroid Build Coastguard Worker if (command_marshal->has_failed())
676*6777b538SAndroid Build Coastguard Worker return;
677*6777b538SAndroid Build Coastguard Worker net::TestCompletionCallback cb;
678*6777b538SAndroid Build Coastguard Worker int rv = command_marshal->cache_backend()->DoomEntry(key, net::HIGHEST,
679*6777b538SAndroid Build Coastguard Worker cb.callback());
680*6777b538SAndroid Build Coastguard Worker if (cb.GetResult(rv) != net::OK)
681*6777b538SAndroid Build Coastguard Worker command_marshal->ReturnFailure("Couldn't delete key.");
682*6777b538SAndroid Build Coastguard Worker else
683*6777b538SAndroid Build Coastguard Worker command_marshal->ReturnSuccess();
684*6777b538SAndroid Build Coastguard Worker }
685*6777b538SAndroid Build Coastguard Worker
686*6777b538SAndroid Build Coastguard Worker // Executes all command from the |command_marshal|.
ExecuteCommands(CommandMarshal * command_marshal)687*6777b538SAndroid Build Coastguard Worker bool ExecuteCommands(CommandMarshal* command_marshal) {
688*6777b538SAndroid Build Coastguard Worker while (!command_marshal->has_failed()) {
689*6777b538SAndroid Build Coastguard Worker std::string subcommand(command_marshal->ReadCommandName());
690*6777b538SAndroid Build Coastguard Worker if (command_marshal->has_failed())
691*6777b538SAndroid Build Coastguard Worker break;
692*6777b538SAndroid Build Coastguard Worker if (subcommand == "stop") {
693*6777b538SAndroid Build Coastguard Worker command_marshal->ReturnSuccess();
694*6777b538SAndroid Build Coastguard Worker return true;
695*6777b538SAndroid Build Coastguard Worker } else if (subcommand == "batch") {
696*6777b538SAndroid Build Coastguard Worker StreamCommandMarshal stream_command_marshal(
697*6777b538SAndroid Build Coastguard Worker command_marshal->cache_backend());
698*6777b538SAndroid Build Coastguard Worker return ExecuteCommands(&stream_command_marshal);
699*6777b538SAndroid Build Coastguard Worker } else if (subcommand == "delete_key") {
700*6777b538SAndroid Build Coastguard Worker DeleteKey(command_marshal);
701*6777b538SAndroid Build Coastguard Worker } else if (subcommand == "delete_stream") {
702*6777b538SAndroid Build Coastguard Worker DeleteStreamForKey(command_marshal);
703*6777b538SAndroid Build Coastguard Worker } else if (subcommand == "get_size") {
704*6777b538SAndroid Build Coastguard Worker GetSize(command_marshal);
705*6777b538SAndroid Build Coastguard Worker } else if (subcommand == "get_stream") {
706*6777b538SAndroid Build Coastguard Worker GetStreamForKey(command_marshal);
707*6777b538SAndroid Build Coastguard Worker } else if (subcommand == "list_keys") {
708*6777b538SAndroid Build Coastguard Worker ListKeys(command_marshal);
709*6777b538SAndroid Build Coastguard Worker } else if (subcommand == "update_raw_headers") {
710*6777b538SAndroid Build Coastguard Worker UpdateRawResponseHeaders(command_marshal);
711*6777b538SAndroid Build Coastguard Worker } else if (subcommand == "set_header") {
712*6777b538SAndroid Build Coastguard Worker SetHeader(command_marshal);
713*6777b538SAndroid Build Coastguard Worker } else if (subcommand == "list_dups") {
714*6777b538SAndroid Build Coastguard Worker ListDups(command_marshal);
715*6777b538SAndroid Build Coastguard Worker } else {
716*6777b538SAndroid Build Coastguard Worker // The wrong subcommand is originated from the command line.
717*6777b538SAndroid Build Coastguard Worker command_marshal->ReturnFailure("Unknown command.");
718*6777b538SAndroid Build Coastguard Worker PrintHelp();
719*6777b538SAndroid Build Coastguard Worker }
720*6777b538SAndroid Build Coastguard Worker }
721*6777b538SAndroid Build Coastguard Worker return false;
722*6777b538SAndroid Build Coastguard Worker }
723*6777b538SAndroid Build Coastguard Worker
724*6777b538SAndroid Build Coastguard Worker } // namespace
725*6777b538SAndroid Build Coastguard Worker
main(int argc,char * argv[])726*6777b538SAndroid Build Coastguard Worker int main(int argc, char* argv[]) {
727*6777b538SAndroid Build Coastguard Worker base::AtExitManager at_exit_manager;
728*6777b538SAndroid Build Coastguard Worker base::SingleThreadTaskExecutor io_task_executor(base::MessagePumpType::IO);
729*6777b538SAndroid Build Coastguard Worker base::CommandLine::Init(argc, argv);
730*6777b538SAndroid Build Coastguard Worker const base::CommandLine& command_line =
731*6777b538SAndroid Build Coastguard Worker *base::CommandLine::ForCurrentProcess();
732*6777b538SAndroid Build Coastguard Worker
733*6777b538SAndroid Build Coastguard Worker base::CommandLine::StringVector args = command_line.GetArgs();
734*6777b538SAndroid Build Coastguard Worker if (args.size() < 3U) {
735*6777b538SAndroid Build Coastguard Worker PrintHelp();
736*6777b538SAndroid Build Coastguard Worker return 1;
737*6777b538SAndroid Build Coastguard Worker }
738*6777b538SAndroid Build Coastguard Worker
739*6777b538SAndroid Build Coastguard Worker base::ThreadPoolInstance::CreateAndStartWithDefaultParams("cachetool");
740*6777b538SAndroid Build Coastguard Worker
741*6777b538SAndroid Build Coastguard Worker base::FilePath cache_path(args[0]);
742*6777b538SAndroid Build Coastguard Worker std::string cache_backend_type(args[1]);
743*6777b538SAndroid Build Coastguard Worker
744*6777b538SAndroid Build Coastguard Worker net::BackendType backend_type;
745*6777b538SAndroid Build Coastguard Worker if (cache_backend_type == "simple") {
746*6777b538SAndroid Build Coastguard Worker backend_type = net::CACHE_BACKEND_SIMPLE;
747*6777b538SAndroid Build Coastguard Worker } else if (cache_backend_type == "blockfile") {
748*6777b538SAndroid Build Coastguard Worker backend_type = net::CACHE_BACKEND_BLOCKFILE;
749*6777b538SAndroid Build Coastguard Worker } else {
750*6777b538SAndroid Build Coastguard Worker std::cerr << "Unknown cache type." << std::endl;
751*6777b538SAndroid Build Coastguard Worker PrintHelp();
752*6777b538SAndroid Build Coastguard Worker return 1;
753*6777b538SAndroid Build Coastguard Worker }
754*6777b538SAndroid Build Coastguard Worker
755*6777b538SAndroid Build Coastguard Worker TestBackendResultCompletionCallback cb;
756*6777b538SAndroid Build Coastguard Worker BackendResult result = disk_cache::CreateCacheBackend(
757*6777b538SAndroid Build Coastguard Worker net::DISK_CACHE, backend_type, /*file_operations=*/nullptr, cache_path,
758*6777b538SAndroid Build Coastguard Worker INT_MAX, disk_cache::ResetHandling::kNeverReset, /*net_log=*/nullptr,
759*6777b538SAndroid Build Coastguard Worker cb.callback());
760*6777b538SAndroid Build Coastguard Worker result = cb.GetResult(std::move(result));
761*6777b538SAndroid Build Coastguard Worker if (result.net_error != net::OK) {
762*6777b538SAndroid Build Coastguard Worker std::cerr << "Invalid cache." << std::endl;
763*6777b538SAndroid Build Coastguard Worker return 1;
764*6777b538SAndroid Build Coastguard Worker }
765*6777b538SAndroid Build Coastguard Worker std::unique_ptr<Backend> cache_backend = std::move(result.backend);
766*6777b538SAndroid Build Coastguard Worker
767*6777b538SAndroid Build Coastguard Worker ProgramArgumentCommandMarshal program_argument_marshal(
768*6777b538SAndroid Build Coastguard Worker cache_backend.get(),
769*6777b538SAndroid Build Coastguard Worker base::CommandLine::StringVector(args.begin() + 2, args.end()));
770*6777b538SAndroid Build Coastguard Worker bool successful_commands = ExecuteCommands(&program_argument_marshal);
771*6777b538SAndroid Build Coastguard Worker
772*6777b538SAndroid Build Coastguard Worker base::RunLoop().RunUntilIdle();
773*6777b538SAndroid Build Coastguard Worker cache_backend = nullptr;
774*6777b538SAndroid Build Coastguard Worker disk_cache::FlushCacheThreadForTesting();
775*6777b538SAndroid Build Coastguard Worker base::RunLoop().RunUntilIdle();
776*6777b538SAndroid Build Coastguard Worker return !successful_commands;
777*6777b538SAndroid Build Coastguard Worker }
778