Upstream version 5.34.104.0
[platform/framework/web/crosswalk.git] / src / chrome / browser / media / protected_media_identifier_permission_context.cc
1 // Copyright 2013 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/media/protected_media_identifier_permission_context.h"
6
7 #include <functional>
8 #include <string>
9 #include <vector>
10
11 #include "base/bind.h"
12 #include "base/strings/utf_string_conversions.h"
13 #include "chrome/browser/content_settings/host_content_settings_map.h"
14 #include "chrome/browser/content_settings/permission_request_id.h"
15 #include "chrome/browser/content_settings/tab_specific_content_settings.h"
16 #include "chrome/browser/extensions/extension_service.h"
17 #include "chrome/browser/extensions/suggest_permission_util.h"
18 #include "chrome/browser/profiles/profile.h"
19 #include "chrome/browser/tab_contents/tab_util.h"
20 #include "chrome/common/pref_names.h"
21 #include "content/public/browser/browser_thread.h"
22 #include "content/public/browser/render_view_host.h"
23 #include "content/public/browser/web_contents.h"
24 #include "extensions/browser/extension_system.h"
25 #include "extensions/browser/view_type_utils.h"
26 #include "extensions/common/extension.h"
27
28 using extensions::APIPermission;
29
30 ProtectedMediaIdentifierPermissionContext::
31     ProtectedMediaIdentifierPermissionContext(Profile* profile)
32     : profile_(profile), shutting_down_(false) {}
33
34 ProtectedMediaIdentifierPermissionContext::
35     ~ProtectedMediaIdentifierPermissionContext() {
36   // ProtectedMediaIdentifierPermissionContext may be destroyed on either
37   // the UI thread or the IO thread, but the PermissionQueueController must have
38   // been destroyed on the UI thread.
39   DCHECK(!permission_queue_controller_.get());
40 }
41
42 void ProtectedMediaIdentifierPermissionContext::
43     RequestProtectedMediaIdentifierPermission(
44         int render_process_id,
45         int render_view_id,
46         int bridge_id,
47         int group_id,
48         const GURL& requesting_frame,
49         const base::Callback<void(bool)>& callback) {
50   DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
51   if (shutting_down_)
52     return;
53
54   content::WebContents* web_contents =
55       tab_util::GetWebContentsByID(render_process_id, render_view_id);
56   const PermissionRequestID id(
57       render_process_id, render_view_id, bridge_id, group_id);
58
59   if (extensions::GetViewType(web_contents) !=
60       extensions::VIEW_TYPE_TAB_CONTENTS) {
61     // The tab may have gone away, or the request may not be from a tab at all.
62     LOG(WARNING)
63         << "Attempt to use protected media identifier in tabless renderer: "
64         << id.ToString()
65         << " (can't prompt user without a visible tab)";
66     NotifyPermissionSet(id, requesting_frame, callback, false);
67     return;
68   }
69
70   GURL embedder = web_contents->GetLastCommittedURL();
71   if (!requesting_frame.is_valid() || !embedder.is_valid()) {
72     LOG(WARNING)
73         << "Attempt to use protected media identifier from an invalid URL: "
74         << requesting_frame << "," << embedder
75         << " (proteced media identifier is not supported in popups)";
76     NotifyPermissionSet(id, requesting_frame, callback, false);
77     return;
78   }
79
80   content::RenderViewHost* rvh = web_contents->GetRenderViewHost();
81   DecidePermission(id, requesting_frame, embedder, rvh, callback);
82 }
83
84 void ProtectedMediaIdentifierPermissionContext::
85     CancelProtectedMediaIdentifierPermissionRequests(int group_id) {
86   CancelPendingInfobarRequests(group_id);
87 }
88
89 void ProtectedMediaIdentifierPermissionContext::DecidePermission(
90     const PermissionRequestID& id,
91     const GURL& requesting_frame,
92     const GURL& embedder,
93     content::RenderViewHost* rvh,
94     const base::Callback<void(bool)>& callback) {
95   DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
96
97 #if defined(OS_ANDROID)
98   // Check if the protected media identifier master switch is disabled.
99   if (!profile()->GetPrefs()->GetBoolean(
100         prefs::kProtectedMediaIdentifierEnabled)) {
101     PermissionDecided(id, requesting_frame, embedder, callback, false);
102     return;
103   }
104 #endif
105
106   ContentSetting content_setting =
107      profile_->GetHostContentSettingsMap()->GetContentSetting(
108           requesting_frame,
109           embedder,
110           CONTENT_SETTINGS_TYPE_PROTECTED_MEDIA_IDENTIFIER,
111           std::string());
112   switch (content_setting) {
113     case CONTENT_SETTING_BLOCK:
114       PermissionDecided(id, requesting_frame, embedder, callback, false);
115       break;
116     case CONTENT_SETTING_ALLOW:
117       PermissionDecided(id, requesting_frame, embedder, callback, true);
118       break;
119     case CONTENT_SETTING_ASK:
120       QueueController()->CreateInfoBarRequest(
121           id,
122           requesting_frame,
123           embedder,
124           base::Bind(&ProtectedMediaIdentifierPermissionContext::
125                           NotifyPermissionSet,
126                      base::Unretained(this),
127                      id,
128                      requesting_frame,
129                      callback));
130       rvh->DisableFullscreenEncryptedMediaPlayback();
131       break;
132     default:
133       NOTREACHED();
134   }
135 }
136
137 void ProtectedMediaIdentifierPermissionContext::ShutdownOnUIThread() {
138   DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
139   permission_queue_controller_.reset();
140   shutting_down_ = true;
141 }
142
143 void ProtectedMediaIdentifierPermissionContext::PermissionDecided(
144     const PermissionRequestID& id,
145     const GURL& requesting_frame,
146     const GURL& embedder,
147     const base::Callback<void(bool)>& callback,
148     bool allowed) {
149   NotifyPermissionSet(id, requesting_frame, callback, allowed);
150 }
151
152 void ProtectedMediaIdentifierPermissionContext::NotifyPermissionSet(
153     const PermissionRequestID& id,
154     const GURL& requesting_frame,
155     const base::Callback<void(bool)>& callback,
156     bool allowed) {
157   DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
158
159   // WebContents may have gone away.
160   TabSpecificContentSettings* content_settings =
161       TabSpecificContentSettings::Get(id.render_process_id(),
162                                       id.render_view_id());
163   if (content_settings) {
164     content_settings->OnProtectedMediaIdentifierPermissionSet(
165         requesting_frame.GetOrigin(), allowed);
166   }
167
168   callback.Run(allowed);
169 }
170
171 PermissionQueueController*
172     ProtectedMediaIdentifierPermissionContext::QueueController() {
173   DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
174   DCHECK(!shutting_down_);
175   if (!permission_queue_controller_)
176     permission_queue_controller_.reset(CreateQueueController());
177   return permission_queue_controller_.get();
178 }
179
180 PermissionQueueController*
181     ProtectedMediaIdentifierPermissionContext::CreateQueueController() {
182   DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
183   return new PermissionQueueController(
184       profile(), CONTENT_SETTINGS_TYPE_PROTECTED_MEDIA_IDENTIFIER);
185 }
186
187 void
188 ProtectedMediaIdentifierPermissionContext::CancelPendingInfobarRequests(
189     int group_id) {
190   if (!content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)) {
191     content::BrowserThread::PostTask(
192         content::BrowserThread::UI,
193         FROM_HERE,
194         base::Bind(&ProtectedMediaIdentifierPermissionContext::
195                         CancelPendingInfobarRequests,
196                    this,
197                    group_id));
198     return;
199   }
200   DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
201   if (shutting_down_)
202     return;
203   QueueController()->CancelInfoBarRequests(group_id);
204 }