[modular] Delete StoryProvider.DeleteStory().
Also: perform related cleanups now that some code-paths are simplified.
TEST=existing
MF-13 #comment [modular] Delete StoryProvider.DeleteStory().
Change-Id: I044a9bd9292c8a6ad285c6d72000df19e5f6ee83
diff --git a/bin/sessionmgr/story_runner/story_controller_impl.cc b/bin/sessionmgr/story_runner/story_controller_impl.cc
index 5f2f29a..0fbff7e 100644
--- a/bin/sessionmgr/story_runner/story_controller_impl.cc
+++ b/bin/sessionmgr/story_runner/story_controller_impl.cc
@@ -556,8 +556,7 @@
}
StoryControllerImpl* const story_controller_impl_; // not owned
- const bool
- notify_watchers_; // Whether to notify state change; false in DeleteCall.
+ const bool notify_watchers_; // Whether to notify state change to watchers.
FXL_DISALLOW_COPY_AND_ASSIGN(StopCall);
};
@@ -628,34 +627,6 @@
FXL_DISALLOW_COPY_AND_ASSIGN(StopModuleAndStoryIfEmptyCall);
};
-class StoryControllerImpl::DeleteCall : public Operation<> {
- public:
- DeleteCall(StoryControllerImpl* const story_controller_impl,
- std::function<void()> done)
- : Operation("StoryControllerImpl::DeleteCall", [] {}),
- story_controller_impl_(story_controller_impl),
- done_(std::move(done)) {}
-
- private:
- void Run() override {
- // No call to Done(), in order to block all further operations on the queue
- // until the instance is deleted.
- operation_queue_.Add(new StopCall(story_controller_impl_,
- false /* notify watchers */, done_));
- }
-
- StoryControllerImpl* const story_controller_impl_; // not owned
-
- // Not the result call of the Operation, because it's invoked without
- // unblocking the operation queue, to prevent subsequent operations from
- // executing until the instance is deleted, which cancels those operations.
- std::function<void()> done_;
-
- OperationQueue operation_queue_;
-
- FXL_DISALLOW_COPY_AND_ASSIGN(DeleteCall);
-};
-
class StoryControllerImpl::OnModuleDataUpdatedCall : public Operation<> {
public:
OnModuleDataUpdatedCall(StoryControllerImpl* const story_controller_impl,
@@ -1172,11 +1143,7 @@
}
}
-void StoryControllerImpl::StopForDelete(const StopCallback& done) {
- operation_queue_.Add(new DeleteCall(this, done));
-}
-
-void StoryControllerImpl::StopForTeardown(const StopCallback& done) {
+void StoryControllerImpl::StopWithoutNotifying(const StopCallback& done) {
operation_queue_.Add(new StopCall(this, false /* notify watchers */, done));
}
diff --git a/bin/sessionmgr/story_runner/story_controller_impl.h b/bin/sessionmgr/story_runner/story_controller_impl.h
index 3e212a5..1c1c935 100644
--- a/bin/sessionmgr/story_runner/story_controller_impl.h
+++ b/bin/sessionmgr/story_runner/story_controller_impl.h
@@ -64,21 +64,9 @@
// Called by StoryProviderImpl.
bool IsRunning();
- // Called by StoryProviderImpl.
- //
- // A variant of Stop() that stops the story because the story is being
- // deleted. The StoryControllerImpl instance is deleted by StoryProviderImpl
- // and the story data are deleted from the ledger once the done callback is
- // invoked.
- //
- // No further operations invoked after this one are executed. (The Operation
- // accomplishes this by not calling Done() and instead invoking its callback
- // directly from Run(), such that the OperationQueue stays blocked on it until
- // it gets deleted.)
- void StopForDelete(const std::function<void()>& done);
-
- // Called by StoryProviderImpl.
- void StopForTeardown(const std::function<void()>& done);
+ // Called by StoryProviderImpl. A variant of Stop() which does not notify
+ // listeners that we stopped the story.
+ void StopWithoutNotifying(const std::function<void()>& done);
// Called by StoryProviderImpl.
fuchsia::modular::StoryState GetStoryState() const;
@@ -355,7 +343,6 @@
// Operations implemented here.
class AddIntentCall;
class DefocusCall;
- class DeleteCall;
class FocusCall;
class KillModuleCall;
class LaunchModuleCall;
diff --git a/bin/sessionmgr/story_runner/story_provider_impl.cc b/bin/sessionmgr/story_runner/story_provider_impl.cc
index db42e32..a19449b 100644
--- a/bin/sessionmgr/story_runner/story_provider_impl.cc
+++ b/bin/sessionmgr/story_runner/story_provider_impl.cc
@@ -44,45 +44,36 @@
constexpr char kSnapshotLoaderUrl[] = "snapshot";
-class StoryProviderImpl::DeleteStoryCall : public Operation<> {
+class StoryProviderImpl::StopStoryCall : public Operation<> {
public:
using StoryRuntimesMap = std::map<std::string, struct StoryRuntimeContainer>;
- using PendingDeletion = std::pair<std::string, DeleteStoryCall*>;
- DeleteStoryCall(SessionStorage* session_storage, fidl::StringPtr story_id,
- StoryRuntimesMap* const story_runtime_containers,
- MessageQueueManager* const message_queue_manager,
- const bool already_deleted, ResultCall result_call)
+ StopStoryCall(fidl::StringPtr story_id,
+ StoryRuntimesMap* const story_runtime_containers,
+ MessageQueueManager* const message_queue_manager,
+ ResultCall result_call)
: Operation("StoryProviderImpl::DeleteStoryCall", std::move(result_call)),
- session_storage_(session_storage),
story_id_(story_id),
story_runtime_containers_(story_runtime_containers),
- message_queue_manager_(message_queue_manager),
- already_deleted_(already_deleted) {}
+ message_queue_manager_(message_queue_manager) {}
private:
void Run() override {
FlowToken flow{this};
- if (already_deleted_) {
- Teardown(flow);
- } else {
- session_storage_->DeleteStory(story_id_)->WeakThen(
- GetWeakPtr(), [this, flow] { Teardown(flow); });
- }
- }
-
- void Teardown(FlowToken flow) {
auto i = story_runtime_containers_->find(story_id_);
if (i == story_runtime_containers_->end()) {
+ FXL_LOG(WARNING) << "I was told to teardown story " << story_id_
+ << ", but I can't find it.";
return;
}
FXL_DCHECK(i->second.controller_impl != nullptr);
- i->second.controller_impl->StopForDelete([this, flow] { Erase(flow); });
+ i->second.controller_impl->StopWithoutNotifying(
+ [this, flow] { CleanupRuntime(flow); });
}
- void Erase(FlowToken flow) {
+ void CleanupRuntime(FlowToken flow) {
// Here we delete the instance from whose operation a result callback was
// received. Thus we must assume that the callback returns to a method of
// the instance. If we delete the instance right here, |this| would be
@@ -91,23 +82,21 @@
// functions that run as methods of other objects owned by |this| or
// provided to |this|. To avoid such problems, the delete is invoked
// through the run loop.
+ //
+ // TODO(thatguy); Understand the above comment, and rewrite it.
async::PostTask(async_get_default_dispatcher(), [this, flow] {
story_runtime_containers_->erase(story_id_);
message_queue_manager_->DeleteNamespace(
EncodeModuleComponentNamespace(story_id_), [flow] {});
-
- // TODO(mesch): We must delete the story page too. MI4-1002
});
}
private:
- SessionStorage* const session_storage_; // Not owned.
const fidl::StringPtr story_id_;
StoryRuntimesMap* const story_runtime_containers_;
MessageQueueManager* const message_queue_manager_;
- const bool already_deleted_; // True if called from OnChange();
- FXL_DISALLOW_COPY_AND_ASSIGN(DeleteStoryCall);
+ FXL_DISALLOW_COPY_AND_ASSIGN(StopStoryCall);
};
// Loads a StoryRuntimeContainer object so that the given story is ready to be
@@ -196,12 +185,14 @@
// Each callback has a copy of |flow| which only goes out-of-scope
// once the story corresponding to |it| stops.
//
- // TODO(mesch): If a DeleteCall is executing in front of
- // StopForTeardown(), then the StopCall in StopForTeardown() never
- // executes because the fuchsia::modular::StoryController instance is
- // deleted after the DeleteCall finishes. This will then block unless it
- // runs in a timeout.
- it.second.controller_impl->StopForTeardown(
+ // TODO(thatguy): If the StoryControllerImpl is deleted before it can
+ // complete StopWithoutNotifying(), we will never be called back and the
+ // OperationQueue on which we're running will block. Moving over to
+ // fit::promise will allow us to observe cancellation.
+ //
+ // TODO(thatguy): Use StopStoryCall instead of reproducing some of its
+ // logic here.
+ it.second.controller_impl->StopWithoutNotifying(
[this, story_id = it.first, flow] {
// It is okay to erase story_id because story provider binding has
// been closed and this callback cannot be invoked synchronously.
@@ -435,15 +426,6 @@
}
// |fuchsia::modular::StoryProvider|
-void StoryProviderImpl::DeleteStory(fidl::StringPtr story_id,
- DeleteStoryCallback callback) {
- operation_queue_.Add(new DeleteStoryCall(
- session_storage_, story_id, &story_runtime_containers_,
- component_context_info_.message_queue_manager,
- false /* already_deleted */, callback));
-}
-
-// |fuchsia::modular::StoryProvider|
void StoryProviderImpl::GetStoryInfo(fidl::StringPtr story_id,
GetStoryInfoCallback callback) {
auto on_run = Future<>::Create("StoryProviderImpl.GetStoryInfo.on_run");
@@ -611,14 +593,9 @@
}
void StoryProviderImpl::OnStoryStorageDeleted(fidl::StringPtr story_id) {
- // NOTE: DeleteStoryCall is used here, as well as in DeleteStory(). In this
- // case, either another device deleted the story, or we did and the Ledger
- // is now notifying us. In this case, we pass |already_deleted = true| so
- // that we don't ask to delete the story data again.
- operation_queue_.Add(new DeleteStoryCall(
- session_storage_, story_id, &story_runtime_containers_,
- component_context_info_.message_queue_manager, true /* already_deleted */,
- [this, story_id] {
+ operation_queue_.Add(new StopStoryCall(
+ story_id, &story_runtime_containers_,
+ component_context_info_.message_queue_manager, [this, story_id] {
for (const auto& i : watchers_.ptrs()) {
(*i)->OnDelete(story_id);
}
@@ -662,7 +639,7 @@
const fuchsia::modular::internal::StoryData* const story_data,
const fuchsia::modular::StoryState story_state,
const fuchsia::modular::StoryVisibilityState story_visibility_state) {
- if (story_data->story_options.kind_of_proto_story) {
+ if (!story_data || story_data->story_options.kind_of_proto_story) {
return;
}
for (const auto& i : watchers_.ptrs()) {
diff --git a/bin/sessionmgr/story_runner/story_provider_impl.h b/bin/sessionmgr/story_runner/story_provider_impl.h
index 3b4bcdf..ca04c50 100644
--- a/bin/sessionmgr/story_runner/story_provider_impl.h
+++ b/bin/sessionmgr/story_runner/story_provider_impl.h
@@ -131,8 +131,8 @@
fidl::VectorPtr<fuchsia::modular::OngoingActivityType>
ongoing_activities);
- // Called by StoryControllerImpl. Sends request to fuchsia::modular::SessionShell
- // through PresentationProvider.
+ // Called by StoryControllerImpl. Sends request to
+ // fuchsia::modular::SessionShell through PresentationProvider.
void GetPresentation(
fidl::StringPtr story_id,
fidl::InterfaceRequest<fuchsia::ui::policy::Presentation> request);
@@ -177,10 +177,6 @@
private:
// |fuchsia::modular::StoryProvider|
- void DeleteStory(fidl::StringPtr story_id,
- DeleteStoryCallback callback) override;
-
- // |fuchsia::modular::StoryProvider|
void GetController(fidl::StringPtr story_id,
fidl::InterfaceRequest<fuchsia::modular::StoryController>
request) override;
@@ -270,7 +266,7 @@
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.
+ 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
@@ -313,9 +309,8 @@
fxl::WeakPtrFactory<StoryProviderImpl> weak_factory_;
// Operations implemented here.
- class CreateStoryCall;
- class DeleteStoryCall;
class LoadStoryRuntimeCall;
+ class StopStoryCall;
class StopAllStoriesCall;
class StopStoryShellCall;
class GetStoryEntityProviderCall;
diff --git a/lib/testing/story_provider_mock.h b/lib/testing/story_provider_mock.h
index c0c694c..eda98f7 100644
--- a/lib/testing/story_provider_mock.h
+++ b/lib/testing/story_provider_mock.h
@@ -67,13 +67,6 @@
}
// |fuchsia::modular::StoryProvider|
- void DeleteStory(fidl::StringPtr story_id,
- DeleteStoryCallback callback) override {
- deleted_story_ = story_id;
- callback();
- }
-
- // |fuchsia::modular::StoryProvider|
void GetStoryInfo(fidl::StringPtr story_id,
GetStoryInfoCallback callback) override {
callback(nullptr);
diff --git a/public/fidl/fuchsia.modular/story/story_provider.fidl b/public/fidl/fuchsia.modular/story/story_provider.fidl
index dc0fea6..33f979a 100644
--- a/public/fidl/fuchsia.modular/story/story_provider.fidl
+++ b/public/fidl/fuchsia.modular/story/story_provider.fidl
@@ -12,22 +12,13 @@
// framework.
[Discoverable]
interface StoryProvider {
- // Deletes an existing story from the list of known stories. Returns when the
- // delete notification is received from the Ledger. If the story to be deleted
- // is running, it is first stopped and its story controller disconnected. If
- // the story ID doesn't exist, it silently does nothing and returns.
- //
- // DEPRECATED: To delete stories, use PuppetMaster.
- 3: DeleteStory(string story_id) -> ();
-
// Returns a list of existing stories. If |watcher| is provided, the client will
// be notified of story changes (new stories, deleted stories, runtime
// state changes).
4: GetStories(StoryProviderWatcher? watcher) -> (vector<StoryInfo> story_infos);
// Requests detailed information about the given story. If the story doesn't
- // exist, returns null. GetStoryInfo() called immediately after DeleteStory()
- // (even before DeleteStory() returns) returns null.
+ // exist, returns null.
5: GetStoryInfo(string story_id) -> (StoryInfo? story_info);
// Obtains a controller for a previously created story identified by its story
@@ -89,25 +80,11 @@
1: OnChange(StoryInfo story_info, StoryState story_state,
StoryVisibilityState story_visibility_state);
- // Called in two different situations:
+ // Called when a story record is permanently deleted. The deletion could
+ // have originated on this or on another device.
//
- // * After the story record of a story is deleted from the current device by
- // an invocation of StoryProvider.DeleteStory() on the current device.
- //
- // * When the information reaches the current device through Ledger
- // synchronization that the story record of a story was deleted from another
- // device by an invocation by StoryProvider.DeleteStory() there.
- //
- // I.e. if the story is deleted on *another* device, it eventually *does*
- // cause an OnDelete() call on *this* device. Cf. OnChange() above.
- //
- // Either way, if the story is running on this device at the time the deletion
- // becomes known to this device on this device, it is also stopped first. This
- // stopping of the story does not cause an OnChange() callback, only the
- // OnDelete() here.
- //
- // The OnDelete() call also happen when the story record is deleted while the
- // story is not running.
+ // If the story is running on this device at the time it is deleted,
+ // OnChange() will not be called first.
2: OnDelete(string story_id);
};
diff --git a/tests/link_data/link_data_test_session_shell.cc b/tests/link_data/link_data_test_session_shell.cc
index ff24f7a..dd5ef22 100644
--- a/tests/link_data/link_data_test_session_shell.cc
+++ b/tests/link_data/link_data_test_session_shell.cc
@@ -237,7 +237,7 @@
TestPoint story2_stop_{"Story2 Stop"};
void TestStory2_Delete() {
- story_provider_->DeleteStory(story_info_.id, [this] {
+ puppet_master_->DeleteStory(story_info_.id, [this] {
story2_stop_.Pass();
session_shell_context_->Logout();
});