Pulled out AssistantScreenContextController from AssistantController.

In addition, this CL:
- Adds an AssistantScreenContextModel/Observer.
- Inactivates the Assistant widget on show.
- Activates the Assistant widget on screen context request finished.

The AssistantScreenContextModel will also be used to cache contextual
cards returned from the server. This will be added in a follow up CL.

Bug: b:111008970
Change-Id: I0cd2cb782b880abc520bc4a8fca3c82acc1575c7
Reviewed-on: https://chromium-review.googlesource.com/1131914
Commit-Queue: David Black <[email protected]>
Reviewed-by: Muyuan Li <[email protected]>
Reviewed-by: Xiaohui Chen <[email protected]>
Cr-Commit-Position: refs/heads/master@{#574341}
diff --git a/ash/assistant/assistant_controller.cc b/ash/assistant/assistant_controller.cc
index dc35501..bf4380b 100644
--- a/ash/assistant/assistant_controller.cc
+++ b/ash/assistant/assistant_controller.cc
@@ -7,132 +7,49 @@
 #include "ash/assistant/assistant_controller_observer.h"
 #include "ash/assistant/assistant_interaction_controller.h"
 #include "ash/assistant/assistant_notification_controller.h"
+#include "ash/assistant/assistant_screen_context_controller.h"
 #include "ash/assistant/assistant_ui_controller.h"
 #include "ash/assistant/util/deep_link_util.h"
 #include "ash/new_window_controller.h"
-#include "ash/public/cpp/shell_window_ids.h"
-#include "ash/public/cpp/window_properties.h"
 #include "ash/session/session_controller.h"
 #include "ash/shell.h"
-#include "ash/wm/mru_window_tracker.h"
 #include "base/bind.h"
 #include "base/memory/scoped_refptr.h"
-#include "base/stl_util.h"
-#include "base/task_scheduler/post_task.h"
 #include "base/unguessable_token.h"
-#include "ui/aura/client/aura_constants.h"
-#include "ui/compositor/layer_tree_owner.h"
-#include "ui/gfx/codec/jpeg_codec.h"
-#include "ui/gfx/skbitmap_operations.h"
-#include "ui/snapshot/snapshot.h"
-#include "ui/snapshot/snapshot_aura.h"
-#include "ui/wm/core/window_util.h"
 
 namespace ash {
 
-namespace {
-
-// When screenshot's width or height is smaller than this size, we will stop
-// downsampling.
-constexpr int kScreenshotMaxWidth = 1366;
-constexpr int kScreenshotMaxHeight = 768;
-
-std::vector<uint8_t> DownsampleAndEncodeImage(gfx::Image image) {
-  std::vector<uint8_t> res;
-  // We'll downsample the screenshot to avoid exceeding max allowed size on
-  // assistant server side if we are taking screenshot from high-res screen.
-  gfx::JPEGCodec::Encode(
-      SkBitmapOperations::DownsampleByTwoUntilSize(
-          image.AsBitmap(), kScreenshotMaxWidth, kScreenshotMaxHeight),
-      100 /* quality */, &res);
-  return res;
-}
-
-void EncodeScreenshotAndRunCallback(
-    AssistantController::RequestScreenshotCallback callback,
-    std::unique_ptr<ui::LayerTreeOwner> layer_owner,
-    gfx::Image image) {
-  base::PostTaskWithTraitsAndReplyWithResult(
-      FROM_HERE,
-      base::TaskTraits{base::MayBlock(), base::TaskPriority::USER_BLOCKING},
-      base::BindOnce(&DownsampleAndEncodeImage, std::move(image)),
-      std::move(callback));
-}
-
-std::unique_ptr<ui::LayerTreeOwner> CreateLayerForAssistantSnapshot(
-    aura::Window* root_window) {
-  using LayerSet = base::flat_set<const ui::Layer*>;
-  LayerSet excluded_layers;
-  LayerSet blocked_layers;
-
-  aura::Window* overlay_container =
-      ash::Shell::GetContainer(root_window, kShellWindowId_OverlayContainer);
-  if (overlay_container)
-    excluded_layers.insert(overlay_container->layer());
-
-  MruWindowTracker::WindowList windows =
-      Shell::Get()->mru_window_tracker()->BuildMruWindowList();
-
-  for (aura::Window* window : windows) {
-    if (window->GetProperty(kBlockedForAssistantSnapshotKey))
-      blocked_layers.insert(window->layer());
-  }
-
-  return ::wm::RecreateLayersWithClosure(
-      root_window,
-      base::BindRepeating(
-          [](LayerSet blocked_layers, LayerSet excluded_layers,
-             ui::LayerOwner* owner) -> std::unique_ptr<ui::Layer> {
-            // Parent layer is excluded meaning that it's pointless to clone
-            // current child and all its descendants. This reduces the number
-            // of layers to create.
-            if (base::ContainsKey(blocked_layers, owner->layer()->parent()))
-              return nullptr;
-            if (base::ContainsKey(blocked_layers, owner->layer())) {
-              // Blocked layers are replaced with solid black layers so that
-              // they won't be included in the screenshot but still preserve
-              // the window stacking.
-              auto layer =
-                  std::make_unique<ui::Layer>(ui::LayerType::LAYER_SOLID_COLOR);
-              layer->SetBounds(owner->layer()->bounds());
-              layer->SetColor(SK_ColorBLACK);
-              return layer;
-            }
-            if (excluded_layers.count(owner->layer()))
-              return nullptr;
-            return owner->RecreateLayer();
-
-          },
-          std::move(blocked_layers), std::move(excluded_layers)));
-}
-
-}  // namespace
-
 AssistantController::AssistantController()
     : assistant_interaction_controller_(
           std::make_unique<AssistantInteractionController>(this)),
-      assistant_ui_controller_(std::make_unique<AssistantUiController>(this)),
       assistant_notification_controller_(
           std::make_unique<AssistantNotificationController>(this)),
+      assistant_screen_context_controller_(
+          std::make_unique<AssistantScreenContextController>()),
+      assistant_ui_controller_(std::make_unique<AssistantUiController>(this)),
       weak_factory_(this) {
   // Note that the sub-controllers have a circular dependency.
   // TODO(dmblack): Remove this circular dependency.
   assistant_interaction_controller_->SetAssistantUiController(
       assistant_ui_controller_.get());
+  assistant_screen_context_controller_->SetAssistantInteractionController(
+      assistant_interaction_controller_.get());
+  assistant_screen_context_controller_->SetAssistantUiController(
+      assistant_ui_controller_.get());
   assistant_ui_controller_->SetAssistantInteractionController(
       assistant_interaction_controller_.get());
-
-  assistant_ui_controller_->AddModelObserver(this);
-  Shell::Get()->highlighter_controller()->AddObserver(this);
+  assistant_ui_controller_->SetAssistantScreenContextController(
+      assistant_screen_context_controller_.get());
 }
 
 AssistantController::~AssistantController() {
-  Shell::Get()->highlighter_controller()->RemoveObserver(this);
-  assistant_ui_controller_->RemoveModelObserver(this);
-
   // Explicitly clean up the circular dependency in the sub-controllers.
   assistant_interaction_controller_->SetAssistantUiController(nullptr);
+  assistant_screen_context_controller_->SetAssistantInteractionController(
+      nullptr);
+  assistant_screen_context_controller_->SetAssistantUiController(nullptr);
   assistant_ui_controller_->SetAssistantInteractionController(nullptr);
+  assistant_ui_controller_->SetAssistantScreenContextController(nullptr);
 }
 
 void AssistantController::BindRequest(
@@ -155,8 +72,9 @@
 
   // Provide reference to sub-controllers.
   assistant_interaction_controller_->SetAssistant(assistant_.get());
-  assistant_ui_controller_->SetAssistant(assistant_.get());
   assistant_notification_controller_->SetAssistant(assistant_.get());
+  assistant_screen_context_controller_->SetAssistant(assistant_.get());
+  assistant_ui_controller_->SetAssistant(assistant_.get());
 }
 
 void AssistantController::SetAssistantImageDownloader(
@@ -177,33 +95,13 @@
   web_contents_manager_ = std::move(web_contents_manager);
 }
 
+// TODO(dmblack): Expose AssistantScreenContextController over mojo rather
+// than implementing RequestScreenshot here in AssistantController.
 void AssistantController::RequestScreenshot(
     const gfx::Rect& rect,
     RequestScreenshotCallback callback) {
-  // TODO(muyuanli): handle multi-display when assistant's behavior is defined.
-  aura::Window* root_window = Shell::GetPrimaryRootWindow();
-
-  std::unique_ptr<ui::LayerTreeOwner> layer_owner =
-      CreateLayerForAssistantSnapshot(root_window);
-
-  ui::Layer* root_layer = layer_owner->root();
-
-  gfx::Rect source_rect =
-      rect.IsEmpty() ? gfx::Rect(root_window->bounds().size()) : rect;
-
-  // The root layer might have a scaling transform applied (if the user has
-  // changed the UI scale via Ctrl-Shift-Plus/Minus).
-  // Clear the transform so that the snapshot is taken at 1:1 scale relative
-  // to screen pixels.
-  root_layer->SetTransform(gfx::Transform());
-  root_window->layer()->Add(root_layer);
-  root_window->layer()->StackAtBottom(root_layer);
-
-  ui::GrabLayerSnapshotAsync(
-      root_layer, source_rect,
-      base::BindRepeating(&EncodeScreenshotAndRunCallback,
-                          base::Passed(std::move(callback)),
-                          base::Passed(std::move(layer_owner))));
+  assistant_screen_context_controller_->RequestScreenshot(rect,
+                                                          std::move(callback));
 }
 
 void AssistantController::ManageWebContents(
@@ -262,29 +160,6 @@
   assistant_image_downloader_->Download(account_id, url, std::move(callback));
 }
 
-void AssistantController::OnUiVisibilityChanged(bool visible,
-                                                AssistantSource source) {
-  // We don't initiate a contextual query for caching if the UI is being hidden.
-  if (!visible)
-    return;
-
-  // We don't initiate a contextual query for caching if we are using stylus
-  // input modality because we will do so on metalayer session complete.
-  if (assistant_interaction_controller_->model()->input_modality() ==
-      InputModality::kStylus) {
-    return;
-  }
-
-  // TODO(dmblack): Activate the Assistant UI when the callback is run.
-  assistant_->RequestScreenContext(gfx::Rect(), base::DoNothing());
-}
-
-void AssistantController::OnHighlighterSelectionRecognized(
-    const gfx::Rect& rect) {
-  // TODO(dmblack): Activate the Assistant UI when the callback is run.
-  assistant_->RequestScreenContext(rect, base::DoNothing());
-}
-
 void AssistantController::OnOpenUrlFromTab(const GURL& url) {
   OpenUrl(url);
 }
@@ -306,10 +181,4 @@
   return weak_factory_.GetWeakPtr();
 }
 
-std::unique_ptr<ui::LayerTreeOwner>
-AssistantController::CreateLayerForAssistantSnapshotForTest() {
-  aura::Window* root_window = Shell::GetPrimaryRootWindow();
-  return CreateLayerForAssistantSnapshot(root_window);
-}
-
 }  // namespace ash