forked from chromium/chromium
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add check_android_management device management request/response. BUG=602612 Review-Url: https://codereview.chromium.org/1892093002 Cr-Commit-Position: refs/heads/master@{#390620}
- Loading branch information
pbond
authored and
Commit bot
committed
Apr 29, 2016
1 parent
0a7f020
commit bcd3a5f
Showing
10 changed files
with
353 additions
and
1 deletion.
There are no files selected for viewing
116 changes: 116 additions & 0 deletions
116
chrome/browser/chromeos/policy/android_management_client.cc
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,116 @@ | ||
// Copyright (c) 2016 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/chromeos/policy/android_management_client.h" | ||
|
||
#include "base/bind.h" | ||
#include "base/bind_helpers.h" | ||
#include "base/guid.h" | ||
#include "base/logging.h" | ||
#include "components/policy/core/common/cloud/device_management_service.h" | ||
#include "google_apis/gaia/gaia_constants.h" | ||
#include "google_apis/gaia/google_service_auth_error.h" | ||
#include "policy/proto/device_management_backend.pb.h" | ||
|
||
namespace em = enterprise_management; | ||
|
||
namespace policy { | ||
|
||
AndroidManagementClient::AndroidManagementClient( | ||
DeviceManagementService* device_management_service, | ||
scoped_refptr<net::URLRequestContextGetter> request_context, | ||
const std::string& account_id, | ||
OAuth2TokenService* token_service) | ||
: OAuth2TokenService::Consumer("android_management_client"), | ||
device_management_service_(device_management_service), | ||
request_context_(request_context), | ||
account_id_(account_id), | ||
token_service_(token_service), | ||
weak_ptr_factory_(this) {} | ||
|
||
AndroidManagementClient::~AndroidManagementClient() {} | ||
|
||
void AndroidManagementClient::StartCheckAndroidManagement( | ||
const StatusCallback& callback) { | ||
DCHECK(device_management_service_); | ||
DCHECK(callback_.is_null()); | ||
|
||
callback_ = callback; | ||
RequestAccessToken(); | ||
} | ||
|
||
void AndroidManagementClient::OnGetTokenSuccess( | ||
const OAuth2TokenService::Request* request, | ||
const std::string& access_token, | ||
const base::Time& expiration_time) { | ||
DCHECK_EQ(token_request_.get(), request); | ||
token_request_.reset(); | ||
|
||
CheckAndroidManagement(access_token); | ||
} | ||
|
||
void AndroidManagementClient::OnGetTokenFailure( | ||
const OAuth2TokenService::Request* request, | ||
const GoogleServiceAuthError& error) { | ||
DCHECK_EQ(token_request_.get(), request); | ||
token_request_.reset(); | ||
LOG(ERROR) << "Token request failed: " << error.ToString(); | ||
|
||
callback_.Run(RESULT_ERROR); | ||
callback_.Reset(); | ||
} | ||
|
||
void AndroidManagementClient::RequestAccessToken() { | ||
DCHECK(!token_request_); | ||
// The user must be signed in already. | ||
DCHECK(token_service_->RefreshTokenIsAvailable(account_id_)); | ||
|
||
OAuth2TokenService::ScopeSet scopes; | ||
scopes.insert(GaiaConstants::kDeviceManagementServiceOAuth); | ||
scopes.insert(GaiaConstants::kOAuthWrapBridgeUserInfoScope); | ||
token_request_ = token_service_->StartRequest(account_id_, scopes, this); | ||
} | ||
|
||
void AndroidManagementClient::CheckAndroidManagement( | ||
const std::string& access_token) { | ||
request_job_.reset(device_management_service_->CreateJob( | ||
DeviceManagementRequestJob::TYPE_ANDROID_MANAGEMENT_CHECK, | ||
request_context_.get())); | ||
request_job_->SetOAuthToken(access_token); | ||
request_job_->SetClientID(base::GenerateGUID()); | ||
request_job_->GetRequest()->mutable_check_android_management_request(); | ||
|
||
request_job_->Start( | ||
base::Bind(&AndroidManagementClient::OnAndroidManagementChecked, | ||
weak_ptr_factory_.GetWeakPtr())); | ||
} | ||
|
||
void AndroidManagementClient::OnAndroidManagementChecked( | ||
DeviceManagementStatus status, | ||
int net_error, | ||
const em::DeviceManagementResponse& response) { | ||
if (status == DM_STATUS_SUCCESS && | ||
!response.has_check_android_management_response()) { | ||
LOG(WARNING) << "Invalid check android management response."; | ||
status = DM_STATUS_RESPONSE_DECODING_ERROR; | ||
} | ||
|
||
Result result; | ||
switch (status) { | ||
case DM_STATUS_SUCCESS: | ||
result = RESULT_UNMANAGED; | ||
break; | ||
case DM_STATUS_SERVICE_DEVICE_ID_CONFLICT: | ||
result = RESULT_MANAGED; | ||
break; | ||
default: | ||
result = RESULT_ERROR; | ||
} | ||
|
||
request_job_.reset(); | ||
callback_.Run(result); | ||
callback_.Reset(); | ||
} | ||
|
||
} // namespace policy |
100 changes: 100 additions & 0 deletions
100
chrome/browser/chromeos/policy/android_management_client.h
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,100 @@ | ||
// Copyright (c) 2016 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_CHROMEOS_POLICY_ANDROID_MANAGEMENT_CLIENT_H_ | ||
#define CHROME_BROWSER_CHROMEOS_POLICY_ANDROID_MANAGEMENT_CLIENT_H_ | ||
|
||
#include <memory> | ||
#include <string> | ||
|
||
#include "base/callback.h" | ||
#include "base/macros.h" | ||
#include "base/memory/ref_counted.h" | ||
#include "base/memory/weak_ptr.h" | ||
#include "components/policy/core/common/cloud/cloud_policy_constants.h" | ||
#include "google_apis/gaia/oauth2_token_service.h" | ||
#include "net/url_request/url_request_context_getter.h" | ||
|
||
namespace enterprise_management { | ||
class DeviceManagementResponse; | ||
} | ||
|
||
namespace policy { | ||
|
||
class DeviceManagementRequestJob; | ||
class DeviceManagementService; | ||
|
||
// Interacts with the device management service and determines whether Android | ||
// management is enabled for the user or not. Uses the OAuth2TokenService to | ||
// acquire access tokens for the device management. | ||
class AndroidManagementClient : public OAuth2TokenService::Consumer { | ||
public: | ||
// Indicates result of the android management check. | ||
enum Result { | ||
RESULT_MANAGED, // Android management is enabled. | ||
RESULT_UNMANAGED, // Android management is disabled. | ||
RESULT_ERROR, // Received a error. | ||
}; | ||
|
||
// A callback which receives Result status of an operation. | ||
using StatusCallback = base::Callback<void(Result)>; | ||
|
||
AndroidManagementClient( | ||
DeviceManagementService* service, | ||
scoped_refptr<net::URLRequestContextGetter> request_context, | ||
const std::string& account_id, | ||
OAuth2TokenService* token_service); | ||
~AndroidManagementClient() override; | ||
|
||
// Starts sending of check Android management request to DM server, issues | ||
// access token if neccessary. |callback| is called on check Android | ||
// management completion. | ||
void StartCheckAndroidManagement(const StatusCallback& callback); | ||
|
||
// |access_token| is owned by caller and must exist before | ||
// StartCheckAndroidManagement is called for testing. | ||
static void SetAccessTokenForTesting(const char* access_token); | ||
|
||
private: | ||
// OAuth2TokenService::Consumer: | ||
void OnGetTokenSuccess(const OAuth2TokenService::Request* request, | ||
const std::string& access_token, | ||
const base::Time& expiration_time) override; | ||
void OnGetTokenFailure(const OAuth2TokenService::Request* request, | ||
const GoogleServiceAuthError& error) override; | ||
|
||
// Requests an access token. | ||
void RequestAccessToken(); | ||
|
||
// Sends a CheckAndroidManagementRequest to DM server. | ||
void CheckAndroidManagement(const std::string& access_token); | ||
|
||
// Callback for check Android management requests. | ||
void OnAndroidManagementChecked( | ||
DeviceManagementStatus status, | ||
int net_error, | ||
const enterprise_management::DeviceManagementResponse& response); | ||
|
||
// Used to communicate with the device management service. | ||
DeviceManagementService* const device_management_service_; | ||
scoped_refptr<net::URLRequestContextGetter> request_context_; | ||
std::unique_ptr<DeviceManagementRequestJob> request_job_; | ||
|
||
// The account ID that will be used for the access token fetch. | ||
const std::string account_id_; | ||
// The token service used to retrieve the access token. | ||
OAuth2TokenService* const token_service_; | ||
// The OAuth request to receive the access token. | ||
std::unique_ptr<OAuth2TokenService::Request> token_request_; | ||
|
||
StatusCallback callback_; | ||
|
||
base::WeakPtrFactory<AndroidManagementClient> weak_ptr_factory_; | ||
|
||
DISALLOW_COPY_AND_ASSIGN(AndroidManagementClient); | ||
}; | ||
|
||
} // namespace policy | ||
|
||
#endif // CHROME_BROWSER_CHROMEOS_POLICY_ANDROID_MANAGEMENT_CLIENT_H_ |
108 changes: 108 additions & 0 deletions
108
chrome/browser/chromeos/policy/android_management_client_unittest.cc
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,108 @@ | ||
// Copyright (c) 2016 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 <string> | ||
|
||
#include "base/bind.h" | ||
#include "base/bind_helpers.h" | ||
#include "base/macros.h" | ||
#include "base/memory/ref_counted.h" | ||
#include "base/time/time.h" | ||
#include "chrome/browser/chromeos/policy/android_management_client.h" | ||
#include "components/policy/core/common/cloud/mock_device_management_service.h" | ||
#include "components/signin/core/browser/fake_profile_oauth2_token_service.h" | ||
#include "net/url_request/url_request_context_getter.h" | ||
#include "net/url_request/url_request_test_util.h" | ||
#include "policy/proto/device_management_backend.pb.h" | ||
#include "testing/gmock/include/gmock/gmock.h" | ||
#include "testing/gtest/include/gtest/gtest.h" | ||
|
||
using testing::SaveArg; | ||
using testing::StrictMock; | ||
using testing::_; | ||
|
||
namespace em = enterprise_management; | ||
|
||
namespace policy { | ||
|
||
namespace { | ||
|
||
const char kAccountId[] = "fake-account-id"; | ||
const char kRefreshToken[] = "fake-refresh-token"; | ||
const char kOAuthToken[] = "fake-oauth-token"; | ||
|
||
MATCHER_P(MatchProto, expected, "matches protobuf") { | ||
return arg.SerializePartialAsString() == expected.SerializePartialAsString(); | ||
} | ||
|
||
// A mock class to allow us to set expectations on upload callbacks. | ||
class MockStatusCallbackObserver { | ||
public: | ||
MockStatusCallbackObserver() {} | ||
|
||
MOCK_METHOD1(OnCallbackComplete, void(AndroidManagementClient::Result)); | ||
}; | ||
|
||
} // namespace | ||
|
||
class AndroidManagementClientTest : public testing::Test { | ||
protected: | ||
AndroidManagementClientTest() { | ||
android_management_request_.mutable_check_android_management_request(); | ||
android_management_response_.mutable_check_android_management_response(); | ||
} | ||
|
||
// testing::Test: | ||
void SetUp() override { | ||
request_context_ = | ||
new net::TestURLRequestContextGetter(loop_.task_runner()); | ||
client_.reset(new AndroidManagementClient(&service_, request_context_, | ||
kAccountId, &token_service_)); | ||
} | ||
|
||
// Request protobuf is used as extectation for the client requests. | ||
em::DeviceManagementRequest android_management_request_; | ||
|
||
// Protobuf is used in successfil responsees. | ||
em::DeviceManagementResponse android_management_response_; | ||
|
||
base::MessageLoop loop_; | ||
MockDeviceManagementService service_; | ||
StrictMock<MockStatusCallbackObserver> callback_observer_; | ||
std::unique_ptr<AndroidManagementClient> client_; | ||
// Pointer to the client's request context. | ||
scoped_refptr<net::URLRequestContextGetter> request_context_; | ||
std::string oauh_token_; | ||
FakeProfileOAuth2TokenService token_service_; | ||
}; | ||
|
||
TEST_F(AndroidManagementClientTest, CheckAndroidManagementCall) { | ||
std::string client_id; | ||
EXPECT_CALL( | ||
service_, | ||
CreateJob(DeviceManagementRequestJob::TYPE_ANDROID_MANAGEMENT_CHECK, | ||
request_context_)) | ||
.WillOnce(service_.SucceedJob(android_management_response_)); | ||
EXPECT_CALL(service_, | ||
StartJob(dm_protocol::kValueRequestCheckAndroidManagement, | ||
std::string(), kOAuthToken, std::string(), _, | ||
MatchProto(android_management_request_))) | ||
.WillOnce(SaveArg<4>(&client_id)); | ||
EXPECT_CALL( | ||
callback_observer_, | ||
OnCallbackComplete(AndroidManagementClient::Result::RESULT_UNMANAGED)) | ||
.Times(1); | ||
|
||
AndroidManagementClient::StatusCallback callback = | ||
base::Bind(&MockStatusCallbackObserver::OnCallbackComplete, | ||
base::Unretained(&callback_observer_)); | ||
|
||
token_service_.UpdateCredentials(kAccountId, kRefreshToken); | ||
client_->StartCheckAndroidManagement(callback); | ||
token_service_.IssueAllTokensForAccount(kAccountId, kOAuthToken, | ||
base::Time::Max()); | ||
ASSERT_LT(client_id.size(), 64U); | ||
} | ||
|
||
} // namespace policy |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.