OLD | NEW |
| (Empty) |
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. | |
4 | |
5 #include "base/command_line.h" | |
6 #include "base/i18n/icu_util.h" | |
7 #include "base/logging.h" | |
8 #include "base/macros.h" | |
9 #include "base/message_loop/message_loop.h" | |
10 #include "base/path_service.h" | |
11 #include "base/strings/utf_string_conversions.h" | |
12 #include "base/threading/thread.h" | |
13 #include "gin/v8_initializer.h" | |
14 #include "mojo/application/application_runner_chromium.h" | |
15 #include "mojo/services/html_viewer/blink_platform_impl.h" | |
16 #include "mojo/services/html_viewer/discardable_memory_allocator.h" | |
17 #include "mojo/services/html_viewer/html_document.h" | |
18 #include "mojo/services/html_viewer/web_media_player_factory.h" | |
19 #include "mojo/services/network/public/interfaces/network_service.mojom.h" | |
20 #include "third_party/WebKit/public/web/WebKit.h" | |
21 #include "third_party/WebKit/public/web/WebRuntimeFeatures.h" | |
22 #include "third_party/mojo/src/mojo/public/c/system/main.h" | |
23 #include "third_party/mojo/src/mojo/public/cpp/application/application_connectio
n.h" | |
24 #include "third_party/mojo/src/mojo/public/cpp/application/application_delegate.
h" | |
25 #include "third_party/mojo/src/mojo/public/cpp/application/application_impl.h" | |
26 #include "third_party/mojo/src/mojo/public/cpp/application/connect.h" | |
27 #include "third_party/mojo/src/mojo/public/cpp/application/interface_factory_imp
l.h" | |
28 #include "third_party/mojo/src/mojo/public/cpp/bindings/strong_binding.h" | |
29 #include "third_party/mojo_services/src/content_handler/public/interfaces/conten
t_handler.mojom.h" | |
30 #include "ui/base/resource/resource_bundle.h" | |
31 #include "ui/base/ui_base_paths.h" | |
32 | |
33 using mojo::ApplicationConnection; | |
34 using mojo::Array; | |
35 using mojo::BindToRequest; | |
36 using mojo::ContentHandler; | |
37 using mojo::InterfaceRequest; | |
38 using mojo::ServiceProvider; | |
39 using mojo::ServiceProviderPtr; | |
40 using mojo::ShellPtr; | |
41 using mojo::String; | |
42 using mojo::URLLoaderPtr; | |
43 using mojo::URLResponsePtr; | |
44 | |
45 namespace html_viewer { | |
46 | |
47 // Switches for html_viewer. | |
48 | |
49 // Enable MediaRenderer in media pipeline instead of using the internal | |
50 // media::Renderer implementation. | |
51 const char kEnableMojoMediaRenderer[] = "enable-mojo-media-renderer"; | |
52 | |
53 // Disables support for (unprefixed) Encrypted Media Extensions. | |
54 const char kDisableEncryptedMedia[] = "disable-encrypted-media"; | |
55 | |
56 // Prevents creation of any output surface. | |
57 const char kIsHeadless[] = "is-headless"; | |
58 | |
59 size_t kDesiredMaxMemory = 20 * 1024 * 1024; | |
60 | |
61 class HTMLViewer; | |
62 | |
63 class HTMLViewerApplication : public mojo::Application { | |
64 public: | |
65 HTMLViewerApplication(InterfaceRequest<Application> request, | |
66 URLResponsePtr response, | |
67 scoped_refptr<base::MessageLoopProxy> compositor_thread, | |
68 WebMediaPlayerFactory* web_media_player_factory, | |
69 bool is_headless) | |
70 : url_(response->url), | |
71 binding_(this, request.Pass()), | |
72 initial_response_(response.Pass()), | |
73 compositor_thread_(compositor_thread), | |
74 web_media_player_factory_(web_media_player_factory), | |
75 is_headless_(is_headless) {} | |
76 | |
77 void Initialize(ShellPtr shell, | |
78 Array<String> args, | |
79 const String& url) override { | |
80 ServiceProviderPtr service_provider; | |
81 shell_ = shell.Pass(); | |
82 shell_->ConnectToApplication("mojo:network_service", | |
83 GetProxy(&service_provider), nullptr); | |
84 ConnectToService(service_provider.get(), &network_service_); | |
85 } | |
86 | |
87 void AcceptConnection(const String& requestor_url, | |
88 InterfaceRequest<ServiceProvider> services, | |
89 ServiceProviderPtr exposed_services, | |
90 const String& url) override { | |
91 if (initial_response_) { | |
92 OnResponseReceived(URLLoaderPtr(), services.Pass(), | |
93 initial_response_.Pass()); | |
94 } else { | |
95 URLLoaderPtr loader; | |
96 network_service_->CreateURLLoader(GetProxy(&loader)); | |
97 mojo::URLRequestPtr request(mojo::URLRequest::New()); | |
98 request->url = url_; | |
99 request->auto_follow_redirects = true; | |
100 | |
101 // |loader| will be pass to the OnResponseReceived method through a | |
102 // callback. Because order of evaluation is undefined, a reference to the | |
103 // raw pointer is needed. | |
104 mojo::URLLoader* raw_loader = loader.get(); | |
105 raw_loader->Start( | |
106 request.Pass(), | |
107 base::Bind(&HTMLViewerApplication::OnResponseReceived, | |
108 base::Unretained(this), base::Passed(&loader), | |
109 base::Passed(&services))); | |
110 } | |
111 } | |
112 | |
113 void RequestQuit() override {} | |
114 | |
115 private: | |
116 void OnResponseReceived(URLLoaderPtr loader, | |
117 InterfaceRequest<ServiceProvider> services, | |
118 URLResponsePtr response) { | |
119 new HTMLDocument(services.Pass(), response.Pass(), shell_.get(), | |
120 compositor_thread_, web_media_player_factory_, | |
121 is_headless_); | |
122 } | |
123 | |
124 String url_; | |
125 mojo::StrongBinding<mojo::Application> binding_; | |
126 ShellPtr shell_; | |
127 mojo::NetworkServicePtr network_service_; | |
128 URLResponsePtr initial_response_; | |
129 scoped_refptr<base::MessageLoopProxy> compositor_thread_; | |
130 WebMediaPlayerFactory* web_media_player_factory_; | |
131 bool is_headless_; | |
132 }; | |
133 | |
134 class ContentHandlerImpl : public mojo::InterfaceImpl<ContentHandler> { | |
135 public: | |
136 ContentHandlerImpl(scoped_refptr<base::MessageLoopProxy> compositor_thread, | |
137 WebMediaPlayerFactory* web_media_player_factory, | |
138 bool is_headless) | |
139 : compositor_thread_(compositor_thread), | |
140 web_media_player_factory_(web_media_player_factory), | |
141 is_headless_(is_headless) {} | |
142 ~ContentHandlerImpl() override {} | |
143 | |
144 private: | |
145 // Overridden from ContentHandler: | |
146 void StartApplication(InterfaceRequest<mojo::Application> request, | |
147 URLResponsePtr response) override { | |
148 new HTMLViewerApplication(request.Pass(), response.Pass(), | |
149 compositor_thread_, web_media_player_factory_, | |
150 is_headless_); | |
151 } | |
152 | |
153 scoped_refptr<base::MessageLoopProxy> compositor_thread_; | |
154 WebMediaPlayerFactory* web_media_player_factory_; | |
155 bool is_headless_; | |
156 | |
157 DISALLOW_COPY_AND_ASSIGN(ContentHandlerImpl); | |
158 }; | |
159 | |
160 class HTMLViewer : public mojo::ApplicationDelegate, | |
161 public mojo::InterfaceFactory<ContentHandler> { | |
162 public: | |
163 HTMLViewer() | |
164 : discardable_memory_allocator_(kDesiredMaxMemory), | |
165 compositor_thread_("compositor thread") {} | |
166 | |
167 ~HTMLViewer() override { blink::shutdown(); } | |
168 | |
169 private: | |
170 // Overridden from ApplicationDelegate: | |
171 void Initialize(mojo::ApplicationImpl* app) override { | |
172 base::DiscardableMemoryAllocator::SetInstance( | |
173 &discardable_memory_allocator_); | |
174 | |
175 blink_platform_.reset(new BlinkPlatformImpl(app)); | |
176 #if defined(V8_USE_EXTERNAL_STARTUP_DATA) | |
177 // Note: this requires file system access. | |
178 gin::V8Initializer::LoadV8Snapshot(); | |
179 #endif | |
180 blink::initialize(blink_platform_.get()); | |
181 base::i18n::InitializeICU(); | |
182 | |
183 ui::RegisterPathProvider(); | |
184 | |
185 base::CommandLine* command_line = base::CommandLine::ForCurrentProcess(); | |
186 | |
187 logging::LoggingSettings settings; | |
188 settings.logging_dest = logging::LOG_TO_SYSTEM_DEBUG_LOG; | |
189 logging::InitLogging(settings); | |
190 // Display process ID, thread ID and timestamp in logs. | |
191 logging::SetLogItems(true, true, true, false); | |
192 | |
193 if (command_line->HasSwitch(kDisableEncryptedMedia)) | |
194 blink::WebRuntimeFeatures::enableEncryptedMedia(false); | |
195 | |
196 is_headless_ = command_line->HasSwitch(kIsHeadless); | |
197 if (!is_headless_) { | |
198 // TODO(sky): consider putting this into the .so so that we don't need | |
199 // file system access. | |
200 base::FilePath ui_test_pak_path; | |
201 CHECK(PathService::Get(ui::UI_TEST_PAK, &ui_test_pak_path)); | |
202 ui::ResourceBundle::InitSharedInstanceWithPakPath(ui_test_pak_path); | |
203 } | |
204 | |
205 compositor_thread_.Start(); | |
206 #if defined(OS_ANDROID) | |
207 // TODO(sky): Get WebMediaPlayerFactory working on android. | |
208 NOTIMPLEMENTED(); | |
209 #else | |
210 bool enable_mojo_media_renderer = | |
211 command_line->HasSwitch(kEnableMojoMediaRenderer); | |
212 | |
213 web_media_player_factory_.reset(new WebMediaPlayerFactory( | |
214 compositor_thread_.message_loop_proxy(), enable_mojo_media_renderer)); | |
215 #endif | |
216 } | |
217 | |
218 bool ConfigureIncomingConnection(ApplicationConnection* connection) override { | |
219 connection->AddService(this); | |
220 return true; | |
221 } | |
222 | |
223 // Overridden from InterfaceFactory<ContentHandler> | |
224 void Create(ApplicationConnection* connection, | |
225 mojo::InterfaceRequest<ContentHandler> request) override { | |
226 BindToRequest( | |
227 new ContentHandlerImpl(compositor_thread_.message_loop_proxy(), | |
228 web_media_player_factory_.get(), is_headless_), | |
229 &request); | |
230 } | |
231 | |
232 // Skia requires that we have one of these. Unlike the one used in chrome, | |
233 // this doesn't use purgable shared memory. Instead, it tries to free the | |
234 // oldest unlocked chunks on allocation. | |
235 // | |
236 // TODO(erg): In the long run, delete this allocator and get the real shared | |
237 // memory based purging allocator working here. | |
238 DiscardableMemoryAllocator discardable_memory_allocator_; | |
239 | |
240 scoped_ptr<BlinkPlatformImpl> blink_platform_; | |
241 base::Thread compositor_thread_; | |
242 scoped_ptr<WebMediaPlayerFactory> web_media_player_factory_; | |
243 // Set if the content will never be displayed. | |
244 bool is_headless_; | |
245 | |
246 DISALLOW_COPY_AND_ASSIGN(HTMLViewer); | |
247 }; | |
248 | |
249 } // namespace html_viewer | |
250 | |
251 MojoResult MojoMain(MojoHandle shell_handle) { | |
252 mojo::ApplicationRunnerChromium runner(new html_viewer::HTMLViewer); | |
253 return runner.Run(shell_handle); | |
254 } | |
OLD | NEW |