Home | History | Annotate | Download | only in content_settings
      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/tab_specific_content_settings.h"
     14 #include "chrome/browser/profiles/profile.h"
     15 #include "chrome/browser/ui/website_settings/permission_bubble_manager.h"
     16 #include "chrome/common/pref_names.h"
     17 #include "components/content_settings/core/common/permission_request_id.h"
     18 #include "content/public/browser/browser_thread.h"
     19 #include "content/public/browser/web_contents.h"
     20 
     21 PermissionContextBase::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 
     31 PermissionContextBase::~PermissionContextBase() {
     32   DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
     33 }
     34 
     35 void 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 
     51 void 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 
    122 void 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 
    147 PermissionQueueController* PermissionContextBase::GetQueueController() {
    148   return permission_queue_controller_.get();
    149 }
    150 
    151 void 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 
    166 void PermissionContextBase::CleanUpBubble(const PermissionRequestID& id) {
    167   size_t success = pending_bubbles_.erase(id.ToString());
    168   DCHECK(success == 1) << "Missing request " << id.ToString();
    169 }
    170 
    171 void 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