xref: /aosp_15_r20/external/cronet/net/tools/cachetool/cachetool.cc (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
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