blob: a8c66436d14ab8b66134e3a5f6dcffffa223acd8 [file] [log] [blame]
// 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_);
}
}
}
}