1// Copyright (c) 2012 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#ifndef CONTENT_BROWSER_RENDERER_HOST_RENDER_WIDGET_HELPER_H_
6#define CONTENT_BROWSER_RENDERER_HOST_RENDER_WIDGET_HELPER_H_
7
8#include <map>
9
10#include "base/atomic_sequence_num.h"
11#include "base/containers/hash_tables.h"
12#include "base/memory/ref_counted.h"
13#include "base/process/process.h"
14#include "content/public/browser/browser_thread.h"
15#include "content/public/browser/content_browser_client.h"
16#include "content/public/browser/global_request_id.h"
17#include "content/public/common/window_container_type.h"
18#include "third_party/WebKit/public/web/WebPopupType.h"
19#include "ui/gfx/native_widget_types.h"
20#include "ui/surface/transport_dib.h"
21
22namespace IPC {
23class Message;
24}
25
26namespace base {
27class TimeDelta;
28}
29
30struct GpuHostMsg_AcceleratedSurfaceBuffersSwapped_Params;
31struct ViewHostMsg_CreateWindow_Params;
32struct ViewMsg_SwapOut_Params;
33
34namespace content {
35class GpuProcessHost;
36class ResourceDispatcherHostImpl;
37class SessionStorageNamespace;
38
39// Instantiated per RenderProcessHost to provide various optimizations on
40// behalf of a RenderWidgetHost.  This class bridges between the IO thread
41// where the RenderProcessHost's MessageFilter lives and the UI thread where
42// the RenderWidgetHost lives.
43//
44//
45// OPTIMIZED TAB SWITCHING
46//
47//   When a RenderWidgetHost is in a background tab, it is flagged as hidden.
48//   This causes the corresponding RenderWidget to stop sending BackingStore
49//   messages. The RenderWidgetHost also discards its backingstore when it is
50//   hidden, which helps free up memory.  As a result, when a RenderWidgetHost
51//   is restored, it can be momentarily be without a backingstore.  (Restoring
52//   a RenderWidgetHost results in a WasShown message being sent to the
53//   RenderWidget, which triggers a full BackingStore message.)  This can lead
54//   to an observed rendering glitch as the WebContentsImpl will just have to
55//   fill white overtop the RenderWidgetHost until the RenderWidgetHost
56//   receives a BackingStore message to refresh its backingstore.
57//
58//   To avoid this 'white flash', the RenderWidgetHost again makes use of the
59//   RenderWidgetHelper's WaitForBackingStoreMsg method.  When the
60//   RenderWidgetHost's GetBackingStore method is called, it will call
61//   WaitForBackingStoreMsg if it has no backingstore.
62//
63// TRANSPORT DIB CREATION
64//
65//   On some platforms (currently the Mac) the renderer cannot create transport
66//   DIBs because of sandbox limitations. Thus, it has to make synchronous IPCs
67//   to the browser for them. Since these requests are synchronous, they cannot
68//   terminate on the UI thread. Thus, in this case, this object performs the
69//   allocation and maintains the set of allocated transport DIBs which the
70//   renderers can refer to.
71//
72
73class RenderWidgetHelper
74    : public base::RefCountedThreadSafe<RenderWidgetHelper,
75                                        BrowserThread::DeleteOnIOThread> {
76 public:
77  RenderWidgetHelper();
78
79  void Init(int render_process_id,
80            ResourceDispatcherHostImpl* resource_dispatcher_host);
81
82  // Gets the next available routing id.  This is thread safe.
83  int GetNextRoutingID();
84
85  // IO THREAD ONLY -----------------------------------------------------------
86
87  // Lookup the RenderWidgetHelper from the render_process_host_id. Returns NULL
88  // if not found. NOTE: The raw pointer is for temporary use only. To retain,
89  // store in a scoped_refptr.
90  static RenderWidgetHelper* FromProcessHostID(int render_process_host_id);
91
92  // UI THREAD ONLY -----------------------------------------------------------
93
94  // These four functions provide the backend implementation of the
95  // corresponding functions in RenderProcessHost. See those declarations
96  // for documentation.
97  void ResumeDeferredNavigation(const GlobalRequestID& request_id);
98  void ResumeResponseDeferredAtStart(const GlobalRequestID& request_id);
99
100  // Called to resume the requests for a view after it's ready. The view was
101  // created by CreateNewWindow which initially blocked the requests.
102  void ResumeRequestsForView(int route_id);
103
104  // IO THREAD ONLY -----------------------------------------------------------
105
106  void CreateNewWindow(
107      const ViewHostMsg_CreateWindow_Params& params,
108      bool no_javascript_access,
109      base::ProcessHandle render_process,
110      int* route_id,
111      int* main_frame_route_id,
112      int* surface_id,
113      SessionStorageNamespace* session_storage_namespace);
114  void CreateNewWidget(int opener_id,
115                       blink::WebPopupType popup_type,
116                       int* route_id,
117                       int* surface_id);
118  void CreateNewFullscreenWidget(int opener_id, int* route_id, int* surface_id);
119
120#if defined(OS_POSIX)
121  // Called on the IO thread to handle the allocation of a TransportDIB.  If
122  // |cache_in_browser| is |true|, then a copy of the shmem is kept by the
123  // browser, and it is the caller's repsonsibility to call
124  // FreeTransportDIB().  In all cases, the caller is responsible for deleting
125  // the resulting TransportDIB.
126  void AllocTransportDIB(uint32 size,
127                         bool cache_in_browser,
128                         TransportDIB::Handle* result);
129
130  // Called on the IO thread to handle the freeing of a transport DIB
131  void FreeTransportDIB(TransportDIB::Id dib_id);
132#endif
133
134 private:
135  friend class base::RefCountedThreadSafe<RenderWidgetHelper>;
136  friend struct BrowserThread::DeleteOnThread<BrowserThread::IO>;
137  friend class base::DeleteHelper<RenderWidgetHelper>;
138
139  ~RenderWidgetHelper();
140
141  // Called on the UI thread to finish creating a window.
142  void OnCreateWindowOnUI(
143      const ViewHostMsg_CreateWindow_Params& params,
144      int route_id,
145      int main_frame_route_id,
146      SessionStorageNamespace* session_storage_namespace);
147
148  // Called on the IO thread after a window was created on the UI thread.
149  void OnResumeRequestsForView(int route_id);
150
151  // Called on the UI thread to finish creating a widget.
152  void OnCreateWidgetOnUI(int opener_id,
153                          int route_id,
154                          blink::WebPopupType popup_type);
155
156  // Called on the UI thread to create a fullscreen widget.
157  void OnCreateFullscreenWidgetOnUI(int opener_id, int route_id);
158
159  // Called on the IO thread to resume a paused navigation in the network
160  // stack without transferring it to a new renderer process.
161  void OnResumeDeferredNavigation(const GlobalRequestID& request_id);
162
163  // Called on the IO thread to resume a navigation paused immediately after
164  // receiving response headers.
165  void OnResumeResponseDeferredAtStart(const GlobalRequestID& request_id);
166
167#if defined(OS_POSIX)
168  // Called on destruction to release all allocated transport DIBs
169  void ClearAllocatedDIBs();
170
171  // On POSIX we keep file descriptors to all the allocated DIBs around until
172  // the renderer frees them.
173  base::Lock allocated_dibs_lock_;
174  std::map<TransportDIB::Id, int> allocated_dibs_;
175#endif
176
177  int render_process_id_;
178
179  // The next routing id to use.
180  base::AtomicSequenceNumber next_routing_id_;
181
182  ResourceDispatcherHostImpl* resource_dispatcher_host_;
183
184  DISALLOW_COPY_AND_ASSIGN(RenderWidgetHelper);
185};
186
187}  // namespace content
188
189#endif  // CONTENT_BROWSER_RENDERER_HOST_RENDER_WIDGET_HELPER_H_
190