| // Copyright 2019 The Chromium Authors |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "ash/assistant/model/ui/assistant_card_element.h" |
| |
| #include <utility> |
| |
| #include "ash/assistant/ui/assistant_ui_constants.h" |
| #include "ash/assistant/ui/assistant_view_ids.h" |
| #include "ash/public/cpp/ash_web_view.h" |
| #include "ash/public/cpp/ash_web_view_factory.h" |
| #include "base/base64.h" |
| #include "base/memory/raw_ptr.h" |
| |
| namespace ash { |
| |
| // AssistantCardElement::Processor --------------------------------------------- |
| |
| class AssistantCardElement::Processor : public AshWebView::Observer { |
| public: |
| Processor(AssistantCardElement* card_element, ProcessingCallback callback) |
| : card_element_(card_element), callback_(std::move(callback)) {} |
| |
| Processor(const Processor& copy) = delete; |
| Processor& operator=(const Processor& assign) = delete; |
| |
| ~Processor() override { |
| if (contents_view_) |
| contents_view_->RemoveObserver(this); |
| |
| if (callback_) |
| std::move(callback_).Run(); |
| } |
| |
| void Process() { |
| const int width_dip = |
| card_element_->viewport_width() - 2 * assistant::ui::kHorizontalMargin; |
| |
| // Configure parameters for the card. We want to configure the size as: |
| // - width: It should be width_dip. |
| // - height: It should be calculated from the content. |
| AshWebView::InitParams contents_params; |
| contents_params.enable_auto_resize = true; |
| contents_params.min_size = gfx::Size(width_dip, 1); |
| contents_params.max_size = gfx::Size(width_dip, INT_MAX); |
| contents_params.suppress_navigation = true; |
| contents_params.fix_zoom_level_to_one = true; |
| |
| // Create |contents_view_| and retain ownership until it is added to the |
| // view hierarchy. If that never happens, it will be still be cleaned up. |
| contents_view_ = AshWebViewFactory::Get()->Create(contents_params); |
| contents_view_->SetID(AssistantViewID::kAshWebView); |
| |
| // Observe |contents_view_| so that we are notified when loading is |
| // complete. |
| contents_view_->AddObserver(this); |
| |
| // Encode the html string to be URL-safe. |
| std::string encoded_html; |
| base::Base64Encode(card_element_->html(), &encoded_html); |
| |
| // Navigate to the data URL which represents the card. |
| constexpr char kDataUriPrefix[] = "data:text/html;base64,"; |
| contents_view_->Navigate(GURL(kDataUriPrefix + encoded_html)); |
| } |
| |
| private: |
| // AshWebView::Observer: |
| void DidStopLoading() override { |
| contents_view_->RemoveObserver(this); |
| |
| // Pass ownership of |contents_view_| to the card element that was being |
| // processed and notify our |callback_| of the completion. |
| card_element_->set_contents_view(std::move(contents_view_)); |
| std::move(callback_).Run(); |
| } |
| |
| // |card_element_| should outlive the Processor. |
| const raw_ptr<AssistantCardElement, ExperimentalAsh> card_element_; |
| ProcessingCallback callback_; |
| |
| std::unique_ptr<AshWebView> contents_view_; |
| }; |
| |
| // AssistantCardElement -------------------------------------------------------- |
| |
| AssistantCardElement::AssistantCardElement(const std::string& html, |
| const std::string& fallback, |
| int viewport_width) |
| : AssistantUiElement(AssistantUiElementType::kCard), |
| html_(html), |
| fallback_(fallback), |
| viewport_width_(viewport_width) {} |
| |
| AssistantCardElement::~AssistantCardElement() { |
| // |processor_| should be destroyed before |this| has been deleted. |
| processor_.reset(); |
| } |
| |
| void AssistantCardElement::Process(ProcessingCallback callback) { |
| processor_ = std::make_unique<Processor>(this, std::move(callback)); |
| processor_->Process(); |
| } |
| |
| bool AssistantCardElement::has_contents_view() const { |
| return !!contents_view_; |
| } |
| |
| bool AssistantCardElement::Compare(const AssistantUiElement& other) const { |
| return other.type() == AssistantUiElementType::kCard && |
| static_cast<const AssistantCardElement&>(other).html() == html_; |
| } |
| |
| } // namespace ash |