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