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/content_settings/permission_request_id.h"
11#include "chrome/browser/extensions/suggest_permission_util.h"
12#include "chrome/browser/guest_view/web_view/web_view_guest.h"
13#include "chrome/browser/profiles/profile.h"
14#include "extensions/browser/extension_registry.h"
15#include "extensions/browser/process_map.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  WebViewGuest* guest = WebViewGuest::FromWebContents(web_contents);
45  if (guest) {
46    guest->RequestGeolocationPermission(bridge_id,
47                                        requesting_frame,
48                                        user_gesture,
49                                        callback);
50    *permission_set = false;
51    *new_permission = false;
52    return true;
53  }
54
55  ExtensionRegistry* extension_registry = ExtensionRegistry::Get(profile_);
56  if (extension_registry) {
57    const extensions::Extension* extension =
58        extension_registry->enabled_extensions().GetExtensionOrAppByURL(
59            requesting_frame_origin);
60    if (IsExtensionWithPermissionOrSuggestInConsole(
61            APIPermission::kGeolocation, extension,
62            web_contents->GetRenderViewHost())) {
63      // Make sure the extension is in the calling process.
64      if (extensions::ProcessMap::Get(profile_)->Contains(
65              extension->id(), request_id.render_process_id())) {
66        *permission_set = true;
67        *new_permission = true;
68        return true;
69      }
70    }
71  }
72
73  if (extensions::GetViewType(web_contents) !=
74      extensions::VIEW_TYPE_TAB_CONTENTS) {
75    // The tab may have gone away, or the request may not be from a tab at all.
76    // TODO(mpcomplete): the request could be from a background page or
77    // extension popup (web_contents will have a different ViewType). But why do
78    // we care? Shouldn't we still put an infobar up in the current tab?
79    LOG(WARNING) << "Attempt to use geolocation tabless renderer: "
80                 << request_id.ToString()
81                 << " (can't prompt user without a visible tab)";
82    *permission_set = true;
83    *new_permission = false;
84    return true;
85  }
86#endif  // defined(ENABLE_EXTENSIONS)
87  return false;
88}
89
90bool GeolocationPermissionContextExtensions::CancelPermissionRequest(
91    content::WebContents* web_contents,
92    int bridge_id) {
93#if defined(ENABLE_EXTENSIONS)
94  WebViewGuest* guest =
95      web_contents ? WebViewGuest::FromWebContents(web_contents) : NULL;
96  if (guest) {
97    guest->CancelGeolocationPermissionRequest(bridge_id);
98    return true;
99  }
100#endif  // defined(ENABLE_EXTENSIONS)
101  return false;
102}
103