| // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "content/browser/geolocation/geolocation_dispatcher_host.h" |
| |
| #include <utility> |
| |
| #include "base/bind.h" |
| #include "content/browser/frame_host/render_frame_host_impl.h" |
| #include "content/browser/geolocation/geolocation_provider_impl.h" |
| #include "content/browser/renderer_host/render_message_filter.h" |
| #include "content/browser/web_contents/web_contents_impl.h" |
| #include "content/public/browser/content_browser_client.h" |
| #include "content/common/geolocation_messages.h" |
| |
| namespace content { |
| |
| GeolocationDispatcherHost::PendingPermission::PendingPermission( |
| int render_frame_id, |
| int render_process_id, |
| int bridge_id, |
| const GURL& origin) |
| : render_frame_id(render_frame_id), |
| render_process_id(render_process_id), |
| bridge_id(bridge_id), |
| origin(origin) { |
| } |
| |
| GeolocationDispatcherHost::PendingPermission::~PendingPermission() { |
| } |
| |
| GeolocationDispatcherHost::GeolocationDispatcherHost( |
| WebContents* web_contents) |
| : WebContentsObserver(web_contents), |
| weak_factory_(this) { |
| // This is initialized by WebContentsImpl. Do not add any non-trivial |
| // initialization here, defer to OnStartUpdating which is triggered whenever |
| // a javascript geolocation object is actually initialized. |
| } |
| |
| GeolocationDispatcherHost::~GeolocationDispatcherHost() { |
| } |
| |
| void GeolocationDispatcherHost::RenderFrameDeleted( |
| RenderFrameHost* render_frame_host) { |
| CancelPermissionRequestsForFrame(render_frame_host); |
| } |
| |
| void GeolocationDispatcherHost::DidNavigateAnyFrame( |
| RenderFrameHost* render_frame_host, |
| const LoadCommittedDetails& details, |
| const FrameNavigateParams& params) { |
| if (details.is_in_page) |
| return; |
| |
| CancelPermissionRequestsForFrame(render_frame_host); |
| } |
| |
| bool GeolocationDispatcherHost::OnMessageReceived( |
| const IPC::Message& msg, RenderFrameHost* render_frame_host) { |
| bool handled = true; |
| IPC_BEGIN_MESSAGE_MAP_WITH_PARAM(GeolocationDispatcherHost, msg, |
| render_frame_host) |
| IPC_MESSAGE_HANDLER(GeolocationHostMsg_RequestPermission, |
| OnRequestPermission) |
| IPC_MESSAGE_UNHANDLED(handled = false) |
| IPC_END_MESSAGE_MAP() |
| return handled; |
| } |
| |
| void GeolocationDispatcherHost::OnRequestPermission( |
| RenderFrameHost* render_frame_host, |
| int bridge_id, |
| const GURL& requesting_origin, |
| bool user_gesture) { |
| int render_process_id = render_frame_host->GetProcess()->GetID(); |
| int render_frame_id = render_frame_host->GetRoutingID(); |
| |
| PendingPermission pending_permission( |
| render_frame_id, render_process_id, bridge_id, requesting_origin); |
| pending_permissions_.push_back(pending_permission); |
| |
| GetContentClient()->browser()->RequestPermission( |
| content::PERMISSION_GEOLOCATION, |
| web_contents(), |
| bridge_id, |
| requesting_origin, |
| user_gesture, |
| base::Bind(&GeolocationDispatcherHost::SendGeolocationPermissionResponse, |
| weak_factory_.GetWeakPtr(), |
| render_process_id, |
| render_frame_id, |
| bridge_id)); |
| } |
| |
| void GeolocationDispatcherHost::SendGeolocationPermissionResponse( |
| int render_process_id, |
| int render_frame_id, |
| int bridge_id, |
| bool allowed) { |
| for (size_t i = 0; i < pending_permissions_.size(); ++i) { |
| if (pending_permissions_[i].render_process_id == render_process_id && |
| pending_permissions_[i].render_frame_id == render_frame_id && |
| pending_permissions_[i].bridge_id == bridge_id) { |
| RenderFrameHost* render_frame_host = |
| RenderFrameHost::FromID(render_process_id, render_frame_id); |
| if (render_frame_host) { |
| render_frame_host->Send(new GeolocationMsg_PermissionSet( |
| render_frame_id, bridge_id, allowed)); |
| } |
| |
| if (allowed) { |
| GeolocationProviderImpl::GetInstance()-> |
| UserDidOptIntoLocationServices(); |
| } |
| |
| pending_permissions_.erase(pending_permissions_.begin() + i); |
| return; |
| } |
| } |
| |
| NOTREACHED(); |
| } |
| |
| void GeolocationDispatcherHost::CancelPermissionRequestsForFrame( |
| RenderFrameHost* render_frame_host) { |
| int render_process_id = render_frame_host->GetProcess()->GetID(); |
| int render_frame_id = render_frame_host->GetRoutingID(); |
| |
| for (size_t i = 0; i < pending_permissions_.size(); ++i) { |
| if (pending_permissions_[i].render_process_id == render_process_id && |
| pending_permissions_[i].render_frame_id == render_frame_id) { |
| GetContentClient()->browser()->CancelPermissionRequest( |
| content::PERMISSION_GEOLOCATION, |
| web_contents(), |
| pending_permissions_[i].bridge_id, |
| pending_permissions_[i].origin); |
| pending_permissions_.erase(pending_permissions_.begin() + i); |
| } |
| } |
| } |
| |
| } // namespace content |