| Index: chrome/browser/chromeos/arc/voice_interaction/arc_voice_interaction_framework_service.cc
|
| diff --git a/chrome/browser/chromeos/arc/voice_interaction/arc_voice_interaction_framework_service.cc b/chrome/browser/chromeos/arc/voice_interaction/arc_voice_interaction_framework_service.cc
|
| index c0c1c9d135badab625e71d8ca9b499d6b6d97839..549c76a5d34445bfcb39ba35a7a1979b18eccd90 100644
|
| --- a/chrome/browser/chromeos/arc/voice_interaction/arc_voice_interaction_framework_service.cc
|
| +++ b/chrome/browser/chromeos/arc/voice_interaction/arc_voice_interaction_framework_service.cc
|
| @@ -9,16 +9,29 @@
|
|
|
| #include "ash/accelerators/accelerator_controller.h"
|
| #include "ash/shell.h"
|
| +#include "base/bind.h"
|
| #include "base/command_line.h"
|
| +#include "base/containers/flat_set.h"
|
| #include "base/logging.h"
|
| #include "base/memory/ref_counted.h"
|
| #include "base/task_scheduler/post_task.h"
|
| +#include "chrome/browser/ui/browser.h"
|
| +#include "chrome/browser/ui/browser_list.h"
|
| +#include "chrome/browser/ui/browser_window.h"
|
| #include "chromeos/chromeos_switches.h"
|
| #include "components/arc/arc_bridge_service.h"
|
| #include "components/arc/instance_holder.h"
|
| #include "content/public/browser/browser_thread.h"
|
| #include "ui/aura/window.h"
|
| +#include "ui/compositor/layer.h"
|
| +#include "ui/compositor/layer_owner.h"
|
| +#include "ui/compositor/layer_tree_owner.h"
|
| +#include "ui/gfx/image/image.h"
|
| +#include "ui/gfx/image/image_util.h"
|
| +#include "ui/gfx/native_widget_types.h"
|
| #include "ui/snapshot/snapshot.h"
|
| +#include "ui/snapshot/snapshot_aura.h"
|
| +#include "ui/wm/core/window_util.h"
|
| #include "ui/wm/public/activation_client.h"
|
|
|
| namespace arc {
|
| @@ -37,6 +50,64 @@ void ScreenshotCallback(
|
| callback.Run(result);
|
| }
|
|
|
| +std::unique_ptr<ui::LayerTreeOwner> CreateLayerTreeForSnapshot(
|
| + aura::Window* root_window) {
|
| + using LayerSet = base::flat_set<const ui::Layer*>;
|
| + LayerSet blocked_layers;
|
| + for (auto* browser : *BrowserList::GetInstance()) {
|
| + if (browser->profile()->IsOffTheRecord())
|
| + blocked_layers.insert(browser->window()->GetNativeWindow()->layer());
|
| + }
|
| +
|
| + auto layer_tree_owner = ::wm::RecreateLayersWithClosure(
|
| + root_window, base::BindRepeating(
|
| + [](LayerSet blocked_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 (blocked_layers.count(owner->layer()->parent()))
|
| + return nullptr;
|
| + if (blocked_layers.count(owner->layer())) {
|
| + auto layer = base::MakeUnique<ui::Layer>(
|
| + ui::LayerType::LAYER_SOLID_COLOR);
|
| + layer->SetBounds(owner->layer()->bounds());
|
| + layer->SetColor(SK_ColorBLACK);
|
| + return layer;
|
| + }
|
| + return owner->RecreateLayer();
|
| + },
|
| + std::move(blocked_layers)));
|
| +
|
| + // layer_tree_owner cannot be null since we are starting off from the root
|
| + // window, which could never be incognito.
|
| + DCHECK(layer_tree_owner);
|
| +
|
| + auto* root_layer = layer_tree_owner->root();
|
| + root_window->layer()->Add(root_layer);
|
| + root_window->layer()->StackAtBottom(root_layer);
|
| + return layer_tree_owner;
|
| +}
|
| +
|
| +void EncodeAndReturnImage(
|
| + const ArcVoiceInteractionFrameworkService::CaptureFullscreenCallback&
|
| + callback,
|
| + std::unique_ptr<ui::LayerTreeOwner> old_layer_owner,
|
| + const gfx::Image& image) {
|
| + old_layer_owner.reset();
|
| + base::PostTaskWithTraitsAndReplyWithResult(
|
| + FROM_HERE,
|
| + base::TaskTraits{base::MayBlock(), base::TaskPriority::USER_BLOCKING},
|
| + base::Bind(
|
| + [](const gfx::Image& image) -> std::vector<uint8_t> {
|
| + std::vector<uint8_t> res;
|
| + gfx::JPEG1xEncodedDataFromImage(image, 100, &res);
|
| + return res;
|
| + },
|
| + image),
|
| + callback);
|
| +}
|
| +
|
| } // namespace
|
|
|
| // static
|
| @@ -136,11 +207,12 @@ void ArcVoiceInteractionFrameworkService::CaptureFullscreen(
|
| // the screenshot to it.
|
| aura::Window* window = ash::Shell::GetPrimaryRootWindow();
|
| DCHECK(window);
|
| - ui::GrabWindowSnapshotAsyncJPEG(
|
| - window, gfx::Rect(window->bounds().size()),
|
| - base::CreateTaskRunnerWithTraits(
|
| - {base::MayBlock(), base::TaskPriority::USER_BLOCKING}),
|
| - base::Bind(&ScreenshotCallback, callback));
|
| +
|
| + auto old_layer_owner = CreateLayerTreeForSnapshot(window);
|
| + ui::GrabLayerSnapshotAsync(
|
| + old_layer_owner->root(), gfx::Rect(window->bounds().size()),
|
| + base::Bind(&EncodeAndReturnImage, callback,
|
| + base::Passed(std::move(old_layer_owner))));
|
| }
|
|
|
| void ArcVoiceInteractionFrameworkService::OnMetalayerClosed() {
|
|
|