1a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved. 2a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 3a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)// found in the LICENSE file. 4a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) 5a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)// This example shows how to use the URLLoader in "stream to file" mode where 6a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)// the browser writes incoming data to a file, which you can read out via the 7a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)// file I/O APIs. 8c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch// 9a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)// This example uses PostMessage between the plugin and the url_loader.html 10c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch// page in this directory to start the load and to communicate the result. 11a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) 12f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#include "ppapi/c/ppb_file_io.h" 13f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#include "ppapi/cpp/file_io.h" 14a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "ppapi/cpp/file_ref.h" 15a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)#include "ppapi/cpp/instance.h" 16a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)#include "ppapi/cpp/module.h" 17a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)#include "ppapi/cpp/url_loader.h" 18a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)#include "ppapi/cpp/url_request_info.h" 19a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)#include "ppapi/cpp/url_response_info.h" 20a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)#include "ppapi/utility/completion_callback_factory.h" 21a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) 226e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)// When compiling natively on Windows, PostMessage can be #define-d to 236e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)// something else. 246e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)#ifdef PostMessage 256e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)#undef PostMessage 266e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)#endif 2758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 28a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)// Buffer size for reading network data. 29a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)const int kBufSize = 1024; 3058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 3158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)class MyInstance : public pp::Instance { 3258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) public: 3358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) explicit MyInstance(PP_Instance instance) 3458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) : pp::Instance(instance) { 3558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) factory_.Initialize(this); 3658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) } 37a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) virtual ~MyInstance() { 38a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) // Make sure to explicitly close the loader. If somebody else is holding a 39a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) // reference to the URLLoader object when this class goes out of scope (so 40a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) // the URLLoader outlives "this"), and you have an outstanding read 41a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) // request, the URLLoader will write into invalid memory. 426e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) loader_.Close(); 436e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) } 446e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) 456e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) // Handler for the page sending us messages. 466e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) virtual void HandleMessage(const pp::Var& message_data); 476e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) 486e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) private: 496e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) // Called to initiate the request. 506e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) void StartRequest(const std::string& url); 516e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) 526e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) // Callback for the URLLoader to tell us it finished opening the connection. 536e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) void OnOpenComplete(int32_t result); 546e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) 556e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) // Callback for when the file is completely filled with the download 56a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) void OnStreamComplete(int32_t result); 57a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) 58a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) void OnOpenFileComplete(int32_t result); 59a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) void OnReadComplete(int32_t result); 60a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) 61a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) // Forwards the given string to the page. 62a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) void ReportResponse(const std::string& data); 63a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) 6458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) // Generates completion callbacks scoped to this class. 6558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) pp::CompletionCallbackFactory<MyInstance> factory_; 66a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) 67f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) pp::URLLoader loader_; 68f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) pp::URLResponseInfo response_; 69f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) pp::FileRef dest_file_; 70f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) pp::FileIO file_io_; 71a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) 72a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) // The buffer used for the current read request. This is filled and then 73a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) // 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 80void MyInstance::HandleMessage(const pp::Var& message_data) { 81 if (message_data.is_string() && message_data.AsString() == "go") 82 StartRequest("./fetched_content.html"); 83} 84 85void 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 98void 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 110void 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 120void 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 132void 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 147void 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. 153class 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 164namespace pp { 165 166// Factory function for your specialization of the Module object. 167Module* CreateModule() { 168 return new MyModule(); 169} 170 171} // namespace pp 172