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 "base/bind.h" |
5 #include "base/command_line.h" | 6 #include "base/command_line.h" |
6 #include "base/i18n/icu_util.h" | |
7 #include "base/logging.h" | 7 #include "base/logging.h" |
8 #include "base/macros.h" | 8 #include "base/macros.h" |
9 #include "base/message_loop/message_loop.h" | 9 #include "base/message_loop/message_loop.h" |
10 #include "base/path_service.h" | 10 #include "base/path_service.h" |
11 #include "base/strings/utf_string_conversions.h" | 11 #include "base/strings/utf_string_conversions.h" |
12 #include "base/threading/thread.h" | |
13 #include "components/html_viewer/blink_platform_impl.h" | |
14 #include "components/html_viewer/discardable_memory_allocator.h" | |
15 #include "components/html_viewer/html_document.h" | 12 #include "components/html_viewer/html_document.h" |
16 #include "components/html_viewer/web_media_player_factory.h" | 13 #include "components/html_viewer/setup.h" |
17 #include "components/resource_provider/public/cpp/resource_loader.h" | |
18 #include "components/resource_provider/public/interfaces/resource_provider.mojom
.h" | |
19 #include "components/scheduler/renderer/renderer_scheduler.h" | |
20 #include "gin/v8_initializer.h" | |
21 #include "mojo/application/application_runner_chromium.h" | 14 #include "mojo/application/application_runner_chromium.h" |
22 #include "mojo/common/common_type_converters.h" | 15 #include "mojo/common/common_type_converters.h" |
23 #include "mojo/platform_handle/platform_handle_functions.h" | |
24 #include "mojo/services/network/public/interfaces/network_service.mojom.h" | 16 #include "mojo/services/network/public/interfaces/network_service.mojom.h" |
25 #include "third_party/WebKit/public/web/WebKit.h" | 17 #include "third_party/WebKit/public/web/WebKit.h" |
26 #include "third_party/WebKit/public/web/WebRuntimeFeatures.h" | |
27 #include "third_party/mojo/src/mojo/public/c/system/main.h" | 18 #include "third_party/mojo/src/mojo/public/c/system/main.h" |
28 #include "third_party/mojo/src/mojo/public/cpp/application/application_connectio
n.h" | 19 #include "third_party/mojo/src/mojo/public/cpp/application/application_connectio
n.h" |
29 #include "third_party/mojo/src/mojo/public/cpp/application/application_delegate.
h" | 20 #include "third_party/mojo/src/mojo/public/cpp/application/application_delegate.
h" |
30 #include "third_party/mojo/src/mojo/public/cpp/application/application_impl.h" | 21 #include "third_party/mojo/src/mojo/public/cpp/application/application_impl.h" |
31 #include "third_party/mojo/src/mojo/public/cpp/application/connect.h" | 22 #include "third_party/mojo/src/mojo/public/cpp/application/connect.h" |
32 #include "third_party/mojo/src/mojo/public/cpp/application/interface_factory_imp
l.h" | 23 #include "third_party/mojo/src/mojo/public/cpp/application/interface_factory_imp
l.h" |
33 #include "third_party/mojo/src/mojo/public/cpp/bindings/strong_binding.h" | 24 #include "third_party/mojo/src/mojo/public/cpp/bindings/strong_binding.h" |
34 #include "third_party/mojo_services/src/content_handler/public/interfaces/conten
t_handler.mojom.h" | 25 #include "third_party/mojo_services/src/content_handler/public/interfaces/conten
t_handler.mojom.h" |
35 #include "ui/base/resource/resource_bundle.h" | |
36 #include "ui/base/ui_base_paths.h" | |
37 | |
38 #if defined(OS_ANDROID) | |
39 #include "components/html_viewer/ui_setup_android.h" | |
40 #else | |
41 #include "components/html_viewer/ui_setup.h" | |
42 #endif | |
43 | 26 |
44 using mojo::ApplicationConnection; | 27 using mojo::ApplicationConnection; |
45 using mojo::Array; | 28 using mojo::Array; |
46 using mojo::BindToRequest; | 29 using mojo::BindToRequest; |
47 using mojo::ContentHandler; | 30 using mojo::ContentHandler; |
48 using mojo::InterfaceRequest; | 31 using mojo::InterfaceRequest; |
49 using mojo::ServiceProvider; | 32 using mojo::ServiceProvider; |
50 using mojo::ServiceProviderPtr; | 33 using mojo::ServiceProviderPtr; |
51 using mojo::ShellPtr; | 34 using mojo::ShellPtr; |
52 using mojo::String; | 35 using mojo::String; |
53 using mojo::URLLoaderPtr; | 36 using mojo::URLLoaderPtr; |
54 using mojo::URLResponsePtr; | 37 using mojo::URLResponsePtr; |
55 using resource_provider::ResourceLoader; | |
56 | 38 |
57 namespace html_viewer { | 39 namespace html_viewer { |
58 namespace { | |
59 // Switches for html_viewer. | |
60 | |
61 // Enable MediaRenderer in media pipeline instead of using the internal | |
62 // media::Renderer implementation. | |
63 const char kEnableMojoMediaRenderer[] = "enable-mojo-media-renderer"; | |
64 | |
65 // Disables support for (unprefixed) Encrypted Media Extensions. | |
66 const char kDisableEncryptedMedia[] = "disable-encrypted-media"; | |
67 | |
68 // Prevents creation of any output surface. | |
69 const char kIsHeadless[] = "is-headless"; | |
70 | |
71 size_t kDesiredMaxMemory = 20 * 1024 * 1024; | |
72 | |
73 // Paths resources are loaded from. | |
74 const char kResourceIcudtl[] = "icudtl.dat"; | |
75 const char kResourceResourcesPak[] = "html_viewer_resources.pak"; | |
76 const char kResourceUIPak[] = "ui_test.pak"; | |
77 #if defined(V8_USE_EXTERNAL_STARTUP_DATA) | |
78 const char kResourceNativesBlob[] = "natives_blob.bin"; | |
79 const char kResourceSnapshotBlob[] = "snapshot_blob.bin"; | |
80 #endif | |
81 | |
82 } // namespace | |
83 | 40 |
84 class HTMLViewer; | 41 class HTMLViewer; |
85 | 42 |
86 class HTMLViewerApplication : public mojo::Application { | 43 class HTMLViewerApplication : public mojo::Application { |
87 public: | 44 public: |
88 HTMLViewerApplication(InterfaceRequest<Application> request, | 45 HTMLViewerApplication(InterfaceRequest<Application> request, |
89 URLResponsePtr response, | 46 URLResponsePtr response, |
90 scoped_refptr<base::MessageLoopProxy> compositor_thread, | 47 Setup* setup) |
91 WebMediaPlayerFactory* web_media_player_factory, | |
92 bool is_headless) | |
93 : url_(response->url), | 48 : url_(response->url), |
94 binding_(this, request.Pass()), | 49 binding_(this, request.Pass()), |
95 initial_response_(response.Pass()), | 50 initial_response_(response.Pass()), |
96 compositor_thread_(compositor_thread), | 51 setup_(setup) {} |
97 web_media_player_factory_(web_media_player_factory), | |
98 is_headless_(is_headless) {} | |
99 | 52 |
100 void Initialize(ShellPtr shell, | 53 void Initialize(ShellPtr shell, |
101 Array<String> args, | 54 Array<String> args, |
102 const String& url) override { | 55 const String& url) override { |
103 ServiceProviderPtr service_provider; | 56 ServiceProviderPtr service_provider; |
104 shell_ = shell.Pass(); | 57 shell_ = shell.Pass(); |
105 shell_->ConnectToApplication("mojo:network_service", | 58 shell_->ConnectToApplication("mojo:network_service", |
106 GetProxy(&service_provider), nullptr); | 59 GetProxy(&service_provider), nullptr); |
107 ConnectToService(service_provider.get(), &network_service_); | 60 ConnectToService(service_provider.get(), &network_service_); |
108 } | 61 } |
(...skipping 23 matching lines...) Expand all Loading... |
132 base::Passed(&services))); | 85 base::Passed(&services))); |
133 } | 86 } |
134 } | 87 } |
135 | 88 |
136 void RequestQuit() override {} | 89 void RequestQuit() override {} |
137 | 90 |
138 private: | 91 private: |
139 void OnResponseReceived(URLLoaderPtr loader, | 92 void OnResponseReceived(URLLoaderPtr loader, |
140 InterfaceRequest<ServiceProvider> services, | 93 InterfaceRequest<ServiceProvider> services, |
141 URLResponsePtr response) { | 94 URLResponsePtr response) { |
142 new HTMLDocument(services.Pass(), response.Pass(), shell_.get(), | 95 // HTMLDocument is destroyed when the hosting view is destroyed. |
143 compositor_thread_, web_media_player_factory_, | 96 // TODO(sky): when headless, this leaks. |
144 is_headless_); | 97 new HTMLDocument(services.Pass(), response.Pass(), shell_.get(), setup_); |
145 } | 98 } |
146 | 99 |
147 String url_; | 100 String url_; |
148 mojo::StrongBinding<mojo::Application> binding_; | 101 mojo::StrongBinding<mojo::Application> binding_; |
149 ShellPtr shell_; | 102 ShellPtr shell_; |
150 mojo::NetworkServicePtr network_service_; | 103 mojo::NetworkServicePtr network_service_; |
151 URLResponsePtr initial_response_; | 104 URLResponsePtr initial_response_; |
152 scoped_refptr<base::MessageLoopProxy> compositor_thread_; | 105 Setup* setup_; |
153 WebMediaPlayerFactory* web_media_player_factory_; | 106 |
154 bool is_headless_; | 107 DISALLOW_COPY_AND_ASSIGN(HTMLViewerApplication); |
155 }; | 108 }; |
156 | 109 |
157 class ContentHandlerImpl : public mojo::InterfaceImpl<ContentHandler> { | 110 class ContentHandlerImpl : public mojo::InterfaceImpl<ContentHandler> { |
158 public: | 111 public: |
159 ContentHandlerImpl(scoped_refptr<base::MessageLoopProxy> compositor_thread, | 112 explicit ContentHandlerImpl(Setup* setup) : setup_(setup) {} |
160 WebMediaPlayerFactory* web_media_player_factory, | |
161 bool is_headless) | |
162 : compositor_thread_(compositor_thread), | |
163 web_media_player_factory_(web_media_player_factory), | |
164 is_headless_(is_headless) {} | |
165 ~ContentHandlerImpl() override {} | 113 ~ContentHandlerImpl() override {} |
166 | 114 |
167 private: | 115 private: |
168 // Overridden from ContentHandler: | 116 // Overridden from ContentHandler: |
169 void StartApplication(InterfaceRequest<mojo::Application> request, | 117 void StartApplication(InterfaceRequest<mojo::Application> request, |
170 URLResponsePtr response) override { | 118 URLResponsePtr response) override { |
171 new HTMLViewerApplication(request.Pass(), response.Pass(), | 119 // HTMLViewerApplication is owned by the binding. |
172 compositor_thread_, web_media_player_factory_, | 120 new HTMLViewerApplication(request.Pass(), response.Pass(), setup_); |
173 is_headless_); | |
174 } | 121 } |
175 | 122 |
176 scoped_refptr<base::MessageLoopProxy> compositor_thread_; | 123 Setup* setup_; |
177 WebMediaPlayerFactory* web_media_player_factory_; | |
178 bool is_headless_; | |
179 | 124 |
180 DISALLOW_COPY_AND_ASSIGN(ContentHandlerImpl); | 125 DISALLOW_COPY_AND_ASSIGN(ContentHandlerImpl); |
181 }; | 126 }; |
182 | 127 |
183 class HTMLViewer : public mojo::ApplicationDelegate, | 128 class HTMLViewer : public mojo::ApplicationDelegate, |
184 public mojo::InterfaceFactory<ContentHandler> { | 129 public mojo::InterfaceFactory<ContentHandler> { |
185 public: | 130 public: |
186 HTMLViewer() | 131 HTMLViewer() {} |
187 : discardable_memory_allocator_(kDesiredMaxMemory), | |
188 compositor_thread_("compositor thread"), | |
189 is_headless_(false) {} | |
190 | |
191 ~HTMLViewer() override { blink::shutdown(); } | 132 ~HTMLViewer() override { blink::shutdown(); } |
192 | 133 |
193 private: | 134 private: |
194 // Overridden from ApplicationDelegate: | 135 // Overridden from ApplicationDelegate: |
195 void Initialize(mojo::ApplicationImpl* app) override { | 136 void Initialize(mojo::ApplicationImpl* app) override { |
196 std::set<std::string> paths; | 137 setup_.reset(new Setup(app)); |
197 paths.insert(kResourceResourcesPak); | |
198 paths.insert(kResourceIcudtl); | |
199 paths.insert(kResourceUIPak); | |
200 #if defined(V8_USE_EXTERNAL_STARTUP_DATA) | |
201 paths.insert(kResourceNativesBlob); | |
202 paths.insert(kResourceSnapshotBlob); | |
203 #endif | |
204 ResourceLoader resource_loader(app->shell(), paths); | |
205 if (!resource_loader.BlockUntilLoaded()) { | |
206 // Assume on error we're being shut down. | |
207 LOG(WARNING) << "html_viewer errored getting resources, exiting"; | |
208 mojo::ApplicationImpl::Terminate(); | |
209 return; | |
210 } | |
211 | |
212 ui_setup_.reset(new UISetup); | |
213 base::DiscardableMemoryAllocator::SetInstance( | |
214 &discardable_memory_allocator_); | |
215 | |
216 renderer_scheduler_ = scheduler::RendererScheduler::Create(); | |
217 blink_platform_.reset( | |
218 new BlinkPlatformImpl(app, renderer_scheduler_.get())); | |
219 #if defined(V8_USE_EXTERNAL_STARTUP_DATA) | |
220 // Note: this requires file system access. | |
221 CHECK(gin::V8Initializer::LoadV8SnapshotFromFD( | |
222 resource_loader.ReleaseFile(kResourceNativesBlob).TakePlatformFile(), | |
223 0u, 0u, | |
224 resource_loader.ReleaseFile(kResourceSnapshotBlob).TakePlatformFile(), | |
225 0u, 0u)); | |
226 #endif | |
227 blink::initialize(blink_platform_.get()); | |
228 base::i18n::InitializeICUWithFileDescriptor( | |
229 resource_loader.ReleaseFile(kResourceIcudtl).TakePlatformFile(), | |
230 base::MemoryMappedFile::Region::kWholeFile); | |
231 | |
232 ui::RegisterPathProvider(); | |
233 | |
234 base::CommandLine* command_line = base::CommandLine::ForCurrentProcess(); | |
235 | |
236 logging::LoggingSettings settings; | |
237 settings.logging_dest = logging::LOG_TO_SYSTEM_DEBUG_LOG; | |
238 logging::InitLogging(settings); | |
239 // Display process ID, thread ID and timestamp in logs. | |
240 logging::SetLogItems(true, true, true, false); | |
241 | |
242 if (command_line->HasSwitch(kDisableEncryptedMedia)) | |
243 blink::WebRuntimeFeatures::enableEncryptedMedia(false); | |
244 | |
245 is_headless_ = command_line->HasSwitch(kIsHeadless); | |
246 if (!is_headless_) { | |
247 ui::ResourceBundle::InitSharedInstanceWithPakFileRegion( | |
248 resource_loader.ReleaseFile(kResourceResourcesPak), | |
249 base::MemoryMappedFile::Region::kWholeFile); | |
250 ui::ResourceBundle::GetSharedInstance().AddDataPackFromFile( | |
251 resource_loader.ReleaseFile(kResourceUIPak), ui::SCALE_FACTOR_100P); | |
252 } | |
253 | |
254 compositor_thread_.Start(); | |
255 #if defined(OS_ANDROID) | |
256 // TODO(sky): Get WebMediaPlayerFactory working on android. | |
257 NOTIMPLEMENTED(); | |
258 #else | |
259 bool enable_mojo_media_renderer = | |
260 command_line->HasSwitch(kEnableMojoMediaRenderer); | |
261 | |
262 web_media_player_factory_.reset(new WebMediaPlayerFactory( | |
263 compositor_thread_.message_loop_proxy(), enable_mojo_media_renderer)); | |
264 #endif | |
265 } | 138 } |
266 | 139 |
267 bool ConfigureIncomingConnection(ApplicationConnection* connection) override { | 140 bool ConfigureIncomingConnection(ApplicationConnection* connection) override { |
| 141 // If we're not being connected to from the view manager assume we're being |
| 142 // run in tests, or a headless environment, in which case we'll never get a |
| 143 // ui and there is no point in waiting for it. |
| 144 if (connection->GetRemoteApplicationURL() != "mojo://view_manager/" && |
| 145 !setup_->did_init()) { |
| 146 setup_->InitHeadless(); |
| 147 } |
268 connection->AddService(this); | 148 connection->AddService(this); |
269 return true; | 149 return true; |
270 } | 150 } |
271 | 151 |
272 // Overridden from InterfaceFactory<ContentHandler> | 152 // Overridden from InterfaceFactory<ContentHandler> |
273 void Create(ApplicationConnection* connection, | 153 void Create(ApplicationConnection* connection, |
274 mojo::InterfaceRequest<ContentHandler> request) override { | 154 mojo::InterfaceRequest<ContentHandler> request) override { |
275 BindToRequest( | 155 BindToRequest(new ContentHandlerImpl(setup_.get()), &request); |
276 new ContentHandlerImpl(compositor_thread_.message_loop_proxy(), | |
277 web_media_player_factory_.get(), is_headless_), | |
278 &request); | |
279 } | 156 } |
280 | 157 |
281 scoped_ptr<UISetup> ui_setup_; | 158 scoped_ptr<Setup> setup_; |
282 | |
283 // Skia requires that we have one of these. Unlike the one used in chrome, | |
284 // this doesn't use purgable shared memory. Instead, it tries to free the | |
285 // oldest unlocked chunks on allocation. | |
286 // | |
287 // TODO(erg): In the long run, delete this allocator and get the real shared | |
288 // memory based purging allocator working here. | |
289 DiscardableMemoryAllocator discardable_memory_allocator_; | |
290 | |
291 scoped_ptr<scheduler::RendererScheduler> renderer_scheduler_; | |
292 scoped_ptr<BlinkPlatformImpl> blink_platform_; | |
293 base::Thread compositor_thread_; | |
294 scoped_ptr<WebMediaPlayerFactory> web_media_player_factory_; | |
295 // Set if the content will never be displayed. | |
296 bool is_headless_; | |
297 | 159 |
298 DISALLOW_COPY_AND_ASSIGN(HTMLViewer); | 160 DISALLOW_COPY_AND_ASSIGN(HTMLViewer); |
299 }; | 161 }; |
300 | 162 |
301 } // namespace html_viewer | 163 } // namespace html_viewer |
302 | 164 |
303 MojoResult MojoMain(MojoHandle shell_handle) { | 165 MojoResult MojoMain(MojoHandle shell_handle) { |
304 mojo::ApplicationRunnerChromium runner(new html_viewer::HTMLViewer); | 166 mojo::ApplicationRunnerChromium runner(new html_viewer::HTMLViewer); |
305 return runner.Run(shell_handle); | 167 return runner.Run(shell_handle); |
306 } | 168 } |
OLD | NEW |