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