blob: 6239dc960be81b65ebc2b02934adb3f6500feaf2 [file] [log] [blame]
// Copyright 2021 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 "src/modular/bin/sessionmgr/story_runner/annotation_controller_impl.h"
#include <lib/syslog/cpp/macros.h>
#include <unordered_set>
#include "src/modular/bin/sessionmgr/annotations.h"
namespace modular {
AnnotationControllerImpl::AnnotationControllerImpl(std::string story_id,
SessionStorage* const session_storage)
: story_id_(std::move(story_id)), session_storage_(session_storage) {
FX_DCHECK(session_storage_ != nullptr);
}
void AnnotationControllerImpl::Connect(
fidl::InterfaceRequest<fuchsia::element::AnnotationController> request) {
bindings_.AddBinding(this, std::move(request));
}
void AnnotationControllerImpl::UpdateAnnotations(
std::vector<fuchsia::element::Annotation> annotations_to_set,
std::vector<fuchsia::element::AnnotationKey> annotations_to_delete,
UpdateAnnotationsCallback callback) {
fuchsia::element::AnnotationController_UpdateAnnotations_Result result;
// Ensure all keys, by themselves, are valid.
bool keys_to_set_are_valid{true};
for (const auto& annotation : annotations_to_set) {
if (!element::annotations::IsValidKey(annotation.key)) {
FX_LOGS(ERROR) << "Setting invalid key for story id: " << story_id_
<< " annotation key namespace: " << annotation.key.namespace_
<< " annotation key value: " << annotation.key.value;
keys_to_set_are_valid = false;
}
}
if (!keys_to_set_are_valid) {
result.set_err(fuchsia::element::UpdateAnnotationsError::INVALID_ARGS);
callback(std::move(result));
return;
}
bool keys_to_delete_are_valid{true};
for (const auto& annotation_key : annotations_to_delete) {
if (!element::annotations::IsValidKey(annotation_key)) {
FX_LOGS(ERROR) << "Deleting invalid key for story id: " << story_id_
<< " annotation key namespace: " << annotation_key.namespace_
<< " annotation key value: " << annotation_key.value;
keys_to_delete_are_valid = false;
}
}
if (!keys_to_delete_are_valid) {
result.set_err(fuchsia::element::UpdateAnnotationsError::INVALID_ARGS);
callback(std::move(result));
return;
}
// Ensure that there are no annotations being both set and deleted, i.e. that a key
// does not exist in both |annotations_to_set| and |annotations_to_delete|.
std::unordered_set<fuchsia::element::AnnotationKey> to_set_keys;
for (const auto& annotation : annotations_to_set) {
to_set_keys.insert(fidl::Clone(annotation.key));
}
bool is_same_key_set_delete{false};
for (const auto& annotation_key : annotations_to_delete) {
if (to_set_keys.count(annotation_key) > 0) {
FX_LOGS(ERROR) << "Setting and deleting the same annotation key for story id: " << story_id_
<< " annotation key namespace: " << annotation_key.namespace_
<< " annotation key value: " << annotation_key.value;
is_same_key_set_delete = true;
}
}
if (is_same_key_set_delete) {
result.set_err(fuchsia::element::UpdateAnnotationsError::INVALID_ARGS);
callback(std::move(result));
return;
}
auto modular_annotations = element::annotations::ToModularAnnotations(annotations_to_set);
// Add |annotations_to_delete| as Modular annotations with a null value.
// |MergeStoryAnnotations| removes annotations with a null value from the story.
for (const auto& key : annotations_to_delete) {
auto annotation = fuchsia::modular::Annotation{
.key = element::annotations::ToModularAnnotationKey(key), .value = nullptr};
modular_annotations.push_back(std::move(annotation));
}
auto merge_err =
session_storage_->MergeStoryAnnotations(story_id_, std::move(modular_annotations));
if (merge_err.has_value()) {
if (merge_err.value() == fuchsia::modular::AnnotationError::TOO_MANY_ANNOTATIONS) {
result.set_err(fuchsia::element::UpdateAnnotationsError::TOO_MANY_ANNOTATIONS);
} else {
result.set_err(fuchsia::element::UpdateAnnotationsError::INVALID_ARGS);
}
} else {
result.set_response({});
}
callback(std::move(result));
}
void AnnotationControllerImpl::GetAnnotations(GetAnnotationsCallback callback) {
auto story_data = session_storage_->GetStoryData(story_id_);
if (!story_data) {
fuchsia::element::AnnotationController_GetAnnotations_Result result;
result.set_response({});
callback(std::move(result));
return;
}
FX_DCHECK(story_data->has_story_info());
fuchsia::element::AnnotationController_GetAnnotations_Response response;
if (story_data->story_info().has_annotations()) {
response.annotations =
modular::annotations::ToElementAnnotations(story_data->story_info().annotations());
}
fuchsia::element::AnnotationController_GetAnnotations_Result result;
result.set_response(std::move(response));
callback(std::move(result));
}
} // namespace modular