| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "content/browser/web_contents/web_contents_impl.h" | 5 #include "content/browser/web_contents/web_contents_impl.h" |
| 6 | 6 |
| 7 #include <stddef.h> | 7 #include <stddef.h> |
| 8 | 8 |
| 9 #include <cmath> | 9 #include <cmath> |
| 10 #include <utility> | 10 #include <utility> |
| (...skipping 1991 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2002 | 2002 |
| 2003 void WebContentsImpl::OnRenderFrameProxyVisibilityChanged(bool visible) { | 2003 void WebContentsImpl::OnRenderFrameProxyVisibilityChanged(bool visible) { |
| 2004 if (visible && !GetOuterWebContents()->IsHidden()) | 2004 if (visible && !GetOuterWebContents()->IsHidden()) |
| 2005 WasShown(); | 2005 WasShown(); |
| 2006 else if (!visible) | 2006 else if (!visible) |
| 2007 WasHidden(); | 2007 WasHidden(); |
| 2008 } | 2008 } |
| 2009 | 2009 |
| 2010 void WebContentsImpl::CreateNewWindow( | 2010 void WebContentsImpl::CreateNewWindow( |
| 2011 SiteInstance* source_site_instance, | 2011 SiteInstance* source_site_instance, |
| 2012 int32_t route_id, | 2012 int32_t render_view_route_id, |
| 2013 int32_t main_frame_route_id, | 2013 int32_t main_frame_route_id, |
| 2014 int32_t main_frame_widget_route_id, | 2014 int32_t main_frame_widget_route_id, |
| 2015 const mojom::CreateNewWindowParams& params, | 2015 const mojom::CreateNewWindowParams& params, |
| 2016 SessionStorageNamespace* session_storage_namespace) { | 2016 SessionStorageNamespace* session_storage_namespace) { |
| 2017 // We should have zero valid routing ids, or three valid routing IDs. |
| 2018 DCHECK_EQ((render_view_route_id == MSG_ROUTING_NONE), |
| 2019 (main_frame_route_id == MSG_ROUTING_NONE)); |
| 2020 DCHECK_EQ((render_view_route_id == MSG_ROUTING_NONE), |
| 2021 (main_frame_widget_route_id == MSG_ROUTING_NONE)); |
| 2022 |
| 2023 int render_process_id = source_site_instance->GetProcess()->GetID(); |
| 2024 // The route IDs passed into this function can be trusted not to already be in |
| 2025 // use; they were allocated by the RenderWidgetHelper on the IO thread. |
| 2026 DCHECK(!RenderFrameHostImpl::FromID(render_process_id, main_frame_route_id)); |
| 2027 |
| 2017 // We usually create the new window in the same BrowsingInstance (group of | 2028 // We usually create the new window in the same BrowsingInstance (group of |
| 2018 // script-related windows), by passing in the current SiteInstance. However, | 2029 // script-related windows), by passing in the current SiteInstance. However, |
| 2019 // if the opener is being suppressed (in a non-guest), we create a new | 2030 // if the opener is being suppressed (in a non-guest), we create a new |
| 2020 // SiteInstance in its own BrowsingInstance. | 2031 // SiteInstance in its own BrowsingInstance. |
| 2021 bool is_guest = BrowserPluginGuest::IsGuest(this); | 2032 bool is_guest = BrowserPluginGuest::IsGuest(this); |
| 2022 | 2033 |
| 2023 // If the opener is to be suppressed, the new window can be in any process. | 2034 // If the opener is to be suppressed, the new window can be in any process. |
| 2024 // Since routing ids are process specific, we must not have one passed in | 2035 // Since routing ids are process specific, we must not have one passed in |
| 2025 // as argument here. | 2036 // as argument here. |
| 2026 DCHECK(!params.opener_suppressed || route_id == MSG_ROUTING_NONE); | 2037 DCHECK(!params.opener_suppressed || render_view_route_id == MSG_ROUTING_NONE); |
| 2027 | 2038 |
| 2028 scoped_refptr<SiteInstance> site_instance = | 2039 scoped_refptr<SiteInstance> site_instance = |
| 2029 params.opener_suppressed && !is_guest | 2040 params.opener_suppressed && !is_guest |
| 2030 ? SiteInstance::CreateForURL(GetBrowserContext(), params.target_url) | 2041 ? SiteInstance::CreateForURL(GetBrowserContext(), params.target_url) |
| 2031 : source_site_instance; | 2042 : source_site_instance; |
| 2032 | 2043 |
| 2033 // A message to create a new window can only come from a process for a frame | |
| 2034 // in this WebContents' FrameTree. If any other process sends the request, it | |
| 2035 // is invalid and the process must be terminated. | |
| 2036 int render_process_id = source_site_instance->GetProcess()->GetID(); | |
| 2037 if (!HasMatchingProcess(&frame_tree_, render_process_id)) { | |
| 2038 RenderProcessHost* rph = source_site_instance->GetProcess(); | |
| 2039 base::ProcessHandle process_handle = rph->GetHandle(); | |
| 2040 if (process_handle != base::kNullProcessHandle) { | |
| 2041 RecordAction( | |
| 2042 base::UserMetricsAction("Terminate_ProcessMismatch_CreateNewWindow")); | |
| 2043 rph->Shutdown(RESULT_CODE_KILLED, false); | |
| 2044 } | |
| 2045 return; | |
| 2046 } | |
| 2047 | |
| 2048 // We must assign the SessionStorageNamespace before calling Init(). | 2044 // We must assign the SessionStorageNamespace before calling Init(). |
| 2049 // | 2045 // |
| 2050 // http://crbug.com/142685 | 2046 // http://crbug.com/142685 |
| 2051 const std::string& partition_id = | 2047 const std::string& partition_id = |
| 2052 GetContentClient()->browser()-> | 2048 GetContentClient()->browser()-> |
| 2053 GetStoragePartitionIdForSite(GetBrowserContext(), | 2049 GetStoragePartitionIdForSite(GetBrowserContext(), |
| 2054 site_instance->GetSiteURL()); | 2050 site_instance->GetSiteURL()); |
| 2055 StoragePartition* partition = BrowserContext::GetStoragePartition( | 2051 StoragePartition* partition = BrowserContext::GetStoragePartition( |
| 2056 GetBrowserContext(), site_instance.get()); | 2052 GetBrowserContext(), site_instance.get()); |
| 2057 DOMStorageContextWrapper* dom_storage_context = | 2053 DOMStorageContextWrapper* dom_storage_context = |
| 2058 static_cast<DOMStorageContextWrapper*>(partition->GetDOMStorageContext()); | 2054 static_cast<DOMStorageContextWrapper*>(partition->GetDOMStorageContext()); |
| 2059 SessionStorageNamespaceImpl* session_storage_namespace_impl = | 2055 SessionStorageNamespaceImpl* session_storage_namespace_impl = |
| 2060 static_cast<SessionStorageNamespaceImpl*>(session_storage_namespace); | 2056 static_cast<SessionStorageNamespaceImpl*>(session_storage_namespace); |
| 2061 CHECK(session_storage_namespace_impl->IsFromContext(dom_storage_context)); | 2057 CHECK(session_storage_namespace_impl->IsFromContext(dom_storage_context)); |
| 2062 | 2058 |
| 2063 if (delegate_ && | 2059 if (delegate_ && |
| 2064 !delegate_->ShouldCreateWebContents( | 2060 !delegate_->ShouldCreateWebContents( |
| 2065 this, source_site_instance, route_id, main_frame_route_id, | 2061 this, source_site_instance, render_view_route_id, main_frame_route_id, |
| 2066 main_frame_widget_route_id, params.window_container_type, | 2062 main_frame_widget_route_id, params.window_container_type, |
| 2067 params.opener_url, params.frame_name, params.target_url, partition_id, | 2063 params.opener_url, params.frame_name, params.target_url, partition_id, |
| 2068 session_storage_namespace)) { | 2064 session_storage_namespace)) { |
| 2069 if (route_id != MSG_ROUTING_NONE && | |
| 2070 !RenderViewHost::FromID(render_process_id, route_id)) { | |
| 2071 // If the embedder didn't create a WebContents for this route, we need to | |
| 2072 // delete the RenderView that had already been created. | |
| 2073 Send(new ViewMsg_Close(route_id)); | |
| 2074 } | |
| 2075 // Note: even though we're not creating a WebContents here, it could have | 2065 // Note: even though we're not creating a WebContents here, it could have |
| 2076 // been created by the embedder so ensure that the RenderFrameHost is | 2066 // been created by the embedder so ensure that the RenderFrameHost is |
| 2077 // properly initialized. | 2067 // properly initialized. |
| 2078 // It's safe to only target the frame because the render process will not | 2068 // It's safe to only target the frame because the render process will not |
| 2079 // have a chance to create more frames at this point. | 2069 // have a chance to create more frames at this point. |
| 2080 RenderFrameHostImpl* rfh = | 2070 RenderFrameHostImpl* rfh = |
| 2081 RenderFrameHostImpl::FromID(render_process_id, main_frame_route_id); | 2071 RenderFrameHostImpl::FromID(render_process_id, main_frame_route_id); |
| 2082 if (rfh) | 2072 if (rfh) { |
| 2073 DCHECK(rfh->IsRenderFrameLive()); |
| 2083 rfh->Init(); | 2074 rfh->Init(); |
| 2075 } |
| 2084 return; | 2076 return; |
| 2085 } | 2077 } |
| 2086 | 2078 |
| 2087 // Create the new web contents. This will automatically create the new | 2079 // Create the new web contents. This will automatically create the new |
| 2088 // WebContentsView. In the future, we may want to create the view separately. | 2080 // WebContentsView. In the future, we may want to create the view separately. |
| 2089 CreateParams create_params(GetBrowserContext(), site_instance.get()); | 2081 CreateParams create_params(GetBrowserContext(), site_instance.get()); |
| 2090 create_params.routing_id = route_id; | 2082 create_params.routing_id = render_view_route_id; |
| 2091 create_params.main_frame_routing_id = main_frame_route_id; | 2083 create_params.main_frame_routing_id = main_frame_route_id; |
| 2092 create_params.main_frame_widget_routing_id = main_frame_widget_route_id; | 2084 create_params.main_frame_widget_routing_id = main_frame_widget_route_id; |
| 2093 create_params.main_frame_name = params.frame_name; | 2085 create_params.main_frame_name = params.frame_name; |
| 2094 create_params.opener_render_process_id = render_process_id; | 2086 create_params.opener_render_process_id = render_process_id; |
| 2095 create_params.opener_render_frame_id = params.opener_render_frame_id; | 2087 create_params.opener_render_frame_id = params.opener_render_frame_id; |
| 2096 create_params.opener_suppressed = params.opener_suppressed; | 2088 create_params.opener_suppressed = params.opener_suppressed; |
| 2097 if (params.disposition == WindowOpenDisposition::NEW_BACKGROUND_TAB) | 2089 if (params.disposition == WindowOpenDisposition::NEW_BACKGROUND_TAB) |
| 2098 create_params.initially_hidden = true; | 2090 create_params.initially_hidden = true; |
| 2099 create_params.renderer_initiated_creation = | 2091 create_params.renderer_initiated_creation = |
| 2100 main_frame_route_id != MSG_ROUTING_NONE; | 2092 main_frame_route_id != MSG_ROUTING_NONE; |
| (...skipping 24 matching lines...) Expand all Loading... |
| 2125 if (!is_guest) { | 2117 if (!is_guest) { |
| 2126 WebContentsView* new_view = new_contents->view_.get(); | 2118 WebContentsView* new_view = new_contents->view_.get(); |
| 2127 | 2119 |
| 2128 // TODO(brettw): It seems bogus that we have to call this function on the | 2120 // TODO(brettw): It seems bogus that we have to call this function on the |
| 2129 // newly created object and give it one of its own member variables. | 2121 // newly created object and give it one of its own member variables. |
| 2130 new_view->CreateViewForWidget( | 2122 new_view->CreateViewForWidget( |
| 2131 new_contents->GetRenderViewHost()->GetWidget(), false); | 2123 new_contents->GetRenderViewHost()->GetWidget(), false); |
| 2132 } | 2124 } |
| 2133 // Save the created window associated with the route so we can show it | 2125 // Save the created window associated with the route so we can show it |
| 2134 // later. | 2126 // later. |
| 2135 DCHECK_NE(MSG_ROUTING_NONE, route_id); | 2127 DCHECK_NE(MSG_ROUTING_NONE, main_frame_widget_route_id); |
| 2136 pending_contents_[std::make_pair(render_process_id, route_id)] = | 2128 pending_contents_[std::make_pair( |
| 2137 new_contents; | 2129 render_process_id, main_frame_widget_route_id)] = new_contents; |
| 2138 AddDestructionObserver(new_contents); | 2130 AddDestructionObserver(new_contents); |
| 2139 } | 2131 } |
| 2140 | 2132 |
| 2141 if (delegate_) { | 2133 if (delegate_) { |
| 2142 delegate_->WebContentsCreated( | 2134 delegate_->WebContentsCreated( |
| 2143 this, render_process_id, params.opener_render_frame_id, | 2135 this, render_process_id, params.opener_render_frame_id, |
| 2144 params.frame_name, params.target_url, new_contents); | 2136 params.frame_name, params.target_url, new_contents); |
| 2145 } | 2137 } |
| 2146 | 2138 |
| 2147 if (params.opener_suppressed) { | 2139 if (params.opener_suppressed) { |
| (...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2219 widget_view; | 2211 widget_view; |
| 2220 | 2212 |
| 2221 #if defined(OS_MACOSX) | 2213 #if defined(OS_MACOSX) |
| 2222 // A RenderWidgetHostViewMac has lifetime scoped to the view. We'll retain it | 2214 // A RenderWidgetHostViewMac has lifetime scoped to the view. We'll retain it |
| 2223 // to allow it to survive the trip without being hosted. | 2215 // to allow it to survive the trip without being hosted. |
| 2224 base::mac::NSObjectRetain(widget_view->GetNativeView()); | 2216 base::mac::NSObjectRetain(widget_view->GetNativeView()); |
| 2225 #endif | 2217 #endif |
| 2226 } | 2218 } |
| 2227 | 2219 |
| 2228 void WebContentsImpl::ShowCreatedWindow(int process_id, | 2220 void WebContentsImpl::ShowCreatedWindow(int process_id, |
| 2229 int route_id, | 2221 int main_frame_widget_route_id, |
| 2230 WindowOpenDisposition disposition, | 2222 WindowOpenDisposition disposition, |
| 2231 const gfx::Rect& initial_rect, | 2223 const gfx::Rect& initial_rect, |
| 2232 bool user_gesture) { | 2224 bool user_gesture) { |
| 2233 WebContentsImpl* contents = GetCreatedWindow(process_id, route_id); | 2225 WebContentsImpl* contents = |
| 2226 GetCreatedWindow(process_id, main_frame_widget_route_id); |
| 2234 if (contents) { | 2227 if (contents) { |
| 2235 WebContentsDelegate* delegate = GetDelegate(); | 2228 WebContentsDelegate* delegate = GetDelegate(); |
| 2236 contents->is_resume_pending_ = true; | 2229 contents->is_resume_pending_ = true; |
| 2237 if (!delegate || delegate->ShouldResumeRequestsForCreatedWindow()) | 2230 if (!delegate || delegate->ShouldResumeRequestsForCreatedWindow()) |
| 2238 contents->ResumeLoadingCreatedWebContents(); | 2231 contents->ResumeLoadingCreatedWebContents(); |
| 2239 | 2232 |
| 2240 if (delegate) { | 2233 if (delegate) { |
| 2241 delegate->AddNewContents( | 2234 delegate->AddNewContents(this, contents, disposition, initial_rect, |
| 2242 this, contents, disposition, initial_rect, user_gesture, NULL); | 2235 user_gesture, NULL); |
| 2243 } | 2236 } |
| 2237 |
| 2238 RenderWidgetHostImpl* rwh = contents->GetMainFrame()->GetRenderWidgetHost(); |
| 2239 DCHECK_EQ(main_frame_widget_route_id, rwh->GetRoutingID()); |
| 2240 rwh->Send(new ViewMsg_Move_ACK(rwh->GetRoutingID())); |
| 2244 } | 2241 } |
| 2245 } | 2242 } |
| 2246 | 2243 |
| 2247 void WebContentsImpl::ShowCreatedWidget(int process_id, | 2244 void WebContentsImpl::ShowCreatedWidget(int process_id, |
| 2248 int route_id, | 2245 int route_id, |
| 2249 const gfx::Rect& initial_rect) { | 2246 const gfx::Rect& initial_rect) { |
| 2250 ShowCreatedWidget(process_id, route_id, false, initial_rect); | 2247 ShowCreatedWidget(process_id, route_id, false, initial_rect); |
| 2251 } | 2248 } |
| 2252 | 2249 |
| 2253 void WebContentsImpl::ShowCreatedFullscreenWidget(int process_id, | 2250 void WebContentsImpl::ShowCreatedFullscreenWidget(int process_id, |
| (...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2300 render_widget_host_impl->set_allow_privileged_mouse_lock(is_fullscreen); | 2297 render_widget_host_impl->set_allow_privileged_mouse_lock(is_fullscreen); |
| 2301 | 2298 |
| 2302 #if defined(OS_MACOSX) | 2299 #if defined(OS_MACOSX) |
| 2303 // A RenderWidgetHostViewMac has lifetime scoped to the view. Now that it's | 2300 // A RenderWidgetHostViewMac has lifetime scoped to the view. Now that it's |
| 2304 // properly embedded (or purposefully ignored) we can release the retain we | 2301 // properly embedded (or purposefully ignored) we can release the retain we |
| 2305 // took in CreateNewWidget(). | 2302 // took in CreateNewWidget(). |
| 2306 base::mac::NSObjectRelease(widget_host_view->GetNativeView()); | 2303 base::mac::NSObjectRelease(widget_host_view->GetNativeView()); |
| 2307 #endif | 2304 #endif |
| 2308 } | 2305 } |
| 2309 | 2306 |
| 2310 WebContentsImpl* WebContentsImpl::GetCreatedWindow(int process_id, | 2307 WebContentsImpl* WebContentsImpl::GetCreatedWindow( |
| 2311 int route_id) { | 2308 int process_id, |
| 2312 auto iter = pending_contents_.find(std::make_pair(process_id, route_id)); | 2309 int main_frame_widget_route_id) { |
| 2310 auto key = std::make_pair(process_id, main_frame_widget_route_id); |
| 2311 auto iter = pending_contents_.find(key); |
| 2313 | 2312 |
| 2314 // Certain systems can block the creation of new windows. If we didn't succeed | 2313 // Certain systems can block the creation of new windows. If we didn't succeed |
| 2315 // in creating one, just return NULL. | 2314 // in creating one, just return NULL. |
| 2316 if (iter == pending_contents_.end()) | 2315 if (iter == pending_contents_.end()) |
| 2317 return nullptr; | 2316 return nullptr; |
| 2318 | 2317 |
| 2319 WebContentsImpl* new_contents = iter->second; | 2318 WebContentsImpl* new_contents = iter->second; |
| 2320 pending_contents_.erase(std::make_pair(process_id, route_id)); | 2319 pending_contents_.erase(key); |
| 2321 RemoveDestructionObserver(new_contents); | 2320 RemoveDestructionObserver(new_contents); |
| 2322 | 2321 |
| 2323 // Don't initialize the guest WebContents immediately. | 2322 // Don't initialize the guest WebContents immediately. |
| 2324 if (BrowserPluginGuest::IsGuest(new_contents)) | 2323 if (BrowserPluginGuest::IsGuest(new_contents)) |
| 2325 return new_contents; | 2324 return new_contents; |
| 2326 | 2325 |
| 2327 if (!new_contents->GetRenderProcessHost()->HasConnection() || | 2326 if (!new_contents->GetMainFrame()->GetProcess()->HasConnection() || |
| 2328 !new_contents->GetRenderViewHost()->GetWidget()->GetView()) | 2327 !new_contents->GetMainFrame()->GetView()) { |
| 2328 // TODO(nick): http://crbug.com/674318 -- Who deletes |new_contents|? |
| 2329 return nullptr; | 2329 return nullptr; |
| 2330 } |
| 2330 | 2331 |
| 2331 return new_contents; | 2332 return new_contents; |
| 2332 } | 2333 } |
| 2333 | 2334 |
| 2334 RenderWidgetHostView* WebContentsImpl::GetCreatedWidget(int process_id, | 2335 RenderWidgetHostView* WebContentsImpl::GetCreatedWidget(int process_id, |
| 2335 int route_id) { | 2336 int route_id) { |
| 2336 auto iter = pending_widget_views_.find(std::make_pair(process_id, route_id)); | 2337 auto iter = pending_widget_views_.find(std::make_pair(process_id, route_id)); |
| 2337 if (iter == pending_widget_views_.end()) { | 2338 if (iter == pending_widget_views_.end()) { |
| 2338 DCHECK(false); | 2339 DCHECK(false); |
| 2339 return nullptr; | 2340 return nullptr; |
| (...skipping 2940 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5280 dialog_manager_ = dialog_manager; | 5281 dialog_manager_ = dialog_manager; |
| 5281 } | 5282 } |
| 5282 | 5283 |
| 5283 void WebContentsImpl::RemoveBindingSet(const std::string& interface_name) { | 5284 void WebContentsImpl::RemoveBindingSet(const std::string& interface_name) { |
| 5284 auto it = binding_sets_.find(interface_name); | 5285 auto it = binding_sets_.find(interface_name); |
| 5285 if (it != binding_sets_.end()) | 5286 if (it != binding_sets_.end()) |
| 5286 binding_sets_.erase(it); | 5287 binding_sets_.erase(it); |
| 5287 } | 5288 } |
| 5288 | 5289 |
| 5289 } // namespace content | 5290 } // namespace content |
| OLD | NEW |