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..e9cf9ae65e730dea87f4b30dc4504575262e5e60 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 |
@@ -4,21 +4,34 @@ |
#include "chrome/browser/chromeos/arc/voice_interaction/arc_voice_interaction_framework_service.h" |
+#include <set> |
#include <utility> |
#include <vector> |
#include "ash/accelerators/accelerator_controller.h" |
#include "ash/shell.h" |
+#include "base/bind.h" |
#include "base/command_line.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,43 @@ void ScreenshotCallback( |
callback.Run(result); |
} |
+std::unique_ptr<ui::LayerTreeOwner> BlockIncognitoWindows( |
+ aura::Window* root_window) { |
+ using LayerSet = std::set<const ui::Layer*>; |
+ auto blocked_layers = LayerSet(); |
Luis Héctor Chávez
2017/05/15 16:47:52
Why not
LayerSet blocked_layers;
? It's shorter
Muyuan
2017/05/15 18:09:54
Done.
|
+ auto* browser_list = BrowserList::GetInstance(); |
+ for (auto* browser : *browser_list) { |
Luis Héctor Chávez
2017/05/15 16:47:51
nit: BrowserList itself does
for (auto* browser :
Muyuan
2017/05/15 18:09:54
Done.
|
+ if (browser->profile()->IsOffTheRecord()) |
+ blocked_layers.insert(browser->window()->GetNativeWindow()->layer()); |
+ } |
+ |
+ auto layer_tree_owner = ::wm::MapLayers( |
+ root_window, base::Bind( |
+ [](LayerSet 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 (layers.count(owner->layer()->parent())) |
+ return nullptr; |
+ if (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))); |
+ if (layer_tree_owner) { |
Luis Héctor Chávez
2017/05/15 16:47:52
nit: use the guard clause pattern:
if (!layer_tre
Muyuan
2017/05/15 18:09:54
Done.
|
+ auto* root_layer = layer_tree_owner->root(); |
+ root_window->layer()->Add(root_layer); |
+ root_window->layer()->StackAtBottom(root_layer); |
+ } |
+ return layer_tree_owner; |
+} |
+ |
} // namespace |
// static |
@@ -136,11 +186,14 @@ 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)); |
+ |
+ old_layer_owner_ = BlockIncognitoWindows(window); |
Luis Héctor Chávez
2017/05/15 16:47:52
It doesn't seem like you *need* to store this as a
|
+ DCHECK(old_layer_owner_); |
Luis Héctor Chávez
2017/05/15 16:47:52
I don't think you can DCHECK here since it seems l
Muyuan
2017/05/15 18:09:54
Done.
|
+ |
+ ui::GrabLayerSnapshotAsync( |
+ old_layer_owner_->root(), gfx::Rect(window->bounds().size()), |
+ base::Bind(&ArcVoiceInteractionFrameworkService::EncodeAndReturnImage, |
+ base::Unretained(this), callback)); |
} |
void ArcVoiceInteractionFrameworkService::OnMetalayerClosed() { |
@@ -196,4 +249,21 @@ void ArcVoiceInteractionFrameworkService::SetMetalayerVisibility(bool visible) { |
framework_instance->SetMetalayerVisibility(visible); |
} |
+void ArcVoiceInteractionFrameworkService::EncodeAndReturnImage( |
+ const CaptureFullscreenCallback& callback, |
+ const gfx::Image& image) { |
+ old_layer_owner_.reset(); |
+ base::PostTaskWithTraitsAndReplyWithResult( |
+ FROM_HERE, |
+ base::TaskTraits({base::MayBlock(), base::TaskPriority::USER_BLOCKING}), |
Luis Héctor Chávez
2017/05/15 16:47:51
nit:
base::TaskTraits{base::MayBlock(), base::Tas
Muyuan
2017/05/15 18:09:54
Done.
|
+ 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 arc |