1// Copyright 2014 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#include "chrome/browser/geolocation/geolocation_permission_context_extensions.h"
6
7#include "base/callback.h"
8
9#if defined(ENABLE_EXTENSIONS)
10#include "chrome/browser/profiles/profile.h"
11#include "components/content_settings/core/common/permission_request_id.h"
12#include "extensions/browser/extension_registry.h"
13#include "extensions/browser/guest_view/web_view/web_view_permission_helper.h"
14#include "extensions/browser/process_map.h"
15#include "extensions/browser/suggest_permission_util.h"
16#include "extensions/browser/view_type_utils.h"
17#include "extensions/common/extension.h"
18
19using extensions::APIPermission;
20using extensions::ExtensionRegistry;
21#endif
22
23GeolocationPermissionContextExtensions::
24GeolocationPermissionContextExtensions(Profile* profile)
25    : profile_(profile) {
26}
27
28GeolocationPermissionContextExtensions::
29~GeolocationPermissionContextExtensions() {
30}
31
32bool GeolocationPermissionContextExtensions::RequestPermission(
33    content::WebContents* web_contents,
34    const PermissionRequestID& request_id,
35    int bridge_id,
36    const GURL& requesting_frame,
37    bool user_gesture,
38    base::Callback<void(bool)> callback,
39    bool* permission_set,
40    bool* new_permission) {
41#if defined(ENABLE_EXTENSIONS)
42  GURL requesting_frame_origin = requesting_frame.GetOrigin();
43
44  extensions::WebViewPermissionHelper* web_view_permission_helper =
45      extensions::WebViewPermissionHelper::FromWebContents(web_contents);
46  if (web_view_permission_helper) {
47    web_view_permission_helper->RequestGeolocationPermission(
48        bridge_id, requesting_frame, user_gesture, callback);
49    *permission_set = false;
50    *new_permission = false;
51    return true;
52  }
53
54  ExtensionRegistry* extension_registry = ExtensionRegistry::Get(profile_);
55  if (extension_registry) {
56    const extensions::Extension* extension =
57        extension_registry->enabled_extensions().GetExtensionOrAppByURL(
58            requesting_frame_origin);
59    if (IsExtensionWithPermissionOrSuggestInConsole(
60            APIPermission::kGeolocation, extension,
61            web_contents->GetRenderViewHost())) {
62      // Make sure the extension is in the calling process.
63      if (extensions::ProcessMap::Get(profile_)->Contains(
64              extension->id(), request_id.render_process_id())) {
65        *permission_set = true;
66        *new_permission = true;
67        return true;
68      }
69    }
70  }
71
72  if (extensions::GetViewType(web_contents) !=
73      extensions::VIEW_TYPE_TAB_CONTENTS) {
74    // The tab may have gone away, or the request may not be from a tab at all.
75    // TODO(mpcomplete): the request could be from a background page or
76    // extension popup (web_contents will have a different ViewType). But why do
77    // we care? Shouldn't we still put an infobar up in the current tab?
78    LOG(WARNING) << "Attempt to use geolocation tabless renderer: "
79                 << request_id.ToString()
80                 << " (can't prompt user without a visible tab)";
81    *permission_set = true;
82    *new_permission = false;
83    return true;
84  }
85#endif  // defined(ENABLE_EXTENSIONS)
86  return false;
87}
88
89bool GeolocationPermissionContextExtensions::CancelPermissionRequest(
90    content::WebContents* web_contents,
91    int bridge_id) {
92#if defined(ENABLE_EXTENSIONS)
93  extensions::WebViewPermissionHelper* web_view_permission_helper =
94      web_contents ?
95      extensions::WebViewPermissionHelper::FromWebContents(web_contents)
96      : NULL;
97  if (web_view_permission_helper) {
98    web_view_permission_helper->CancelGeolocationPermissionRequest(bridge_id);
99    return true;
100  }
101#endif  // defined(ENABLE_EXTENSIONS)
102  return false;
103}
104