1 // Copyright 2010 The Native Client SDK Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can
3 // be found in the LICENSE file.
8 #include <ppapi/c/pp_errors.h>
9 #include <ppapi/c/ppb_instance.h>
10 #include <ppapi/cpp/module.h>
11 #include <ppapi/cpp/var.h>
12 #include <ppapi/cpp/url_response_info.h>
13 #include <boost/format.hpp>
16 #include <boost/xpressive/xpressive.hpp>
17 #include <boost/lexical_cast.hpp>
18 #include <boost/format.hpp>
20 #include "geturl_handler.h"
22 namespace x = boost::xpressive;
24 extern void LogMsg (void* instance,const char* format,...);
27 bool IsError(int32_t result) {
28 return ((PP_OK != result) && (PP_OK_COMPLETIONPENDING != result));
32 std::string GetURLHandler::js_empty_;
34 GetURLHandler* GetURLHandler::Create(pp::Instance* instance,
35 const std::string& url,std::vector<char>& result_data,complete_func_type func ) {
36 return new GetURLHandler(instance, url,result_data,func);
39 GetURLHandler::GetURLHandler(pp::Instance* instance,
40 const std::string& url,std::vector<char>& result_data,complete_func_type func)
41 : instance_(instance),
43 url_request_(instance),
44 url_loader_(instance),
45 url_response_body_(result_data),
46 cc_factory_(this),load_success_(false) ,received_bytes_(0),total_bytes_(0),func_(func),status_(init){
47 url_response_body_.clear();
48 url_request_.SetURL(url);
49 url_request_.SetMethod("GET");
53 GetURLHandler::~GetURLHandler() {
56 bool GetURLHandler::Start() {
57 LogMsg(instance_,"GetURLHandler::Start () Enter" );
58 pp::CompletionCallback cc = cc_factory_.NewCallback(&GetURLHandler::OnOpen);
59 int32_t res = url_loader_.Open(url_request_, cc);
60 LogMsg(instance_,"GetURLHandler::Start::result = %d",res);
61 if ((PP_OK_COMPLETIONPENDING) != res )
67 void GetURLHandler::OnOpen(int32_t result) {
68 LogMsg(instance_,"GetURLHandler::OnOpen::result = %d",result);
69 pp::URLResponseInfo info(url_loader_.GetResponseInfo());
70 LogMsg(instance_,"GetURLHandler::OnOpen::result = %d,Status Code = %d",result,info.GetStatusCode());
71 LogMsg(instance_,"Headers: %s",info.GetProperty(PP_URLRESPONSEPROPERTY_HEADERS).AsString().c_str());
72 if (result < 0 || info.GetStatusCode() >= 400){
73 std::string result_str((boost::format("pp::URLLoader::Open() failed: %d %s") % result % info.GetStatusLine().AsString()).str());
74 LogMsg(instance_, result_str.c_str());
75 func_(open,false,*this);
76 CallbackEventJS(open,false,result_str);
78 // ReportResultAndDie(url_, "pp::URLLoader::Open() failed", false);
80 x::sregex reg = "Content-Length: " >> ( x::s1 = +x::_d ) ;
81 //x::sregex reg = x::sregex::compile("Content\\-Length\\:\\s([0-9]+)\\s");
83 if(x::regex_search(info.GetProperty(PP_URLRESPONSEPROPERTY_HEADERS).AsString(),m,reg))
85 total_bytes_ = boost::lexical_cast<int32_t>(m[1].str());
86 LogMsg(instance_, "regex:match() success");
88 LogMsg(instance_, "pp::URLLoader::Open() Success.");
89 CallbackEventJS(open,true,pp::Var((int32_t)total_bytes_));
91 func_(open,true,*this);
96 void GetURLHandler::CallbackEventJS(status_id id,bool status,const pp::Var& reason)
98 LogMsg(instance_, "CallbackEventJS");
99 if(reason.is_string()){
100 instance_->PostMessage(pp::Var((boost::format("GetURLHandler:%d:%d:%s") % id % status % reason.AsString()).str()));
102 instance_->PostMessage(pp::Var((boost::format("GetURLHandler:%d:%d:%d") % id % status % reason.AsInt()).str()));
107 void GetURLHandler::OnRead(int32_t result) {
109 static int count = 0;
110 pp::URLResponseInfo info(url_loader_.GetResponseInfo());
112 if (result < 0 && info.GetStatusCode() >= 400) {
113 //
\83G
\83\89\81[
\8f\88\97\9d
114 result_string_ = (boost::format("pp::URLLoader::OnRead() file: %s result: %d status code:%d") % url_.c_str() % result % info.GetStatusCode()).str();
115 LogMsg(instance_, result_string_.c_str());
116 load_success_ = false;
117 CallbackEventJS(loading,load_success_,result_string_);
118 func_(loading,load_success_,*this);
120 } else if (result != 0 ) {
121 /*
\83X
\83e
\81[
\83^
\83X
\83R
\81[
\83h
\83`
\83F
\83b
\83N*/
123 int32_t num_bytes = result < kBufferSize ? result : sizeof(buffer_);
124 url_response_body_.reserve(url_response_body_.size() + num_bytes);
125 url_response_body_.insert(url_response_body_.end(),
127 buffer_ + num_bytes);
129 //pp::FileRef_Dev d(info.
130 //url_loader_.GetDownloadProgress(&received_bytes_,&total_bytes_);
131 received_bytes_ += num_bytes;
132 count = (++count) & 0x3;
134 CallbackEventJS(loading,true,(int32_t)(received_bytes_));
135 LogMsg(instance_,"pp::URLLoader::OnRead() File: %s Success: %d bytes Status: %d" ,url_.c_str(),num_bytes,info.GetStatusCode());
139 } else { // result == 0, end of stream
140 load_success_ = true;
141 LogMsg(instance_,"Load Success. File Size is %d bytes.\n",url_response_body_.size());
142 CallbackEventJS(complete,load_success_,(int32_t)(url_response_body_.size()));
143 func_(complete,load_success_,*this);
147 /* TODO:
\90i
\92»
\8fó
\91Ô
\82Ì
\93Ç
\82Ý
\8eæ
\82è
\82ð
\8dì
\82é */
149 void GetURLHandler::ReadBody() {
150 // Reads the response body (asynchronous) into this->buffer_.
151 // OnRead() will be called when bytes are received or when an error occurs.
152 // Look at <ppapi/c/dev/ppb_url_loader> for more details.
153 pp::CompletionCallback cc = cc_factory_.NewCallback(&GetURLHandler::OnRead);
154 int32_t res = url_loader_.ReadResponseBody(buffer_,
157 if (PP_OK_COMPLETIONPENDING != res)
161 //void GetURLHandler::ReportResultAndDie(const std::string& fname,
162 // const std::string& text,
164 // ReportResult(fname, text, success);
168 //void GetURLHandler::ReportResult(const std::string& fname,
169 // const std::string& text,
172 // printf("GetURLHandler::ReportResult(Ok).\n");
174 // printf("GetURLHandler::ReportResult(Err). %s\n", text.c_str());
176 // pp::Module* module = pp::Module::Get();
177 // if (NULL == module)
180 // pp::Instance* instance = module->InstanceForPPInstance(instance_id_);
181 // if (NULL == instance)
184 // pp::Var window = instance->GetWindowObject();
185 // // calls JavaScript function reportResult(url, result, success)
186 // // defined in geturl.html.
187 // pp::Var exception;
188 // window.Call("reportResult", fname, text, success, &exception);