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
20namespace {
21
22class 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
46MetadataRequestHandler::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
53MetadataRequestHandler::~MetadataRequestHandler() {
54}
55
56net::URLRequestJob* MetadataRequestHandler::Factory(net::URLRequest* request,
57                                               const std::string& scheme) {
58  return new MetadataRequestHandler(request);
59}
60
61void 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
69void MetadataRequestHandler::Kill() {
70}
71
72bool 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
121bool MetadataRequestHandler::GetMimeType(std::string* mime_type) const {
122  *mime_type = "application/json";
123  return true;
124}
125
126void MetadataRequestHandler::StartAsync() {
127  NotifyHeadersComplete();
128}
129
130}  // namespace
131
132void RegisterMetadataURLRequestHandler() {
133#if defined(OS_CHROMEOS)
134  net::URLRequest::RegisterProtocolFactory(chrome::kMetadataScheme,
135                                           &MetadataRequestHandler::Factory);
136#endif
137}
138