| 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/memory/scoped_ptr.h" |
| 7 #include "base/message_loop/message_loop.h" | 8 #include "base/message_loop/message_loop.h" |
| 8 #include "base/strings/string_tokenizer.h" | 9 #include "base/strings/string_tokenizer.h" |
| 9 #include "mojo/examples/media_viewer/media_viewer.mojom.h" | 10 #include "mojo/examples/media_viewer/media_viewer.mojom.h" |
| 10 #include "mojo/public/c/system/main.h" | 11 #include "mojo/public/c/system/main.h" |
| 11 #include "mojo/public/cpp/application/application_connection.h" | 12 #include "mojo/public/cpp/application/application_connection.h" |
| 12 #include "mojo/public/cpp/application/application_delegate.h" | 13 #include "mojo/public/cpp/application/application_delegate.h" |
| 14 #include "mojo/public/cpp/application/application_impl.h" |
| 13 #include "mojo/public/cpp/application/application_runner_chromium.h" | 15 #include "mojo/public/cpp/application/application_runner_chromium.h" |
| 14 #include "mojo/public/cpp/application/interface_factory_impl.h" | 16 #include "mojo/public/cpp/application/interface_factory_impl.h" |
| 17 #include "mojo/public/cpp/application/service_provider_impl.h" |
| 15 #include "mojo/services/public/cpp/view_manager/types.h" | 18 #include "mojo/services/public/cpp/view_manager/types.h" |
| 16 #include "mojo/services/public/cpp/view_manager/view.h" | 19 #include "mojo/services/public/cpp/view_manager/view.h" |
| 17 #include "mojo/services/public/cpp/view_manager/view_manager.h" | 20 #include "mojo/services/public/cpp/view_manager/view_manager.h" |
| 18 #include "mojo/services/public/cpp/view_manager/view_manager_client_factory.h" | 21 #include "mojo/services/public/cpp/view_manager/view_manager_client_factory.h" |
| 19 #include "mojo/services/public/cpp/view_manager/view_manager_delegate.h" | 22 #include "mojo/services/public/cpp/view_manager/view_manager_delegate.h" |
| 20 #include "mojo/services/public/cpp/view_manager/view_observer.h" | 23 #include "mojo/services/public/cpp/view_manager/view_observer.h" |
| 21 #include "mojo/services/public/interfaces/navigation/navigation.mojom.h" | 24 #include "mojo/services/public/interfaces/content_handler/content_handler.mojom.
h" |
| 22 #include "skia/ext/platform_canvas.h" | 25 #include "skia/ext/platform_canvas.h" |
| 23 #include "skia/ext/refptr.h" | 26 #include "skia/ext/refptr.h" |
| 24 #include "third_party/skia/include/core/SkBitmap.h" | 27 #include "third_party/skia/include/core/SkBitmap.h" |
| 25 #include "third_party/skia/include/core/SkCanvas.h" | 28 #include "third_party/skia/include/core/SkCanvas.h" |
| 26 #include "third_party/skia/include/core/SkPaint.h" | 29 #include "third_party/skia/include/core/SkPaint.h" |
| 27 #include "third_party/skia/include/core/SkScalar.h" | 30 #include "third_party/skia/include/core/SkScalar.h" |
| 28 #include "ui/gfx/codec/png_codec.h" | 31 #include "ui/gfx/codec/png_codec.h" |
| 29 | 32 |
| 30 namespace mojo { | 33 namespace mojo { |
| 31 namespace examples { | 34 namespace examples { |
| 32 | 35 |
| 33 class PNGViewer; | 36 class PNGViewer; |
| 34 | 37 |
| 35 class ZoomableMediaImpl : public InterfaceImpl<ZoomableMedia> { | 38 // TODO(aa): Hook up ZoomableMedia interface again. |
| 39 class PNGView : public ViewManagerDelegate, public ViewObserver { |
| 36 public: | 40 public: |
| 37 explicit ZoomableMediaImpl(PNGViewer* viewer) : viewer_(viewer) {} | 41 static void Spawn(URLResponsePtr response, |
| 38 virtual ~ZoomableMediaImpl() {} | 42 ServiceProviderImpl* exported_services, |
| 43 scoped_ptr<ServiceProvider> imported_services, |
| 44 Shell* shell) { |
| 45 // PNGView deletes itself when its View is destroyed. |
| 46 new PNGView( |
| 47 response.Pass(), exported_services, imported_services.Pass(), shell); |
| 48 } |
| 39 | 49 |
| 40 private: | 50 private: |
| 41 // Overridden from ZoomableMedia: | 51 static const uint16_t kMaxZoomPercentage = 400; |
| 42 virtual void ZoomIn() OVERRIDE; | 52 static const uint16_t kMinZoomPercentage = 20; |
| 43 virtual void ZoomOut() OVERRIDE; | 53 static const uint16_t kDefaultZoomPercentage = 100; |
| 44 virtual void ZoomToActualSize() OVERRIDE; | 54 static const uint16_t kZoomStep = 20; |
| 45 | 55 |
| 46 PNGViewer* viewer_; | 56 PNGView(URLResponsePtr response, |
| 57 ServiceProviderImpl* exported_services, |
| 58 scoped_ptr<ServiceProvider> imported_services, |
| 59 Shell* shell) |
| 60 : imported_services_(imported_services.Pass()), |
| 61 root_(NULL), |
| 62 view_manager_client_factory_(shell, this), |
| 63 zoom_percentage_(kDefaultZoomPercentage) { |
| 64 exported_services->AddService(&view_manager_client_factory_); |
| 65 DecodePNG(response.Pass()); |
| 66 } |
| 47 | 67 |
| 48 DISALLOW_COPY_AND_ASSIGN(ZoomableMediaImpl); | 68 virtual ~PNGView() { |
| 49 }; | 69 if (root_) |
| 70 root_->RemoveObserver(this); |
| 71 } |
| 50 | 72 |
| 51 class NavigatorImpl : public InterfaceImpl<Navigator> { | 73 // Overridden from ViewManagerDelegate: |
| 52 public: | 74 virtual void OnEmbed(ViewManager* view_manager, |
| 53 explicit NavigatorImpl(PNGViewer* viewer) : viewer_(viewer) {} | 75 View* root, |
| 54 virtual ~NavigatorImpl() {} | 76 ServiceProviderImpl* exported_services, |
| 77 scoped_ptr<ServiceProvider> imported_services) OVERRIDE { |
| 78 root_ = root; |
| 79 root_->AddObserver(this); |
| 80 root_->SetColor(SK_ColorGRAY); |
| 81 if (!bitmap_.isNull()) |
| 82 DrawBitmap(); |
| 83 } |
| 55 | 84 |
| 56 private: | 85 virtual void OnViewManagerDisconnected(ViewManager* view_manager) OVERRIDE { |
| 57 // Overridden from Navigator: | 86 // TODO(aa): Need to figure out how shutdown works. |
| 58 virtual void Navigate( | 87 } |
| 59 uint32_t view_id, | 88 |
| 60 NavigationDetailsPtr navigation_details, | 89 // Overridden from ViewObserver: |
| 61 ResponseDetailsPtr response_details) OVERRIDE { | 90 virtual void OnViewBoundsChanged(View* view, |
| 62 int content_length = GetContentLength(response_details->response->headers); | 91 const gfx::Rect& old_bounds, |
| 63 unsigned char* data = new unsigned char[content_length]; | 92 const gfx::Rect& new_bounds) OVERRIDE { |
| 64 unsigned char* buf = data; | 93 DCHECK_EQ(view, root_); |
| 94 DrawBitmap(); |
| 95 } |
| 96 |
| 97 virtual void OnViewDestroyed(View* view) OVERRIDE { |
| 98 DCHECK_EQ(view, root_); |
| 99 delete this; |
| 100 } |
| 101 |
| 102 void DecodePNG(URLResponsePtr response) { |
| 103 int content_length = GetContentLength(response->headers); |
| 104 scoped_ptr<unsigned char[]> data(new unsigned char[content_length]); |
| 105 unsigned char* buf = data.get(); |
| 65 uint32_t bytes_remaining = content_length; | 106 uint32_t bytes_remaining = content_length; |
| 66 uint32_t num_bytes = bytes_remaining; | 107 uint32_t num_bytes = bytes_remaining; |
| 67 while (bytes_remaining > 0) { | 108 while (bytes_remaining > 0) { |
| 68 MojoResult result = ReadDataRaw( | 109 MojoResult result = ReadDataRaw( |
| 69 response_details->response->body.get(), | 110 response->body.get(), buf, &num_bytes, MOJO_READ_DATA_FLAG_NONE); |
| 70 buf, | |
| 71 &num_bytes, | |
| 72 MOJO_READ_DATA_FLAG_NONE); | |
| 73 if (result == MOJO_RESULT_SHOULD_WAIT) { | 111 if (result == MOJO_RESULT_SHOULD_WAIT) { |
| 74 Wait(response_details->response->body.get(), | 112 Wait(response->body.get(), |
| 75 MOJO_HANDLE_SIGNAL_READABLE, | 113 MOJO_HANDLE_SIGNAL_READABLE, |
| 76 MOJO_DEADLINE_INDEFINITE); | 114 MOJO_DEADLINE_INDEFINITE); |
| 77 } else if (result == MOJO_RESULT_OK) { | 115 } else if (result == MOJO_RESULT_OK) { |
| 78 buf += num_bytes; | 116 buf += num_bytes; |
| 79 num_bytes = bytes_remaining -= num_bytes; | 117 num_bytes = bytes_remaining -= num_bytes; |
| 80 } else { | 118 } else { |
| 81 break; | 119 break; |
| 82 } | 120 } |
| 83 } | 121 } |
| 84 | 122 |
| 85 SkBitmap bitmap; | 123 gfx::PNGCodec::Decode(static_cast<const unsigned char*>(data.get()), |
| 86 gfx::PNGCodec::Decode(static_cast<const unsigned char*>(data), | 124 content_length, |
| 87 content_length, &bitmap); | 125 &bitmap_); |
| 88 UpdateView(view_id, bitmap); | |
| 89 | |
| 90 delete[] data; | |
| 91 } | 126 } |
| 92 | 127 |
| 93 void UpdateView(Id view_id, const SkBitmap& bitmap); | 128 void DrawBitmap() { |
| 129 if (!root_) |
| 130 return; |
| 94 | 131 |
| 95 int GetContentLength(const Array<String>& headers) { | 132 skia::RefPtr<SkCanvas> canvas(skia::AdoptRef(skia::CreatePlatformCanvas( |
| 96 for (size_t i = 0; i < headers.size(); ++i) { | 133 root_->bounds().width(), root_->bounds().height(), true))); |
| 97 base::StringTokenizer t(headers[i], ": ;="); | 134 canvas->drawColor(SK_ColorGRAY); |
| 98 while (t.GetNext()) { | 135 SkPaint paint; |
| 99 if (!t.token_is_delim() && t.token() == "Content-Length") { | 136 SkScalar scale = |
| 100 while (t.GetNext()) { | 137 SkFloatToScalar(zoom_percentage_ * 1.0f / kDefaultZoomPercentage); |
| 101 if (!t.token_is_delim()) | 138 canvas->scale(scale, scale); |
| 102 return atoi(t.token().c_str()); | 139 canvas->drawBitmap(bitmap_, 0, 0, &paint); |
| 103 } | 140 root_->SetContents(skia::GetTopDevice(*canvas)->accessBitmap(true)); |
| 104 } | |
| 105 } | |
| 106 } | |
| 107 return 0; | |
| 108 } | |
| 109 | |
| 110 PNGViewer* viewer_; | |
| 111 | |
| 112 DISALLOW_COPY_AND_ASSIGN(NavigatorImpl); | |
| 113 }; | |
| 114 | |
| 115 class PNGViewer | |
| 116 : public ApplicationDelegate, | |
| 117 public ViewManagerDelegate, | |
| 118 public ViewObserver { | |
| 119 public: | |
| 120 PNGViewer() | |
| 121 : navigator_factory_(this), | |
| 122 zoomable_media_factory_(this), | |
| 123 view_manager_client_factory_(this), | |
| 124 root_(NULL), | |
| 125 zoom_percentage_(kDefaultZoomPercentage) {} | |
| 126 virtual ~PNGViewer() { | |
| 127 if (root_) | |
| 128 root_->RemoveObserver(this); | |
| 129 } | |
| 130 | |
| 131 void UpdateView(Id view_id, const SkBitmap& bitmap) { | |
| 132 bitmap_ = bitmap; | |
| 133 zoom_percentage_ = kDefaultZoomPercentage; | |
| 134 DrawBitmap(); | |
| 135 } | 141 } |
| 136 | 142 |
| 137 void ZoomIn() { | 143 void ZoomIn() { |
| 138 if (zoom_percentage_ >= kMaxZoomPercentage) | 144 if (zoom_percentage_ >= kMaxZoomPercentage) |
| 139 return; | 145 return; |
| 140 zoom_percentage_ += kZoomStep; | 146 zoom_percentage_ += kZoomStep; |
| 141 DrawBitmap(); | 147 DrawBitmap(); |
| 142 } | 148 } |
| 143 | 149 |
| 144 void ZoomOut() { | 150 void ZoomOut() { |
| 145 if (zoom_percentage_ <= kMinZoomPercentage) | 151 if (zoom_percentage_ <= kMinZoomPercentage) |
| 146 return; | 152 return; |
| 147 zoom_percentage_ -= kZoomStep; | 153 zoom_percentage_ -= kZoomStep; |
| 148 DrawBitmap(); | 154 DrawBitmap(); |
| 149 } | 155 } |
| 150 | 156 |
| 151 void ZoomToActualSize() { | 157 void ZoomToActualSize() { |
| 152 if (zoom_percentage_ == kDefaultZoomPercentage) | 158 if (zoom_percentage_ == kDefaultZoomPercentage) |
| 153 return; | 159 return; |
| 154 zoom_percentage_ = kDefaultZoomPercentage; | 160 zoom_percentage_ = kDefaultZoomPercentage; |
| 155 DrawBitmap(); | 161 DrawBitmap(); |
| 156 } | 162 } |
| 157 | 163 |
| 164 int GetContentLength(const Array<String>& headers) { |
| 165 for (size_t i = 0; i < headers.size(); ++i) { |
| 166 base::StringTokenizer t(headers[i], ": ;="); |
| 167 while (t.GetNext()) { |
| 168 if (!t.token_is_delim() && t.token() == "Content-Length") { |
| 169 while (t.GetNext()) { |
| 170 if (!t.token_is_delim()) |
| 171 return atoi(t.token().c_str()); |
| 172 } |
| 173 } |
| 174 } |
| 175 } |
| 176 return 0; |
| 177 } |
| 178 |
| 179 SkBitmap bitmap_; |
| 180 scoped_ptr<ServiceProvider> imported_services_; |
| 181 View* root_; |
| 182 ViewManagerClientFactory view_manager_client_factory_; |
| 183 uint16_t zoom_percentage_; |
| 184 |
| 185 DISALLOW_COPY_AND_ASSIGN(PNGView); |
| 186 }; |
| 187 |
| 188 class ContentHandlerImpl : public InterfaceImpl<ContentHandler> { |
| 189 public: |
| 190 explicit ContentHandlerImpl(Shell* shell) : shell_(shell) {} |
| 191 virtual ~ContentHandlerImpl() {} |
| 192 |
| 158 private: | 193 private: |
| 159 static const uint16_t kMaxZoomPercentage = 400; | 194 // Overridden from ContentHandler: |
| 160 static const uint16_t kMinZoomPercentage = 20; | 195 virtual void OnConnect( |
| 161 static const uint16_t kDefaultZoomPercentage = 100; | 196 const mojo::String& url, |
| 162 static const uint16_t kZoomStep = 20; | 197 URLResponsePtr response, |
| 198 InterfaceRequest<ServiceProvider> service_provider) OVERRIDE { |
| 199 ServiceProviderImpl* exported_services = new ServiceProviderImpl(); |
| 200 BindToRequest(exported_services, &service_provider); |
| 201 scoped_ptr<ServiceProvider> remote( |
| 202 exported_services->CreateRemoteServiceProvider()); |
| 203 PNGView::Spawn(response.Pass(), exported_services, remote.Pass(), shell_); |
| 204 } |
| 205 |
| 206 Shell* shell_; |
| 207 |
| 208 DISALLOW_COPY_AND_ASSIGN(ContentHandlerImpl); |
| 209 }; |
| 210 |
| 211 class PNGViewer : public ApplicationDelegate { |
| 212 public: |
| 213 PNGViewer() {} |
| 214 private: |
| 215 // Overridden from ApplicationDelegate: |
| 216 virtual void Initialize(ApplicationImpl* app) MOJO_OVERRIDE { |
| 217 content_handler_factory_.reset( |
| 218 new InterfaceFactoryImplWithContext<ContentHandlerImpl, Shell>( |
| 219 app->shell())); |
| 220 } |
| 163 | 221 |
| 164 // Overridden from ApplicationDelegate: | 222 // Overridden from ApplicationDelegate: |
| 165 virtual bool ConfigureIncomingConnection(ApplicationConnection* connection) | 223 virtual bool ConfigureIncomingConnection(ApplicationConnection* connection) |
| 166 MOJO_OVERRIDE { | 224 MOJO_OVERRIDE { |
| 167 connection->AddService(&navigator_factory_); | 225 connection->AddService(content_handler_factory_.get()); |
| 168 connection->AddService(&zoomable_media_factory_); | |
| 169 connection->AddService(&view_manager_client_factory_); | |
| 170 return true; | 226 return true; |
| 171 } | 227 } |
| 172 | 228 |
| 173 // Overridden from ViewManagerDelegate: | 229 scoped_ptr<InterfaceFactoryImplWithContext<ContentHandlerImpl, Shell> > |
| 174 virtual void OnEmbed(ViewManager* view_manager, | 230 content_handler_factory_; |
| 175 View* root, | |
| 176 ServiceProviderImpl* exported_services, | |
| 177 scoped_ptr<ServiceProvider> imported_services) OVERRIDE { | |
| 178 root_ = root; | |
| 179 root_->AddObserver(this); | |
| 180 root_->SetColor(SK_ColorGRAY); | |
| 181 if (!bitmap_.isNull()) | |
| 182 DrawBitmap(); | |
| 183 } | |
| 184 virtual void OnViewManagerDisconnected( | |
| 185 ViewManager* view_manager) OVERRIDE { | |
| 186 base::MessageLoop::current()->Quit(); | |
| 187 } | |
| 188 | |
| 189 void DrawBitmap() { | |
| 190 if (!root_) | |
| 191 return; | |
| 192 | |
| 193 skia::RefPtr<SkCanvas> canvas(skia::AdoptRef(skia::CreatePlatformCanvas( | |
| 194 root_->bounds().width(), | |
| 195 root_->bounds().height(), | |
| 196 true))); | |
| 197 canvas->drawColor(SK_ColorGRAY); | |
| 198 SkPaint paint; | |
| 199 SkScalar scale = | |
| 200 SkFloatToScalar(zoom_percentage_ * 1.0f / kDefaultZoomPercentage); | |
| 201 canvas->scale(scale, scale); | |
| 202 canvas->drawBitmap(bitmap_, 0, 0, &paint); | |
| 203 root_->SetContents(skia::GetTopDevice(*canvas)->accessBitmap(true)); | |
| 204 } | |
| 205 | |
| 206 // ViewObserver: | |
| 207 virtual void OnViewBoundsChanged(View* view, | |
| 208 const gfx::Rect& old_bounds, | |
| 209 const gfx::Rect& new_bounds) OVERRIDE { | |
| 210 DCHECK_EQ(view, root_); | |
| 211 DrawBitmap(); | |
| 212 } | |
| 213 virtual void OnViewDestroyed(View* view) OVERRIDE { | |
| 214 DCHECK_EQ(view, root_); | |
| 215 view->RemoveObserver(this); | |
| 216 root_ = NULL; | |
| 217 } | |
| 218 | |
| 219 InterfaceFactoryImplWithContext<NavigatorImpl, PNGViewer> navigator_factory_; | |
| 220 InterfaceFactoryImplWithContext<ZoomableMediaImpl, PNGViewer> | |
| 221 zoomable_media_factory_; | |
| 222 ViewManagerClientFactory view_manager_client_factory_; | |
| 223 | |
| 224 View* root_; | |
| 225 SkBitmap bitmap_; | |
| 226 uint16_t zoom_percentage_; | |
| 227 | 231 |
| 228 DISALLOW_COPY_AND_ASSIGN(PNGViewer); | 232 DISALLOW_COPY_AND_ASSIGN(PNGViewer); |
| 229 }; | 233 }; |
| 230 | 234 |
| 231 void ZoomableMediaImpl::ZoomIn() { | |
| 232 viewer_->ZoomIn(); | |
| 233 } | |
| 234 | |
| 235 void ZoomableMediaImpl::ZoomOut() { | |
| 236 viewer_->ZoomOut(); | |
| 237 } | |
| 238 | |
| 239 void ZoomableMediaImpl::ZoomToActualSize() { | |
| 240 viewer_->ZoomToActualSize(); | |
| 241 } | |
| 242 | |
| 243 void NavigatorImpl::UpdateView(Id view_id, | |
| 244 const SkBitmap& bitmap) { | |
| 245 viewer_->UpdateView(view_id, bitmap); | |
| 246 } | |
| 247 | |
| 248 } // namespace examples | 235 } // namespace examples |
| 249 } // namespace mojo | 236 } // namespace mojo |
| 250 | 237 |
| 251 MojoResult MojoMain(MojoHandle shell_handle) { | 238 MojoResult MojoMain(MojoHandle shell_handle) { |
| 252 mojo::ApplicationRunnerChromium runner(new mojo::examples::PNGViewer); | 239 mojo::ApplicationRunnerChromium runner(new mojo::examples::PNGViewer); |
| 253 return runner.Run(shell_handle); | 240 return runner.Run(shell_handle); |
| 254 } | 241 } |
| OLD | NEW |