Commit 4db65f95 authored by akuegel@chromium.org's avatar akuegel@chromium.org

Add permission request creator class.

BUG=372381

Review URL: https://codereview.chromium.org/288913003

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@271665 0039d316-1c4b-4281-b951-d872f2087c98
parent cd8fd37f
......@@ -19,10 +19,11 @@
#include "chrome/browser/managed_mode/managed_user_registration_utility.h"
#include "chrome/browser/managed_mode/managed_user_settings_service.h"
#include "chrome/browser/managed_mode/managed_user_settings_service_factory.h"
#include "chrome/browser/managed_mode/managed_user_shared_settings_service.h"
#include "chrome/browser/managed_mode/managed_user_shared_settings_service_factory.h"
#include "chrome/browser/managed_mode/managed_user_sync_service.h"
#include "chrome/browser/managed_mode/managed_user_sync_service_factory.h"
#include "chrome/browser/managed_mode/permission_request_creator_apiary.h"
#include "chrome/browser/managed_mode/permission_request_creator_sync.h"
#include "chrome/browser/managed_mode/supervised_user_pref_mapping_service.h"
#include "chrome/browser/managed_mode/supervised_user_pref_mapping_service_factory.h"
#include "chrome/browser/profiles/profile.h"
......@@ -61,16 +62,6 @@ using base::DictionaryValue;
using base::UserMetricsAction;
using content::BrowserThread;
const char kManagedUserAccessRequestKeyPrefix[] =
"X-ManagedUser-AccessRequests";
const char kManagedUserAccessRequestTime[] = "timestamp";
const char kManagedUserName[] = "name";
// Key for the notification setting of the custodian. This is a shared setting
// so we can include the setting in the access request data that is used to
// trigger notifications.
const char kNotificationSetting[] = "custodian-notification-setting";
ManagedUserService::URLFilterContext::URLFilterContext()
: ui_url_filter_(new ManagedModeURLFilter),
io_url_filter_(new ManagedModeURLFilter) {}
......@@ -140,6 +131,7 @@ ManagedUserService::ManagedUserService(Profile* profile)
is_profile_active_(false),
elevated_for_testing_(false),
did_shutdown_(false),
waiting_for_permissions_(false),
weak_ptr_factory_(this) {
}
......@@ -444,6 +436,9 @@ void ManagedUserService::UpdateSiteLists() {
}
bool ManagedUserService::AccessRequestsEnabled() {
if (waiting_for_permissions_)
return false;
ProfileSyncService* service =
ProfileSyncServiceFactory::GetForProfile(profile_);
GoogleServiceAuthError::State state = service->GetAuthError().state();
......@@ -453,6 +448,13 @@ bool ManagedUserService::AccessRequestsEnabled() {
state == GoogleServiceAuthError::SERVICE_UNAVAILABLE);
}
void ManagedUserService::OnPermissionRequestIssued() {
waiting_for_permissions_ = false;
// TODO(akuegel): Figure out how to show the result of issuing the permission
// request in the UI. Currently, we assume the permission request was created
// successfully.
}
void ManagedUserService::AddAccessRequest(const GURL& url) {
// Normalize the URL.
GURL normalized_url = ManagedModeURLFilter::Normalize(url);
......@@ -460,35 +462,11 @@ void ManagedUserService::AddAccessRequest(const GURL& url) {
// Escape the URL.
std::string output(net::EscapeQueryParamValue(normalized_url.spec(), true));
// Add the prefix.
std::string key = ManagedUserSettingsService::MakeSplitSettingKey(
kManagedUserAccessRequestKeyPrefix, output);
scoped_ptr<base::DictionaryValue> dict(new base::DictionaryValue);
// TODO(sergiu): Use sane time here when it's ready.
dict->SetDouble(kManagedUserAccessRequestTime, base::Time::Now().ToJsTime());
dict->SetString(kManagedUserName,
profile_->GetPrefs()->GetString(prefs::kProfileName));
// Copy the notification setting of the custodian.
std::string managed_user_id =
profile_->GetPrefs()->GetString(prefs::kManagedUserId);
const base::Value* value =
ManagedUserSharedSettingsServiceFactory::GetForBrowserContext(profile_)
->GetValue(managed_user_id, kNotificationSetting);
bool notifications_enabled = false;
if (CommandLine::ForCurrentProcess()->HasSwitch(
switches::kEnableAccessRequestNotifications)) {
notifications_enabled = true;
} else if (value) {
bool success = value->GetAsBoolean(&notifications_enabled);
DCHECK(success);
}
dict->SetBoolean(kNotificationSetting, notifications_enabled);
GetSettingsService()->UploadItem(key, dict.PassAs<base::Value>());
waiting_for_permissions_ = true;
permissions_creator_->CreatePermissionRequest(
output,
base::Bind(&ManagedUserService::OnPermissionRequestIssued,
weak_ptr_factory_.GetWeakPtr()));
}
ManagedUserService::ManualBehavior ManagedUserService::GetManualBehaviorForHost(
......@@ -568,6 +546,18 @@ void ManagedUserService::Init() {
ProfileOAuth2TokenService* token_service =
ProfileOAuth2TokenServiceFactory::GetForProfile(profile_);
token_service->LoadCredentials(managed_users::kManagedUserPseudoEmail);
if (CommandLine::ForCurrentProcess()->HasSwitch(
switches::kPermissionRequestApiUrl)) {
permissions_creator_ =
PermissionRequestCreatorApiary::CreateWithProfile(profile_);
} else {
PrefService* pref_service = profile_->GetPrefs();
permissions_creator_.reset(new PermissionRequestCreatorSync(
settings_service,
ManagedUserSharedSettingsServiceFactory::GetForBrowserContext(profile_),
pref_service->GetString(prefs::kProfileName),
pref_service->GetString(prefs::kManagedUserId)));
}
extensions::ExtensionSystem* extension_system =
extensions::ExtensionSystem::Get(profile_);
......
......@@ -28,6 +28,7 @@ class ManagedModeURLFilter;
class ManagedModeSiteList;
class ManagedUserRegistrationUtility;
class ManagedUserSettingsService;
class PermissionRequestCreator;
class Profile;
namespace user_prefs {
......@@ -81,6 +82,8 @@ class ManagedUserService : public KeyedService,
// Whether the user can request access to blocked URLs.
bool AccessRequestsEnabled();
void OnPermissionRequestIssued();
// Adds an access request for the given URL. The requests are stored using
// a prefix followed by a URIEncoded version of the URL. Each entry contains
// a dictionary which currently has the timestamp of the request in it.
......@@ -244,6 +247,12 @@ class ManagedUserService : public KeyedService,
URLFilterContext url_filter_context_;
// Used to create permission requests.
scoped_ptr<PermissionRequestCreator> permissions_creator_;
// True iff we are waiting for a permission request to be issued.
bool waiting_for_permissions_;
base::WeakPtrFactory<ManagedUserService> weak_ptr_factory_;
};
......
// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef CHROME_BROWSER_MANAGED_MODE_PERMISSION_REQUEST_CREATOR_H_
#define CHROME_BROWSER_MANAGED_MODE_PERMISSION_REQUEST_CREATOR_H_
#include <string>
#include "base/callback_forward.h"
class PermissionRequestCreator {
public:
virtual ~PermissionRequestCreator() {}
virtual void CreatePermissionRequest(const std::string& url_requested,
const base::Closure& callback) = 0;
};
#endif // CHROME_BROWSER_MANAGED_MODE_PERMISSION_REQUEST_CREATOR_H_
// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chrome/browser/managed_mode/permission_request_creator_apiary.h"
#include "base/callback.h"
#include "base/command_line.h"
#include "base/json/json_reader.h"
#include "base/json/json_writer.h"
#include "base/logging.h"
#include "base/strings/stringprintf.h"
#include "base/values.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/signin/profile_oauth2_token_service_factory.h"
#include "chrome/browser/signin/signin_manager_factory.h"
#include "chrome/browser/sync/managed_user_signin_manager_wrapper.h"
#include "chrome/common/chrome_switches.h"
#include "components/signin/core/browser/profile_oauth2_token_service.h"
#include "components/signin/core/browser/signin_manager.h"
#include "components/signin/core/browser/signin_manager_base.h"
#include "google_apis/gaia/google_service_auth_error.h"
#include "net/base/load_flags.h"
#include "net/base/net_errors.h"
#include "net/http/http_status_code.h"
#include "net/url_request/url_fetcher.h"
#include "net/url_request/url_request_status.h"
using net::URLFetcher;
const int kNumRetries = 1;
const char kIdKey[] = "id";
const char kNamespace[] = "CHROME";
const char kState[] = "PENDING";
static const char kAuthorizationHeaderFormat[] = "Authorization: Bearer %s";
PermissionRequestCreatorApiary::PermissionRequestCreatorApiary(
OAuth2TokenService* oauth2_token_service,
scoped_ptr<ManagedUserSigninManagerWrapper> signin_wrapper,
net::URLRequestContextGetter* context)
: OAuth2TokenService::Consumer("permissions_creator"),
oauth2_token_service_(oauth2_token_service),
signin_wrapper_(signin_wrapper.Pass()),
context_(context),
access_token_expired_(false) {}
PermissionRequestCreatorApiary::~PermissionRequestCreatorApiary() {}
// static
scoped_ptr<PermissionRequestCreator>
PermissionRequestCreatorApiary::CreateWithProfile(Profile* profile) {
ProfileOAuth2TokenService* token_service =
ProfileOAuth2TokenServiceFactory::GetForProfile(profile);
SigninManagerBase* signin = SigninManagerFactory::GetForProfile(profile);
scoped_ptr<ManagedUserSigninManagerWrapper> signin_wrapper(
new ManagedUserSigninManagerWrapper(profile, signin));
scoped_ptr<PermissionRequestCreator> creator(
new PermissionRequestCreatorApiary(
token_service, signin_wrapper.Pass(), profile->GetRequestContext()));
return creator.Pass();
}
void PermissionRequestCreatorApiary::CreatePermissionRequest(
const std::string& url_requested,
const base::Closure& callback) {
url_requested_ = url_requested;
callback_ = callback;
StartFetching();
}
void PermissionRequestCreatorApiary::StartFetching() {
OAuth2TokenService::ScopeSet scopes;
scopes.insert(signin_wrapper_->GetSyncScopeToUse());
access_token_request_ = oauth2_token_service_->StartRequest(
signin_wrapper_->GetAccountIdToUse(), scopes, this);
}
void PermissionRequestCreatorApiary::OnGetTokenSuccess(
const OAuth2TokenService::Request* request,
const std::string& access_token,
const base::Time& expiration_time) {
DCHECK_EQ(access_token_request_.get(), request);
access_token_ = access_token;
GURL url(CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
switches::kPermissionRequestApiUrl));
const int id = 0;
url_fetcher_.reset(URLFetcher::Create(id, url, URLFetcher::POST, this));
url_fetcher_->SetRequestContext(context_);
url_fetcher_->SetLoadFlags(net::LOAD_DO_NOT_SEND_COOKIES |
net::LOAD_DO_NOT_SAVE_COOKIES);
url_fetcher_->SetAutomaticallyRetryOnNetworkChanges(kNumRetries);
url_fetcher_->AddExtraRequestHeader(
base::StringPrintf(kAuthorizationHeaderFormat, access_token.c_str()));
base::DictionaryValue dict;
dict.SetStringWithoutPathExpansion("namespace", kNamespace);
dict.SetStringWithoutPathExpansion("objectRef", url_requested_);
dict.SetStringWithoutPathExpansion("state", kState);
std::string body;
base::JSONWriter::Write(&dict, &body);
url_fetcher_->SetUploadData("application/json", body);
url_fetcher_->Start();
}
void PermissionRequestCreatorApiary::OnGetTokenFailure(
const OAuth2TokenService::Request* request,
const GoogleServiceAuthError& error) {
DCHECK_EQ(access_token_request_.get(), request);
callback_.Run();
callback_.Reset();
}
void PermissionRequestCreatorApiary::OnURLFetchComplete(
const URLFetcher* source) {
const net::URLRequestStatus& status = source->GetStatus();
if (!status.is_success()) {
DispatchNetworkError(status.error());
return;
}
int response_code = source->GetResponseCode();
if (response_code == net::HTTP_UNAUTHORIZED && !access_token_expired_) {
access_token_expired_ = true;
OAuth2TokenService::ScopeSet scopes;
scopes.insert(signin_wrapper_->GetSyncScopeToUse());
oauth2_token_service_->InvalidateToken(
signin_wrapper_->GetAccountIdToUse(), scopes, access_token_);
StartFetching();
return;
}
if (response_code != net::HTTP_OK) {
DLOG(WARNING) << "HTTP error " << response_code;
DispatchGoogleServiceAuthError(
GoogleServiceAuthError(GoogleServiceAuthError::CONNECTION_FAILED));
return;
}
std::string response_body;
source->GetResponseAsString(&response_body);
scoped_ptr<base::Value> value(base::JSONReader::Read(response_body));
base::DictionaryValue* dict = NULL;
if (!value || !value->GetAsDictionary(&dict)) {
DispatchNetworkError(net::ERR_INVALID_RESPONSE);
return;
}
std::string id;
if (!dict->GetString(kIdKey, &id)) {
DispatchNetworkError(net::ERR_INVALID_RESPONSE);
return;
}
callback_.Run();
callback_.Reset();
}
void PermissionRequestCreatorApiary::DispatchNetworkError(int error_code) {
DispatchGoogleServiceAuthError(
GoogleServiceAuthError::FromConnectionError(error_code));
}
void PermissionRequestCreatorApiary::DispatchGoogleServiceAuthError(
const GoogleServiceAuthError& error) {
callback_.Run();
callback_.Reset();
}
// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef CHROME_BROWSER_MANAGED_MODE_PERMISSION_REQUEST_CREATOR_APIARY_H_
#define CHROME_BROWSER_MANAGED_MODE_PERMISSION_REQUEST_CREATOR_APIARY_H_
#include "chrome/browser/managed_mode/permission_request_creator.h"
#include "base/memory/scoped_ptr.h"
#include "google_apis/gaia/oauth2_token_service.h"
#include "net/url_request/url_fetcher_delegate.h"
class ManagedUserSigninManagerWrapper;
class Profile;
namespace base {
class Time;
}
namespace net {
class URLFetcher;
class URLRequestContextGetter;
}
class PermissionRequestCreatorApiary : public PermissionRequestCreator,
public OAuth2TokenService::Consumer,
public net::URLFetcherDelegate {
public:
PermissionRequestCreatorApiary(
OAuth2TokenService* oauth2_token_service,
scoped_ptr<ManagedUserSigninManagerWrapper> signin_wrapper,
net::URLRequestContextGetter* context);
virtual ~PermissionRequestCreatorApiary();
static scoped_ptr<PermissionRequestCreator> CreateWithProfile(
Profile* profile);
// PermissionRequestCreator implementation:
virtual void CreatePermissionRequest(const std::string& url_requested,
const base::Closure& callback) OVERRIDE;
private:
// OAuth2TokenService::Consumer implementation:
virtual void OnGetTokenSuccess(const OAuth2TokenService::Request* request,
const std::string& access_token,
const base::Time& expiration_time) OVERRIDE;
virtual void OnGetTokenFailure(const OAuth2TokenService::Request* request,
const GoogleServiceAuthError& error) OVERRIDE;
// net::URLFetcherDelegate implementation.
virtual void OnURLFetchComplete(const net::URLFetcher* source) OVERRIDE;
// Requests an access token, which is the first thing we need. This is where
// we restart when the returned access token has expired.
void StartFetching();
void DispatchNetworkError(int error_code);
void DispatchGoogleServiceAuthError(const GoogleServiceAuthError& error);
OAuth2TokenService* oauth2_token_service_;
scoped_ptr<ManagedUserSigninManagerWrapper> signin_wrapper_;
base::Closure callback_;
net::URLRequestContextGetter* context_;
std::string url_requested_;
scoped_ptr<OAuth2TokenService::Request> access_token_request_;
std::string access_token_;
bool access_token_expired_;
scoped_ptr<net::URLFetcher> url_fetcher_;
};
#endif // CHROME_BROWSER_MANAGED_MODE_PERMISSION_REQUEST_CREATOR_APIARY_H_
// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chrome/browser/managed_mode/permission_request_creator_sync.h"
#include "base/callback.h"
#include "base/command_line.h"
#include "base/values.h"
#include "chrome/browser/managed_mode/managed_user_settings_service.h"
#include "chrome/browser/managed_mode/managed_user_shared_settings_service.h"
#include "chrome/common/chrome_switches.h"
using base::Time;
const char kManagedUserAccessRequestKeyPrefix[] =
"X-ManagedUser-AccessRequests";
const char kManagedUserAccessRequestTime[] = "timestamp";
const char kManagedUserName[] = "name";
// Key for the notification setting of the custodian. This is a shared setting
// so we can include the setting in the access request data that is used to
// trigger notifications.
const char kNotificationSetting[] = "custodian-notification-setting";
PermissionRequestCreatorSync::PermissionRequestCreatorSync(
ManagedUserSettingsService* settings_service,
ManagedUserSharedSettingsService* shared_settings_service,
const std::string& name,
const std::string& managed_user_id)
: settings_service_(settings_service),
shared_settings_service_(shared_settings_service),
name_(name),
managed_user_id_(managed_user_id) {
}
PermissionRequestCreatorSync::~PermissionRequestCreatorSync() {}
void PermissionRequestCreatorSync::CreatePermissionRequest(
const std::string& url_requested,
const base::Closure& callback) {
// Add the prefix.
std::string key = ManagedUserSettingsService::MakeSplitSettingKey(
kManagedUserAccessRequestKeyPrefix, url_requested);
scoped_ptr<base::DictionaryValue> dict(new base::DictionaryValue);
// TODO(sergiu): Use sane time here when it's ready.
dict->SetDouble(kManagedUserAccessRequestTime, base::Time::Now().ToJsTime());
dict->SetString(kManagedUserName, name_);
// Copy the notification setting of the custodian.
const base::Value* value = shared_settings_service_->GetValue(
managed_user_id_, kNotificationSetting);
bool notifications_enabled = false;
if (CommandLine::ForCurrentProcess()->HasSwitch(
switches::kEnableAccessRequestNotifications)) {
notifications_enabled = true;
} else if (value) {
bool success = value->GetAsBoolean(&notifications_enabled);
DCHECK(success);
}
dict->SetBoolean(kNotificationSetting, notifications_enabled);
settings_service_->UploadItem(key, dict.PassAs<base::Value>());
callback.Run();
}
// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef CHROME_BROWSER_MANAGED_MODE_PERMISSION_REQUEST_CREATOR_SYNC_H_
#define CHROME_BROWSER_MANAGED_MODE_PERMISSION_REQUEST_CREATOR_SYNC_H_
#include "chrome/browser/managed_mode/permission_request_creator.h"
#include "base/memory/scoped_ptr.h"
class ManagedUserSettingsService;
class ManagedUserSharedSettingsService;
class ManagedUserSigninManagerWrapper;
class PermissionRequestCreatorSync : public PermissionRequestCreator {
public:
PermissionRequestCreatorSync(
ManagedUserSettingsService* settings_service,
ManagedUserSharedSettingsService* shared_settings_service,
const std::string& name,
const std::string& managed_user_id);
virtual ~PermissionRequestCreatorSync();
// PermissionRequestCreator implementation:
virtual void CreatePermissionRequest(const std::string& url_requested,
const base::Closure& callback) OVERRIDE;
private:
ManagedUserSettingsService* settings_service_;
ManagedUserSharedSettingsService* shared_settings_service_;
std::string name_;
std::string managed_user_id_;
};
#endif // CHROME_BROWSER_MANAGED_MODE_PERMISSION_REQUEST_CREATOR_SYNC_H_
......@@ -1046,6 +1046,11 @@
'browser/managed_mode/managed_user_theme.cc',
'browser/managed_mode/managed_user_theme.h',
'browser/managed_mode/managed_users.h',
'browser/managed_mode/permission_request_creator.h',
'browser/managed_mode/permission_request_creator_apiary.cc',
'browser/managed_mode/permission_request_creator_apiary.h',
'browser/managed_mode/permission_request_creator_sync.cc',
'browser/managed_mode/permission_request_creator_sync.h',
'browser/managed_mode/supervised_user_pref_mapping_service.cc',
'browser/managed_mode/supervised_user_pref_mapping_service.h',
'browser/managed_mode/supervised_user_pref_mapping_service_factory.cc',
......
......@@ -982,6 +982,11 @@ const char kParentProfile[] = "parent-profile";
// default interval is used).
const char kPerformanceMonitorGathering[] = "performance-monitor-gathering";
// Development flag for permission request API. This flag is needed until
// the API is finalized.
// TODO(akuegel): Remove when this flag is not needed anymore.
const char kPermissionRequestApiUrl[] = "permission-request-api-url";
// Read previously recorded data from the cache. Only cached data is read.
// See kRecordMode.
const char kPlaybackMode[] = "playback-mode";
......
......@@ -272,6 +272,7 @@ extern const char kPackExtension[];
extern const char kPackExtensionKey[];
extern const char kParentProfile[];
extern const char kPerformanceMonitorGathering[];
extern const char kPermissionRequestApiUrl[];
extern const char kPlaybackMode[];
extern const char kPpapiFlashPath[];
extern const char kPpapiFlashVersion[];
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment