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