1 // Copyright (c) 2011 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "chrome/browser/net/metadata_url_request.h"
6
7 #include "base/compiler_specific.h"
8 #include "base/file_path.h"
9 #include "base/message_loop.h"
10 #include "base/task.h"
11 #include "build/build_config.h"
12 #include "chrome/browser/parsers/metadata_parser_manager.h"
13 #include "chrome/browser/parsers/metadata_parser.h"
14 #include "chrome/common/url_constants.h"
15 #include "net/base/io_buffer.h"
16 #include "net/base/net_util.h"
17 #include "net/url_request/url_request.h"
18 #include "net/url_request/url_request_job.h"
19
20 namespace {
21
22 class MetadataRequestHandler : public net::URLRequestJob {
23 public:
24 explicit MetadataRequestHandler(net::URLRequest* request);
25
26 static net::URLRequestJob* Factory(net::URLRequest* request,
27 const std::string& scheme);
28
29 // net::URLRequestJob implementation.
30 virtual void Start();
31 virtual void Kill();
32 virtual bool ReadRawData(net::IOBuffer* buf, int buf_size, int *bytes_read);
33 virtual bool GetMimeType(std::string* mime_type) const;
34
35 private:
36 ~MetadataRequestHandler();
37
38 void StartAsync();
39 std::string result_;
40 bool parsed;
41 int data_offset_;
42 ScopedRunnableMethodFactory<MetadataRequestHandler> method_factory_;
43 DISALLOW_COPY_AND_ASSIGN(MetadataRequestHandler);
44 };
45
MetadataRequestHandler(net::URLRequest * request)46 MetadataRequestHandler::MetadataRequestHandler(net::URLRequest* request)
47 : net::URLRequestJob(request),
48 data_offset_(0),
49 ALLOW_THIS_IN_INITIALIZER_LIST(method_factory_(this)) {
50 parsed = false;
51 }
52
~MetadataRequestHandler()53 MetadataRequestHandler::~MetadataRequestHandler() {
54 }
55
Factory(net::URLRequest * request,const std::string & scheme)56 net::URLRequestJob* MetadataRequestHandler::Factory(net::URLRequest* request,
57 const std::string& scheme) {
58 return new MetadataRequestHandler(request);
59 }
60
Start()61 void MetadataRequestHandler::Start() {
62 // Start reading asynchronously so that all error reporting and data
63 // callbacks happen as they would for network requests.
64 MessageLoop::current()->PostTask(
65 FROM_HERE,
66 method_factory_.NewRunnableMethod(&MetadataRequestHandler::StartAsync));
67 }
68
Kill()69 void MetadataRequestHandler::Kill() {
70 }
71
ReadRawData(net::IOBuffer * buf,int buf_size,int * bytes_read)72 bool MetadataRequestHandler::ReadRawData(net::IOBuffer* buf, int buf_size,
73 int *bytes_read) {
74 FilePath path;
75
76 if (!request()->url().is_valid()) {
77 return false;
78 }
79 if (!net::FileURLToFilePath(request()->url(), &path)) {
80 return false;
81 }
82 if (!parsed) {
83 MetadataParserManager* manager = MetadataParserManager::GetInstance();
84 scoped_ptr<MetadataParser> parser(manager->GetParserForFile(path));
85 if (parser != NULL) {
86 result_ = "{\n";
87 parser->Parse();
88 MetadataPropertyIterator *iter = parser->GetPropertyIterator();
89 while (!iter->IsEnd()) {
90 std::string key;
91 std::string value;
92 if (iter->GetNext(&key, &value)) {
93 result_ += "\"";
94 result_ += key;
95 result_ += "\":";
96 result_ += "\"";
97 result_ += value;
98 result_ += "\",\n";
99 } else {
100 break;
101 }
102 }
103 result_ += "}";
104 delete iter;
105 } else {
106 result_ = "{}";
107 }
108 parsed = true;
109 }
110 int remaining = static_cast<int>(result_.size()) - data_offset_;
111 if (buf_size > remaining)
112 buf_size = remaining;
113 if (buf_size > 0) {
114 memcpy(buf->data(), &result_[data_offset_], buf_size);
115 data_offset_ += buf_size;
116 }
117 *bytes_read = buf_size;
118 return true;
119 }
120
GetMimeType(std::string * mime_type) const121 bool MetadataRequestHandler::GetMimeType(std::string* mime_type) const {
122 *mime_type = "application/json";
123 return true;
124 }
125
StartAsync()126 void MetadataRequestHandler::StartAsync() {
127 NotifyHeadersComplete();
128 }
129
130 } // namespace
131
RegisterMetadataURLRequestHandler()132 void RegisterMetadataURLRequestHandler() {
133 #if defined(OS_CHROMEOS)
134 net::URLRequest::RegisterProtocolFactory(chrome::kMetadataScheme,
135 &MetadataRequestHandler::Factory);
136 #endif
137 }
138