blob: 625abbee1acd86d41f30a01d5db2b3f3e0b9c8f9 [file] [log] [blame]
// Copyright 2016 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.
#ifndef PERIDOT_BIN_SESSIONMGR_STORY_RUNNER_STORY_PROVIDER_IMPL_H_
#define PERIDOT_BIN_SESSIONMGR_STORY_RUNNER_STORY_PROVIDER_IMPL_H_
#include <map>
#include <memory>
#include <set>
#include <fuchsia/ledger/cpp/fidl.h>
#include <fuchsia/modular/cpp/fidl.h>
#include <fuchsia/modular/internal/cpp/fidl.h>
#include <fuchsia/scenic/snapshot/cpp/fidl.h>
#include <fuchsia/ui/policy/cpp/fidl.h>
#include <fuchsia/ui/viewsv1/cpp/fidl.h>
#include <fuchsia/ui/viewsv1token/cpp/fidl.h>
#include <lib/async/cpp/operation.h>
#include <lib/fidl/cpp/binding_set.h>
#include <lib/fidl/cpp/interface_ptr.h>
#include <lib/fidl/cpp/interface_ptr_set.h>
#include <lib/fidl/cpp/interface_request.h>
#include <lib/fidl/cpp/string.h>
#include <lib/fit/function.h>
#include <lib/fxl/macros.h>
#include "peridot/bin/sessionmgr/agent_runner/agent_runner.h"
#include "peridot/bin/sessionmgr/component_context_impl.h"
#include "peridot/bin/sessionmgr/message_queue/message_queue_manager.h"
#include "peridot/bin/sessionmgr/story_runner/story_entity_provider.h"
#include "peridot/lib/fidl/app_client.h"
#include "peridot/lib/fidl/environment.h"
#include "peridot/lib/fidl/proxy.h"
#include "peridot/lib/ledger_client/ledger_client.h"
#include "peridot/lib/ledger_client/page_client.h"
#include "peridot/lib/ledger_client/types.h"
#include "peridot/lib/module_manifest/module_facet_reader.h"
namespace modular {
class PresentationProvider;
class Resolver;
class SessionStorage;
class StoryControllerImpl;
class StoryStorage;
class StoryProviderImpl : fuchsia::modular::StoryProvider,
fuchsia::modular::FocusWatcher {
public:
StoryProviderImpl(
Environment* user_environment, std::string device_id,
SessionStorage* session_storage, fuchsia::modular::AppConfig story_shell,
const ComponentContextInfo& component_context_info,
fuchsia::modular::FocusProviderPtr focus_provider,
fuchsia::modular::UserIntelligenceProvider* user_intelligence_provider,
fuchsia::modular::ModuleResolver* module_resolver,
EntityProviderRunner* entity_provider_runner,
modular::ModuleFacetReader* module_facet_reader,
PresentationProvider* presentation_provider,
fuchsia::ui::viewsv1::ViewSnapshotPtr view_snapshot, bool test);
~StoryProviderImpl() override;
void Connect(fidl::InterfaceRequest<fuchsia::modular::StoryProvider> request);
void StopAllStories(const std::function<void()>& callback);
// Stops serving the fuchsia::modular::StoryProvider interface and stops all
// stories.
void Teardown(const std::function<void()>& callback);
// Called by StoryControllerImpl.
const Environment* user_environment() const { return user_environment_; }
// The device ID for this user/device.
const std::string device_id() const { return device_id_; }
// Called by StoryControllerImpl.
const ComponentContextInfo& component_context_info() {
return component_context_info_;
}
// Called by StoryControllerImpl.
fuchsia::modular::UserIntelligenceProvider* user_intelligence_provider() {
return user_intelligence_provider_;
}
// Called by StoryControllerImpl.
fuchsia::modular::ModuleResolver* module_resolver() {
return module_resolver_;
}
fuchsia::modular::EntityResolver* entity_resolver() {
return entity_provider_runner_;
}
modular::ModuleFacetReader* module_facet_reader() {
return module_facet_reader_;
}
// Called by StoryControllerImpl.
const fuchsia::modular::AppConfig& story_shell() const {
return story_shell_;
}
// Called by StoryControllerImpl.
//
// Returns an AppClient rather than taking an interface request
// as an argument because the application is preloaded.
std::unique_ptr<AppClient<fuchsia::modular::Lifecycle>> StartStoryShell(
fidl::StringPtr story_id,
fidl::InterfaceRequest<fuchsia::ui::viewsv1token::ViewOwner> request);
// |fuchsia::modular::StoryProvider|, also used by StoryControllerImpl.
void GetStoryInfo(fidl::StringPtr story_id,
GetStoryInfoCallback callback) override;
// Called by StoryControllerImpl. Sends request to
// fuchsia::modular::FocusProvider
void RequestStoryFocus(fidl::StringPtr story_id);
// Called by StoryControllerImpl.
void NotifyStoryStateChange(
fidl::StringPtr story_id, fuchsia::modular::StoryState story_state,
fuchsia::modular::StoryVisibilityState story_visibility_state);
// Called by StoryControllerImpl.
void NotifyStoryActivityChange(
fidl::StringPtr story_id,
fidl::VectorPtr<fuchsia::modular::OngoingActivityType>
ongoing_activities);
// Called by StoryControllerImpl. Sends request to
// fuchsia::modular::SessionShell through PresentationProvider.
void GetPresentation(
fidl::StringPtr story_id,
fidl::InterfaceRequest<fuchsia::ui::policy::Presentation> request);
void WatchVisualState(
fidl::StringPtr story_id,
fidl::InterfaceHandle<fuchsia::modular::StoryVisualStateWatcher> watcher);
// Called by StoryControllerImpl. Takes a snapshot of the story by the given
// |story_id|. Callback is returned with the snapshot of the story, or an
// empty buffer (size == 0) if the snapshot could not be taken.
void TakeSnapshot(fidl::StringPtr story_id,
fit::function<void(fuchsia::mem::Buffer)> callback);
// Called by StoryControllerImpl. Creates a new view with the given
// |view_owner_request| and connects the snapshot loader with the given
// |loader_request|.
void StartSnapshotLoader(
fidl::InterfaceRequest<fuchsia::ui::viewsv1token::ViewOwner>
view_owner_request,
fidl::InterfaceRequest<fuchsia::scenic::snapshot::Loader> loader_request);
// Creates an entity with the specified |type| and |data| in the story with
// |story_id|.
//
// |callback| will be called with a reference to the created entity. If the
// creation failed the |entity_request| is dropped.
void CreateEntity(
const std::string& story_id, fidl::StringPtr type,
fuchsia::mem::Buffer data,
fidl::InterfaceRequest<fuchsia::modular::Entity> entity_request,
std::function<void(std::string /* entity_reference */)> callback);
// Creates an entity with the specified |type| and |data| in the story with
// |story_id|.
//
// The story provider guarantees the uniqueness of the EntityProvider
// associated with any given story.
void ConnectToStoryEntityProvider(
const std::string& story_id,
fidl::InterfaceRequest<fuchsia::modular::EntityProvider>
entity_provider_request);
private:
// |fuchsia::modular::StoryProvider|
void GetController(fidl::StringPtr story_id,
fidl::InterfaceRequest<fuchsia::modular::StoryController>
request) override;
// |fuchsia::modular::StoryProvider|
void GetStories(
fidl::InterfaceHandle<fuchsia::modular::StoryProviderWatcher> watcher,
PreviousStoriesCallback callback) override;
// |fuchsia::modular::StoryProvider|
void PreviousStories(PreviousStoriesCallback callback) override;
// |fuchsia::modular::StoryProvider|
void RunningStories(RunningStoriesCallback callback) override;
// |fuchsia::modular::StoryProvider|
void Watch(fidl::InterfaceHandle<fuchsia::modular::StoryProviderWatcher>
watcher) override;
// |fuchsia::modular::StoryProvider|
void WatchActivity(
fidl::InterfaceHandle<fuchsia::modular::StoryActivityWatcher> watcher)
override;
// |fuchsia::modular::FocusWatcher|
void OnFocusChange(fuchsia::modular::FocusInfoPtr info) override;
// Called by *session_storage_.
void OnStoryStorageDeleted(fidl::StringPtr story_id);
void OnStoryStorageUpdated(fidl::StringPtr story_id,
fuchsia::modular::internal::StoryData story_data);
void NotifyStoryWatchers(
const fuchsia::modular::internal::StoryData* const story_data,
fuchsia::modular::StoryState story_state,
fuchsia::modular::StoryVisibilityState story_visibility_state);
void MaybeLoadStoryShell();
void MaybeLoadStoryShellDelayed();
Environment* const user_environment_;
SessionStorage* session_storage_; // Not owned.
// Unique ID generated for this user/device combination.
const std::string device_id_;
// The bindings for this instance.
fidl::BindingSet<fuchsia::modular::StoryProvider> bindings_;
// Used to preload story shell before it is requested.
fuchsia::modular::AppConfig story_shell_;
std::unique_ptr<AppClient<fuchsia::modular::Lifecycle>>
preloaded_story_shell_app_;
// When running in a test, we don't preload story shells, because then the
// preloaded next instance of the story doesn't pass its test points.
const bool test_;
fidl::InterfacePtrSet<fuchsia::modular::StoryProviderWatcher> watchers_;
fidl::InterfacePtrSet<fuchsia::modular::StoryActivityWatcher>
activity_watchers_;
// The story controllers of the currently active stories, indexed by their
// story IDs.
//
// Only user logout or delete story calls ever remove story controllers from
// this collection, but controllers for stopped stories stay in it.
//
// Also keeps a cached version of the fuchsia::modular::StoryInfo for every
// story, to send it to newly registered story provider watchers, and to story
// provider watchers when only the story state changes.
struct StoryRuntimeContainer {
std::unique_ptr<StoryControllerImpl> controller_impl;
std::unique_ptr<StoryStorage> storage;
std::unique_ptr<StoryEntityProvider> entity_provider;
fuchsia::modular::StoryInfoPtr current_info;
};
std::map<std::string, StoryRuntimeContainer> story_runtime_containers_;
const ComponentContextInfo component_context_info_;
fuchsia::modular::UserIntelligenceProvider* const
user_intelligence_provider_; // Not owned.
fuchsia::modular::ModuleResolver* const module_resolver_; // Not owned.
EntityProviderRunner* const entity_provider_runner_; // Not owned.
modular::ModuleFacetReader* const module_facet_reader_; // Not owned.
PresentationProvider* const presentation_provider_; // Not owned.
// When a story gets created, or when it gets focused on this device, we write
// a record of the current context in the story page. So we need to watch the
// context and the focus. This serves to compute relative importance of
// stories in the timeline, as determined by the current context.
fuchsia::modular::FocusProviderPtr focus_provider_;
fidl::Binding<fuchsia::modular::FocusWatcher> focus_watcher_binding_;
// Service provided by scenic to take snapshots of stories.
fuchsia::ui::viewsv1::ViewSnapshotPtr view_snapshot_;
// Cached mapping of story ID's to the story view koids. Used as a token to
// take snapshots of stories. This is a temporary hack because koids are
// guessable. The intention is to have this hack until the framework is
// provided with a more secure API from scenic to take snapshots, which is
// TBD.
std::map<fidl::StringPtr, zx_koid_t> view_endpoints_;
// Snapshot loader component which is used to create new snapshot views. There
// is only one instance of this component running per session.
std::unique_ptr<AppClient<fuchsia::modular::Lifecycle>> snapshot_loader_app_;
// This is a container of all operations that are currently enqueued to run in
// a FIFO manner. All operations exposed via |fuchsia::modular::StoryProvider|
// interface are queued here.
//
// The advantage of doing this is that if an operation consists of multiple
// asynchronous calls then no state needs to be maintained for incomplete /
// pending operations.
//
// TODO(mesch): If a story provider operation invokes a story operation that
// causes the story updating its story info state, that update operation gets
// scheduled on this queue again, after the current operation. It would be
// better to be able to schedule such an operation on the story queue because
// it's a per story operation even if it affects the per story key in the root
// page, and then the update of story info is bounded by the outer operation.
OperationQueue operation_queue_;
fxl::WeakPtrFactory<StoryProviderImpl> weak_factory_;
// Operations implemented here.
class LoadStoryRuntimeCall;
class StopStoryCall;
class StopAllStoriesCall;
class StopStoryShellCall;
class GetStoryEntityProviderCall;
FXL_DISALLOW_COPY_AND_ASSIGN(StoryProviderImpl);
};
} // namespace modular
#endif // PERIDOT_BIN_SESSIONMGR_STORY_RUNNER_STORY_PROVIDER_IMPL_H_