OLD | NEW |
---|---|
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 <algorithm> | 5 #include <algorithm> |
6 | 6 |
7 #include "base/macros.h" | 7 #include "base/macros.h" |
8 #include "base/memory/scoped_ptr.h" | 8 #include "base/memory/scoped_ptr.h" |
9 #include "base/message_loop/message_loop.h" | 9 #include "base/message_loop/message_loop.h" |
10 #include "base/strings/string_tokenizer.h" | 10 #include "base/strings/string_tokenizer.h" |
(...skipping 13 matching lines...) Expand all Loading... | |
24 #include "mojo/services/public/cpp/view_manager/view_manager_client_factory.h" | 24 #include "mojo/services/public/cpp/view_manager/view_manager_client_factory.h" |
25 #include "mojo/services/public/cpp/view_manager/view_manager_delegate.h" | 25 #include "mojo/services/public/cpp/view_manager/view_manager_delegate.h" |
26 #include "mojo/services/public/cpp/view_manager/view_observer.h" | 26 #include "mojo/services/public/cpp/view_manager/view_observer.h" |
27 #include "mojo/services/public/interfaces/content_handler/content_handler.mojom. h" | 27 #include "mojo/services/public/interfaces/content_handler/content_handler.mojom. h" |
28 #include "third_party/skia/include/core/SkColor.h" | 28 #include "third_party/skia/include/core/SkColor.h" |
29 #include "ui/gfx/codec/png_codec.h" | 29 #include "ui/gfx/codec/png_codec.h" |
30 | 30 |
31 namespace mojo { | 31 namespace mojo { |
32 namespace examples { | 32 namespace examples { |
33 | 33 |
34 namespace { | |
35 | |
36 class EmbedderData { | |
37 public: | |
38 EmbedderData(Shell* shell, View* root) : bitmap_uploader_(root) { | |
39 bitmap_uploader_.Init(shell); | |
40 bitmap_uploader_.SetColor(SK_ColorGRAY); | |
41 } | |
42 | |
43 BitmapUploader& bitmap_uploader() { return bitmap_uploader_; } | |
44 | |
45 private: | |
46 BitmapUploader bitmap_uploader_; | |
47 | |
48 DISALLOW_COPY_AND_ASSIGN(EmbedderData); | |
49 }; | |
50 | |
51 } // namespace | |
52 | |
34 // TODO(aa): Hook up ZoomableMedia interface again. | 53 // TODO(aa): Hook up ZoomableMedia interface again. |
35 class PNGView : public ApplicationDelegate, | 54 class PNGView : public ApplicationDelegate, |
36 public ViewManagerDelegate, | 55 public ViewManagerDelegate, |
37 public ViewObserver { | 56 public ViewObserver { |
38 public: | 57 public: |
39 PNGView(URLResponsePtr response) | 58 PNGView(URLResponsePtr response) |
40 : width_(0), | 59 : width_(0), |
41 height_(0), | 60 height_(0), |
42 app_(nullptr), | 61 app_(nullptr), |
43 root_(nullptr), | |
44 zoom_percentage_(kDefaultZoomPercentage) { | 62 zoom_percentage_(kDefaultZoomPercentage) { |
45 DecodePNG(response.Pass()); | 63 DecodePNG(response.Pass()); |
46 } | 64 } |
47 | 65 |
48 virtual ~PNGView() { | 66 virtual ~PNGView() { |
49 if (root_) | 67 for (auto& roots : embedder_for_roots_) { |
50 root_->RemoveObserver(this); | 68 roots.first->RemoveObserver(this); |
69 delete roots.second; | |
70 } | |
51 } | 71 } |
52 | 72 |
53 private: | 73 private: |
54 static const uint16_t kMaxZoomPercentage = 400; | 74 static const uint16_t kMaxZoomPercentage = 400; |
55 static const uint16_t kMinZoomPercentage = 20; | 75 static const uint16_t kMinZoomPercentage = 20; |
56 static const uint16_t kDefaultZoomPercentage = 100; | 76 static const uint16_t kDefaultZoomPercentage = 100; |
57 static const uint16_t kZoomStep = 20; | 77 static const uint16_t kZoomStep = 20; |
58 | 78 |
59 // Overridden from ApplicationDelegate: | 79 // Overridden from ApplicationDelegate: |
60 virtual void Initialize(ApplicationImpl* app) override { | 80 virtual void Initialize(ApplicationImpl* app) override { |
61 app_ = app; | 81 app_ = app; |
62 view_manager_client_factory_.reset( | 82 view_manager_client_factory_.reset( |
63 new ViewManagerClientFactory(app->shell(), this)); | 83 new ViewManagerClientFactory(app->shell(), this)); |
64 } | 84 } |
65 | 85 |
66 // Overridden from ApplicationDelegate: | 86 // Overridden from ApplicationDelegate: |
67 virtual bool ConfigureIncomingConnection( | 87 virtual bool ConfigureIncomingConnection( |
68 ApplicationConnection* connection) override { | 88 ApplicationConnection* connection) override { |
69 connection->AddService(view_manager_client_factory_.get()); | 89 connection->AddService(view_manager_client_factory_.get()); |
70 return true; | 90 return true; |
71 } | 91 } |
72 | 92 |
73 // Overridden from ViewManagerDelegate: | 93 // Overridden from ViewManagerDelegate: |
74 virtual void OnEmbed(ViewManager* view_manager, | 94 virtual void OnEmbed(ViewManager* view_manager, |
75 View* root, | 95 View* root, |
76 ServiceProviderImpl* exported_services, | 96 ServiceProviderImpl* exported_services, |
77 scoped_ptr<ServiceProvider> imported_services) override { | 97 scoped_ptr<ServiceProvider> imported_services) override { |
78 // TODO(qsr): The same view should be embeddable on multiple views. | 98 // TODO(qsr): The same view should be embeddable on multiple views. |
79 DCHECK(!root_); | 99 DCHECK(embedder_for_roots_.find(root) == embedder_for_roots_.end()); |
80 root_ = root; | 100 root->AddObserver(this); |
81 root_->AddObserver(this); | 101 EmbedderData* embedder_data = new EmbedderData(app_->shell(), root); |
82 bitmap_uploader_.reset(new BitmapUploader(root_)); | 102 embedder_for_roots_[root] = embedder_data; |
83 bitmap_uploader_->Init(app_->shell()); | 103 embedder_data->bitmap_uploader().SetBitmap( |
84 bitmap_uploader_->SetColor(SK_ColorGRAY); | 104 width_, height_, |
85 if (bitmap_.get()) | 105 make_scoped_ptr(new std::vector<unsigned char>(*bitmap_)), |
86 DrawBitmap(); | 106 BitmapUploader::BGRA); |
87 } | 107 } |
88 | 108 |
89 virtual void OnViewManagerDisconnected(ViewManager* view_manager) override { | 109 virtual void OnViewManagerDisconnected(ViewManager* view_manager) override { |
90 // TODO(aa): Need to figure out how shutdown works. | 110 // TODO(aa): Need to figure out how shutdown works. |
Aaron Boodman
2014/11/19 15:58:15
Can you remove this comment? Or move it to OnViewD
qsr
2014/11/19 16:37:21
Done.
| |
91 } | 111 } |
92 | 112 |
93 // Overridden from ViewObserver: | 113 // Overridden from ViewObserver: |
94 virtual void OnViewBoundsChanged(View* view, | 114 virtual void OnViewBoundsChanged(View* view, |
95 const Rect& old_bounds, | 115 const Rect& old_bounds, |
96 const Rect& new_bounds) override { | 116 const Rect& new_bounds) override { |
97 DCHECK_EQ(view, root_); | 117 DCHECK(embedder_for_roots_.find(view) != embedder_for_roots_.end()); |
98 DrawBitmap(); | |
99 } | 118 } |
100 | 119 |
101 virtual void OnViewDestroyed(View* view) override { | 120 virtual void OnViewDestroyed(View* view) override { |
102 DCHECK_EQ(view, root_); | 121 const auto& it = embedder_for_roots_.find(view); |
103 // TODO(qsr): It should not be necessary to cleanup the uploader, but it | 122 DCHECK(it != embedder_for_roots_.end()); |
104 // crashes if the GL context goes away. | 123 delete it->second; |
105 bitmap_uploader_.reset(); | 124 embedder_for_roots_.erase(it); |
106 ApplicationImpl::Terminate(); | 125 if (embedder_for_roots_.size() == 0) |
107 } | 126 ApplicationImpl::Terminate(); |
Aaron Boodman
2014/11/18 23:46:15
Out of scope for this CL, but I don't think this i
qsr
2014/11/19 13:42:37
Can you elaborate? I can always change it in a nex
Aaron Boodman
2014/11/19 15:58:15
This depends on the order you receive OnEmbed() an
qsr
2014/11/19 16:37:21
Hum... I really hope I can count on receiving OnEm
Aaron Boodman
2014/11/20 00:59:01
No what I mean is that, during navigation for exam
| |
108 | |
109 void DrawBitmap() { | |
110 if (!root_) | |
111 return; | |
112 | |
113 bitmap_uploader_->SetBitmap( | |
114 width_, height_, bitmap_.Pass(), BitmapUploader::BGRA); | |
115 } | 127 } |
116 | 128 |
117 void ZoomIn() { | 129 void ZoomIn() { |
130 // TODO(qsr,aa) Zoom should be per embedder view. | |
118 if (zoom_percentage_ >= kMaxZoomPercentage) | 131 if (zoom_percentage_ >= kMaxZoomPercentage) |
119 return; | 132 return; |
120 zoom_percentage_ += kZoomStep; | 133 zoom_percentage_ += kZoomStep; |
121 DrawBitmap(); | |
122 } | 134 } |
123 | 135 |
124 void ZoomOut() { | 136 void ZoomOut() { |
125 if (zoom_percentage_ <= kMinZoomPercentage) | 137 if (zoom_percentage_ <= kMinZoomPercentage) |
126 return; | 138 return; |
127 zoom_percentage_ -= kZoomStep; | 139 zoom_percentage_ -= kZoomStep; |
128 DrawBitmap(); | |
129 } | 140 } |
130 | 141 |
131 void ZoomToActualSize() { | 142 void ZoomToActualSize() { |
132 if (zoom_percentage_ == kDefaultZoomPercentage) | 143 if (zoom_percentage_ == kDefaultZoomPercentage) |
133 return; | 144 return; |
134 zoom_percentage_ = kDefaultZoomPercentage; | 145 zoom_percentage_ = kDefaultZoomPercentage; |
135 DrawBitmap(); | |
136 } | 146 } |
137 | 147 |
138 void DecodePNG(URLResponsePtr response) { | 148 void DecodePNG(URLResponsePtr response) { |
139 int content_length = GetContentLength(response->headers); | 149 int content_length = GetContentLength(response->headers); |
140 scoped_ptr<unsigned char[]> data(new unsigned char[content_length]); | 150 scoped_ptr<unsigned char[]> data(new unsigned char[content_length]); |
141 unsigned char* buf = data.get(); | 151 unsigned char* buf = data.get(); |
142 uint32_t bytes_remaining = content_length; | 152 uint32_t bytes_remaining = content_length; |
143 uint32_t num_bytes = bytes_remaining; | 153 uint32_t num_bytes = bytes_remaining; |
144 while (bytes_remaining > 0) { | 154 while (bytes_remaining > 0) { |
145 MojoResult result = ReadDataRaw( | 155 MojoResult result = ReadDataRaw(response->body.get(), buf, &num_bytes, |
146 response->body.get(), buf, &num_bytes, MOJO_READ_DATA_FLAG_NONE); | 156 MOJO_READ_DATA_FLAG_NONE); |
147 if (result == MOJO_RESULT_SHOULD_WAIT) { | 157 if (result == MOJO_RESULT_SHOULD_WAIT) { |
148 Wait(response->body.get(), | 158 Wait(response->body.get(), MOJO_HANDLE_SIGNAL_READABLE, |
149 MOJO_HANDLE_SIGNAL_READABLE, | |
150 MOJO_DEADLINE_INDEFINITE); | 159 MOJO_DEADLINE_INDEFINITE); |
151 } else if (result == MOJO_RESULT_OK) { | 160 } else if (result == MOJO_RESULT_OK) { |
152 buf += num_bytes; | 161 buf += num_bytes; |
153 num_bytes = bytes_remaining -= num_bytes; | 162 num_bytes = bytes_remaining -= num_bytes; |
154 } else { | 163 } else { |
155 break; | 164 break; |
156 } | 165 } |
157 } | 166 } |
158 | 167 |
159 bitmap_.reset(new std::vector<unsigned char>); | 168 bitmap_.reset(new std::vector<unsigned char>); |
160 gfx::PNGCodec::Decode(static_cast<const unsigned char*>(data.get()), | 169 gfx::PNGCodec::Decode(static_cast<const unsigned char*>(data.get()), |
161 content_length, | 170 content_length, gfx::PNGCodec::FORMAT_BGRA, |
162 gfx::PNGCodec::FORMAT_BGRA, | 171 bitmap_.get(), &width_, &height_); |
163 bitmap_.get(), | |
164 &width_, | |
165 &height_); | |
166 } | 172 } |
167 | 173 |
168 int GetContentLength(const Array<String>& headers) { | 174 int GetContentLength(const Array<String>& headers) { |
169 for (size_t i = 0; i < headers.size(); ++i) { | 175 for (size_t i = 0; i < headers.size(); ++i) { |
170 base::StringTokenizer t(headers[i], ": ;="); | 176 base::StringTokenizer t(headers[i], ": ;="); |
171 while (t.GetNext()) { | 177 while (t.GetNext()) { |
172 if (!t.token_is_delim() && t.token() == "Content-Length") { | 178 if (!t.token_is_delim() && t.token() == "Content-Length") { |
173 while (t.GetNext()) { | 179 while (t.GetNext()) { |
174 if (!t.token_is_delim()) | 180 if (!t.token_is_delim()) |
175 return atoi(t.token().c_str()); | 181 return atoi(t.token().c_str()); |
176 } | 182 } |
177 } | 183 } |
178 } | 184 } |
179 } | 185 } |
180 return 0; | 186 return 0; |
181 } | 187 } |
182 | 188 |
183 int width_; | 189 int width_; |
184 int height_; | 190 int height_; |
185 scoped_ptr<std::vector<unsigned char>> bitmap_; | 191 scoped_ptr<std::vector<unsigned char>> bitmap_; |
186 ApplicationImpl* app_; | 192 ApplicationImpl* app_; |
187 View* root_; | 193 std::map<View*, EmbedderData*> embedder_for_roots_; |
188 scoped_ptr<ViewManagerClientFactory> view_manager_client_factory_; | 194 scoped_ptr<ViewManagerClientFactory> view_manager_client_factory_; |
189 uint16_t zoom_percentage_; | 195 uint16_t zoom_percentage_; |
190 scoped_ptr<BitmapUploader> bitmap_uploader_; | |
191 | 196 |
192 DISALLOW_COPY_AND_ASSIGN(PNGView); | 197 DISALLOW_COPY_AND_ASSIGN(PNGView); |
193 }; | 198 }; |
194 | 199 |
195 class PNGViewer : public ApplicationDelegate, | 200 class PNGViewer : public ApplicationDelegate, |
196 public ContentHandlerFactory::Delegate { | 201 public ContentHandlerFactory::Delegate { |
197 public: | 202 public: |
198 PNGViewer() : content_handler_factory_(this) {} | 203 PNGViewer() : content_handler_factory_(this) {} |
199 | 204 |
200 private: | 205 private: |
(...skipping 16 matching lines...) Expand all Loading... | |
217 DISALLOW_COPY_AND_ASSIGN(PNGViewer); | 222 DISALLOW_COPY_AND_ASSIGN(PNGViewer); |
218 }; | 223 }; |
219 | 224 |
220 } // namespace examples | 225 } // namespace examples |
221 } // namespace mojo | 226 } // namespace mojo |
222 | 227 |
223 MojoResult MojoMain(MojoHandle shell_handle) { | 228 MojoResult MojoMain(MojoHandle shell_handle) { |
224 mojo::ApplicationRunnerChromium runner(new mojo::examples::PNGViewer()); | 229 mojo::ApplicationRunnerChromium runner(new mojo::examples::PNGViewer()); |
225 return runner.Run(shell_handle); | 230 return runner.Run(shell_handle); |
226 } | 231 } |
OLD | NEW |