permission_context_base.cc revision 6e8cce623b6e4fe0c9e4af605d675dd9d0338c38
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/content_settings/permission_context_base.h"
6
7#include "base/logging.h"
8#include "base/prefs/pref_service.h"
9#include "chrome/browser/content_settings/host_content_settings_map.h"
10#include "chrome/browser/content_settings/permission_bubble_request_impl.h"
11#include "chrome/browser/content_settings/permission_context_uma_util.h"
12#include "chrome/browser/content_settings/permission_queue_controller.h"
13#include "chrome/browser/content_settings/permission_request_id.h"
14#include "chrome/browser/content_settings/tab_specific_content_settings.h"
15#include "chrome/browser/profiles/profile.h"
16#include "chrome/browser/ui/website_settings/permission_bubble_manager.h"
17#include "chrome/common/pref_names.h"
18#include "content/public/browser/browser_thread.h"
19#include "content/public/browser/web_contents.h"
20
21PermissionContextBase::PermissionContextBase(
22    Profile* profile,
23    const ContentSettingsType permission_type)
24    : profile_(profile),
25      permission_type_(permission_type),
26      weak_factory_(this) {
27  permission_queue_controller_.reset(
28      new PermissionQueueController(profile_, permission_type_));
29}
30
31PermissionContextBase::~PermissionContextBase() {
32  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
33}
34
35void PermissionContextBase::RequestPermission(
36    content::WebContents* web_contents,
37    const PermissionRequestID& id,
38    const GURL& requesting_frame,
39    bool user_gesture,
40    const BrowserPermissionCallback& callback) {
41  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
42
43  DecidePermission(web_contents,
44                   id,
45                   requesting_frame.GetOrigin(),
46                   web_contents->GetLastCommittedURL().GetOrigin(),
47                   user_gesture,
48                   callback);
49}
50
51void PermissionContextBase::DecidePermission(
52    content::WebContents* web_contents,
53    const PermissionRequestID& id,
54    const GURL& requesting_origin,
55    const GURL& embedder_origin,
56    bool user_gesture,
57    const BrowserPermissionCallback& callback) {
58  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
59
60  ContentSetting content_setting =
61      profile_->GetHostContentSettingsMap()->GetContentSetting(
62          requesting_origin, embedder_origin, permission_type_, std::string());
63  switch (content_setting) {
64    case CONTENT_SETTING_BLOCK:
65      NotifyPermissionSet(id, requesting_origin, embedder_origin,
66                          callback, false /* persist */, false /* granted */);
67      return;
68    case CONTENT_SETTING_ALLOW:
69      NotifyPermissionSet(id, requesting_origin, embedder_origin,
70                          callback, false /* persist */, true /* granted */);
71      return;
72    default:
73      break;
74  }
75
76  PermissionContextUmaUtil::PermissionRequested(permission_type_);
77
78  if (PermissionBubbleManager::Enabled()) {
79    PermissionBubbleManager* bubble_manager =
80        PermissionBubbleManager::FromWebContents(web_contents);
81    DCHECK(bubble_manager);
82    scoped_ptr<PermissionBubbleRequest> request_ptr(
83        new PermissionBubbleRequestImpl(
84            requesting_origin,
85            user_gesture,
86            permission_type_,
87            profile_->GetPrefs()->GetString(prefs::kAcceptLanguages),
88            base::Bind(&PermissionContextBase::PermissionDecided,
89                       weak_factory_.GetWeakPtr(),
90                       id,
91                       requesting_origin,
92                       embedder_origin,
93                       callback),
94            base::Bind(&PermissionContextBase::CleanUpBubble,
95                       weak_factory_.GetWeakPtr(), id)));
96    PermissionBubbleRequest* request = request_ptr.get();
97
98    bool inserted = pending_bubbles_.add(
99        id.ToString(), request_ptr.Pass()).second;
100    DCHECK(inserted) << "Duplicate id " << id.ToString();
101    bubble_manager->AddRequest(request);
102    return;
103  }
104
105  // TODO(gbillock): Delete this and the infobar delegate when
106  // we're using only bubbles. crbug.com/337458
107  GetQueueController()->CreateInfoBarRequest(
108      id,
109      requesting_origin,
110      embedder_origin,
111      base::Bind(&PermissionContextBase::PermissionDecided,
112                 weak_factory_.GetWeakPtr(),
113                 id,
114                 requesting_origin,
115                 embedder_origin,
116                 callback,
117                 // the queue controller takes care of persisting the
118                 // permission
119                 false));
120}
121
122void PermissionContextBase::PermissionDecided(
123    const PermissionRequestID& id,
124    const GURL& requesting_origin,
125    const GURL& embedder_origin,
126    const BrowserPermissionCallback& callback,
127    bool persist,
128    bool allowed) {
129
130  // Infobar persistance and its related UMA is tracked on the infobar
131  // controller directly.
132  if (PermissionBubbleManager::Enabled()) {
133    if (persist) {
134      if (allowed)
135        PermissionContextUmaUtil::PermissionGranted(permission_type_);
136      else
137        PermissionContextUmaUtil::PermissionDenied(permission_type_);
138    } else {
139      PermissionContextUmaUtil::PermissionDismissed(permission_type_);
140    }
141  }
142
143  NotifyPermissionSet(
144      id, requesting_origin, embedder_origin, callback, persist, allowed);
145}
146
147PermissionQueueController* PermissionContextBase::GetQueueController() {
148  return permission_queue_controller_.get();
149}
150
151void PermissionContextBase::NotifyPermissionSet(
152    const PermissionRequestID& id,
153    const GURL& requesting_origin,
154    const GURL& embedder_origin,
155    const BrowserPermissionCallback& callback,
156    bool persist,
157    bool allowed) {
158  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
159  if (persist)
160    UpdateContentSetting(requesting_origin, embedder_origin, allowed);
161
162  UpdateTabContext(id, requesting_origin, allowed);
163  callback.Run(allowed);
164}
165
166void PermissionContextBase::CleanUpBubble(const PermissionRequestID& id) {
167  size_t success = pending_bubbles_.erase(id.ToString());
168  DCHECK(success == 1) << "Missing request " << id.ToString();
169}
170
171void PermissionContextBase::UpdateContentSetting(
172    const GURL& requesting_origin,
173    const GURL& embedder_origin,
174    bool allowed) {
175  DCHECK_EQ(requesting_origin, requesting_origin.GetOrigin());
176  DCHECK_EQ(embedder_origin, embedder_origin.GetOrigin());
177  ContentSetting content_setting =
178      allowed ? CONTENT_SETTING_ALLOW : CONTENT_SETTING_BLOCK;
179  profile_->GetHostContentSettingsMap()->SetContentSetting(
180      ContentSettingsPattern::FromURLNoWildcard(requesting_origin),
181      ContentSettingsPattern::FromURLNoWildcard(embedder_origin),
182      permission_type_,
183      std::string(),
184      content_setting);
185}
186