- add sources.
[platform/framework/web/crosswalk.git] / src / ppapi / examples / url_loader / stream_to_file.cc
1 // Copyright (c) 2012 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 // This example shows how to use the URLLoader in "stream to file" mode where
6 // the browser writes incoming data to a file, which you can read out via the
7 // file I/O APIs.
8 //
9 // This example uses PostMessage between the plugin and the url_loader.html
10 // page in this directory to start the load and to communicate the result.
11
12 #include "ppapi/c/ppb_file_io.h"
13 #include "ppapi/cpp/file_io.h"
14 #include "ppapi/cpp/file_ref.h"
15 #include "ppapi/cpp/instance.h"
16 #include "ppapi/cpp/module.h"
17 #include "ppapi/cpp/url_loader.h"
18 #include "ppapi/cpp/url_request_info.h"
19 #include "ppapi/cpp/url_response_info.h"
20 #include "ppapi/utility/completion_callback_factory.h"
21
22 // When compiling natively on Windows, PostMessage can be #define-d to
23 // something else.
24 #ifdef PostMessage
25 #undef PostMessage
26 #endif
27
28 // Buffer size for reading network data.
29 const int kBufSize = 1024;
30
31 class MyInstance : public pp::Instance {
32  public:
33   explicit MyInstance(PP_Instance instance)
34       : pp::Instance(instance) {
35     factory_.Initialize(this);
36   }
37   virtual ~MyInstance() {
38     // Make sure to explicitly close the loader. If somebody else is holding a
39     // reference to the URLLoader object when this class goes out of scope (so
40     // the URLLoader outlives "this"), and you have an outstanding read
41     // request, the URLLoader will write into invalid memory.
42     loader_.Close();
43   }
44
45   // Handler for the page sending us messages.
46   virtual void HandleMessage(const pp::Var& message_data);
47
48  private:
49   // Called to initiate the request.
50   void StartRequest(const std::string& url);
51
52   // Callback for the URLLoader to tell us it finished opening the connection.
53   void OnOpenComplete(int32_t result);
54
55   // Callback for when the file is completely filled with the download
56   void OnStreamComplete(int32_t result);
57
58   void OnOpenFileComplete(int32_t result);
59   void OnReadComplete(int32_t result);
60
61   // Forwards the given string to the page.
62   void ReportResponse(const std::string& data);
63
64   // Generates completion callbacks scoped to this class.
65   pp::CompletionCallbackFactory<MyInstance> factory_;
66
67   pp::URLLoader loader_;
68   pp::URLResponseInfo response_;
69   pp::FileRef dest_file_;
70   pp::FileIO file_io_;
71
72   // The buffer used for the current read request. This is filled and then
73   // copied into content_ to build up the entire document.
74   char buf_[kBufSize];
75
76   // All the content loaded so far.
77   std::string content_;
78 };
79
80 void MyInstance::HandleMessage(const pp::Var& message_data) {
81   if (message_data.is_string() && message_data.AsString() == "go")
82     StartRequest("./fetched_content.html");
83 }
84
85 void MyInstance::StartRequest(const std::string& url) {
86   content_.clear();
87
88   pp::URLRequestInfo request(this);
89   request.SetURL(url);
90   request.SetMethod("GET");
91   request.SetStreamToFile(true);
92
93   loader_ = pp::URLLoader(this);
94   loader_.Open(request,
95                factory_.NewCallback(&MyInstance::OnOpenComplete));
96 }
97
98 void MyInstance::OnOpenComplete(int32_t result) {
99   if (result != PP_OK) {
100     ReportResponse("URL could not be requested");
101     return;
102   }
103
104   loader_.FinishStreamingToFile(
105       factory_.NewCallback(&MyInstance::OnStreamComplete));
106   response_ = loader_.GetResponseInfo();
107   dest_file_ = response_.GetBodyAsFileRef();
108 }
109
110 void MyInstance::OnStreamComplete(int32_t result) {
111   if (result == PP_OK) {
112     file_io_ = pp::FileIO(this);
113     file_io_.Open(dest_file_, PP_FILEOPENFLAG_READ,
114         factory_.NewCallback(&MyInstance::OnOpenFileComplete));
115   } else {
116     ReportResponse("Could not stream to file");
117   }
118 }
119
120 void MyInstance::OnOpenFileComplete(int32_t result) {
121   if (result == PP_OK) {
122     // Note we only read the first 1024 bytes from the file in this example
123     // to keep things simple. Please see a file I/O example for more details
124     // on reading files.
125     file_io_.Read(0, buf_, kBufSize,
126         factory_.NewCallback(&MyInstance::OnReadComplete));
127   } else {
128     ReportResponse("Could not open file");
129   }
130 }
131
132 void MyInstance::OnReadComplete(int32_t result) {
133   if (result >= 0) {
134     content_.append(buf_, result);
135     ReportResponse(buf_);
136   } else {
137     ReportResponse("Could not read file");
138   }
139
140   // Release everything.
141   loader_ = pp::URLLoader();
142   response_ = pp::URLResponseInfo();
143   dest_file_ = pp::FileRef();
144   file_io_ = pp::FileIO();
145 }
146
147 void MyInstance::ReportResponse(const std::string& data) {
148   PostMessage(pp::Var(data));
149 }
150
151 // This object is the global object representing this plugin library as long
152 // as it is loaded.
153 class MyModule : public pp::Module {
154  public:
155   MyModule() : pp::Module() {}
156   virtual ~MyModule() {}
157
158   // Override CreateInstance to create your customized Instance object.
159   virtual pp::Instance* CreateInstance(PP_Instance instance) {
160     return new MyInstance(instance);
161   }
162 };
163
164 namespace pp {
165
166 // Factory function for your specialization of the Module object.
167 Module* CreateModule() {
168   return new MyModule();
169 }
170
171 }  // namespace pp