Upstream version 5.34.92.0
[platform/framework/web/crosswalk.git] / src / chrome / browser / extensions / api / permissions / permissions_api.cc
1 // Copyright (c) 2012 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/extensions/api/permissions/permissions_api.h"
6
7 #include "base/memory/scoped_ptr.h"
8 #include "chrome/browser/chrome_notification_types.h"
9 #include "chrome/browser/extensions/api/permissions/permissions_api_helpers.h"
10 #include "chrome/browser/extensions/permissions_updater.h"
11 #include "chrome/browser/profiles/profile.h"
12 #include "chrome/common/extensions/api/permissions.h"
13 #include "extensions/browser/extension_prefs.h"
14 #include "extensions/common/error_utils.h"
15 #include "extensions/common/extension.h"
16 #include "extensions/common/permissions/permission_message_provider.h"
17 #include "extensions/common/permissions/permissions_data.h"
18 #include "extensions/common/permissions/permissions_info.h"
19 #include "extensions/common/url_pattern_set.h"
20 #include "url/gurl.h"
21
22 namespace extensions {
23
24 using api::permissions::Permissions;
25
26 namespace Contains = api::permissions::Contains;
27 namespace GetAll = api::permissions::GetAll;
28 namespace Remove = api::permissions::Remove;
29 namespace Request  = api::permissions::Request;
30 namespace helpers = permissions_api_helpers;
31
32 namespace {
33
34 const char kCantRemoveRequiredPermissionsError[] =
35     "You cannot remove required permissions.";
36 const char kNotInOptionalPermissionsError[] =
37     "Optional permissions must be listed in extension manifest.";
38 const char kNotWhitelistedError[] =
39     "The optional permissions API does not support '*'.";
40 const char kUserGestureRequiredError[] =
41     "This function must be called during a user gesture";
42
43 enum AutoConfirmForTest {
44   DO_NOT_SKIP = 0,
45   PROCEED,
46   ABORT
47 };
48 AutoConfirmForTest auto_confirm_for_tests = DO_NOT_SKIP;
49 bool ignore_user_gesture_for_tests = false;
50
51 }  // namespace
52
53 bool PermissionsContainsFunction::RunImpl() {
54   scoped_ptr<Contains::Params> params(Contains::Params::Create(*args_));
55   EXTENSION_FUNCTION_VALIDATE(params);
56
57   scoped_refptr<PermissionSet> permissions = helpers::UnpackPermissionSet(
58       params->permissions,
59       ExtensionPrefs::Get(GetProfile())->AllowFileAccess(extension_->id()),
60       &error_);
61   if (!permissions.get())
62     return false;
63
64   results_ = Contains::Results::Create(
65       GetExtension()->GetActivePermissions()->Contains(*permissions.get()));
66   return true;
67 }
68
69 bool PermissionsGetAllFunction::RunImpl() {
70   scoped_ptr<Permissions> permissions =
71       helpers::PackPermissionSet(GetExtension()->GetActivePermissions().get());
72   results_ = GetAll::Results::Create(*permissions);
73   return true;
74 }
75
76 bool PermissionsRemoveFunction::RunImpl() {
77   scoped_ptr<Remove::Params> params(Remove::Params::Create(*args_));
78   EXTENSION_FUNCTION_VALIDATE(params);
79
80   scoped_refptr<PermissionSet> permissions = helpers::UnpackPermissionSet(
81       params->permissions,
82       ExtensionPrefs::Get(GetProfile())->AllowFileAccess(extension_->id()),
83       &error_);
84   if (!permissions.get())
85     return false;
86
87   const Extension* extension = GetExtension();
88
89   // Make sure they're only trying to remove permissions supported by this API.
90   APIPermissionSet apis = permissions->apis();
91   for (APIPermissionSet::const_iterator i = apis.begin();
92        i != apis.end(); ++i) {
93     if (!i->info()->supports_optional()) {
94       error_ = ErrorUtils::FormatErrorMessage(
95           kNotWhitelistedError, i->name());
96       return false;
97     }
98   }
99
100   // Make sure we don't remove any required pemissions.
101   const PermissionSet* required =
102       PermissionsData::GetRequiredPermissions(extension);
103   scoped_refptr<PermissionSet> intersection(
104       PermissionSet::CreateIntersection(permissions.get(), required));
105   if (!intersection->IsEmpty()) {
106     error_ = kCantRemoveRequiredPermissionsError;
107     return false;
108   }
109
110   PermissionsUpdater(GetProfile())
111       .RemovePermissions(extension, permissions.get());
112   results_ = Remove::Results::Create(true);
113   return true;
114 }
115
116 // static
117 void PermissionsRequestFunction::SetAutoConfirmForTests(bool should_proceed) {
118   auto_confirm_for_tests = should_proceed ? PROCEED : ABORT;
119 }
120
121 // static
122 void PermissionsRequestFunction::SetIgnoreUserGestureForTests(
123     bool ignore) {
124   ignore_user_gesture_for_tests = ignore;
125 }
126
127 PermissionsRequestFunction::PermissionsRequestFunction() {}
128
129 void PermissionsRequestFunction::InstallUIProceed() {
130   PermissionsUpdater perms_updater(GetProfile());
131   perms_updater.AddPermissions(GetExtension(), requested_permissions_.get());
132
133   results_ = Request::Results::Create(true);
134   SendResponse(true);
135
136   Release();  // Balanced in RunImpl().
137 }
138
139 void PermissionsRequestFunction::InstallUIAbort(bool user_initiated) {
140   SendResponse(true);
141
142   Release();  // Balanced in RunImpl().
143 }
144
145 PermissionsRequestFunction::~PermissionsRequestFunction() {}
146
147 bool PermissionsRequestFunction::RunImpl() {
148   results_ = Request::Results::Create(false);
149
150   if (!user_gesture() &&
151       !ignore_user_gesture_for_tests &&
152       extension_->location() != Manifest::COMPONENT) {
153     error_ = kUserGestureRequiredError;
154     return false;
155   }
156
157   scoped_ptr<Request::Params> params(Request::Params::Create(*args_));
158   EXTENSION_FUNCTION_VALIDATE(params);
159
160   requested_permissions_ = helpers::UnpackPermissionSet(
161       params->permissions,
162       ExtensionPrefs::Get(GetProfile())->AllowFileAccess(extension_->id()),
163       &error_);
164   if (!requested_permissions_.get())
165     return false;
166
167   // Make sure they're only requesting permissions supported by this API.
168   APIPermissionSet apis = requested_permissions_->apis();
169   for (APIPermissionSet::const_iterator i = apis.begin();
170        i != apis.end(); ++i) {
171     if (!i->info()->supports_optional()) {
172       error_ = ErrorUtils::FormatErrorMessage(
173           kNotWhitelistedError, i->name());
174       return false;
175     }
176   }
177
178   // The requested permissions must be defined as optional in the manifest.
179   if (!PermissionsData::GetOptionalPermissions(GetExtension())
180           ->Contains(*requested_permissions_.get())) {
181     error_ = kNotInOptionalPermissionsError;
182     return false;
183   }
184
185   // We don't need to prompt the user if the requested permissions are a subset
186   // of the granted permissions set.
187   scoped_refptr<const PermissionSet> granted = ExtensionPrefs::Get(
188       GetProfile())->GetGrantedPermissions(GetExtension()->id());
189   if (granted.get() && granted->Contains(*requested_permissions_.get())) {
190     PermissionsUpdater perms_updater(GetProfile());
191     perms_updater.AddPermissions(GetExtension(), requested_permissions_.get());
192     results_ = Request::Results::Create(true);
193     SendResponse(true);
194     return true;
195   }
196
197   // Filter out the granted permissions so we only prompt for new ones.
198   requested_permissions_ = PermissionSet::CreateDifference(
199       requested_permissions_.get(), granted.get());
200
201   AddRef();  // Balanced in InstallUIProceed() / InstallUIAbort().
202
203   // We don't need to show the prompt if there are no new warnings, or if
204   // we're skipping the confirmation UI. All extension types but INTERNAL
205   // are allowed to silently increase their permission level.
206   bool has_no_warnings =
207       PermissionMessageProvider::Get()->GetWarningMessages(
208           requested_permissions_, GetExtension()->GetType()).empty();
209   if (auto_confirm_for_tests == PROCEED || has_no_warnings ||
210       extension_->location() == Manifest::COMPONENT) {
211     InstallUIProceed();
212   } else if (auto_confirm_for_tests == ABORT) {
213     // Pretend the user clicked cancel.
214     InstallUIAbort(true);
215   } else {
216     CHECK_EQ(DO_NOT_SKIP, auto_confirm_for_tests);
217     install_ui_.reset(new ExtensionInstallPrompt(GetAssociatedWebContents()));
218     install_ui_->ConfirmPermissions(
219         this, GetExtension(), requested_permissions_.get());
220   }
221
222   return true;
223 }
224
225 }  // namespace extensions