Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(44)

Side by Side Diff: chrome/browser/thumbnails/render_widget_snapshot_taker.cc

Issue 154083008: Remove Tabpose feature on mac, and supporting infrastructure (PaintAtSize) (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: rebase, merge Created 6 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
1 // Copyright (c) 2012 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/thumbnails/render_widget_snapshot_taker.h"
6
7 #include "base/bind.h"
8 #include "base/memory/scoped_ptr.h"
9 #include "content/public/browser/notification_details.h"
10 #include "content/public/browser/notification_source.h"
11 #include "content/public/browser/notification_types.h"
12 #include "content/public/browser/render_process_host.h"
13 #include "content/public/browser/render_view_host.h"
14 #include "content/public/browser/render_widget_host_view.h"
15 #include "ui/base/layout.h"
16 #include "ui/gfx/size.h"
17 #include "ui/gfx/size_conversions.h"
18 #include "ui/surface/transport_dib.h"
19
20 using content::RenderWidgetHost;
21
22 struct RenderWidgetSnapshotTaker::AsyncRequestInfo {
23 SnapshotReadyCallback callback;
24 scoped_ptr<TransportDIB> thumbnail_dib;
25 RenderWidgetHost* renderer; // Not owned.
26 };
27
28 RenderWidgetSnapshotTaker::RenderWidgetSnapshotTaker() {
29 // The BrowserProcessImpl creates this non-lazily. If you add nontrivial
30 // stuff here, be sure to convert it to being lazily created.
31 //
32 // We don't register for notifications here since BrowserProcessImpl creates
33 // us before the NotificationService is.
34 }
35
36 RenderWidgetSnapshotTaker::~RenderWidgetSnapshotTaker() {
37 }
38
39 void RenderWidgetSnapshotTaker::AskForSnapshot(
40 RenderWidgetHost* renderer,
41 const SnapshotReadyCallback& callback,
42 gfx::Size page_size,
43 gfx::Size desired_size) {
44 // We are going to render the thumbnail asynchronously now, so keep
45 // this callback for later lookup when the rendering is done.
46 static int sequence_num = 0;
47 sequence_num++;
48 float scale_factor = ui::GetImageScale(ui::GetScaleFactorForNativeView(
49 renderer->GetView()->GetNativeView()));
50 gfx::Size desired_size_in_pixel = gfx::ToFlooredSize(
51 gfx::ScaleSize(desired_size, scale_factor));
52 scoped_ptr<TransportDIB> thumbnail_dib(TransportDIB::Create(
53 desired_size_in_pixel.GetArea() * 4, sequence_num));
54
55 #if defined(OS_LINUX)
56 // TODO: IPC a handle to the renderer like Windows.
57 // http://code.google.com/p/chromium/issues/detail?id=89777
58 NOTIMPLEMENTED();
59 return;
60 #else
61
62 #if defined(OS_WIN)
63 // Duplicate the handle to the DIB here because the renderer process does not
64 // have permission. The duplicated handle is owned by the renderer process,
65 // which is responsible for closing it.
66 TransportDIB::Handle renderer_dib_handle;
67 DuplicateHandle(GetCurrentProcess(), thumbnail_dib->handle(),
68 renderer->GetProcess()->GetHandle(), &renderer_dib_handle,
69 STANDARD_RIGHTS_REQUIRED | FILE_MAP_READ | FILE_MAP_WRITE,
70 FALSE, 0);
71 if (!renderer_dib_handle) {
72 LOG(WARNING) << "Could not duplicate dib handle for renderer";
73 return;
74 }
75 #else
76 TransportDIB::Handle renderer_dib_handle = thumbnail_dib->handle();
77 #endif
78
79 linked_ptr<AsyncRequestInfo> request_info(new AsyncRequestInfo);
80 request_info->callback = callback;
81 request_info->thumbnail_dib.reset(thumbnail_dib.release());
82 request_info->renderer = renderer;
83 SnapshotCallbackMap::value_type new_value(sequence_num, request_info);
84 std::pair<SnapshotCallbackMap::iterator, bool> result =
85 callback_map_.insert(new_value);
86 if (!result.second) {
87 NOTREACHED() << "Callback already registered?";
88 return;
89 }
90
91 MonitorRenderer(renderer, true);
92 renderer->PaintAtSize(
93 renderer_dib_handle, sequence_num, page_size, desired_size);
94
95 #endif // defined(USE_X11)
96 }
97
98 void RenderWidgetSnapshotTaker::CancelSnapshot(
99 content::RenderWidgetHost* renderer) {
100 SnapshotCallbackMap::iterator iterator = callback_map_.begin();
101 while (iterator != callback_map_.end()) {
102 if (iterator->second->renderer == renderer) {
103 SnapshotCallbackMap::iterator nuked = iterator;
104 ++iterator;
105 callback_map_.erase(nuked);
106 MonitorRenderer(renderer, false);
107 continue;
108 }
109 ++iterator;
110 }
111 }
112
113 void RenderWidgetSnapshotTaker::WidgetDidReceivePaintAtSizeAck(
114 RenderWidgetHost* widget,
115 int sequence_num,
116 const gfx::Size& size) {
117 // Lookup the callback, run it, and erase it.
118 SnapshotCallbackMap::iterator item = callback_map_.find(sequence_num);
119 if (item != callback_map_.end()) {
120 DCHECK_EQ(widget, item->second->renderer);
121 TransportDIB* dib = item->second->thumbnail_dib.get();
122 DCHECK(dib);
123 if (!dib || !dib->Map()) {
124 return;
125 }
126
127 // Create an SkBitmap from the DIB.
128 SkBitmap non_owned_bitmap;
129 SkBitmap result;
130
131 // Fill out the non_owned_bitmap with the right config. Note that
132 // this code assumes that the transport dib is a 32-bit ARGB
133 // image.
134 non_owned_bitmap.setConfig(SkBitmap::kARGB_8888_Config,
135 size.width(), size.height());
136 if (dib->size() < non_owned_bitmap.getSafeSize())
137 return;
138 non_owned_bitmap.setPixels(dib->memory());
139
140 // Now alloc/copy the memory so we own it and can pass it around,
141 // and the memory won't go away when the DIB goes away.
142 // TODO: Figure out a way to avoid this copy?
143 non_owned_bitmap.copyTo(&result, SkBitmap::kARGB_8888_Config);
144
145 item->second->callback.Run(result);
146
147 // We're done with the callback, and with the DIB, so delete both.
148 callback_map_.erase(item);
149 MonitorRenderer(widget, false);
150 }
151 }
152
153 void RenderWidgetSnapshotTaker::Observe(
154 int type,
155 const content::NotificationSource& source,
156 const content::NotificationDetails& details) {
157 switch (type) {
158 case content::NOTIFICATION_RENDER_WIDGET_HOST_DID_RECEIVE_PAINT_AT_SIZE_ACK: {
159 std::pair<int, gfx::Size>* size_ack_details =
160 content::Details<std::pair<int, gfx::Size> >(details).ptr();
161 WidgetDidReceivePaintAtSizeAck(
162 content::Source<RenderWidgetHost>(source).ptr(),
163 size_ack_details->first,
164 size_ack_details->second);
165 break;
166 }
167
168 default:
169 NOTREACHED() << "Unexpected notification type: " << type;
170 }
171 }
172
173 void RenderWidgetSnapshotTaker::MonitorRenderer(RenderWidgetHost* renderer,
174 bool monitor) {
175 content::Source<RenderWidgetHost> renderer_source =
176 content::Source<RenderWidgetHost>(renderer);
177 if (monitor) {
178 int new_count = ++host_monitor_counts_[renderer];
179 if (new_count == 1) {
180 registrar_.Add(
181 this,
182 content::NOTIFICATION_RENDER_WIDGET_HOST_DID_RECEIVE_PAINT_AT_SIZE_ACK ,
183 renderer_source);
184 }
185 } else {
186 int new_count = --host_monitor_counts_[renderer];
187 if (new_count == 0) {
188 host_monitor_counts_.erase(renderer);
189 registrar_.Remove(
190 this,
191 content::NOTIFICATION_RENDER_WIDGET_HOST_DID_RECEIVE_PAINT_AT_SIZE_ACK ,
192 renderer_source);
193 }
194 }
195 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698