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 22 namespace IPC { 23 class Message; 24 } 25 26 namespace base { 27 class TimeDelta; 28 } 29 30 struct GpuHostMsg_AcceleratedSurfaceBuffersSwapped_Params; 31 struct ViewHostMsg_CreateWindow_Params; 32 struct ViewMsg_SwapOut_Params; 33 34 namespace content { 35 class GpuProcessHost; 36 class ResourceDispatcherHostImpl; 37 class 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 73 class 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