Index: ui/snapshot/snapshot_aura.cc |
diff --git a/ui/snapshot/snapshot_aura.cc b/ui/snapshot/snapshot_aura.cc |
index 3e4339299a6c00345d1115d0a5e53fbc1ed42ea3..13c83dcde4e552d88113bbf6605c2f7a84061eab 100644 |
--- a/ui/snapshot/snapshot_aura.cc |
+++ b/ui/snapshot/snapshot_aura.cc |
@@ -12,6 +12,7 @@ |
#include "cc/output/copy_output_request.h" |
#include "third_party/skia/include/core/SkBitmap.h" |
#include "ui/aura/window.h" |
+#include "ui/aura/window_observer.h" |
#include "ui/compositor/compositor.h" |
#include "ui/compositor/dip_util.h" |
#include "ui/compositor/layer.h" |
@@ -19,6 +20,27 @@ |
namespace ui { |
+namespace { |
+ |
+class WindowCapturer : public aura::WindowObserver { |
+ public: |
+ WindowCapturer(aura::Window* window) : window_(window) { |
sadrul
2016/09/29 04:45:09
explicit
|
+ window_->AddObserver(this); |
+ } |
+ ~WindowCapturer() override { |
+ if (window_) |
+ window_->RemoveObserver(this); |
+ } |
+ |
+ void OnWindowDestroyed(aura::Window* window) override { window_ = nullptr; } |
+ aura::Window* window() const { return window_; } |
+ |
+ private: |
+ aura::Window* window_; |
sadrul
2016/09/29 04:45:09
DISALLOW_COPY_AND_ASSIGN
|
+}; |
+ |
+} // namespace |
+ |
bool GrabViewSnapshot(gfx::NativeView view, |
std::vector<unsigned char>* png_representation, |
const gfx::Rect& snapshot_bounds) { |
@@ -42,18 +64,49 @@ static void MakeAsyncCopyRequest( |
window->layer()->RequestCopyOfOutput(std::move(request)); |
} |
+static void FinishedAsyncCopyRequest( |
+ std::unique_ptr<WindowCapturer> capturer, |
+ const gfx::Rect& source_rect, |
+ const cc::CopyOutputRequest::CopyOutputRequestCallback& callback, |
+ int retry_count, |
+ std::unique_ptr<cc::CopyOutputResult> result) { |
+ static const int kMaxRetries = 5; |
+ aura::Window* window = capturer->window(); |
+ |
+ // Retry the copy request if the previous one failed for some reason. |
+ if (window && (retry_count < kMaxRetries) && result->IsEmpty()) { |
+ MakeAsyncCopyRequest( |
sadrul
2016/09/29 04:45:09
Do we want to delay this request? Does the failure
|
+ window, source_rect, |
+ base::Bind(&FinishedAsyncCopyRequest, base::Passed(&capturer), |
+ source_rect, callback, retry_count + 1)); |
+ return; |
+ } |
+ |
+ callback.Run(std::move(result)); |
+} |
+ |
+static void MakeInitialAsyncCopyRequest( |
+ gfx::NativeWindow window, |
+ const gfx::Rect& source_rect, |
+ const cc::CopyOutputRequest::CopyOutputRequestCallback& callback) { |
+ std::unique_ptr<WindowCapturer> capturer = |
+ base::MakeUnique<WindowCapturer>(window); |
sadrul
2016/09/29 04:45:09
You can use aura::WindowTracker if you want instea
|
+ MakeAsyncCopyRequest( |
+ window, source_rect, |
+ base::Bind(&FinishedAsyncCopyRequest, base::Passed(&capturer), |
+ source_rect, callback, 0)); |
+} |
+ |
void GrabWindowSnapshotAndScaleAsync( |
gfx::NativeWindow window, |
const gfx::Rect& source_rect, |
const gfx::Size& target_size, |
scoped_refptr<base::TaskRunner> background_task_runner, |
const GrabWindowSnapshotAsyncCallback& callback) { |
- MakeAsyncCopyRequest(window, |
- source_rect, |
- base::Bind(&SnapshotAsync::ScaleCopyOutputResult, |
- callback, |
- target_size, |
- background_task_runner)); |
+ MakeInitialAsyncCopyRequest( |
+ window, source_rect, |
+ base::Bind(&SnapshotAsync::ScaleCopyOutputResult, callback, target_size, |
+ background_task_runner)); |
} |
void GrabWindowSnapshotAsync( |
@@ -61,11 +114,9 @@ void GrabWindowSnapshotAsync( |
const gfx::Rect& source_rect, |
scoped_refptr<base::TaskRunner> background_task_runner, |
const GrabWindowSnapshotAsyncPNGCallback& callback) { |
- MakeAsyncCopyRequest(window, |
- source_rect, |
- base::Bind(&SnapshotAsync::EncodeCopyOutputResult, |
- callback, |
- background_task_runner)); |
+ MakeInitialAsyncCopyRequest(window, source_rect, |
+ base::Bind(&SnapshotAsync::EncodeCopyOutputResult, |
+ callback, background_task_runner)); |
} |
void GrabViewSnapshotAsync( |