| 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 "components/html_viewer/html_document.h" | 5 #include "components/html_viewer/html_document.h" |
| 6 | 6 |
| 7 #include "base/bind.h" | 7 #include "base/bind.h" |
| 8 #include "base/location.h" | 8 #include "base/location.h" |
| 9 #include "base/memory/scoped_ptr.h" | 9 #include "base/memory/scoped_ptr.h" |
| 10 #include "base/message_loop/message_loop_proxy.h" | 10 #include "base/message_loop/message_loop_proxy.h" |
| 11 #include "base/single_thread_task_runner.h" | 11 #include "base/single_thread_task_runner.h" |
| 12 #include "base/stl_util.h" | 12 #include "base/stl_util.h" |
| 13 #include "base/strings/string_util.h" | 13 #include "base/strings/string_util.h" |
| 14 #include "base/thread_task_runner_handle.h" | 14 #include "base/thread_task_runner_handle.h" |
| 15 #include "components/html_viewer/blink_input_events_type_converters.h" | 15 #include "components/html_viewer/blink_input_events_type_converters.h" |
| 16 #include "components/html_viewer/blink_url_request_type_converters.h" | 16 #include "components/html_viewer/blink_url_request_type_converters.h" |
| 17 #include "components/html_viewer/setup.h" |
| 17 #include "components/html_viewer/web_layer_tree_view_impl.h" | 18 #include "components/html_viewer/web_layer_tree_view_impl.h" |
| 18 #include "components/html_viewer/web_media_player_factory.h" | 19 #include "components/html_viewer/web_media_player_factory.h" |
| 19 #include "components/html_viewer/web_storage_namespace_impl.h" | 20 #include "components/html_viewer/web_storage_namespace_impl.h" |
| 20 #include "components/html_viewer/web_url_loader_impl.h" | 21 #include "components/html_viewer/web_url_loader_impl.h" |
| 21 #include "components/surfaces/public/interfaces/surfaces.mojom.h" | 22 #include "components/surfaces/public/interfaces/surfaces.mojom.h" |
| 22 #include "components/view_manager/public/cpp/view.h" | 23 #include "components/view_manager/public/cpp/view.h" |
| 23 #include "media/blink/webencryptedmediaclient_impl.h" | 24 #include "media/blink/webencryptedmediaclient_impl.h" |
| 24 #include "media/cdm/default_cdm_factory.h" | 25 #include "media/cdm/default_cdm_factory.h" |
| 25 #include "media/filters/default_media_permission.h" | 26 #include "media/filters/default_media_permission.h" |
| 26 #include "skia/ext/refptr.h" | 27 #include "skia/ext/refptr.h" |
| 27 #include "third_party/WebKit/public/platform/Platform.h" | 28 #include "third_party/WebKit/public/platform/Platform.h" |
| 28 #include "third_party/WebKit/public/platform/WebHTTPHeaderVisitor.h" | 29 #include "third_party/WebKit/public/platform/WebHTTPHeaderVisitor.h" |
| 29 #include "third_party/WebKit/public/platform/WebSize.h" | 30 #include "third_party/WebKit/public/platform/WebSize.h" |
| 30 #include "third_party/WebKit/public/web/WebConsoleMessage.h" | 31 #include "third_party/WebKit/public/web/WebConsoleMessage.h" |
| 31 #include "third_party/WebKit/public/web/WebDocument.h" | 32 #include "third_party/WebKit/public/web/WebDocument.h" |
| 32 #include "third_party/WebKit/public/web/WebElement.h" | 33 #include "third_party/WebKit/public/web/WebElement.h" |
| 33 #include "third_party/WebKit/public/web/WebInputEvent.h" | 34 #include "third_party/WebKit/public/web/WebInputEvent.h" |
| 34 #include "third_party/WebKit/public/web/WebLocalFrame.h" | 35 #include "third_party/WebKit/public/web/WebLocalFrame.h" |
| 35 #include "third_party/WebKit/public/web/WebScriptSource.h" | 36 #include "third_party/WebKit/public/web/WebScriptSource.h" |
| 36 #include "third_party/WebKit/public/web/WebSettings.h" | 37 #include "third_party/WebKit/public/web/WebSettings.h" |
| 37 #include "third_party/WebKit/public/web/WebView.h" | 38 #include "third_party/WebKit/public/web/WebView.h" |
| 38 #include "third_party/mojo/src/mojo/public/cpp/application/application_impl.h" | 39 #include "third_party/mojo/src/mojo/public/cpp/application/application_impl.h" |
| 39 #include "third_party/mojo/src/mojo/public/cpp/application/connect.h" | 40 #include "third_party/mojo/src/mojo/public/cpp/application/connect.h" |
| 40 #include "third_party/mojo/src/mojo/public/cpp/system/data_pipe.h" | 41 #include "third_party/mojo/src/mojo/public/cpp/system/data_pipe.h" |
| 41 #include "third_party/mojo/src/mojo/public/interfaces/application/shell.mojom.h" | 42 #include "third_party/mojo/src/mojo/public/interfaces/application/shell.mojom.h" |
| 42 #include "third_party/skia/include/core/SkCanvas.h" | 43 #include "third_party/skia/include/core/SkCanvas.h" |
| 43 #include "third_party/skia/include/core/SkColor.h" | 44 #include "third_party/skia/include/core/SkColor.h" |
| 44 #include "third_party/skia/include/core/SkDevice.h" | 45 #include "third_party/skia/include/core/SkDevice.h" |
| 45 #include "ui/gfx/geometry/dip_util.h" | 46 #include "ui/gfx/geometry/dip_util.h" |
| 47 #include "ui/gfx/geometry/size.h" |
| 46 | 48 |
| 47 using mojo::AxProvider; | 49 using mojo::AxProvider; |
| 48 using mojo::Rect; | 50 using mojo::Rect; |
| 49 using mojo::ServiceProviderPtr; | 51 using mojo::ServiceProviderPtr; |
| 50 using mojo::URLResponsePtr; | 52 using mojo::URLResponsePtr; |
| 51 using mojo::View; | 53 using mojo::View; |
| 52 using mojo::ViewManager; | 54 using mojo::ViewManager; |
| 53 using mojo::WeakBindToRequest; | 55 using mojo::WeakBindToRequest; |
| 54 | 56 |
| 55 namespace html_viewer { | 57 namespace html_viewer { |
| (...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 114 // platform. | 116 // platform. |
| 115 return false; | 117 return false; |
| 116 } | 118 } |
| 117 | 119 |
| 118 } // namespace | 120 } // namespace |
| 119 | 121 |
| 120 HTMLDocument::HTMLDocument( | 122 HTMLDocument::HTMLDocument( |
| 121 mojo::InterfaceRequest<mojo::ServiceProvider> services, | 123 mojo::InterfaceRequest<mojo::ServiceProvider> services, |
| 122 URLResponsePtr response, | 124 URLResponsePtr response, |
| 123 mojo::Shell* shell, | 125 mojo::Shell* shell, |
| 124 scoped_refptr<base::MessageLoopProxy> compositor_thread, | 126 Setup* setup) |
| 125 WebMediaPlayerFactory* web_media_player_factory, | |
| 126 bool is_headless) | |
| 127 : response_(response.Pass()), | 127 : response_(response.Pass()), |
| 128 shell_(shell), | 128 shell_(shell), |
| 129 web_view_(nullptr), | 129 web_view_(nullptr), |
| 130 root_(nullptr), | 130 root_(nullptr), |
| 131 view_manager_client_factory_(shell_, this), | 131 view_manager_client_factory_(shell_, this), |
| 132 compositor_thread_(compositor_thread), | 132 setup_(setup) { |
| 133 web_media_player_factory_(web_media_player_factory), | |
| 134 is_headless_(is_headless), | |
| 135 device_pixel_ratio_(1.0) { | |
| 136 exported_services_.AddService(this); | 133 exported_services_.AddService(this); |
| 137 exported_services_.AddService(&view_manager_client_factory_); | 134 exported_services_.AddService(&view_manager_client_factory_); |
| 138 exported_services_.Bind(services.Pass()); | 135 exported_services_.Bind(services.Pass()); |
| 139 Load(response_.Pass()); | 136 if (setup_->did_init()) |
| 137 Load(response_.Pass()); |
| 140 } | 138 } |
| 141 | 139 |
| 142 HTMLDocument::~HTMLDocument() { | 140 HTMLDocument::~HTMLDocument() { |
| 143 STLDeleteElements(&ax_providers_); | 141 STLDeleteElements(&ax_providers_); |
| 144 STLDeleteElements(&ax_provider_requests_); | 142 STLDeleteElements(&ax_provider_requests_); |
| 145 | 143 |
| 146 if (web_view_) | 144 if (web_view_) |
| 147 web_view_->close(); | 145 web_view_->close(); |
| 148 if (root_) | 146 if (root_) |
| 149 root_->RemoveObserver(this); | 147 root_->RemoveObserver(this); |
| 150 } | 148 } |
| 151 | 149 |
| 152 void HTMLDocument::OnEmbed( | 150 void HTMLDocument::OnEmbed( |
| 153 View* root, | 151 View* root, |
| 154 mojo::InterfaceRequest<mojo::ServiceProvider> services, | 152 mojo::InterfaceRequest<mojo::ServiceProvider> services, |
| 155 mojo::ServiceProviderPtr exposed_services) { | 153 mojo::ServiceProviderPtr exposed_services) { |
| 156 DCHECK(!is_headless_); | 154 DCHECK(!setup_->is_headless()); |
| 157 root_ = root; | 155 root_ = root; |
| 156 root_->AddObserver(this); |
| 158 embedder_service_provider_ = exposed_services.Pass(); | 157 embedder_service_provider_ = exposed_services.Pass(); |
| 159 navigator_host_.set_service_provider(embedder_service_provider_.get()); | 158 navigator_host_.set_service_provider(embedder_service_provider_.get()); |
| 160 UpdateWebviewSizeFromViewSize(); | 159 |
| 161 web_layer_tree_view_impl_->set_view(root_); | 160 InitSetupAndLoadIfNecessary(); |
| 162 root_->AddObserver(this); | |
| 163 } | 161 } |
| 164 | 162 |
| 165 void HTMLDocument::OnViewManagerDisconnected(ViewManager* view_manager) { | 163 void HTMLDocument::OnViewManagerDisconnected(ViewManager* view_manager) { |
| 166 // TODO(aa): Need to figure out how shutdown works. | 164 // TODO(aa): Need to figure out how shutdown works. |
| 167 } | 165 } |
| 168 | 166 |
| 169 void HTMLDocument::Create(mojo::ApplicationConnection* connection, | 167 void HTMLDocument::Create(mojo::ApplicationConnection* connection, |
| 170 mojo::InterfaceRequest<AxProvider> request) { | 168 mojo::InterfaceRequest<AxProvider> request) { |
| 171 if (!did_finish_load_) { | 169 if (!did_finish_load_) { |
| 172 // Cache AxProvider interface requests until the document finishes loading. | 170 // Cache AxProvider interface requests until the document finishes loading. |
| (...skipping 21 matching lines...) Expand all Loading... |
| 194 | 192 |
| 195 blink::WebURLRequest web_request; | 193 blink::WebURLRequest web_request; |
| 196 web_request.initialize(); | 194 web_request.initialize(); |
| 197 web_request.setURL(url); | 195 web_request.setURL(url); |
| 198 web_request.setExtraData(extra_data); | 196 web_request.setExtraData(extra_data); |
| 199 | 197 |
| 200 web_view_->mainFrame()->loadRequest(web_request); | 198 web_view_->mainFrame()->loadRequest(web_request); |
| 201 } | 199 } |
| 202 | 200 |
| 203 void HTMLDocument::UpdateWebviewSizeFromViewSize() { | 201 void HTMLDocument::UpdateWebviewSizeFromViewSize() { |
| 204 device_pixel_ratio_ = root_->viewport_metrics().device_pixel_ratio; | 202 web_view_->setDeviceScaleFactor(setup_->device_pixel_ratio()); |
| 205 web_view_->setDeviceScaleFactor(device_pixel_ratio_); | |
| 206 const gfx::Size size_in_pixels(root_->bounds().width, root_->bounds().height); | 203 const gfx::Size size_in_pixels(root_->bounds().width, root_->bounds().height); |
| 207 const gfx::Size size_in_dips = gfx::ConvertSizeToDIP( | 204 const gfx::Size size_in_dips = gfx::ConvertSizeToDIP( |
| 208 root_->viewport_metrics().device_pixel_ratio, size_in_pixels); | 205 root_->viewport_metrics().device_pixel_ratio, size_in_pixels); |
| 209 web_view_->resize( | 206 web_view_->resize( |
| 210 blink::WebSize(size_in_dips.width(), size_in_dips.height())); | 207 blink::WebSize(size_in_dips.width(), size_in_dips.height())); |
| 211 web_layer_tree_view_impl_->setViewportSize(size_in_pixels); | 208 web_layer_tree_view_impl_->setViewportSize(size_in_pixels); |
| 212 } | 209 } |
| 213 | 210 |
| 211 void HTMLDocument::InitSetupAndLoadIfNecessary() { |
| 212 DCHECK(root_); |
| 213 if (web_view_ || root_->viewport_metrics().device_pixel_ratio == 0.f) |
| 214 return; |
| 215 |
| 216 setup_->InitIfNecessary(gfx::Size(root_->viewport_metrics().size->width, |
| 217 root_->viewport_metrics().size->height), |
| 218 root_->viewport_metrics().device_pixel_ratio); |
| 219 Load(response_.Pass()); |
| 220 |
| 221 UpdateWebviewSizeFromViewSize(); |
| 222 web_layer_tree_view_impl_->set_view(root_); |
| 223 } |
| 224 |
| 214 blink::WebStorageNamespace* HTMLDocument::createSessionStorageNamespace() { | 225 blink::WebStorageNamespace* HTMLDocument::createSessionStorageNamespace() { |
| 215 return new WebStorageNamespaceImpl(); | 226 return new WebStorageNamespaceImpl(); |
| 216 } | 227 } |
| 217 | 228 |
| 218 void HTMLDocument::initializeLayerTreeView() { | 229 void HTMLDocument::initializeLayerTreeView() { |
| 219 if (is_headless_) { | 230 if (setup_->is_headless()) { |
| 220 web_layer_tree_view_impl_.reset( | 231 web_layer_tree_view_impl_.reset(new WebLayerTreeViewImpl( |
| 221 new WebLayerTreeViewImpl(compositor_thread_, nullptr, nullptr)); | 232 setup_->compositor_thread(), nullptr, nullptr)); |
| 222 return; | 233 return; |
| 223 } | 234 } |
| 224 | 235 |
| 225 ServiceProviderPtr surfaces_service_provider; | 236 ServiceProviderPtr surfaces_service_provider; |
| 226 shell_->ConnectToApplication("mojo:surfaces_service", | 237 shell_->ConnectToApplication("mojo:surfaces_service", |
| 227 GetProxy(&surfaces_service_provider), nullptr); | 238 GetProxy(&surfaces_service_provider), nullptr); |
| 228 mojo::SurfacePtr surface; | 239 mojo::SurfacePtr surface; |
| 229 ConnectToService(surfaces_service_provider.get(), &surface); | 240 ConnectToService(surfaces_service_provider.get(), &surface); |
| 230 | 241 |
| 231 ServiceProviderPtr gpu_service_provider; | 242 ServiceProviderPtr gpu_service_provider; |
| 232 // TODO(jamesr): Should be mojo:gpu_service | 243 // TODO(jamesr): Should be mojo:gpu_service |
| 233 shell_->ConnectToApplication("mojo:native_viewport_service", | 244 shell_->ConnectToApplication("mojo:native_viewport_service", |
| 234 GetProxy(&gpu_service_provider), nullptr); | 245 GetProxy(&gpu_service_provider), nullptr); |
| 235 mojo::GpuPtr gpu_service; | 246 mojo::GpuPtr gpu_service; |
| 236 ConnectToService(gpu_service_provider.get(), &gpu_service); | 247 ConnectToService(gpu_service_provider.get(), &gpu_service); |
| 237 web_layer_tree_view_impl_.reset(new WebLayerTreeViewImpl( | 248 web_layer_tree_view_impl_.reset(new WebLayerTreeViewImpl( |
| 238 compositor_thread_, surface.Pass(), gpu_service.Pass())); | 249 setup_->compositor_thread(), surface.Pass(), gpu_service.Pass())); |
| 239 } | 250 } |
| 240 | 251 |
| 241 blink::WebLayerTreeView* HTMLDocument::layerTreeView() { | 252 blink::WebLayerTreeView* HTMLDocument::layerTreeView() { |
| 242 return web_layer_tree_view_impl_.get(); | 253 return web_layer_tree_view_impl_.get(); |
| 243 } | 254 } |
| 244 | 255 |
| 245 blink::WebMediaPlayer* HTMLDocument::createMediaPlayer( | 256 blink::WebMediaPlayer* HTMLDocument::createMediaPlayer( |
| 246 blink::WebLocalFrame* frame, | 257 blink::WebLocalFrame* frame, |
| 247 const blink::WebURL& url, | 258 const blink::WebURL& url, |
| 248 blink::WebMediaPlayerClient* client) { | 259 blink::WebMediaPlayerClient* client) { |
| 249 return createMediaPlayer(frame, url, client, nullptr); | 260 return createMediaPlayer(frame, url, client, nullptr); |
| 250 } | 261 } |
| 251 | 262 |
| 252 blink::WebMediaPlayer* HTMLDocument::createMediaPlayer( | 263 blink::WebMediaPlayer* HTMLDocument::createMediaPlayer( |
| 253 blink::WebLocalFrame* frame, | 264 blink::WebLocalFrame* frame, |
| 254 const blink::WebURL& url, | 265 const blink::WebURL& url, |
| 255 blink::WebMediaPlayerClient* client, | 266 blink::WebMediaPlayerClient* client, |
| 256 blink::WebContentDecryptionModule* initial_cdm) { | 267 blink::WebContentDecryptionModule* initial_cdm) { |
| 257 blink::WebMediaPlayer* player = | 268 blink::WebMediaPlayer* player = |
| 258 web_media_player_factory_ | 269 setup_->web_media_player_factory() |
| 259 ? web_media_player_factory_->CreateMediaPlayer( | 270 ? setup_->web_media_player_factory()->CreateMediaPlayer( |
| 260 frame, url, client, GetMediaPermission(), GetCdmFactory(), | 271 frame, url, client, GetMediaPermission(), GetCdmFactory(), |
| 261 initial_cdm, shell_) | 272 initial_cdm, shell_) |
| 262 : nullptr; | 273 : nullptr; |
| 263 return player; | 274 return player; |
| 264 } | 275 } |
| 265 | 276 |
| 266 blink::WebFrame* HTMLDocument::createChildFrame( | 277 blink::WebFrame* HTMLDocument::createChildFrame( |
| 267 blink::WebLocalFrame* parent, | 278 blink::WebLocalFrame* parent, |
| 268 const blink::WebString& frameName, | 279 const blink::WebString& frameName, |
| 269 blink::WebSandboxFlags sandboxFlags) { | 280 blink::WebSandboxFlags sandboxFlags) { |
| (...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 340 return web_encrypted_media_client_.get(); | 351 return web_encrypted_media_client_.get(); |
| 341 } | 352 } |
| 342 | 353 |
| 343 void HTMLDocument::OnViewBoundsChanged(View* view, | 354 void HTMLDocument::OnViewBoundsChanged(View* view, |
| 344 const Rect& old_bounds, | 355 const Rect& old_bounds, |
| 345 const Rect& new_bounds) { | 356 const Rect& new_bounds) { |
| 346 DCHECK_EQ(view, root_); | 357 DCHECK_EQ(view, root_); |
| 347 UpdateWebviewSizeFromViewSize(); | 358 UpdateWebviewSizeFromViewSize(); |
| 348 } | 359 } |
| 349 | 360 |
| 361 void HTMLDocument::OnViewViewportMetricsChanged( |
| 362 mojo::View* view, |
| 363 const mojo::ViewportMetrics& old_metrics, |
| 364 const mojo::ViewportMetrics& new_metrics) { |
| 365 InitSetupAndLoadIfNecessary(); |
| 366 } |
| 367 |
| 350 void HTMLDocument::OnViewDestroyed(View* view) { | 368 void HTMLDocument::OnViewDestroyed(View* view) { |
| 351 DCHECK_EQ(view, root_); | 369 DCHECK_EQ(view, root_); |
| 352 root_ = nullptr; | 370 root_ = nullptr; |
| 353 delete this; | 371 delete this; |
| 354 mojo::ApplicationImpl::Terminate(); | 372 mojo::ApplicationImpl::Terminate(); |
| 355 } | 373 } |
| 356 | 374 |
| 357 void HTMLDocument::OnViewInputEvent(View* view, const mojo::EventPtr& event) { | 375 void HTMLDocument::OnViewInputEvent(View* view, const mojo::EventPtr& event) { |
| 358 if (event->pointer_data) { | 376 if (event->pointer_data) { |
| 359 // Blink expects coordintes to be in DIPs. | 377 // Blink expects coordintes to be in DIPs. |
| 360 event->pointer_data->x /= device_pixel_ratio_; | 378 event->pointer_data->x /= setup_->device_pixel_ratio(); |
| 361 event->pointer_data->y /= device_pixel_ratio_; | 379 event->pointer_data->y /= setup_->device_pixel_ratio(); |
| 362 event->pointer_data->screen_x /= device_pixel_ratio_; | 380 event->pointer_data->screen_x /= setup_->device_pixel_ratio(); |
| 363 event->pointer_data->screen_y /= device_pixel_ratio_; | 381 event->pointer_data->screen_y /= setup_->device_pixel_ratio(); |
| 364 } | 382 } |
| 365 | 383 |
| 366 if ((event->action == mojo::EVENT_TYPE_POINTER_DOWN || | 384 if ((event->action == mojo::EVENT_TYPE_POINTER_DOWN || |
| 367 event->action == mojo::EVENT_TYPE_POINTER_UP || | 385 event->action == mojo::EVENT_TYPE_POINTER_UP || |
| 368 event->action == mojo::EVENT_TYPE_POINTER_CANCEL || | 386 event->action == mojo::EVENT_TYPE_POINTER_CANCEL || |
| 369 event->action == mojo::EVENT_TYPE_POINTER_MOVE) && | 387 event->action == mojo::EVENT_TYPE_POINTER_MOVE) && |
| 370 event->pointer_data->kind == mojo::POINTER_KIND_TOUCH) { | 388 event->pointer_data->kind == mojo::POINTER_KIND_TOUCH) { |
| 371 touch_handler_->OnTouchEvent(*event); | 389 touch_handler_->OnTouchEvent(*event); |
| 372 return; | 390 return; |
| 373 } | 391 } |
| 374 scoped_ptr<blink::WebInputEvent> web_event = | 392 scoped_ptr<blink::WebInputEvent> web_event = |
| 375 event.To<scoped_ptr<blink::WebInputEvent>>(); | 393 event.To<scoped_ptr<blink::WebInputEvent>>(); |
| 376 if (web_event) | 394 if (web_event) |
| 377 web_view_->handleInputEvent(*web_event); | 395 web_view_->handleInputEvent(*web_event); |
| 378 } | 396 } |
| 379 | 397 |
| 380 media::MediaPermission* HTMLDocument::GetMediaPermission() { | 398 media::MediaPermission* HTMLDocument::GetMediaPermission() { |
| 381 if (!media_permission_) | 399 if (!media_permission_) |
| 382 media_permission_.reset(new media::DefaultMediaPermission(true)); | 400 media_permission_.reset(new media::DefaultMediaPermission(true)); |
| 383 return media_permission_.get(); | 401 return media_permission_.get(); |
| 384 } | 402 } |
| 385 | 403 |
| 386 media::CdmFactory* HTMLDocument::GetCdmFactory() { | 404 media::CdmFactory* HTMLDocument::GetCdmFactory() { |
| 387 if (!cdm_factory_) | 405 if (!cdm_factory_) |
| 388 cdm_factory_.reset(new media::DefaultCdmFactory()); | 406 cdm_factory_.reset(new media::DefaultCdmFactory()); |
| 389 return cdm_factory_.get(); | 407 return cdm_factory_.get(); |
| 390 } | 408 } |
| 391 | 409 |
| 392 } // namespace html_viewer | 410 } // namespace html_viewer |
| OLD | NEW |