| // Copyright 2017 The Fuchsia Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "topaz/runtime/web_view/web_view_provider.h" |
| |
| #include <lib/fsl/vmo/strings.h> |
| |
| #include "lib/icu_data/cpp/icu_data.h" |
| #include "peridot/lib/rapidjson/rapidjson.h" |
| |
| WebViewProvider::WebViewProvider(async::Loop* loop, const std::string url) |
| : loop_(loop), |
| url_(url), |
| context_(component::StartupContext::CreateFromStartupInfo()), |
| old_view_provider_binding_(this), |
| view_provider_binding_(this), |
| lifecycle_binding_(this), |
| main_link_watcher_binding_(this) { |
| FXL_DCHECK(loop); |
| if (!icu_data::Initialize(context_.get(), nullptr)) { |
| FXL_LOG(WARNING) << "Could not load ICU data"; |
| } |
| |
| context_->outgoing().AddPublicService<fuchsia::ui::app::ViewProvider>( |
| [this](fidl::InterfaceRequest<fuchsia::ui::app::ViewProvider> request) { |
| FXL_LOG(INFO) << "Add ViewProvider binding"; |
| view_provider_binding_.Bind(std::move(request)); |
| }); |
| context_->outgoing().AddPublicService<fuchsia::ui::viewsv1::ViewProvider>( |
| [this]( |
| fidl::InterfaceRequest<fuchsia::ui::viewsv1::ViewProvider> request) { |
| FXL_LOG(INFO) << "Add V1 ViewProvider binding"; |
| old_view_provider_binding_.Bind(std::move(request)); |
| }); |
| context_->outgoing().AddPublicService<fuchsia::modular::Lifecycle>( |
| [this](fidl::InterfaceRequest<fuchsia::modular::Lifecycle> request) { |
| FXL_LOG(INFO) << "got request for lifecycle service"; |
| lifecycle_binding_.Bind(std::move(request)); |
| }); |
| |
| context_->ConnectToEnvironmentService(module_context_.NewRequest()); |
| module_context_->GetLink(nullptr, main_link_.NewRequest()); |
| main_link_->Watch(main_link_watcher_binding_.NewBinding()); |
| |
| #ifdef EXPERIMENTAL_WEB_ENTITY_EXTRACTION |
| fuchsia::modular::IntelligenceServicesPtr intelligence_services; |
| context_->ConnectToEnvironmentService(intelligence_services.NewRequest()); |
| intelligence_services->GetContextWriter(context_writer_.NewRequest()); |
| context_ptr->GetComponentContext(component_context_.NewRequest()); |
| |
| if (view_) { |
| view_->set_context_writer(std::move(context_writer_)); |
| view_->set_component_context(std::move(component_context_)); |
| } |
| #endif |
| } |
| |
| void WebViewProvider::CreateView( |
| zx::eventpair view_token, |
| fidl::InterfaceRequest<fuchsia::sys::ServiceProvider> incoming_services, |
| fidl::InterfaceHandle<fuchsia::sys::ServiceProvider> outgoing_services) { |
| FXL_LOG(INFO) << "CreateView"; |
| FXL_DCHECK(!view_); |
| |
| auto scenic = |
| context_->ConnectToEnvironmentService<fuchsia::ui::scenic::Scenic>(); |
| scenic::ViewContext view_context = { |
| .session_and_listener_request = |
| scenic::CreateScenicSessionPtrAndListenerRequest(scenic.get()), |
| .view_token = std::move(view_token), |
| .incoming_services = std::move(incoming_services), |
| .outgoing_services = std::move(outgoing_services), |
| .startup_context = context_.get(), |
| }; |
| view_ = std::make_unique<WebViewImpl>( |
| std::move(view_context), |
| context_->ConnectToEnvironmentService<fuchsia::ui::input::ImeService>(), |
| url_); |
| #ifdef EXPERIMENTAL_WEB_ENTITY_EXTRACTION |
| if (context_writer_) { |
| view_->set_context_writer(std::move(context_writer_)); |
| } |
| if (component_context_) { |
| view_->set_component_context(std::move(component_context_)); |
| } |
| #endif |
| |
| view_->SetReleaseHandler([this](zx_status_t status) { |
| FXL_LOG(INFO) << "release handler"; |
| view_ = nullptr; |
| }); |
| } |
| |
| void WebViewProvider::CreateView( |
| fidl::InterfaceRequest<fuchsia::ui::viewsv1token::ViewOwner> |
| view_owner_request, |
| fidl::InterfaceRequest<fuchsia::sys::ServiceProvider> view_services) { |
| CreateView(zx::eventpair(view_owner_request.TakeChannel().release()), |
| std::move(view_services), nullptr); |
| } |
| |
| void WebViewProvider::Terminate() { loop_->Quit(); } |
| |
| void WebViewProvider::Notify(fuchsia::mem::Buffer json) { |
| std::string json_string; |
| FXL_CHECK(fsl::StringFromVmo(json, &json_string)); |
| |
| // Echo back the input URL to our "output_url" link. This is useful for |
| // testing. |
| { |
| fuchsia::mem::Buffer output_json; |
| FXL_CHECK(fsl::VmoFromString(json_string, &output_json)); |
| |
| fuchsia::modular::LinkPtr output_url_link; |
| module_context_->GetLink("output_url", output_url_link.NewRequest()); |
| output_url_link->Set(nullptr, std::move(output_json)); |
| output_url_link->Sync([] {}); |
| } |
| |
| modular::JsonDoc parsed_json; |
| parsed_json.Parse(json_string); |
| |
| if (!parsed_json.IsObject()) { |
| FXL_LOG(WARNING) << "Not an object: " |
| << modular::JsonValueToPrettyString(parsed_json); |
| return; |
| } |
| |
| const auto contract_it = parsed_json.FindMember("view"); |
| if (contract_it != parsed_json.MemberEnd()) { |
| const auto& contract = contract_it->value; |
| auto url_it = contract.FindMember("uri"); |
| if (url_it == contract.MemberEnd() || !url_it->value.IsString()) { |
| FXL_LOG(WARNING) << "/view/uri must be a string in " << json_string; |
| } else { |
| url_ = url_it->value.GetString(); |
| if (view_) { |
| view_->SetUrl(url_); |
| } |
| } |
| } |
| } |