Introduce new SPDY Version UMA histogram.
[chromium-blink-merge.git] / mojo / examples / png_viewer / png_viewer.cc
blob4e0b6c7bc1cebe0d45d65c7df82d9946f0b6ef85
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
3 // found in the LICENSE file.
5 #include <algorithm>
7 #include "base/memory/scoped_ptr.h"
8 #include "base/message_loop/message_loop.h"
9 #include "base/strings/string_tokenizer.h"
10 #include "mojo/application/application_runner_chromium.h"
11 #include "mojo/examples/media_viewer/media_viewer.mojom.h"
12 #include "mojo/public/c/system/main.h"
13 #include "mojo/public/cpp/application/application_connection.h"
14 #include "mojo/public/cpp/application/application_delegate.h"
15 #include "mojo/public/cpp/application/application_impl.h"
16 #include "mojo/public/cpp/application/interface_factory_impl.h"
17 #include "mojo/public/cpp/application/service_provider_impl.h"
18 #include "mojo/services/public/cpp/view_manager/types.h"
19 #include "mojo/services/public/cpp/view_manager/view.h"
20 #include "mojo/services/public/cpp/view_manager/view_manager.h"
21 #include "mojo/services/public/cpp/view_manager/view_manager_client_factory.h"
22 #include "mojo/services/public/cpp/view_manager/view_manager_delegate.h"
23 #include "mojo/services/public/cpp/view_manager/view_observer.h"
24 #include "mojo/services/public/interfaces/content_handler/content_handler.mojom.h"
25 #include "skia/ext/platform_canvas.h"
26 #include "skia/ext/refptr.h"
27 #include "third_party/skia/include/core/SkBitmap.h"
28 #include "third_party/skia/include/core/SkCanvas.h"
29 #include "third_party/skia/include/core/SkPaint.h"
30 #include "third_party/skia/include/core/SkScalar.h"
31 #include "ui/gfx/codec/png_codec.h"
33 namespace mojo {
34 namespace examples {
36 class PNGViewer;
38 // TODO(aa): Hook up ZoomableMedia interface again.
39 class PNGView : public ViewManagerDelegate, public ViewObserver {
40 public:
41 static void Spawn(URLResponsePtr response,
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);
50 private:
51 static const uint16_t kMaxZoomPercentage = 400;
52 static const uint16_t kMinZoomPercentage = 20;
53 static const uint16_t kDefaultZoomPercentage = 100;
54 static const uint16_t kZoomStep = 20;
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());
68 virtual ~PNGView() {
69 if (root_)
70 root_->RemoveObserver(this);
73 // Overridden from ViewManagerDelegate:
74 virtual void OnEmbed(ViewManager* view_manager,
75 View* root,
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();
85 virtual void OnViewManagerDisconnected(ViewManager* view_manager) OVERRIDE {
86 // TODO(aa): Need to figure out how shutdown works.
89 // Overridden from ViewObserver:
90 virtual void OnViewBoundsChanged(View* view,
91 const gfx::Rect& old_bounds,
92 const gfx::Rect& new_bounds) OVERRIDE {
93 DCHECK_EQ(view, root_);
94 DrawBitmap();
97 virtual void OnViewDestroyed(View* view) OVERRIDE {
98 DCHECK_EQ(view, root_);
99 delete this;
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();
106 uint32_t bytes_remaining = content_length;
107 uint32_t num_bytes = bytes_remaining;
108 while (bytes_remaining > 0) {
109 MojoResult result = ReadDataRaw(
110 response->body.get(), buf, &num_bytes, MOJO_READ_DATA_FLAG_NONE);
111 if (result == MOJO_RESULT_SHOULD_WAIT) {
112 Wait(response->body.get(),
113 MOJO_HANDLE_SIGNAL_READABLE,
114 MOJO_DEADLINE_INDEFINITE);
115 } else if (result == MOJO_RESULT_OK) {
116 buf += num_bytes;
117 num_bytes = bytes_remaining -= num_bytes;
118 } else {
119 break;
123 gfx::PNGCodec::Decode(static_cast<const unsigned char*>(data.get()),
124 content_length,
125 &bitmap_);
128 void DrawBitmap() {
129 if (!root_)
130 return;
132 skia::RefPtr<SkCanvas> canvas(skia::AdoptRef(skia::CreatePlatformCanvas(
133 root_->bounds().width(), root_->bounds().height(), true)));
134 canvas->drawColor(SK_ColorGRAY);
135 SkPaint paint;
136 SkScalar scale =
137 SkFloatToScalar(zoom_percentage_ * 1.0f / kDefaultZoomPercentage);
138 canvas->scale(scale, scale);
139 canvas->drawBitmap(bitmap_, 0, 0, &paint);
140 root_->SetContents(skia::GetTopDevice(*canvas)->accessBitmap(true));
143 void ZoomIn() {
144 if (zoom_percentage_ >= kMaxZoomPercentage)
145 return;
146 zoom_percentage_ += kZoomStep;
147 DrawBitmap();
150 void ZoomOut() {
151 if (zoom_percentage_ <= kMinZoomPercentage)
152 return;
153 zoom_percentage_ -= kZoomStep;
154 DrawBitmap();
157 void ZoomToActualSize() {
158 if (zoom_percentage_ == kDefaultZoomPercentage)
159 return;
160 zoom_percentage_ = kDefaultZoomPercentage;
161 DrawBitmap();
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());
176 return 0;
179 SkBitmap bitmap_;
180 scoped_ptr<ServiceProvider> imported_services_;
181 View* root_;
182 ViewManagerClientFactory view_manager_client_factory_;
183 uint16_t zoom_percentage_;
185 DISALLOW_COPY_AND_ASSIGN(PNGView);
188 class ContentHandlerImpl : public InterfaceImpl<ContentHandler> {
189 public:
190 explicit ContentHandlerImpl(Shell* shell) : shell_(shell) {}
191 virtual ~ContentHandlerImpl() {}
193 private:
194 // Overridden from ContentHandler:
195 virtual void OnConnect(
196 const mojo::String& url,
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_);
206 Shell* shell_;
208 DISALLOW_COPY_AND_ASSIGN(ContentHandlerImpl);
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()));
222 // Overridden from ApplicationDelegate:
223 virtual bool ConfigureIncomingConnection(ApplicationConnection* connection)
224 MOJO_OVERRIDE {
225 connection->AddService(content_handler_factory_.get());
226 return true;
229 scoped_ptr<InterfaceFactoryImplWithContext<ContentHandlerImpl, Shell> >
230 content_handler_factory_;
232 DISALLOW_COPY_AND_ASSIGN(PNGViewer);
235 } // namespace examples
236 } // namespace mojo
238 MojoResult MojoMain(MojoHandle shell_handle) {
239 mojo::ApplicationRunnerChromium runner(new mojo::examples::PNGViewer);
240 return runner.Run(shell_handle);