| // Copyright 2021 The Chromium Authors |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "components/cast_receiver/browser/web_runtime_application.h" |
| |
| #include "base/task/bind_post_task.h" |
| #include "components/cast_receiver/browser/public/embedder_application.h" |
| #include "components/cast_receiver/browser/public/message_port_service.h" |
| #include "components/url_rewrite/browser/url_request_rewrite_rules_manager.h" |
| #include "content/public/browser/navigation_entry.h" |
| #include "content/public/browser/web_contents.h" |
| #include "mojo/public/cpp/bindings/associated_remote.h" |
| #include "net/base/net_errors.h" |
| #include "third_party/blink/public/common/associated_interfaces/associated_interface_provider.h" |
| |
| namespace cast_receiver { |
| |
| WebRuntimeApplication::WebRuntimeApplication( |
| std::string cast_session_id, |
| ApplicationConfig config, |
| ApplicationClient& application_client) |
| : RuntimeApplicationBase(std::move(cast_session_id), |
| std::move(config), |
| application_client) { |
| DCHECK(app_url().is_valid()); |
| } |
| |
| WebRuntimeApplication::~WebRuntimeApplication() { |
| DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); |
| StopApplication(EmbedderApplication::ApplicationStopReason::kUserRequest, |
| net::ERR_ABORTED); |
| } |
| |
| void WebRuntimeApplication::Launch(StatusCallback callback) { |
| DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); |
| |
| DVLOG(1) << "Launching application: " << *this; |
| |
| SetContentPermissions(*embedder_application().GetWebContents()); |
| |
| embedder_application().GetAllBindings(base::BindPostTask( |
| task_runner(), |
| base::BindOnce(&WebRuntimeApplication::OnAllBindingsReceived, |
| weak_factory_.GetWeakPtr()))); |
| |
| // Signal that application is launching. |
| std::move(callback).Run(OkStatus()); |
| } |
| |
| bool WebRuntimeApplication::IsStreamingApplication() const { |
| DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); |
| return false; |
| } |
| |
| void WebRuntimeApplication::InnerWebContentsCreated( |
| content::WebContents* inner_web_contents) { |
| DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); |
| DCHECK(inner_web_contents); |
| |
| DVLOG(1) << "Inner web contents created"; |
| |
| auto* outer_web_contents = embedder_application().GetWebContents(); |
| if (outer_web_contents) { |
| url_rewrite::UrlRequestRewriteRulesManager& |
| url_request_rewrite_rules_manager = |
| GetApplicationControls().GetUrlRequestRewriteRulesManager(); |
| SetContentPermissions(*inner_web_contents); |
| url_request_rewrite_rules_manager.AddWebContents(inner_web_contents); |
| } |
| } |
| |
| void WebRuntimeApplication::MediaStartedPlaying( |
| const MediaPlayerInfo& video_type, |
| const content::MediaPlayerId& id) { |
| DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); |
| |
| if (IsApplicationRunning()) { |
| embedder_application().NotifyMediaPlaybackChanged(true); |
| } |
| } |
| |
| void WebRuntimeApplication::MediaStoppedPlaying( |
| const MediaPlayerInfo& video_type, |
| const content::MediaPlayerId& id, |
| content::WebContentsObserver::MediaStoppedReason reason) { |
| DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); |
| |
| if (IsApplicationRunning()) { |
| embedder_application().NotifyMediaPlaybackChanged(false); |
| } |
| } |
| |
| void WebRuntimeApplication::OnAllBindingsReceived( |
| Status status, |
| std::vector<std::string> bindings) { |
| DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); |
| if (!status.ok()) { |
| LOG(ERROR) << "Failed to get all bindings: " << status; |
| StopApplication(EmbedderApplication::ApplicationStopReason::kRuntimeError, |
| net::ERR_FAILED); |
| return; |
| } |
| |
| content::WebContentsObserver::Observe( |
| embedder_application().GetWebContents()); |
| PageStateObserver::Observe(embedder_application().GetWebContents()); |
| auto* message_port_sevice = embedder_application().GetMessagePortService(); |
| DCHECK(message_port_sevice); |
| bindings_manager_ = |
| std::make_unique<BindingsManager>(*this, *message_port_sevice); |
| for (auto& binding : bindings) { |
| bindings_manager_->AddBinding(std::move(binding)); |
| } |
| bindings_manager_->ConfigureWebContents( |
| embedder_application().GetWebContents()); |
| |
| // Application is initialized now - we can load the URL. |
| NavigateToPage(app_url()); |
| } |
| |
| void WebRuntimeApplication::OnPageLoadComplete() { |
| DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); |
| OnPageNavigationComplete(); |
| } |
| |
| void WebRuntimeApplication::OnError() { |
| DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); |
| StopApplication(EmbedderApplication::ApplicationStopReason::kRuntimeError, |
| net::ERR_UNEXPECTED); |
| } |
| |
| void WebRuntimeApplication::OnPageStopped(StopReason reason, |
| net::Error error_code) { |
| DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); |
| switch (reason) { |
| case PageStateObserver::StopReason::kUnknown: |
| StopApplication(EmbedderApplication::ApplicationStopReason::kRuntimeError, |
| error_code); |
| break; |
| case PageStateObserver::StopReason::kApplicationRequest: |
| StopApplication( |
| EmbedderApplication::ApplicationStopReason::kApplicationRequest, |
| error_code); |
| break; |
| case PageStateObserver::StopReason::kHttpError: |
| StopApplication(EmbedderApplication::ApplicationStopReason::kHttpError, |
| error_code); |
| break; |
| } |
| } |
| |
| } // namespace cast_receiver |