1 // Copyright 2018 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "chrome/browser/ui/ash/assistant/assistant_context_util.h"
6
7 #include <utility>
8
9 #include "base/bind.h"
10 #include "chrome/browser/chromeos/profiles/profile_helper.h"
11 #include "chrome/browser/ui/browser.h"
12 #include "chrome/browser/ui/browser_list.h"
13 #include "chrome/browser/ui/browser_window.h"
14 #include "chrome/browser/ui/tabs/tab_strip_model.h"
15 #include "chromeos/ui/base/window_properties.h"
16 #include "components/arc/arc_service_manager.h"
17 #include "components/arc/mojom/app.mojom.h"
18 #include "components/arc/session/arc_bridge_service.h"
19 #include "content/public/browser/browser_thread.h"
20 #include "content/public/browser/web_contents.h"
21 #include "ui/accessibility/ax_assistant_structure.h"
22 #include "ui/aura/window.h"
23 #include "ui/aura/window_tree_host.h"
24 #include "ui/gfx/geometry/point.h"
25 #include "ui/snapshot/snapshot.h"
26
27 namespace {
28
CreateAssistantStructureAndRunCallback(RequestAssistantStructureCallback callback,ax::mojom::AssistantExtraPtr assistant_extra,const ui::AXTreeUpdate & update)29 void CreateAssistantStructureAndRunCallback(
30 RequestAssistantStructureCallback callback,
31 ax::mojom::AssistantExtraPtr assistant_extra,
32 const ui::AXTreeUpdate& update) {
33 std::move(callback).Run(std::move(assistant_extra),
34 ui::CreateAssistantTree(update, false));
35 }
36
CreateAssistantExtra(content::WebContents * web_contents,const gfx::Rect & bounds_pixel)37 ax::mojom::AssistantExtraPtr CreateAssistantExtra(
38 content::WebContents* web_contents,
39 const gfx::Rect& bounds_pixel) {
40 auto assistant_extra = ax::mojom::AssistantExtra::New();
41 assistant_extra->url = web_contents->GetLastCommittedURL();
42 assistant_extra->title = web_contents->GetTitle();
43 assistant_extra->bounds_pixel = bounds_pixel;
44 return assistant_extra;
45 }
46
47 } // namespace
48
RequestAssistantStructureForActiveBrowserWindow(RequestAssistantStructureCallback callback)49 void RequestAssistantStructureForActiveBrowserWindow(
50 RequestAssistantStructureCallback callback) {
51 Browser* browser = BrowserList::GetInstance()->GetLastActive();
52 if (!browser || !browser->window()->IsActive()) {
53 DCHECK(arc::ArcServiceManager::Get());
54 arc::mojom::AppInstance* app_instance = ARC_GET_INSTANCE_FOR_METHOD(
55 arc::ArcServiceManager::Get()->arc_bridge_service()->app(),
56 RequestAssistStructure);
57 if (!app_instance) {
58 std::move(callback).Run(nullptr, nullptr);
59 return;
60 }
61
62 app_instance->RequestAssistStructure(std::move(callback));
63 return;
64 }
65
66 // Only returns context from the profile with assistant, which is primary
67 // profile.
68 if (!chromeos::ProfileHelper::IsPrimaryProfile(browser->profile())) {
69 std::move(callback).Run(nullptr, nullptr);
70 return;
71 }
72
73 aura::Window* window = browser->window()->GetNativeWindow();
74 // Ignore incognito window.
75 if (window->GetProperty(chromeos::kBlockedForAssistantSnapshotKey)) {
76 std::move(callback).Run(nullptr, nullptr);
77 return;
78 }
79
80 // We follow same convention as Clank and thus the contents are all in
81 // pixels. The bounds of the window need to be converted to pixel in order
82 // to be consistent with rest of the view hierarchy.
83 gfx::Rect bounds = browser->window()->GetBounds();
84 gfx::Point top_left = bounds.origin();
85 gfx::Point bottom_right = bounds.bottom_right();
86 auto* window_tree_host = window->GetRootWindow()->GetHost();
87 // TODO: Revisit once multi-monitor support is planned.
88 window_tree_host->ConvertDIPToScreenInPixels(&top_left);
89 window_tree_host->ConvertDIPToScreenInPixels(&bottom_right);
90
91 content::WebContents* web_contents =
92 browser->tab_strip_model()->GetActiveWebContents();
93 web_contents->RequestAXTreeSnapshot(
94 base::BindOnce(
95 &CreateAssistantStructureAndRunCallback, std::move(callback),
96 CreateAssistantExtra(web_contents,
97 gfx::Rect(top_left.x(), top_left.y(),
98 bottom_right.x() - top_left.x(),
99 bottom_right.y() - top_left.y()))),
100 ui::kAXModeComplete);
101 }
102
RequestAssistantStructureForWebContentsForTesting(content::WebContents * web_contents,RequestAssistantStructureCallback callback)103 void RequestAssistantStructureForWebContentsForTesting(
104 content::WebContents* web_contents,
105 RequestAssistantStructureCallback callback) {
106 web_contents->RequestAXTreeSnapshot(
107 base::BindOnce(
108 &CreateAssistantStructureAndRunCallback, std::move(callback),
109 CreateAssistantExtra(web_contents, gfx::Rect(0, 0, 100, 100))),
110 ui::kAXModeComplete);
111 }
112