Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(443)

Side by Side Diff: examples/pdf_viewer/pdf_viewer.cc

Issue 741453002: Make sure that Content Handled application can be connected multiple times. (Closed) Base URL: https://github.com/domokit/mojo.git@master
Patch Set: Created 6 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | examples/png_viewer/png_viewer.cc » ('j') | examples/png_viewer/png_viewer.cc » ('J')
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2014 The Chromium Authors. All rights reserved. 1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "base/strings/string_tokenizer.h" 5 #include "base/strings/string_tokenizer.h"
6 #include "examples/bitmap_uploader/bitmap_uploader.h" 6 #include "examples/bitmap_uploader/bitmap_uploader.h"
7 #include "mojo/application/application_runner_chromium.h" 7 #include "mojo/application/application_runner_chromium.h"
8 #include "mojo/application/content_handler_factory.h" 8 #include "mojo/application/content_handler_factory.h"
9 #include "mojo/public/c/system/main.h" 9 #include "mojo/public/c/system/main.h"
10 #include "mojo/public/cpp/application/application_connection.h" 10 #include "mojo/public/cpp/application/application_connection.h"
(...skipping 12 matching lines...) Expand all
23 #include "mojo/services/public/interfaces/input_events/input_key_codes.mojom.h" 23 #include "mojo/services/public/interfaces/input_events/input_key_codes.mojom.h"
24 #include "third_party/pdfium/fpdfsdk/include/fpdf_ext.h" 24 #include "third_party/pdfium/fpdfsdk/include/fpdf_ext.h"
25 #include "third_party/pdfium/fpdfsdk/include/fpdfview.h" 25 #include "third_party/pdfium/fpdfsdk/include/fpdfview.h"
26 #include "v8/include/v8.h" 26 #include "v8/include/v8.h"
27 27
28 #define BACKGROUND_COLOR 0xFF888888 28 #define BACKGROUND_COLOR 0xFF888888
29 29
30 namespace mojo { 30 namespace mojo {
31 namespace examples { 31 namespace examples {
32 32
33 namespace {
Aaron Boodman 2014/11/18 23:46:15 It feels more natural to me that applications such
qsr 2014/11/19 13:42:37 Can we delay those changes to a next CL?
Aaron Boodman 2014/11/19 15:58:15 yes.
34
35 class EmbedderData {
36 public:
37 EmbedderData(Shell* shell, View* root) : bitmap_uploader_(root) {
38 bitmap_uploader_.Init(shell);
39 bitmap_uploader_.SetColor(BACKGROUND_COLOR);
40 }
41
42 BitmapUploader& bitmap_uploader() { return bitmap_uploader_; }
43
44 private:
45 BitmapUploader bitmap_uploader_;
46
47 DISALLOW_COPY_AND_ASSIGN(EmbedderData);
48 };
49
50 } // namespace
51
33 class PDFView : public ApplicationDelegate, 52 class PDFView : public ApplicationDelegate,
34 public ViewManagerDelegate, 53 public ViewManagerDelegate,
35 public ViewObserver { 54 public ViewObserver {
36 public: 55 public:
37 PDFView(URLResponsePtr response) 56 PDFView(URLResponsePtr response)
38 : current_page_(0), 57 : current_page_(0), page_count_(0), doc_(NULL), app_(nullptr) {
39 page_count_(0),
40 doc_(NULL),
41 app_(nullptr),
42 root_(nullptr) {
43 FetchPDF(response.Pass()); 58 FetchPDF(response.Pass());
44 } 59 }
45 60
46 virtual ~PDFView() { 61 virtual ~PDFView() {
47 if (doc_) 62 if (doc_)
48 FPDF_CloseDocument(doc_); 63 FPDF_CloseDocument(doc_);
49 if (root_) 64 for (auto& roots : embedder_for_roots_) {
50 root_->RemoveObserver(this); 65 roots.first->RemoveObserver(this);
66 delete roots.second;
67 }
51 } 68 }
52 69
53 private: 70 private:
54 // Overridden from ApplicationDelegate: 71 // Overridden from ApplicationDelegate:
55 virtual void Initialize(ApplicationImpl* app) override { 72 virtual void Initialize(ApplicationImpl* app) override {
56 app_ = app; 73 app_ = app;
57 view_manager_client_factory_.reset( 74 view_manager_client_factory_.reset(
58 new ViewManagerClientFactory(app->shell(), this)); 75 new ViewManagerClientFactory(app->shell(), this));
59 } 76 }
60 77
61 virtual bool ConfigureIncomingConnection( 78 virtual bool ConfigureIncomingConnection(
62 ApplicationConnection* connection) override { 79 ApplicationConnection* connection) override {
63 connection->AddService(view_manager_client_factory_.get()); 80 connection->AddService(view_manager_client_factory_.get());
64 return true; 81 return true;
65 } 82 }
66 83
67 // Overridden from ViewManagerDelegate: 84 // Overridden from ViewManagerDelegate:
68 virtual void OnEmbed(ViewManager* view_manager, 85 virtual void OnEmbed(ViewManager* view_manager,
69 View* root, 86 View* root,
70 ServiceProviderImpl* exported_services, 87 ServiceProviderImpl* exported_services,
71 scoped_ptr<ServiceProvider> imported_services) override { 88 scoped_ptr<ServiceProvider> imported_services) override {
72 root_ = root; 89 DCHECK(embedder_for_roots_.find(root) == embedder_for_roots_.end());
73 root_->AddObserver(this); 90 root->AddObserver(this);
74 bitmap_uploader_.reset(new BitmapUploader(root_)); 91 EmbedderData* embedder_data = new EmbedderData(app_->shell(), root);
75 bitmap_uploader_->Init(app_->shell()); 92 embedder_for_roots_[root] = embedder_data;
76 bitmap_uploader_->SetColor(BACKGROUND_COLOR); 93 DrawBitmap(embedder_data);
77 DrawBitmap();
78 } 94 }
79 95
80 virtual void OnViewManagerDisconnected(ViewManager* view_manager) override { 96 virtual void OnViewManagerDisconnected(ViewManager* view_manager) override {}
81 }
82 97
83 // Overridden from ViewObserver: 98 // Overridden from ViewObserver:
84 virtual void OnViewBoundsChanged(View* view, 99 virtual void OnViewBoundsChanged(View* view,
85 const Rect& old_bounds, 100 const Rect& old_bounds,
86 const Rect& new_bounds) override { 101 const Rect& new_bounds) override {
87 DCHECK_EQ(view, root_); 102 DCHECK(embedder_for_roots_.find(view) != embedder_for_roots_.end());
88 DrawBitmap(); 103 DrawBitmap(embedder_for_roots_[view]);
89 } 104 }
90 105
91 virtual void OnViewInputEvent(View* view, const EventPtr& event) override { 106 virtual void OnViewInputEvent(View* view, const EventPtr& event) override {
107 DCHECK(embedder_for_roots_.find(view) != embedder_for_roots_.end());
92 if (event->key_data && 108 if (event->key_data &&
93 (event->action != EVENT_TYPE_KEY_PRESSED || 109 (event->action != EVENT_TYPE_KEY_PRESSED || event->key_data->is_char)) {
94 event->key_data->is_char)) {
95 return; 110 return;
96 } 111 }
97 if ((event->key_data && 112 if ((event->key_data &&
98 event->key_data->windows_key_code == KEYBOARD_CODE_DOWN) || 113 event->key_data->windows_key_code == KEYBOARD_CODE_DOWN) ||
99 (event->wheel_data && event->wheel_data->y_offset < 0)) { 114 (event->wheel_data && event->wheel_data->y_offset < 0)) {
100 if (current_page_ < (page_count_ - 1)) { 115 if (current_page_ < (page_count_ - 1)) {
101 current_page_++; 116 current_page_++;
102 DrawBitmap(); 117 DrawBitmap(embedder_for_roots_[view]);
103 } 118 }
104 } else if ((event->key_data && 119 } else if ((event->key_data &&
105 event->key_data->windows_key_code == KEYBOARD_CODE_UP) || 120 event->key_data->windows_key_code == KEYBOARD_CODE_UP) ||
106 (event->wheel_data && event->wheel_data->y_offset > 0)) { 121 (event->wheel_data && event->wheel_data->y_offset > 0)) {
107 if (current_page_ > 0) { 122 if (current_page_ > 0) {
108 current_page_--; 123 current_page_--;
109 DrawBitmap(); 124 DrawBitmap(embedder_for_roots_[view]);
110 } 125 }
111 } 126 }
112 } 127 }
113 128
114 virtual void OnViewDestroyed(View* view) override { 129 virtual void OnViewDestroyed(View* view) override {
115 DCHECK_EQ(view, root_); 130 DCHECK(embedder_for_roots_.find(view) != embedder_for_roots_.end());
116 // TODO(qsr): It should not be necessary to cleanup the uploader, but it 131 const auto& it = embedder_for_roots_.find(view);
117 // crashes if the GL context goes away. 132 DCHECK(it != embedder_for_roots_.end());
118 bitmap_uploader_.reset(); 133 delete it->second;
119 ApplicationImpl::Terminate(); 134 embedder_for_roots_.erase(it);
135 if (embedder_for_roots_.size() == 0)
136 ApplicationImpl::Terminate();
120 } 137 }
121 138
122 void DrawBitmap() { 139 void DrawBitmap(EmbedderData* embedder_data) {
123 if (!root_ || !doc_) 140 if (!doc_)
124 return; 141 return;
125 142
126 FPDF_PAGE page = FPDF_LoadPage(doc_, current_page_); 143 FPDF_PAGE page = FPDF_LoadPage(doc_, current_page_);
127 int width = static_cast<int>(FPDF_GetPageWidth(page)); 144 int width = static_cast<int>(FPDF_GetPageWidth(page));
128 int height = static_cast<int>(FPDF_GetPageHeight(page)); 145 int height = static_cast<int>(FPDF_GetPageHeight(page));
129 146
130 scoped_ptr<std::vector<unsigned char>> bitmap; 147 scoped_ptr<std::vector<unsigned char>> bitmap;
131 bitmap.reset(new std::vector<unsigned char>); 148 bitmap.reset(new std::vector<unsigned char>);
132 bitmap->resize(width * height * 4); 149 bitmap->resize(width * height * 4);
133 150
134 FPDF_BITMAP f_bitmap = FPDFBitmap_CreateEx( 151 FPDF_BITMAP f_bitmap = FPDFBitmap_CreateEx(width, height, FPDFBitmap_BGRA,
135 width, height, FPDFBitmap_BGRA, &(*bitmap)[0], width * 4); 152 &(*bitmap)[0], width * 4);
136 FPDFBitmap_FillRect(f_bitmap, 0, 0, width, height, 0xFFFFFFFF); 153 FPDFBitmap_FillRect(f_bitmap, 0, 0, width, height, 0xFFFFFFFF);
137 FPDF_RenderPageBitmap(f_bitmap, page, 0, 0, width, height, 0, 0); 154 FPDF_RenderPageBitmap(f_bitmap, page, 0, 0, width, height, 0, 0);
138 FPDFBitmap_Destroy(f_bitmap); 155 FPDFBitmap_Destroy(f_bitmap);
139 156
140 FPDF_ClosePage(page); 157 FPDF_ClosePage(page);
141 158
142 bitmap_uploader_->SetBitmap(width, height, bitmap.Pass(), 159 embedder_data->bitmap_uploader().SetBitmap(width, height, bitmap.Pass(),
143 BitmapUploader::BGRA); 160 BitmapUploader::BGRA);
144 } 161 }
145 162
146 void FetchPDF(URLResponsePtr response) { 163 void FetchPDF(URLResponsePtr response) {
147 int content_length = GetContentLength(response->headers); 164 int content_length = GetContentLength(response->headers);
148 scoped_ptr<unsigned char[]> data; 165 scoped_ptr<unsigned char[]> data;
149 data_.reset(new unsigned char[content_length]); 166 data_.reset(new unsigned char[content_length]);
150 unsigned char* buf = data_.get(); 167 unsigned char* buf = data_.get();
151 uint32_t bytes_remaining = content_length; 168 uint32_t bytes_remaining = content_length;
152 uint32_t num_bytes = bytes_remaining; 169 uint32_t num_bytes = bytes_remaining;
153 while (bytes_remaining > 0) { 170 while (bytes_remaining > 0) {
154 MojoResult result = ReadDataRaw( 171 MojoResult result = ReadDataRaw(response->body.get(), buf, &num_bytes,
155 response->body.get(), buf, &num_bytes, MOJO_READ_DATA_FLAG_NONE); 172 MOJO_READ_DATA_FLAG_NONE);
156 if (result == MOJO_RESULT_SHOULD_WAIT) { 173 if (result == MOJO_RESULT_SHOULD_WAIT) {
157 Wait(response->body.get(), 174 Wait(response->body.get(), MOJO_HANDLE_SIGNAL_READABLE,
158 MOJO_HANDLE_SIGNAL_READABLE,
159 MOJO_DEADLINE_INDEFINITE); 175 MOJO_DEADLINE_INDEFINITE);
160 } else if (result == MOJO_RESULT_OK) { 176 } else if (result == MOJO_RESULT_OK) {
161 buf += num_bytes; 177 buf += num_bytes;
162 num_bytes = bytes_remaining -= num_bytes; 178 num_bytes = bytes_remaining -= num_bytes;
163 } else { 179 } else {
164 break; 180 break;
165 } 181 }
166 } 182 }
167 183
168 doc_ = FPDF_LoadMemDocument(data_.get(), content_length, NULL); 184 doc_ = FPDF_LoadMemDocument(data_.get(), content_length, NULL);
(...skipping 13 matching lines...) Expand all
182 } 198 }
183 } 199 }
184 return 0; 200 return 0;
185 } 201 }
186 202
187 scoped_ptr<unsigned char[]> data_; 203 scoped_ptr<unsigned char[]> data_;
188 int current_page_; 204 int current_page_;
189 int page_count_; 205 int page_count_;
190 FPDF_DOCUMENT doc_; 206 FPDF_DOCUMENT doc_;
191 ApplicationImpl* app_; 207 ApplicationImpl* app_;
192 View* root_; 208 std::map<View*, EmbedderData*> embedder_for_roots_;
193 scoped_ptr<ViewManagerClientFactory> view_manager_client_factory_; 209 scoped_ptr<ViewManagerClientFactory> view_manager_client_factory_;
194 scoped_ptr<BitmapUploader> bitmap_uploader_;
195 210
196 DISALLOW_COPY_AND_ASSIGN(PDFView); 211 DISALLOW_COPY_AND_ASSIGN(PDFView);
197 }; 212 };
198 213
199 class PDFViewer : public ApplicationDelegate, 214 class PDFViewer : public ApplicationDelegate,
200 public ContentHandlerFactory::Delegate { 215 public ContentHandlerFactory::Delegate {
201 public: 216 public:
202 PDFViewer() : content_handler_factory_(this) { 217 PDFViewer() : content_handler_factory_(this) {
203 v8::V8::InitializeICU(); 218 v8::V8::InitializeICU();
204 FPDF_InitLibrary(NULL); 219 FPDF_InitLibrary(NULL);
(...skipping 21 matching lines...) Expand all
226 DISALLOW_COPY_AND_ASSIGN(PDFViewer); 241 DISALLOW_COPY_AND_ASSIGN(PDFViewer);
227 }; 242 };
228 243
229 } // namespace examples 244 } // namespace examples
230 } // namespace mojo 245 } // namespace mojo
231 246
232 MojoResult MojoMain(MojoHandle shell_handle) { 247 MojoResult MojoMain(MojoHandle shell_handle) {
233 mojo::ApplicationRunnerChromium runner(new mojo::examples::PDFViewer()); 248 mojo::ApplicationRunnerChromium runner(new mojo::examples::PDFViewer());
234 return runner.Run(shell_handle); 249 return runner.Run(shell_handle);
235 } 250 }
OLDNEW
« no previous file with comments | « no previous file | examples/png_viewer/png_viewer.cc » ('j') | examples/png_viewer/png_viewer.cc » ('J')

Powered by Google App Engine
This is Rietveld 408576698