1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129
|
// Copyright 2018 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef ASH_ASSISTANT_MODEL_ASSISTANT_RESPONSE_H_
#define ASH_ASSISTANT_MODEL_ASSISTANT_RESPONSE_H_
#include <deque>
#include <memory>
#include <vector>
#include "base/component_export.h"
#include "base/functional/callback.h"
#include "base/memory/ref_counted.h"
#include "base/observer_list.h"
#include "chromeos/ash/services/libassistant/public/cpp/assistant_suggestion.h"
namespace base {
class UnguessableToken;
} // namespace base
namespace ash {
class AssistantResponseObserver;
class AssistantUiElement;
// TODO(dmblack): Remove ProcessingState after launch of response processing v2.
// Models a renderable Assistant response.
// It is refcounted so that views that display the response can safely
// reference the data inside this response.
class COMPONENT_EXPORT(ASSISTANT_MODEL) AssistantResponse
: public base::RefCounted<AssistantResponse> {
public:
using AssistantSuggestion = assistant::AssistantSuggestion;
using ProcessingCallback = base::OnceCallback<void(bool)>;
enum class ProcessingState {
kUnprocessed, // Response has not yet been processed.
kProcessing, // Response is currently being processed.
kProcessed, // Response has finished processing.
};
AssistantResponse();
AssistantResponse(const AssistantResponse&) = delete;
AssistantResponse& operator=(const AssistantResponse&) = delete;
// Adds/removes the specified |observer|.
// NOTE: only the AssistantInteractionController is able to obtain non-const
// access to an AssistantResponse through its owned model, but there are const
// accessors who wish to observe the response for changes in its underlying
// data. To accomplish this, we make AddObserver() and RemoveObserver() const,
// though these methods do modify the underlying ObserverList. This is safe to
// do as AssistantResponseObserver only exposes const access to the underlying
// response data and so doesn't expose AssistantResponse for modification.
void AddObserver(AssistantResponseObserver* observer) const;
void RemoveObserver(AssistantResponseObserver* observer) const;
// Adds the specified |ui_element| that should be rendered for the
// interaction.
void AddUiElement(std::unique_ptr<AssistantUiElement> ui_element);
// Returns all UI elements belonging to the response.
const std::vector<std::unique_ptr<AssistantUiElement>>& GetUiElements() const;
// Adds the specified |suggestions| that should be rendered for the
// interaction.
void AddSuggestions(const std::vector<AssistantSuggestion>& suggestions);
// Returns the suggestion uniquely identified by |id|.
const AssistantSuggestion* GetSuggestionById(
const base::UnguessableToken& id) const;
// Returns all suggestions belongs to the response.
const std::vector<AssistantSuggestion>& GetSuggestions() const;
// Gets/sets the processing state for the response.
ProcessingState processing_state() const { return processing_state_; }
void set_processing_state(ProcessingState processing_state) {
processing_state_ = processing_state;
}
// Gets/sets if the response has TTS. This can only be reliably checked after
// the response is finalized for obvious reasons.
bool has_tts() const { return has_tts_; }
void set_has_tts(bool has_tts) { has_tts_ = has_tts; }
// Invoke to begin processing the response. The specified |callback| will be
// run to indicate whether or not the processor has completed processing of
// all UI elements in the response.
void Process(ProcessingCallback callback);
// Return true if this response contains an identical ui element.
bool ContainsUiElement(const AssistantUiElement* element) const;
private:
void NotifyUiElementAdded(const AssistantUiElement* ui_element);
void NotifySuggestionsAdded(const std::vector<AssistantSuggestion>&);
// Return true if the pending ui elements contain an identical ui element.
bool ContainsPendingUiElement(const AssistantUiElement* other) const;
struct PendingUiElement;
class Processor;
friend class base::RefCounted<AssistantResponse>;
~AssistantResponse();
std::deque<std::unique_ptr<PendingUiElement>> pending_ui_elements_;
std::vector<AssistantSuggestion> suggestions_;
ProcessingState processing_state_ = ProcessingState::kUnprocessed;
bool has_tts_ = false;
// We specify the declaration order below as intended because we want
// |processor_| to be destroyed before |ui_elements_| (we also forced this
// order in the destructor), so that when the response processing got
// interrupted, the |ProcessingCallback| can have a chance to return false
// during the destruction to indicate the failure of completion.
std::vector<std::unique_ptr<AssistantUiElement>> ui_elements_;
std::unique_ptr<Processor> processor_;
mutable base::ObserverList<AssistantResponseObserver> observers_;
base::WeakPtrFactory<AssistantResponse> weak_factory_{this};
};
} // namespace ash
#endif // ASH_ASSISTANT_MODEL_ASSISTANT_RESPONSE_H_
|