OLD | NEW |
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "chrome/browser/permissions/permission_context_base.h" | 5 #include "chrome/browser/permissions/permission_context_base.h" |
6 | 6 |
7 #include <stddef.h> | 7 #include <stddef.h> |
| 8 |
| 9 #include <queue> |
8 #include <utility> | 10 #include <utility> |
9 | 11 |
| 12 #include "base/location.h" |
10 #include "base/logging.h" | 13 #include "base/logging.h" |
11 #include "base/prefs/pref_service.h" | 14 #include "base/prefs/pref_service.h" |
| 15 #include "base/rand_util.h" |
| 16 #include "base/single_thread_task_runner.h" |
12 #include "base/strings/stringprintf.h" | 17 #include "base/strings/stringprintf.h" |
| 18 #include "base/thread_task_runner_handle.h" |
| 19 #include "base/timer/timer.h" |
13 #include "build/build_config.h" | 20 #include "build/build_config.h" |
14 #include "chrome/browser/content_settings/host_content_settings_map_factory.h" | 21 #include "chrome/browser/content_settings/host_content_settings_map_factory.h" |
15 #include "chrome/browser/permissions/permission_request_id.h" | 22 #include "chrome/browser/permissions/permission_request_id.h" |
16 #include "chrome/browser/permissions/permission_uma_util.h" | 23 #include "chrome/browser/permissions/permission_uma_util.h" |
17 #include "chrome/browser/permissions/permission_util.h" | 24 #include "chrome/browser/permissions/permission_util.h" |
18 #include "chrome/browser/profiles/profile.h" | 25 #include "chrome/browser/profiles/profile.h" |
19 #include "chrome/common/pref_names.h" | 26 #include "chrome/common/pref_names.h" |
| 27 #include "components/content_settings/core/browser/content_settings_info.h" |
| 28 #include "components/content_settings/core/browser/content_settings_registry.h" |
20 #include "components/content_settings/core/browser/host_content_settings_map.h" | 29 #include "components/content_settings/core/browser/host_content_settings_map.h" |
21 #include "components/content_settings/core/browser/website_settings_registry.h" | 30 #include "components/content_settings/core/browser/website_settings_registry.h" |
22 #include "components/variations/variations_associated_data.h" | 31 #include "components/variations/variations_associated_data.h" |
23 #include "content/public/browser/browser_thread.h" | 32 #include "content/public/browser/browser_thread.h" |
24 #include "content/public/browser/render_frame_host.h" | 33 #include "content/public/browser/render_frame_host.h" |
25 #include "content/public/browser/web_contents.h" | 34 #include "content/public/browser/web_contents.h" |
| 35 #include "content/public/browser/web_contents_observer.h" |
| 36 #include "content/public/browser/web_contents_user_data.h" |
26 #include "content/public/common/origin_util.h" | 37 #include "content/public/common/origin_util.h" |
27 | 38 |
28 #if defined(OS_ANDROID) | 39 #if defined(OS_ANDROID) |
29 #include "chrome/browser/permissions/permission_queue_controller.h" | 40 #include "chrome/browser/permissions/permission_queue_controller.h" |
30 #else | 41 #else |
31 #include "chrome/browser/permissions/permission_bubble_request_impl.h" | 42 #include "chrome/browser/permissions/permission_bubble_request_impl.h" |
32 #include "chrome/browser/ui/website_settings/permission_bubble_manager.h" | 43 #include "chrome/browser/ui/website_settings/permission_bubble_manager.h" |
33 #endif | 44 #endif |
34 | 45 |
| 46 namespace { |
| 47 |
| 48 // At most one of these is attached to each WebContents. |
| 49 class VisibilityTimerTabHelper |
| 50 : public content::WebContentsObserver, |
| 51 public content::WebContentsUserData<VisibilityTimerTabHelper> { |
| 52 public: |
| 53 ~VisibilityTimerTabHelper() override {}; |
| 54 |
| 55 // Runs |task| after the WebContents has been visible for a consecutive |
| 56 // duration of at least |visible_delay|. |
| 57 void PostTaskAfterVisibleDelay(const tracked_objects::Location& from_here, |
| 58 const base::Closure& task, |
| 59 base::TimeDelta visible_delay); |
| 60 |
| 61 // WebContentsObserver: |
| 62 void WasShown() override; |
| 63 void WasHidden() override; |
| 64 void WebContentsDestroyed() override; |
| 65 |
| 66 private: |
| 67 friend class content::WebContentsUserData<VisibilityTimerTabHelper>; |
| 68 explicit VisibilityTimerTabHelper(content::WebContents* contents); |
| 69 |
| 70 void RunTask(const base::Closure& task); |
| 71 |
| 72 bool is_visible_; |
| 73 std::queue<scoped_ptr<base::Timer>> task_queue_; |
| 74 |
| 75 DISALLOW_COPY_AND_ASSIGN(VisibilityTimerTabHelper); |
| 76 }; |
| 77 |
| 78 VisibilityTimerTabHelper::VisibilityTimerTabHelper( |
| 79 content::WebContents* contents) |
| 80 : content::WebContentsObserver(contents) { |
| 81 if (!contents->GetMainFrame()) { |
| 82 is_visible_ = false; |
| 83 } else { |
| 84 switch (contents->GetMainFrame()->GetVisibilityState()) { |
| 85 case blink::WebPageVisibilityStateHidden: |
| 86 case blink::WebPageVisibilityStatePrerender: |
| 87 is_visible_ = false; |
| 88 break; |
| 89 case blink::WebPageVisibilityStateVisible: |
| 90 is_visible_ = true; |
| 91 break; |
| 92 } |
| 93 } |
| 94 } |
| 95 |
| 96 void VisibilityTimerTabHelper::PostTaskAfterVisibleDelay( |
| 97 const tracked_objects::Location& from_here, |
| 98 const base::Closure& task, |
| 99 base::TimeDelta visible_delay) { |
| 100 // Safe to use Unretained, as destroying this will destroy task_queue_, hence |
| 101 // cancelling all timers. |
| 102 task_queue_.push(make_scoped_ptr(new base::Timer( |
| 103 from_here, visible_delay, base::Bind(&VisibilityTimerTabHelper::RunTask, |
| 104 base::Unretained(this), task), |
| 105 false /* is_repeating */))); |
| 106 DCHECK(!task_queue_.back()->IsRunning()); |
| 107 if (is_visible_ && task_queue_.size() == 1) |
| 108 task_queue_.front()->Reset(); |
| 109 } |
| 110 |
| 111 void VisibilityTimerTabHelper::WasShown() { |
| 112 if (!is_visible_ && !task_queue_.empty()) |
| 113 task_queue_.front()->Reset(); |
| 114 is_visible_ = true; |
| 115 } |
| 116 |
| 117 void VisibilityTimerTabHelper::WasHidden() { |
| 118 if (is_visible_ && !task_queue_.empty()) |
| 119 task_queue_.front()->Stop(); |
| 120 is_visible_ = false; |
| 121 } |
| 122 |
| 123 void VisibilityTimerTabHelper::WebContentsDestroyed() { |
| 124 // Delete ourselves, to avoid running tasks after WebContents is destroyed. |
| 125 web_contents()->RemoveUserData(UserDataKey()); |
| 126 // |this| has been deleted now. |
| 127 } |
| 128 |
| 129 void VisibilityTimerTabHelper::RunTask(const base::Closure& task) { |
| 130 DCHECK(is_visible_); |
| 131 task.Run(); |
| 132 task_queue_.pop(); |
| 133 if (!task_queue_.empty()) { |
| 134 task_queue_.front()->Reset(); |
| 135 return; |
| 136 } |
| 137 web_contents()->RemoveUserData(UserDataKey()); |
| 138 // |this| has been deleted now. |
| 139 } |
| 140 |
| 141 } // namespace |
| 142 |
| 143 DEFINE_WEB_CONTENTS_USER_DATA_KEY(VisibilityTimerTabHelper); |
| 144 |
35 // static | 145 // static |
36 const char PermissionContextBase::kPermissionsKillSwitchFieldStudy[] = | 146 const char PermissionContextBase::kPermissionsKillSwitchFieldStudy[] = |
37 "PermissionsKillSwitch"; | 147 "PermissionsKillSwitch"; |
38 // static | 148 // static |
39 const char PermissionContextBase::kPermissionsKillSwitchBlockedValue[] = | 149 const char PermissionContextBase::kPermissionsKillSwitchBlockedValue[] = |
40 "blocked"; | 150 "blocked"; |
41 | 151 |
42 PermissionContextBase::PermissionContextBase( | 152 PermissionContextBase::PermissionContextBase( |
43 Profile* profile, | 153 Profile* profile, |
44 const content::PermissionType permission_type, | 154 const content::PermissionType permission_type, |
(...skipping 117 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
162 | 272 |
163 void PermissionContextBase::DecidePermission( | 273 void PermissionContextBase::DecidePermission( |
164 content::WebContents* web_contents, | 274 content::WebContents* web_contents, |
165 const PermissionRequestID& id, | 275 const PermissionRequestID& id, |
166 const GURL& requesting_origin, | 276 const GURL& requesting_origin, |
167 const GURL& embedding_origin, | 277 const GURL& embedding_origin, |
168 bool user_gesture, | 278 bool user_gesture, |
169 const BrowserPermissionCallback& callback) { | 279 const BrowserPermissionCallback& callback) { |
170 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); | 280 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); |
171 | 281 |
| 282 // Some permissions are always denied in incognito. To prevent sites from |
| 283 // using these to detect whether incognito mode is active, we deny after a |
| 284 // random time delay, to simulate a user clicking a bubble/infobar. |
| 285 if (profile()->IsOffTheRecord()) { |
| 286 const content_settings::ContentSettingsInfo* info = |
| 287 content_settings::ContentSettingsRegistry::GetInstance()->Get( |
| 288 content_settings_type_); |
| 289 if (info && |
| 290 info->incognito_behavior() == content_settings::ContentSettingsInfo:: |
| 291 DENY_IN_INCOGNITO_AFTER_DELAY) { |
| 292 // Random number of seconds in the range [1.0, 2.0). |
| 293 double delay_seconds = 1.0 + 1.0 * base::RandDouble(); |
| 294 VisibilityTimerTabHelper::CreateForWebContents(web_contents); |
| 295 VisibilityTimerTabHelper::FromWebContents(web_contents) |
| 296 ->PostTaskAfterVisibleDelay( |
| 297 FROM_HERE, |
| 298 base::Bind(&PermissionContextBase::NotifyPermissionSet, |
| 299 weak_factory_.GetWeakPtr(), id, requesting_origin, |
| 300 embedding_origin, callback, true /* persist */, |
| 301 CONTENT_SETTING_BLOCK), |
| 302 base::TimeDelta::FromSecondsD(delay_seconds)); |
| 303 return; |
| 304 } |
| 305 } |
| 306 |
172 #if !defined(OS_ANDROID) | 307 #if !defined(OS_ANDROID) |
173 PermissionBubbleManager* bubble_manager = | 308 PermissionBubbleManager* bubble_manager = |
174 PermissionBubbleManager::FromWebContents(web_contents); | 309 PermissionBubbleManager::FromWebContents(web_contents); |
175 // TODO(felt): sometimes |bubble_manager| is null. This check is meant to | 310 // TODO(felt): sometimes |bubble_manager| is null. This check is meant to |
176 // prevent crashes. See crbug.com/457091. | 311 // prevent crashes. See crbug.com/457091. |
177 if (!bubble_manager) | 312 if (!bubble_manager) |
178 return; | 313 return; |
179 scoped_ptr<PermissionBubbleRequest> request_ptr( | 314 scoped_ptr<PermissionBubbleRequest> request_ptr( |
180 new PermissionBubbleRequestImpl( | 315 new PermissionBubbleRequestImpl( |
181 requesting_origin, user_gesture, permission_type_, | 316 requesting_origin, user_gesture, permission_type_, |
(...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
285 content_settings_type_, std::string(), content_setting); | 420 content_settings_type_, std::string(), content_setting); |
286 } | 421 } |
287 | 422 |
288 bool PermissionContextBase::IsPermissionKillSwitchOn() const { | 423 bool PermissionContextBase::IsPermissionKillSwitchOn() const { |
289 const std::string param = variations::GetVariationParamValue( | 424 const std::string param = variations::GetVariationParamValue( |
290 kPermissionsKillSwitchFieldStudy, | 425 kPermissionsKillSwitchFieldStudy, |
291 PermissionUtil::GetPermissionString(permission_type_)); | 426 PermissionUtil::GetPermissionString(permission_type_)); |
292 | 427 |
293 return param == kPermissionsKillSwitchBlockedValue; | 428 return param == kPermissionsKillSwitchBlockedValue; |
294 } | 429 } |
OLD | NEW |