13f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen// Copyright (c) 2011 The Chromium Authors. All rights reserved.
2c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Use of this source code is governed by a BSD-style license that can be
3c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// found in the LICENSE file.
4c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
5c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/aeropeek_manager.h"
6c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
7c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include <dwmapi.h>
8c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include <shobjidl.h>
9c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
103f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen#include "app/win/shell.h"
11c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/command_line.h"
12ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "base/memory/scoped_native_library.h"
133f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen#include "base/synchronization/waitable_event.h"
14ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "base/win/scoped_comptr.h"
153f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen#include "base/win/scoped_gdi_object.h"
163f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen#include "base/win/scoped_hdc.h"
17731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick#include "base/win/windows_version.h"
18c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/app_icon_win.h"
19c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/browser_process.h"
20c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/tab_contents/thumbnail_generator.h"
213345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#include "chrome/browser/tabs/tab_strip_model.h"
22ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "chrome/browser/ui/browser_list.h"
2321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen#include "chrome/browser/ui/tab_contents/tab_contents_wrapper.h"
24c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/common/chrome_constants.h"
25c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/common/chrome_switches.h"
26c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/installer/util/browser_distribution.h"
27dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "content/browser/browser_thread.h"
28dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "content/browser/renderer_host/backing_store.h"
29dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "content/browser/renderer_host/render_view_host.h"
30dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "content/browser/tab_contents/tab_contents.h"
31dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "content/browser/tab_contents/tab_contents_delegate.h"
32dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "content/browser/tab_contents/tab_contents_view.h"
33c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "skia/ext/image_operations.h"
34c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "skia/ext/platform_canvas.h"
35c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "third_party/skia/include/core/SkBitmap.h"
3672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "ui/base/win/window_impl.h"
3772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "ui/gfx/gdi_util.h"
3872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "ui/gfx/icon_util.h"
3972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "views/widget/widget_win.h"
40c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
41c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochnamespace {
42c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
43c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Macros and COM interfaces used in this file.
44c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// These interface declarations are copied from Windows SDK 7.
45c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// TODO(hbono): Bug 16903: to be deleted when we use Windows SDK 7.
46c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
47c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Windows SDK 7 defines these macros only when _WIN32_WINNT >= 0x0601.
48c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Since Chrome currently sets _WIN32_WINNT to 0x0600, copy these defines here
49c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// so we can use them.
50c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#ifndef WM_DWMSENDICONICTHUMBNAIL
51c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#define WM_DWMSENDICONICTHUMBNAIL           0x0323
52c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#endif
53c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#ifndef WM_DWMSENDICONICLIVEPREVIEWBITMAP
54c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#define WM_DWMSENDICONICLIVEPREVIEWBITMAP   0x0326
55c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#endif
56c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
57c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// COM interfaces defined only in Windows SDK 7.
58c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#ifndef __ITaskbarList2_INTERFACE_DEFINED__
59c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#define __ITaskbarList2_INTERFACE_DEFINED__
60c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
61c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// EXTERN_C const IID IID_ITaskbarList2;
62c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochMIDL_INTERFACE("602D4995-B13A-429b-A66E-1935E44F4317")
63c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochITaskbarList2 : public ITaskbarList {
64c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch public:
65c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  virtual HRESULT STDMETHODCALLTYPE MarkFullscreenWindow(
66c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      /* [in] */ __RPC__in HWND hwnd,
67c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      /* [in] */ BOOL fFullscreen) = 0;
68c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch};
69c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
70c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#endif  /* __ITaskbarList2_INTERFACE_DEFINED__ */
71c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
72c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#ifndef __ITaskbarList3_INTERFACE_DEFINED__
73c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#define __ITaskbarList3_INTERFACE_DEFINED__
74c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
75c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochtypedef struct tagTHUMBBUTTON {
76c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DWORD dwMask;
77c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  UINT iId;
78c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  UINT iBitmap;
79c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  HICON hIcon;
80c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  WCHAR szTip[ 260 ];
81c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DWORD dwFlags;
82c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} THUMBBUTTON;
83c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
84c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochtypedef struct tagTHUMBBUTTON *LPTHUMBBUTTON;
85c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
86c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// THUMBBUTTON flags
87c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#define THBF_ENABLED             0x0000
88c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#define THBF_DISABLED            0x0001
89c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#define THBF_DISMISSONCLICK      0x0002
90c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#define THBF_NOBACKGROUND        0x0004
91c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#define THBF_HIDDEN              0x0008
92c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// THUMBBUTTON mask
93c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#define THB_BITMAP          0x0001
94c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#define THB_ICON            0x0002
95c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#define THB_TOOLTIP         0x0004
96c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#define THB_FLAGS           0x0008
97c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#define THBN_CLICKED        0x1800
98c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
99c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochtypedef /* [v1_enum] */ enum TBPFLAG {
100c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  TBPF_NOPROGRESS = 0,
101c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  TBPF_INDETERMINATE = 0x1,
102c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  TBPF_NORMAL = 0x2,
103c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  TBPF_ERROR = 0x4,
104c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  TBPF_PAUSED = 0x8
105c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} TBPFLAG;
106c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
107c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// EXTERN_C const IID IID_ITaskbarList3;
108c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
109c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochMIDL_INTERFACE("ea1afb91-9e28-4b86-90e9-9e9f8a5eefaf")
110c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochITaskbarList3 : public ITaskbarList2 {
111c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch public:
112c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  virtual HRESULT STDMETHODCALLTYPE SetProgressValue(
113c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      /* [in] */ __RPC__in HWND hwnd,
114c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      /* [in] */ ULONGLONG ullCompleted,
115c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      /* [in] */ ULONGLONG ullTotal) = 0;
116c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  virtual HRESULT STDMETHODCALLTYPE SetProgressState(
117c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      /* [in] */ __RPC__in HWND hwnd,
118c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      /* [in] */ TBPFLAG tbpFlags) = 0;
119c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  virtual HRESULT STDMETHODCALLTYPE RegisterTab(
120c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      /* [in] */ __RPC__in HWND hwndTab,
121c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      /* [in] */ __RPC__in HWND hwndMDI) = 0;
122c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  virtual HRESULT STDMETHODCALLTYPE UnregisterTab(
123c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      /* [in] */ __RPC__in HWND hwndTab) = 0;
124c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  virtual HRESULT STDMETHODCALLTYPE SetTabOrder(
125c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      /* [in] */ __RPC__in HWND hwndTab,
126c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      /* [in] */ __RPC__in HWND hwndInsertBefore) = 0;
127c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  virtual HRESULT STDMETHODCALLTYPE SetTabActive(
128c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      /* [in] */ __RPC__in HWND hwndTab,
129c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      /* [in] */ __RPC__in HWND hwndMDI,
130c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      /* [in] */ DWORD dwReserved) = 0;
131c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  virtual HRESULT STDMETHODCALLTYPE ThumbBarAddButtons(
132c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      /* [in] */ __RPC__in HWND hwnd,
133c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      /* [in] */ UINT cButtons,
134c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      /* [size_is][in] */ __RPC__in_ecount_full(cButtons)
135c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      LPTHUMBBUTTON pButton) = 0;
136c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  virtual HRESULT STDMETHODCALLTYPE ThumbBarUpdateButtons(
137c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      /* [in] */ __RPC__in HWND hwnd,
138c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      /* [in] */ UINT cButtons,
139c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      /* [size_is][in] */ __RPC__in_ecount_full(cButtons)
140c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      LPTHUMBBUTTON pButton) = 0;
141c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  virtual HRESULT STDMETHODCALLTYPE ThumbBarSetImageList(
142c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      /* [in] */ __RPC__in HWND hwnd,
143c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      /* [in] */ __RPC__in_opt HIMAGELIST himl) = 0;
144c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  virtual HRESULT STDMETHODCALLTYPE SetOverlayIcon(
145c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      /* [in] */ __RPC__in HWND hwnd,
146c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      /* [in] */ __RPC__in HICON hIcon,
147c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      /* [string][in] */ __RPC__in_string LPCWSTR pszDescription) = 0;
148c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  virtual HRESULT STDMETHODCALLTYPE SetThumbnailTooltip(
149c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      /* [in] */ __RPC__in HWND hwnd,
150c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      /* [string][in] */ __RPC__in_string LPCWSTR pszTip) = 0;
151c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  virtual HRESULT STDMETHODCALLTYPE SetThumbnailClip(
152c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      /* [in] */ __RPC__in HWND hwnd,
153c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      /* [in] */ __RPC__in RECT *prcClip) = 0;
154c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch};
155c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#endif  // __ITaskbarList3_INTERFACE_DEFINED__
156c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
157c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// END OF WINDOWS SDK 7.0
158c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
159c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}  // namespace
160c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
161c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochnamespace {
162c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
163c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Sends a thumbnail bitmap to Windows. Windows assumes this function is called
164c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// when a WM_DWMSENDICONICTHUMBNAIL message sent to a place-holder window. We
165c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// can use DwmInvalidateIconicBitmap() to force Windows to send the message.
166c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochHRESULT CallDwmSetIconicThumbnail(HWND window, HBITMAP bitmap, DWORD flags) {
167c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  FilePath dwmapi_path(base::GetNativeLibraryName(L"dwmapi"));
168c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  base::ScopedNativeLibrary dwmapi(dwmapi_path);
169c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
170c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  typedef HRESULT (STDAPICALLTYPE *DwmSetIconicThumbnailProc)(
171c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      HWND, HBITMAP, DWORD);
172c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DwmSetIconicThumbnailProc dwm_set_iconic_thumbnail =
173c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      static_cast<DwmSetIconicThumbnailProc>(
174c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      dwmapi.GetFunctionPointer("DwmSetIconicThumbnail"));
175c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
176c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (!dwm_set_iconic_thumbnail)
177c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return E_FAIL;
178c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
179c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return dwm_set_iconic_thumbnail(window, bitmap, flags);
180c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
181c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
182c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Sends a preview bitmap to Windows. Windows assumes this function is called
183c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// when a WM_DWMSENDICONICLIVEPREVIEWBITMAP message sent to a place-holder
184c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// window.
185c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochHRESULT CallDwmSetIconicLivePreviewBitmap(HWND window,
186c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                          HBITMAP bitmap,
187c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                          POINT* client,
188c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                          DWORD flags) {
189c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  FilePath dwmapi_path(base::GetNativeLibraryName(L"dwmapi"));
190c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  base::ScopedNativeLibrary dwmapi(dwmapi_path);
191c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
192c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  typedef HRESULT (STDAPICALLTYPE *DwmSetIconicLivePreviewBitmapProc)(
193c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      HWND, HBITMAP, POINT*, DWORD);
194c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DwmSetIconicLivePreviewBitmapProc dwm_set_live_preview_bitmap =
195c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      static_cast<DwmSetIconicLivePreviewBitmapProc>(
196c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      dwmapi.GetFunctionPointer("DwmSetIconicLivePreviewBitmap"));
197c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
198c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (!dwm_set_live_preview_bitmap)
199c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return E_FAIL;
200c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
201c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return dwm_set_live_preview_bitmap(window, bitmap, client, flags);
202c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
203c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
204c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Invalidates the thumbnail image of the specified place-holder window. (See
205c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// the comments in CallDwmSetIconicThumbnai()).
206c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochHRESULT CallDwmInvalidateIconicBitmaps(HWND window) {
207c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  FilePath dwmapi_path(base::GetNativeLibraryName(L"dwmapi"));
208c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  base::ScopedNativeLibrary dwmapi(dwmapi_path);
209c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
210c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  typedef HRESULT (STDAPICALLTYPE *DwmInvalidateIconicBitmapsProc)(HWND);
211c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DwmInvalidateIconicBitmapsProc dwm_invalidate_iconic_bitmaps =
212c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      static_cast<DwmInvalidateIconicBitmapsProc>(
213c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      dwmapi.GetFunctionPointer("DwmInvalidateIconicBitmaps"));
214c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
215c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (!dwm_invalidate_iconic_bitmaps)
216c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return E_FAIL;
217c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
218c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return dwm_invalidate_iconic_bitmaps(window);
219c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
220c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
221c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}  // namespace
222c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
223c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochnamespace {
224c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
225c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Tasks used in this file.
226c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// This file uses three I/O tasks to implement AeroPeek:
227c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// * RegisterThumbnailTask
228c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch//   Register a tab into the thumbnail list of Windows.
229c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// * SendThumbnailTask
230c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch//   Create a thumbnail image and send it to Windows.
231c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// * SendLivePreviewTask
232c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch//   Create a preview image and send it to Windows.
233c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// These I/O tasks indirectly access the specified tab through the
234c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// AeroPeekWindowDelegate interface to prevent these tasks from accessing the
235c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// deleted tabs.
236c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
237c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// A task that registers a thumbnail window as a child of the specified
238c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// browser application.
239c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochclass RegisterThumbnailTask : public Task {
240c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch public:
241c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  RegisterThumbnailTask(HWND frame_window, HWND window, bool active)
242c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      : frame_window_(frame_window),
243c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        window_(window),
244c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        active_(active) {
245c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
246c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
247c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch private:
248c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  void Run() {
249c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // Set the App ID of the browser for this place-holder window to tell
250c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // that this window is a child of the browser application, i.e. to tell
251c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // that this thumbnail window should be displayed when we hover the
252c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // browser icon in the taskbar.
253c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // TODO(mattm): This should use ShellIntegration::GetChromiumAppId to work
254c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // properly with multiple profiles.
2553f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen    app::win::SetAppIdForWindow(
256c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        BrowserDistribution::GetDistribution()->GetBrowserAppId(), window_);
257c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
258c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // Register this place-holder window to the taskbar as a child of
259c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // the browser window and add it to the end of its tab list.
260c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // Correctly, this registration should be called after this browser window
261c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // receives a registered window message "TaskbarButtonCreated", which
262c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // means that Windows creates a taskbar button for this window in its
263c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // taskbar. But it seems to be OK to register it without checking the
264c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // message.
265c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // TODO(hbono): we need to check this registered message?
266ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    base::win::ScopedComPtr<ITaskbarList3> taskbar;
267731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    if (FAILED(taskbar.CreateInstance(CLSID_TaskbarList, NULL,
268731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick                                      CLSCTX_INPROC_SERVER)) ||
269731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick        FAILED(taskbar->HrInit()) ||
270731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick        FAILED(taskbar->RegisterTab(window_, frame_window_)) ||
271731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick        FAILED(taskbar->SetTabOrder(window_, NULL)))
272c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      return;
273731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    if (active_)
274731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick      taskbar->SetTabActive(window_, frame_window_, 0);
275c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
276c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
277c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch private:
278c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // An application window to which we are going to register a tab window.
279c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // This "application window" is a browser frame in terms of Chrome.
280c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  HWND frame_window_;
281c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
282c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // A tab window.
283c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // After we register this window as a child of the above application window,
284c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Windows sends AeroPeek events to this window.
285c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // It seems this window MUST be a tool window.
286c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  HWND window_;
287c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
288c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Whether or not we need to activate this tab by default.
289c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  bool active_;
290c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch};
291c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
292c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// A task which creates a thumbnail image used by AeroPeek and sends it to
293c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Windows.
294c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochclass SendThumbnailTask : public Task {
295c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch public:
296c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  SendThumbnailTask(HWND aeropeek_window,
297c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                    const gfx::Rect& content_bounds,
298c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                    const gfx::Size& aeropeek_size,
299c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                    const SkBitmap& tab_bitmap,
300c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                    base::WaitableEvent* ready)
301c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      : aeropeek_window_(aeropeek_window),
302c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        content_bounds_(content_bounds),
303c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        aeropeek_size_(aeropeek_size),
304c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        tab_bitmap_(tab_bitmap),
305c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        ready_(ready) {
306c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
307c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
308c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  ~SendThumbnailTask() {
309c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    if (ready_)
310c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      ready_->Signal();
311c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
312c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
313c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch private:
314c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  void Run() {
315c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // Calculate the size of the aeropeek thumbnail and resize the tab bitmap
316c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // to the size. When the given bitmap is an empty bitmap, we create a dummy
317c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // bitmap from the content-area rectangle to create a DIB. (We don't need to
318c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // allocate pixels for this case since we don't use them.)
319c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    gfx::Size thumbnail_size;
320c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    SkBitmap thumbnail_bitmap;
321c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
322c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    if (tab_bitmap_.isNull() || tab_bitmap_.empty()) {
323c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      GetThumbnailSize(content_bounds_.width(), content_bounds_.height(),
324c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                       &thumbnail_size);
325c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
326c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      thumbnail_bitmap.setConfig(SkBitmap::kARGB_8888_Config,
327c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                 thumbnail_size.width(),
328c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                 thumbnail_size.height());
329c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    } else {
330c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      GetThumbnailSize(tab_bitmap_.width(), tab_bitmap_.height(),
331c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                       &thumbnail_size);
332c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
333c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      thumbnail_bitmap = skia::ImageOperations::Resize(
334c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          tab_bitmap_,
335c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          skia::ImageOperations::RESIZE_LANCZOS3,
336c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          thumbnail_size.width(),
337c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          thumbnail_size.height());
338c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
339c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
340c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // Create a DIB, copy the resized image, and send the DIB to Windows.
341c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // We can delete this DIB after sending it to Windows since Windows creates
342c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // a copy of the DIB and use it.
3433f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen    base::win::ScopedHDC hdc(CreateCompatibleDC(NULL));
344c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    if (!hdc.Get()) {
345c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      LOG(ERROR) << "cannot create a memory DC: " << GetLastError();
346c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      return;
347c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
348c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
349c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    BITMAPINFOHEADER header;
350c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    gfx::CreateBitmapHeader(thumbnail_size.width(), thumbnail_size.height(),
351c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                            &header);
352c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
353c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    void* bitmap_data = NULL;
3543f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen    base::win::ScopedBitmap bitmap(
3553f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen        CreateDIBSection(hdc,
3563f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen                         reinterpret_cast<BITMAPINFO*>(&header),
3573f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen                         DIB_RGB_COLORS,
3583f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen                         &bitmap_data,
3593f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen                         NULL,
3603f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen                         0));
361c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
362c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    if (!bitmap.Get() || !bitmap_data) {
363c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      LOG(ERROR) << "cannot create a bitmap: " << GetLastError();
364c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      return;
365c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
366c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
367c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    SkAutoLockPixels lock(thumbnail_bitmap);
368c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    int* content_pixels = reinterpret_cast<int*>(bitmap_data);
369c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    for (int y = 0; y < thumbnail_size.height(); ++y) {
370c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      for (int x = 0; x < thumbnail_size.width(); ++x) {
371c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        content_pixels[y * thumbnail_size.width() + x] =
372c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch            GetPixel(thumbnail_bitmap, x, y);
373c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      }
374c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
375c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
376c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    HRESULT result = CallDwmSetIconicThumbnail(aeropeek_window_, bitmap, 0);
377c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    if (FAILED(result))
378c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      LOG(ERROR) << "cannot set a tab thumbnail: " << result;
379c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
380c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
381c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Calculates the thumbnail size sent to Windows so we can preserve the pixel
382c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // aspect-ratio of the source bitmap. Since Windows returns an error when we
383c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // send an image bigger than the given size, we decrease either the thumbnail
384c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // width or the thumbnail height so we can fit the longer edge of the source
385c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // window.
386c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  void GetThumbnailSize(int width, int height, gfx::Size* output) const {
387c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    float thumbnail_width = static_cast<float>(aeropeek_size_.width());
388c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    float thumbnail_height = static_cast<float>(aeropeek_size_.height());
389c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    float source_width = static_cast<float>(width);
390c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    float source_height = static_cast<float>(height);
391c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    DCHECK(source_width && source_height);
392c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
393c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    float ratio_width = thumbnail_width / source_width;
394c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    float ratio_height = thumbnail_height / source_height;
395c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    if (ratio_width > ratio_height) {
396c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      thumbnail_width = source_width * ratio_height;
397c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    } else {
398c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      thumbnail_height = source_height * ratio_width;
399c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
400c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
401c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    output->set_width(static_cast<int>(thumbnail_width));
402c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    output->set_height(static_cast<int>(thumbnail_height));
403c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
404c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
405c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Returns a pixel of the specified bitmap. If this bitmap is a dummy bitmap,
406c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // this function returns an opaque white pixel instead.
407c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  int GetPixel(const SkBitmap& bitmap, int x, int y) const {
408c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    const int* tab_pixels = reinterpret_cast<const int*>(bitmap.getPixels());
409c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    if (!tab_pixels)
410c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      return 0xFFFFFFFF;
411c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return tab_pixels[y * bitmap.width() + x];
412c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
413c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
414c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch private:
415c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // A window handle to the place-holder window used by AeroPeek.
416c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  HWND aeropeek_window_;
417c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
418c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // The bounding rectangle of the user-perceived content area.
419c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // This rectangle is used only for creating a fall-back bitmap.
420c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  gfx::Rect content_bounds_;
421c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
422c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // The size of an output image to be sent to Windows.
423c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  gfx::Size aeropeek_size_;
424c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
425c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // The source bitmap.
426c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  SkBitmap tab_bitmap_;
427c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
428c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // An event to notify when this task finishes.
429c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  base::WaitableEvent* ready_;
430c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch};
431c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
432c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// A task which creates a preview image used by AeroPeek and sends it to
433c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Windows.
434c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// This task becomes more complicated than SendThumbnailTask because this task
435c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// calculates the rectangle of the user-perceived content area (infobars +
436c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// content area) so Windows can paste the preview image on it.
437c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// This task is used if an AeroPeek window receives a
438c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// WM_DWMSENDICONICLIVEPREVIEWBITMAP message.
439c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochclass SendLivePreviewTask : public Task {
440c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch public:
441c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  SendLivePreviewTask(HWND aeropeek_window,
442c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                      const gfx::Rect& content_bounds,
443c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                      const SkBitmap& tab_bitmap)
444c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      : aeropeek_window_(aeropeek_window),
445c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        content_bounds_(content_bounds),
446c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        tab_bitmap_(tab_bitmap) {
447c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
448c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
449c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  ~SendLivePreviewTask() {
450c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
451c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
452c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch private:
453c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  void Run() {
454c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // Create a DIB for the user-perceived content area of the tab, copy the
455c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // tab image into the DIB, and send it to Windows.
456c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // We don't need to paste this tab image onto the frame image since Windows
457c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // automatically pastes it for us.
4583f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen    base::win::ScopedHDC hdc(CreateCompatibleDC(NULL));
459c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    if (!hdc.Get()) {
460c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      LOG(ERROR) << "cannot create a memory DC: " << GetLastError();
461c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      return;
462c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
463c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
464c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    BITMAPINFOHEADER header;
465c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    gfx::CreateBitmapHeader(content_bounds_.width(), content_bounds_.height(),
466c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                            &header);
467c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
468c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    void* bitmap_data = NULL;
4693f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen    base::win::ScopedBitmap bitmap(
4703f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen        CreateDIBSection(hdc.Get(),
4713f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen                         reinterpret_cast<BITMAPINFO*>(&header),
4723f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen                         DIB_RGB_COLORS, &bitmap_data,
4733f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen                         NULL, 0));
474c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    if (!bitmap.Get() || !bitmap_data) {
475c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      LOG(ERROR) << "cannot create a bitmap: " << GetLastError();
476c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      return;
477c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
478c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
479c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // Copy the tab image onto the DIB.
480c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    SkAutoLockPixels lock(tab_bitmap_);
481c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    int* content_pixels = reinterpret_cast<int*>(bitmap_data);
482c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    for (int y = 0; y < content_bounds_.height(); ++y) {
483c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      for (int x = 0; x < content_bounds_.width(); ++x)
484c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        content_pixels[y * content_bounds_.width() + x] = GetTabPixel(x, y);
485c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
486c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
487c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // Send the preview image to Windows.
488c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // We can set its offset to the top left corner of the user-perceived
489c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // content area so Windows can paste this bitmap onto the correct
490c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // position.
491c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    POINT content_offset = {content_bounds_.x(), content_bounds_.y()};
492c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    HRESULT result = CallDwmSetIconicLivePreviewBitmap(
493c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        aeropeek_window_, bitmap, &content_offset, 0);
494c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    if (FAILED(result))
495c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      LOG(ERROR) << "cannot send a content image: " << result;
496c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
497c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
498c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  int GetTabPixel(int x, int y) const {
499c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // Return the opaque while pixel to prevent old foreground tab from being
500c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // shown when we cannot get the specified pixel.
501c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    const int* tab_pixels = reinterpret_cast<int*>(tab_bitmap_.getPixels());
502c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    if (!tab_pixels || x >= tab_bitmap_.width() || y >= tab_bitmap_.height())
503c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      return 0xFFFFFFFF;
504c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
505c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // DWM uses alpha values to distinguish opaque colors and transparent ones.
506c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // Set the alpha value of this source pixel to prevent the original window
507c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // from being shown through.
508c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return 0xFF000000 | tab_pixels[y * tab_bitmap_.width() + x];
509c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
510c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
511c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch private:
512c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // A window handle to the AeroPeek window.
513c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  HWND aeropeek_window_;
514c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
515c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // The bounding rectangle of the user-perceived content area. When a tab
516c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // hasn't been rendered since a browser window is resized, this size doesn't
517c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // become the same as the bitmap size as shown below.
518c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  //     +----------------------+
519c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  //     |     frame window     |
520c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  //     | +---------------------+
521c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  //     | |     tab contents    |
522c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  //     | +---------------------+
523c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  //     | | old tab contents | |
524c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  //     | +------------------+ |
525c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  //     +----------------------+
526c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // This rectangle is used for clipping the width and height of the bitmap and
527c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // cleaning the old tab contents.
528c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  //     +----------------------+
529c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  //     |     frame window     |
530c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  //     | +------------------+ |
531c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  //     | |   tab contents   | |
532c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  //     | +------------------+ |
533c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  //     | |      blank       | |
534c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  //     | +------------------+ |
535c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  //     +----------------------+
536c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  gfx::Rect content_bounds_;
537c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
538c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // The bitmap of the source tab.
539c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  SkBitmap tab_bitmap_;
540c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch};
541c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
542c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}  // namespace
543c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
544c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// A class which implements a place-holder window used by AeroPeek.
545c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// The major work of this class are:
546c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// * Updating the status of Tab Thumbnails;
547c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// * Receiving messages from Windows, and;
548c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// * Translating received messages for TabStrip.
549c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// This class is used by the AeroPeekManager class, which is a proxy
550c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// between TabStrip and Windows 7.
55172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenclass AeroPeekWindow : public ui::WindowImpl {
552c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch public:
553c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  AeroPeekWindow(HWND frame_window,
554c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                 AeroPeekWindowDelegate* delegate,
555c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                 int tab_id,
556c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                 bool tab_active,
557c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                 const std::wstring& title,
558c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                 const SkBitmap& favicon_bitmap);
559c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  ~AeroPeekWindow();
560c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
561c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Activates or deactivates this window.
562c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // This window uses this information not only for highlighting the selected
563c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // tab when Windows shows the thumbnail list, but also for preventing us
564c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // from rendering AeroPeek images for deactivated windows so often.
565c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  void Activate();
566c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  void Deactivate();
567c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
568c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Updates the image of this window.
569c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // When the AeroPeekManager class calls this function, this window starts
570c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // a task which updates its thumbnail image.
571c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // NOTE: to prevent sending lots of tasks that update the thumbnail images
572c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // and hurt the system performance, we post a task only when |is_loading| is
573c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // false for non-active tabs. (On the other hand, we always post an update
574c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // task for an active tab as IE8 does.)
575c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  void Update(bool is_loading);
576c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
577c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Destroys this window.
578c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // This function removes this window from the thumbnail list and deletes
579c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // all the resources attached to this window, i.e. this object is not valid
580c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // any longer after calling this function.
581c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  void Destroy();
582c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
583c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Updates the title of this window.
584c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // This function just sends a WM_SETTEXT message to update the window title.
585c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  void SetTitle(const std::wstring& title);
586c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
587c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Updates the icon used for AeroPeek. Unlike SetTitle(), this function just
588c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // saves a copy of the given bitmap since it takes time to create a Windows
589c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // icon from this bitmap set it as the window icon. We will create a Windows
590c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // when Windows sends a WM_GETICON message to retrieve it.
591ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  void SetFavicon(const SkBitmap& favicon);
592c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
593c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Returns the tab ID associated with this window.
594c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  int tab_id() { return tab_id_; }
595c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
596c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Message handlers.
597c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  BEGIN_MSG_MAP_EX(TabbedThumbnailWindow)
598c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    MESSAGE_HANDLER_EX(WM_DWMSENDICONICTHUMBNAIL, OnDwmSendIconicThumbnail)
599c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    MESSAGE_HANDLER_EX(WM_DWMSENDICONICLIVEPREVIEWBITMAP,
600c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                       OnDwmSendIconicLivePreviewBitmap)
601c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
602c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    MSG_WM_ACTIVATE(OnActivate)
603c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    MSG_WM_CLOSE(OnClose)
604c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    MSG_WM_CREATE(OnCreate)
605c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    MSG_WM_GETICON(OnGetIcon)
606c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  END_MSG_MAP()
607c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
608c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch private:
609c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Updates the thumbnail image of this window.
610c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // This function is a wrapper function of CallDwmInvalidateIconicBitmaps()
611c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // but it invalidates the thumbnail only when |ready_| is signaled to prevent
612c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // us from posting two or more tasks.
613c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  void UpdateThumbnail();
614c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
615c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Returns the user-perceived content area.
616c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  gfx::Rect GetContentBounds() const;
617c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
618c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Message-handler functions.
619c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Called when a window has been created.
620c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  LRESULT OnCreate(LPCREATESTRUCT create_struct);
621c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
622c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Called when this thumbnail window is activated, i.e. a user clicks this
623c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // thumbnail window.
624c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  void OnActivate(UINT action, BOOL minimized, HWND window);
625c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
626c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Called when this thumbnail window is closed, i.e. a user clicks the close
627c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // button of this thumbnail window.
628c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  void OnClose();
629c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
630c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Called when Windows needs a thumbnail image for this thumbnail window.
631c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Windows can send a WM_DWMSENDICONICTHUMBNAIL message anytime when it
632c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // needs the thumbnail bitmap for this place-holder window (e.g. when we
633c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // register this place-holder window to Windows, etc.)
634c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // When this window receives a WM_DWMSENDICONICTHUMBNAIL message, it HAS TO
635c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // create a thumbnail bitmap and send it to Windows through a
636c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // DwmSendIconicThumbnail() call. (Windows shows a "page-loading" animation
637c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // while it waits for a thumbnail bitmap.)
638c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  LRESULT OnDwmSendIconicThumbnail(UINT message,
639c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                   WPARAM wparam,
640c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                   LPARAM lparam);
641c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
642c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Called when Windows needs a preview image for this thumbnail window.
643c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Same as above, Windows can send a WM_DWMSENDICONICLIVEPREVIEWBITMAP
644c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // message anytime when it needs a preview bitmap and we have to create and
645c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // send the bitmap when it needs it.
646c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  LRESULT OnDwmSendIconicLivePreviewBitmap(UINT message,
647c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                           WPARAM wparam,
648c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                           LPARAM lparam);
649c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
650c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Called when Windows needs an icon for this thumbnail window.
651c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Windows sends a WM_GETICON message with ICON_SMALL when it needs an
652c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // AeroPeek icon. we handle WM_GETICON messages by ourselves so we can create
653c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // a custom icon from a favicon only when Windows need it.
654c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  HICON OnGetIcon(UINT index);
655c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
656c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch private:
657c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // An application window which owns this tab.
658c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // We show this thumbnail image of this window when a user hovers a mouse
659c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // cursor onto the taskbar icon of this application window.
660c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  HWND frame_window_;
661c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
662c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // An interface which dispatches events received from Window.
663c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // This window notifies events received from Windows to TabStrip through
664c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // this interface.
665c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // We should not directly access TabContents members since Windows may send
666c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // AeroPeek events to a tab closed by Chrome.
667c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // To prevent such race condition, we get access to TabContents through
668c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // AeroPeekManager.
669c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  AeroPeekWindowDelegate* delegate_;
670c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
671c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // A tab ID associated with this window.
672c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  int tab_id_;
673c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
674c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // A flag that represents whether or not this tab is active.
675c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // This flag is used for preventing us from updating the thumbnail images
676c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // when this window is not active.
677c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  bool tab_active_;
678c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
679c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // An event that represents whether or not we can post a task which updates
680c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // the thumbnail image of this window.
681c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // We post a task only when this event is signaled.
682c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  base::WaitableEvent ready_to_update_thumbnail_;
683c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
684c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // The title of this tab.
685c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  std::wstring title_;
686c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
687c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // The favicon for this tab.
688c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  SkBitmap favicon_bitmap_;
6893f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen  base::win::ScopedHICON favicon_;
690c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
691c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // The icon used by the frame window.
692c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // This icon is used when this tab doesn't have a favicon.
693c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  HICON frame_icon_;
694c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
695c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DISALLOW_COPY_AND_ASSIGN(AeroPeekWindow);
696c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch};
697c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
698c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochAeroPeekWindow::AeroPeekWindow(HWND frame_window,
699c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                               AeroPeekWindowDelegate* delegate,
700c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                               int tab_id,
701c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                               bool tab_active,
702c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                               const std::wstring& title,
703c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                               const SkBitmap& favicon_bitmap)
704c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    : frame_window_(frame_window),
705c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      delegate_(delegate),
706c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      tab_id_(tab_id),
707c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      tab_active_(tab_active),
708c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      ready_to_update_thumbnail_(false, true),
709c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      title_(title),
710c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      favicon_bitmap_(favicon_bitmap),
711c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      frame_icon_(NULL) {
712c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Set the class styles and window styles for this thumbnail window.
713c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // An AeroPeek window should be a tool window. (Otherwise,
714c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Windows doesn't send WM_DWMSENDICONICTHUMBNAIL messages.)
715c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  set_initial_class_style(0);
716c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  set_window_style(WS_POPUP | WS_BORDER | WS_SYSMENU | WS_CAPTION);
717c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  set_window_ex_style(WS_EX_TOOLWINDOW | WS_EX_NOACTIVATE);
718c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
719c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
720c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochAeroPeekWindow::~AeroPeekWindow() {
721c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
722c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
723c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid AeroPeekWindow::Activate() {
724c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  tab_active_ = true;
725c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
726c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Create a place-holder window and add it to the tab list if it has not been
727c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // created yet. (This case happens when we re-attached a detached window.)
728c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (!IsWindow(hwnd())) {
729c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    Update(false);
730c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return;
731c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
732c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
733c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Notify Windows to set the thumbnail focus to this window.
734ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  base::win::ScopedComPtr<ITaskbarList3> taskbar;
735c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  HRESULT result = taskbar.CreateInstance(CLSID_TaskbarList, NULL,
736c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                          CLSCTX_INPROC_SERVER);
737c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (FAILED(result)) {
738c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    LOG(ERROR) << "failed creating an ITaskbarList3 interface.";
739c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return;
740c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
741c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
742c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  result = taskbar->HrInit();
743c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (FAILED(result)) {
744c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    LOG(ERROR) << "failed initializing an ITaskbarList3 interface.";
745c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return;
746c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
747c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
748c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  result = taskbar->ActivateTab(hwnd());
749c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (FAILED(result)) {
750c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    LOG(ERROR) << "failed activating a thumbnail window.";
751c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return;
752c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
753c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
754c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Update the thumbnail image to the up-to-date one.
755c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  UpdateThumbnail();
756c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
757c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
758c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid AeroPeekWindow::Deactivate() {
759c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  tab_active_ = false;
760c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
761c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
762c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid AeroPeekWindow::Update(bool is_loading) {
763c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Create a place-holder window used by AeroPeek if it has not been created
764c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // so Windows can send events used by AeroPeek to this window.
765c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Windows automatically sends a WM_DWMSENDICONICTHUMBNAIL message after this
766c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // window is registered to Windows. So, we don't have to invalidate the
767c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // thumbnail image of this window now.
768c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (!hwnd()) {
769c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    gfx::Rect bounds;
770c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    WindowImpl::Init(frame_window_, bounds);
771c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return;
772c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
773c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
774c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Invalidate the thumbnail image of this window.
775c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // When we invalidate the thumbnail image, we HAVE TO handle a succeeding
776c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // WM_DWMSENDICONICTHUMBNAIL message and update the thumbnail image with a
777c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // DwmSetIconicThumbnail() call. So, we should not call this function when
778c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // we don't have enough information to create a thumbnail.
779c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (tab_active_ || !is_loading)
780c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    UpdateThumbnail();
781c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
782c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
783c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid AeroPeekWindow::Destroy() {
784c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (!IsWindow(hwnd()))
785c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return;
786c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
787c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Remove this window from the tab list of Windows.
788ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  base::win::ScopedComPtr<ITaskbarList3> taskbar;
789c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  HRESULT result = taskbar.CreateInstance(CLSID_TaskbarList, NULL,
790c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                          CLSCTX_INPROC_SERVER);
791c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (FAILED(result))
792c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return;
793c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
794c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  result = taskbar->HrInit();
795c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (FAILED(result))
796c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return;
797c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
798c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  result = taskbar->UnregisterTab(hwnd());
799c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
800c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Destroy this window.
801c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DestroyWindow(hwnd());
802c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
803c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
804c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid AeroPeekWindow::SetTitle(const std::wstring& title) {
805c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  title_ = title;
806c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
807c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
808ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenvoid AeroPeekWindow::SetFavicon(const SkBitmap& favicon) {
809c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  favicon_bitmap_ = favicon;
810c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
811c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
812c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid AeroPeekWindow::UpdateThumbnail() {
813c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // We post a task to actually create a new thumbnail. So, this function may
814c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // be called while we are creating a thumbnail. To prevent this window from
815c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // posting two or more tasks, we don't invalidate the current thumbnail
816c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // when this event is not signaled.
817c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (ready_to_update_thumbnail_.IsSignaled())
818c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    CallDwmInvalidateIconicBitmaps(hwnd());
819c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
820c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
821c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochgfx::Rect AeroPeekWindow::GetContentBounds() const {
822c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  RECT content_rect;
823c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  GetClientRect(frame_window_, &content_rect);
824c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
825c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  gfx::Insets content_insets;
826c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  delegate_->GetContentInsets(&content_insets);
827c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
828c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  gfx::Rect content_bounds(content_rect);
829c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  content_bounds.Inset(content_insets.left(),
830c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                       content_insets.top(),
831c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                       content_insets.right(),
832c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                       content_insets.bottom());
833c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return content_bounds;
834c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
835c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
836c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// message handlers
837c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
838c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid AeroPeekWindow::OnActivate(UINT action,
839c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                BOOL minimized,
840c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                HWND window) {
841c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Windows sends a WM_ACTIVATE message not only when a user clicks this
842c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // window (i.e. this window gains the thumbnail focus) but also a user clicks
843c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // another window (i.e. this window loses the thumbnail focus.)
844c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Return when this window loses the thumbnail focus since we don't have to
845c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // do anything for this case.
846c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (action == WA_INACTIVE)
847c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return;
848c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
849c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Ask Chrome to activate the tab associated with this thumbnail window.
850c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Since TabStripModel calls AeroPeekManager::TabSelectedAt() when it
851c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // finishes activating the tab. We will move the tab focus of AeroPeek there.
852c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (delegate_)
853c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    delegate_->ActivateTab(tab_id_);
854c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
855c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
856c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochLRESULT AeroPeekWindow::OnCreate(LPCREATESTRUCT create_struct) {
857c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Initialize the window title now since WindowImpl::Init() always calls
858c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // CreateWindowEx() with its window name NULL.
859c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (!title_.empty()) {
860c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    SendMessage(hwnd(), WM_SETTEXT, 0,
861c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                reinterpret_cast<LPARAM>(title_.c_str()));
862c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
863c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
864c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Window attributes for DwmSetWindowAttribute().
865c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // These enum values are copied from Windows SDK 7 so we can compile this
866c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // file with or without it.
867c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // TODO(hbono): Bug 16903: to be deleted when we use Windows SDK 7.
868c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  enum {
869c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    DWMWA_NCRENDERING_ENABLED = 1,
870c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    DWMWA_NCRENDERING_POLICY,
871c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    DWMWA_TRANSITIONS_FORCEDISABLED,
872c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    DWMWA_ALLOW_NCPAINT,
873c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    DWMWA_CAPTION_BUTTON_BOUNDS,
874c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    DWMWA_NONCLIENT_RTL_LAYOUT,
875c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    DWMWA_FORCE_ICONIC_REPRESENTATION,
876c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    DWMWA_FLIP3D_POLICY,
877c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    DWMWA_EXTENDED_FRAME_BOUNDS,
878c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    DWMWA_HAS_ICONIC_BITMAP,
879c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    DWMWA_DISALLOW_PEEK,
880c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    DWMWA_EXCLUDED_FROM_PEEK,
881c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    DWMWA_LAST
882c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  };
883c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
884c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Set DWM attributes to tell Windows that this window can provide the
885c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // bitmaps used by AeroPeek.
886c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  BOOL force_iconic_representation = TRUE;
887c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DwmSetWindowAttribute(hwnd(),
888c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                        DWMWA_FORCE_ICONIC_REPRESENTATION,
889c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                        &force_iconic_representation,
890c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                        sizeof(force_iconic_representation));
891c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
892c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  BOOL has_iconic_bitmap = TRUE;
893c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DwmSetWindowAttribute(hwnd(),
894c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                        DWMWA_HAS_ICONIC_BITMAP,
895c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                        &has_iconic_bitmap,
896c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                        sizeof(has_iconic_bitmap));
897c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
898c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Post a task that registers this thumbnail window to Windows because it
899c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // may take some time. (For example, when we create an ITaskbarList3
900c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // interface for the first time, Windows loads DLLs and we need to wait for
901c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // some time.)
902731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  BrowserThread::PostTask(
903731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick      BrowserThread::IO,
904731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick      FROM_HERE,
905731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick      new RegisterThumbnailTask(frame_window_, hwnd(), tab_active_));
906731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
907c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return 0;
908c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
909c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
910c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid AeroPeekWindow::OnClose() {
911c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Unregister this window from the tab list of Windows and destroy this
912c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // window.
913c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // The resources attached to this object will be deleted when TabStrip calls
914c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // AeroPeekManager::TabClosingAt(). (Please read the comment in TabClosingAt()
915c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // for its details.)
916c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  Destroy();
917c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
918c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Ask AeroPeekManager to close the tab associated with this thumbnail
919c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // window.
920c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (delegate_)
921c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    delegate_->CloseTab(tab_id_);
922c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
923c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
924c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochLRESULT AeroPeekWindow::OnDwmSendIconicThumbnail(UINT message,
925c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                                 WPARAM wparam,
926c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                                 LPARAM lparam) {
927c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Update the window title to synchronize the title.
928c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  SendMessage(hwnd(), WM_SETTEXT, 0, reinterpret_cast<LPARAM>(title_.c_str()));
929c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
930c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Create an I/O task since it takes long time to resize these images and
931c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // send them to Windows. This task signals |ready_to_update_thumbnail_| in
932c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // its destructor to notify us when this task has been finished. (We create an
933c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // I/O task even when the given thumbnail is empty to stop the "loading"
934c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // animation.)
935c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DCHECK(delegate_);
936c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
937c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  SkBitmap thumbnail;
938c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  delegate_->GetTabThumbnail(tab_id_, &thumbnail);
939c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
940c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  gfx::Size aeropeek_size(HIWORD(lparam), LOWORD(lparam));
941731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  BrowserThread::PostTask(BrowserThread::IO,
942731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick                          FROM_HERE,
943731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick                          new SendThumbnailTask(hwnd(),
944731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick                                                GetContentBounds(),
945731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick                                                aeropeek_size,
946731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick                                                thumbnail,
947731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick                                                &ready_to_update_thumbnail_));
948c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return 0;
949c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
950c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
951c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochLRESULT AeroPeekWindow::OnDwmSendIconicLivePreviewBitmap(UINT message,
952c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                                         WPARAM wparam,
953c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                                         LPARAM lparam) {
954c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Same as OnDwmSendIconicThumbnail(), we create an I/O task which creates
955c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // a preview image used by AeroPeek and send it to Windows. Unlike
956c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // OnDwmSendIconicThumbnail(), we don't have to use events for preventing this
957c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // window from sending two or more tasks because Windows doesn't send
958c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // WM_DWMSENDICONICLIVEPREVIEWBITMAP messages before we send the preview image
959c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // to Windows.
960c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DCHECK(delegate_);
961c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
962c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  SkBitmap preview;
963c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  delegate_->GetTabPreview(tab_id_, &preview);
964c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
965731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  BrowserThread::PostTask(
966731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick      BrowserThread::IO,
967731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick      FROM_HERE,
968731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick      new SendLivePreviewTask(hwnd(), GetContentBounds(), preview));
969731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
970c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return 0;
971c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
972c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
973c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochHICON AeroPeekWindow::OnGetIcon(UINT index) {
974c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Return the application icon if this window doesn't have favicons.
975c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // We save this application icon to avoid calling LoadIcon() twice or more.
976c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (favicon_bitmap_.isNull()) {
977c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    if (!frame_icon_) {
978c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      frame_icon_ = GetAppIcon();
979c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
980c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return frame_icon_;
981c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
982c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
983c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Create a Windows icon from SkBitmap and send it to Windows. We set this
984c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // icon to the ScopedIcon object to delete it in the destructor.
985c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  favicon_.Set(IconUtil::CreateHICONFromSkBitmap(favicon_bitmap_));
986c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return favicon_.Get();
987c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
988c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
989c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochAeroPeekManager::AeroPeekManager(HWND application_window)
9904a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch    : application_window_(application_window),
9914a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch      border_left_(0),
9924a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch      border_top_(0),
9934a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch      toolbar_top_(0) {
994c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
995c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
996c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochAeroPeekManager::~AeroPeekManager() {
997c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Delete all AeroPeekWindow objects.
998c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  for (std::list<AeroPeekWindow*>::iterator i = tab_list_.begin();
999c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch       i != tab_list_.end(); ++i) {
1000c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    AeroPeekWindow* window = *i;
1001c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    delete window;
1002c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
1003c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
1004c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
1005c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid AeroPeekManager::SetContentInsets(const gfx::Insets& insets) {
1006c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  content_insets_ = insets;
1007c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
1008c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
1009c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// static
1010c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool AeroPeekManager::Enabled() {
1011c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // We enable our custom AeroPeek only when:
1012c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // * Chrome is running on Windows 7 and Aero is enabled,
1013c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // * Chrome is not launched in application mode, and
1014c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // * Chrome is launched with the "--enable-aero-peek-tabs" option.
1015c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // TODO(hbono): Bug 37957 <http://crbug.com/37957>: find solutions that avoid
1016c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // flooding users with tab thumbnails.
1017c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  const CommandLine* command_line = CommandLine::ForCurrentProcess();
1018731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  return base::win::GetVersion() >= base::win::VERSION_WIN7 &&
101972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      views::WidgetWin::IsAeroGlassEnabled() &&
1020c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      !command_line->HasSwitch(switches::kApp) &&
1021c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      command_line->HasSwitch(switches::kEnableAeroPeekTabs);
1022c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
1023c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
1024c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid AeroPeekManager::DeleteAeroPeekWindow(int tab_id) {
1025c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // This function does NOT call AeroPeekWindow::Destroy() before deleting
1026c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // the AeroPeekWindow instance.
1027c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  for (std::list<AeroPeekWindow*>::iterator i = tab_list_.begin();
1028c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch       i != tab_list_.end(); ++i) {
1029c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    AeroPeekWindow* window = *i;
1030c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    if (window->tab_id() == tab_id) {
1031c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      tab_list_.erase(i);
1032c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      delete window;
1033c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      return;
1034c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
1035c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
1036c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
1037dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
1038dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenvoid AeroPeekManager::DeleteAeroPeekWindowForTab(TabContentsWrapper* tab) {
1039dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  // Delete the AeroPeekWindow object associated with this tab and all its
1040dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  // resources. (AeroPeekWindow::Destory() also removes this tab from the tab
1041dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  // list of Windows.)
1042dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  AeroPeekWindow* window = GetAeroPeekWindow(GetTabID(tab->tab_contents()));
1043dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  if (!window)
1044dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    return;
1045dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
1046dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  window->Destroy();
1047dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  DeleteAeroPeekWindow(GetTabID(tab->tab_contents()));
1048dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen}
1049dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
1050c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochAeroPeekWindow* AeroPeekManager::GetAeroPeekWindow(int tab_id) const {
1051c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  size_t size = tab_list_.size();
1052c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  for (std::list<AeroPeekWindow*>::const_iterator i = tab_list_.begin();
1053c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch       i != tab_list_.end(); ++i) {
1054c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    AeroPeekWindow* window = *i;
1055c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    if (window->tab_id() == tab_id)
1056c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      return window;
1057c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
1058c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return NULL;
1059c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
1060c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
1061dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenvoid AeroPeekManager::CreateAeroPeekWindowIfNecessary(TabContentsWrapper* tab,
1062dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen                                                      bool foreground) {
1063dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  if (GetAeroPeekWindow(GetTabID(tab->tab_contents())))
1064dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    return;
1065dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
1066dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  AeroPeekWindow* window =
1067dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      new AeroPeekWindow(application_window_,
1068dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen                         this,
1069dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen                         GetTabID(tab->tab_contents()),
1070dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen                         foreground,
1071dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen                         tab->tab_contents()->GetTitle(),
1072ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                         tab->tab_contents()->GetFavicon());
1073dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  tab_list_.push_back(window);
1074dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen}
1075dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
1076c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochTabContents* AeroPeekManager::GetTabContents(int tab_id) const {
1077c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  for (TabContentsIterator iterator; !iterator.done(); ++iterator) {
1078ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    TabContents* target_contents = (*iterator)->tab_contents();
1079c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    if (target_contents->controller().session_id().id() == tab_id)
1080c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      return target_contents;
1081c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
1082c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return NULL;
1083c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
1084c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
1085c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochint AeroPeekManager::GetTabID(TabContents* contents) const {
1086c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (!contents)
1087c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return -1;
1088c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return contents->controller().session_id().id();
1089c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
1090c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
1091c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch///////////////////////////////////////////////////////////////////////////////
1092c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// AeroPeekManager, TabStripModelObserver implementation:
1093c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
1094201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdochvoid AeroPeekManager::TabInsertedAt(TabContentsWrapper* contents,
1095c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                    int index,
1096c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                    bool foreground) {
1097201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  if (!contents)
1098201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    return;
1099201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
1100dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  CreateAeroPeekWindowIfNecessary(contents, foreground);
1101c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
1102c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
1103201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdochvoid AeroPeekManager::TabDetachedAt(TabContentsWrapper* contents, int index) {
1104201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  if (!contents)
1105201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    return;
1106201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
1107c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Chrome will call TabInsertedAt() when this tab is inserted to another
1108c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // TabStrip. We will re-create an AeroPeekWindow object for this tab and
1109c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // re-add it to the tab list there.
1110dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  DeleteAeroPeekWindowForTab(contents);
1111c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
1112c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
1113201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdochvoid AeroPeekManager::TabSelectedAt(TabContentsWrapper* old_contents,
1114201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                                    TabContentsWrapper* new_contents,
1115c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                    int index,
1116c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                    bool user_gesture) {
1117dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  if (old_contents == new_contents)
1118dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    return;
1119dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
1120c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Deactivate the old window in the thumbnail list and activate the new one
1121c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // to synchronize the thumbnail list with TabStrip.
1122201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  if (old_contents) {
1123201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    AeroPeekWindow* old_window =
1124201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch        GetAeroPeekWindow(GetTabID(old_contents->tab_contents()));
1125201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    if (old_window)
1126201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch      old_window->Deactivate();
1127201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  }
1128c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
1129201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  if (new_contents) {
1130201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    AeroPeekWindow* new_window =
1131201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch        GetAeroPeekWindow(GetTabID(new_contents->tab_contents()));
1132201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    if (new_window)
1133201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch      new_window->Activate();
1134201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  }
1135c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
1136c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
1137dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenvoid AeroPeekManager::TabReplacedAt(TabStripModel* tab_strip_model,
1138dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen                                    TabContentsWrapper* old_contents,
1139dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen                                    TabContentsWrapper* new_contents,
1140dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen                                    int index) {
1141dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  DeleteAeroPeekWindowForTab(old_contents);
1142dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
1143dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  CreateAeroPeekWindowIfNecessary(new_contents,
1144ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                                  (index == tab_strip_model->active_index()));
1145dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  // We don't need to update the selection as if |new_contents| is selected the
1146dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  // TabStripModel will send TabSelectedAt.
1147dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen}
1148dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
1149201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdochvoid AeroPeekManager::TabMoved(TabContentsWrapper* contents,
1150c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                               int from_index,
1151c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                               int to_index,
1152c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                               bool pinned_state_changed) {
1153c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // TODO(hbono): we need to reorder the thumbnail list of Windows here?
1154c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // (Unfortunately, it is not so trivial to reorder the thumbnail list when
1155c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // we detach/attach tabs.)
1156c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
1157c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
1158201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdochvoid AeroPeekManager::TabChangedAt(TabContentsWrapper* contents,
1159c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                   int index,
1160c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                   TabChangeType change_type) {
1161201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  if (!contents)
1162201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    return;
1163201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
1164c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Retrieve the AeroPeekWindow object associated with this tab, update its
1165c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // title, and post a task that update its thumbnail image if necessary.
1166201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  AeroPeekWindow* window =
1167201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch      GetAeroPeekWindow(GetTabID(contents->tab_contents()));
1168c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (!window)
1169c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return;
1170c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
1171c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Update the title, the favicon, and the thumbnail used for AeroPeek.
1172c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // These function don't actually update the icon and the thumbnail until
1173c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Windows needs them (e.g. when a user hovers a taskbar icon) to avoid
1174c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // hurting the rendering performance. (These functions just save the
1175c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // information needed for handling update requests from Windows.)
1176201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  window->SetTitle(contents->tab_contents()->GetTitle());
1177ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  window->SetFavicon(contents->tab_contents()->GetFavicon());
1178201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  window->Update(contents->tab_contents()->is_loading());
1179c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
1180c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
1181c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch///////////////////////////////////////////////////////////////////////////////
1182c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// AeroPeekManager, AeroPeekWindowDelegate implementation:
1183c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
1184c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid AeroPeekManager::ActivateTab(int tab_id) {
1185c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Ask TabStrip to activate this tab.
1186c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // We don't have to update thumbnails now since TabStrip will call
1187c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // TabSelectedAt() when it actually activates this tab.
1188c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  TabContents* contents = GetTabContents(tab_id);
1189c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (contents && contents->delegate())
1190c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    contents->delegate()->ActivateContents(contents);
1191c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
1192c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
1193c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid AeroPeekManager::CloseTab(int tab_id) {
1194c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Ask TabStrip to close this tab.
1195c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // TabStrip will call TabClosingAt() when it actually closes this tab. We
1196c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // will delete the AeroPeekWindow object attached to this tab there.
1197c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  TabContents* contents = GetTabContents(tab_id);
1198c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (contents && contents->delegate())
1199c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    contents->delegate()->CloseContents(contents);
1200c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
1201c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
1202c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid AeroPeekManager::GetContentInsets(gfx::Insets* insets) {
1203c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  *insets = content_insets_;
1204c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
1205c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
1206c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool AeroPeekManager::GetTabThumbnail(int tab_id, SkBitmap* thumbnail) {
1207c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DCHECK(thumbnail);
1208c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
1209c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Copy the thumbnail image and the favicon of this tab. We will resize the
1210c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // images and send them to Windows.
1211c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  TabContents* contents = GetTabContents(tab_id);
1212c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (!contents)
1213c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return false;
1214c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
1215c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  ThumbnailGenerator* generator = g_browser_process->GetThumbnailGenerator();
1216c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DCHECK(generator);
1217c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  *thumbnail = generator->GetThumbnailForRenderer(contents->render_view_host());
1218c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
1219c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return true;
1220c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
1221c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
1222c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool AeroPeekManager::GetTabPreview(int tab_id, SkBitmap* preview) {
1223c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DCHECK(preview);
1224c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
1225c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Retrieve the BackingStore associated with the given tab and return its
1226c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // SkPlatformCanvas.
1227c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  TabContents* contents = GetTabContents(tab_id);
1228c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (!contents)
1229c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return false;
1230c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
1231c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  RenderViewHost* render_view_host = contents->render_view_host();
1232c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (!render_view_host)
1233c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return false;
1234c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
1235c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  BackingStore* backing_store = render_view_host->GetBackingStore(false);
1236c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (!backing_store)
1237c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return false;
1238c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
1239c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Create a copy of this BackingStore image.
1240c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // This code is just copied from "thumbnail_generator.cc".
1241c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  skia::PlatformCanvas canvas;
1242c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (!backing_store->CopyFromBackingStore(gfx::Rect(backing_store->size()),
1243c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                           &canvas))
1244c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return false;
1245c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
1246c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  const SkBitmap& bitmap = canvas.getTopPlatformDevice().accessBitmap(false);
1247c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  bitmap.copyTo(preview, SkBitmap::kARGB_8888_Config);
1248c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return true;
1249c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
1250