-
Notifications
You must be signed in to change notification settings - Fork 127
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Create a new extension API for enterprise browser reporting.
It introduces new permission, IDL and skeleton of implementation. This privacy API is used to upload browsers and devices status that are collected by extension to the admin console. Bug: 832887 Change-Id: I60780d76c9e7680843acef38ce906e9cbe150025 Reviewed-on: https://chromium-review.googlesource.com/976819 Reviewed-by: Gayane Petrosyan <gayane@chromium.org> Reviewed-by: Devlin <rdevlin.cronin@chromium.org> Commit-Queue: Owen Min <zmin@chromium.org> Cr-Original-Commit-Position: refs/heads/master@{#550521}(cherry picked from commit fdada01) Reviewed-on: https://chromium-review.googlesource.com/1013340 Reviewed-by: Owen Min <zmin@chromium.org> Cr-Commit-Position: refs/branch-heads/3396@{#8} Cr-Branched-From: 9ef2aa8-refs/heads/master@{#550428}
- Loading branch information
Owen Min
committed
Apr 15, 2018
1 parent
6157172
commit 8e87f21
Showing
15 changed files
with
377 additions
and
0 deletions.
There are no files selected for viewing
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
4 changes: 4 additions & 0 deletions
4
chrome/browser/extensions/api/enterprise_reporting_private/OWNERS
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,4 @@ | ||
georgesak@chromium.org | ||
mad@chromium.org | ||
pastarmovj@chromium.org | ||
zmin@chromium.org |
143 changes: 143 additions & 0 deletions
143
...e/browser/extensions/api/enterprise_reporting_private/enterprise_reporting_private_api.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,143 @@ | ||
// Copyright 2018 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/extensions/api/enterprise_reporting_private/enterprise_reporting_private_api.h" | ||
|
||
#include <memory> | ||
|
||
#include "base/bind.h" | ||
#include "base/json/json_writer.h" | ||
#include "base/values.h" | ||
#include "chrome/browser/browser_process.h" | ||
#include "chrome/browser/policy/browser_dm_token_storage.h" | ||
#include "chrome/browser/policy/chrome_browser_policy_connector.h" | ||
#include "chrome/browser/profiles/profile.h" | ||
#include "chrome/common/extensions/api/enterprise_reporting_private.h" | ||
#include "components/policy/core/common/cloud/cloud_policy_client.h" | ||
#include "components/policy/core/common/cloud/device_management_service.h" | ||
#include "components/policy/proto/device_management_backend.pb.h" | ||
#include "net/url_request/url_request_context_getter.h" | ||
|
||
namespace em = enterprise_management; | ||
|
||
namespace extensions { | ||
namespace { | ||
|
||
const char kMachineName[] = "machineName"; | ||
const char kOSInfo[] = "osInfo"; | ||
const char kOSUser[] = "osUser"; | ||
|
||
bool UpdateJSONEncodedStringEntry(const base::Value& dict_value, | ||
const char key[], | ||
std::string* entry) { | ||
if (const base::Value* value = dict_value.FindKey(key)) { | ||
if (!value->is_dict() && !value->is_list()) | ||
return false; | ||
base::JSONWriter::Write(*value, entry); | ||
} | ||
return true; | ||
} | ||
|
||
// Transfer the input from Json file to protobuf. Return nullptr if the input | ||
// is not valid. | ||
std::unique_ptr<enterprise_management::ChromeDesktopReportRequest> | ||
GenerateChromeDesktopReportRequest(const base::DictionaryValue& report) { | ||
std::unique_ptr<em::ChromeDesktopReportRequest> request = | ||
std::make_unique<em::ChromeDesktopReportRequest>(); | ||
|
||
if (!UpdateJSONEncodedStringEntry(report, kMachineName, | ||
request->mutable_machine_name()) || | ||
!UpdateJSONEncodedStringEntry(report, kOSInfo, | ||
request->mutable_os_info()) || | ||
!UpdateJSONEncodedStringEntry(report, kOSUser, | ||
request->mutable_os_user())) { | ||
return nullptr; | ||
} | ||
return request; | ||
} | ||
|
||
} // namespace | ||
|
||
namespace enterprise_reporting { | ||
|
||
const char kInvalidInputErrorMessage[] = "The report is not valid."; | ||
const char kUploadFailed[] = "Failed to upload the report."; | ||
const char kDeviceNotEnrolled[] = "This device has not been enrolled yet."; | ||
|
||
} // namespace enterprise_reporting | ||
|
||
EnterpriseReportingPrivateUploadChromeDesktopReportFunction:: | ||
EnterpriseReportingPrivateUploadChromeDesktopReportFunction() { | ||
policy::DeviceManagementService* device_management_service = | ||
g_browser_process->browser_policy_connector() | ||
->device_management_service(); | ||
// Initial the DeviceManagementService if it exist and hasn't been initialized | ||
if (device_management_service) | ||
device_management_service->ScheduleInitialization(0); | ||
cloud_policy_client_ = std::make_unique<policy::CloudPolicyClient>( | ||
std::string(), std::string(), device_management_service, | ||
g_browser_process->system_request_context(), nullptr, | ||
policy::CloudPolicyClient::DeviceDMTokenCallback()); | ||
dm_token_ = policy::BrowserDMTokenStorage::Get()->RetrieveDMToken(); | ||
client_id_ = policy::BrowserDMTokenStorage::Get()->RetrieveClientId(); | ||
} | ||
|
||
EnterpriseReportingPrivateUploadChromeDesktopReportFunction:: | ||
~EnterpriseReportingPrivateUploadChromeDesktopReportFunction() {} | ||
|
||
ExtensionFunction::ResponseAction | ||
EnterpriseReportingPrivateUploadChromeDesktopReportFunction::Run() { | ||
if (dm_token_.empty() || client_id_.empty()) | ||
return RespondNow(Error(enterprise_reporting::kDeviceNotEnrolled)); | ||
std::unique_ptr< | ||
api::enterprise_reporting_private::UploadChromeDesktopReport::Params> | ||
params(api::enterprise_reporting_private::UploadChromeDesktopReport:: | ||
Params::Create(*args_)); | ||
EXTENSION_FUNCTION_VALIDATE(params.get()); | ||
std::unique_ptr<em::ChromeDesktopReportRequest> request = | ||
GenerateChromeDesktopReportRequest(params->report.additional_properties); | ||
if (!request) { | ||
return RespondNow(Error(enterprise_reporting::kInvalidInputErrorMessage)); | ||
} | ||
|
||
if (!cloud_policy_client_->is_registered()) | ||
cloud_policy_client_->SetupRegistration(dm_token_, client_id_, | ||
std::vector<std::string>()); | ||
|
||
cloud_policy_client_->UploadChromeDesktopReport( | ||
std::move(request), | ||
base::BindRepeating( | ||
&EnterpriseReportingPrivateUploadChromeDesktopReportFunction:: | ||
OnReportUploaded, | ||
this)); | ||
return RespondLater(); | ||
} | ||
|
||
void EnterpriseReportingPrivateUploadChromeDesktopReportFunction:: | ||
SetCloudPolicyClientForTesting( | ||
std::unique_ptr<policy::CloudPolicyClient> client) { | ||
cloud_policy_client_ = std::move(client); | ||
} | ||
|
||
void EnterpriseReportingPrivateUploadChromeDesktopReportFunction:: | ||
SetRegistrationInfoForTesting(const std::string& dm_token, | ||
const std::string& client_id) { | ||
dm_token_ = dm_token; | ||
client_id_ = client_id; | ||
} | ||
|
||
void EnterpriseReportingPrivateUploadChromeDesktopReportFunction:: | ||
OnResponded() { | ||
cloud_policy_client_.reset(); | ||
} | ||
|
||
void EnterpriseReportingPrivateUploadChromeDesktopReportFunction:: | ||
OnReportUploaded(bool status) { | ||
if (status) | ||
Respond(NoArguments()); | ||
else | ||
Respond(Error(enterprise_reporting::kUploadFailed)); | ||
} | ||
|
||
} // namespace extensions |
58 changes: 58 additions & 0 deletions
58
...me/browser/extensions/api/enterprise_reporting_private/enterprise_reporting_private_api.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,58 @@ | ||
// Copyright 2018 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_EXTENSIONS_API_ENTERPRISE_REPORTING_PRIVATE_ENTERPRISE_REPORTING_PRIVATE_API_H_ | ||
#define CHROME_BROWSER_EXTENSIONS_API_ENTERPRISE_REPORTING_PRIVATE_ENTERPRISE_REPORTING_PRIVATE_API_H_ | ||
|
||
#include "extensions/browser/extension_function.h" | ||
|
||
namespace policy { | ||
class CloudPolicyClient; | ||
} | ||
|
||
namespace extensions { | ||
namespace enterprise_reporting { | ||
|
||
extern const char kInvalidInputErrorMessage[]; | ||
extern const char kUploadFailed[]; | ||
extern const char kDeviceNotEnrolled[]; | ||
|
||
} // namespace enterprise_reporting | ||
|
||
class EnterpriseReportingPrivateUploadChromeDesktopReportFunction | ||
: public UIThreadExtensionFunction { | ||
public: | ||
DECLARE_EXTENSION_FUNCTION( | ||
"enterprise.reportingPrivate.uploadChromeDesktopReport", | ||
ENTERPRISEREPORTINGPRIVATE_UPLOADCHROMEDESKTOPREPORT); | ||
EnterpriseReportingPrivateUploadChromeDesktopReportFunction(); | ||
|
||
// ExtensionFunction | ||
ExtensionFunction::ResponseAction Run() override; | ||
|
||
void SetCloudPolicyClientForTesting( | ||
std::unique_ptr<policy::CloudPolicyClient> client); | ||
void SetRegistrationInfoForTesting(const std::string& dm_token, | ||
const std::string& client_id); | ||
|
||
private: | ||
~EnterpriseReportingPrivateUploadChromeDesktopReportFunction() override; | ||
|
||
// ExtensionFunction | ||
void OnResponded() override; | ||
|
||
// Callback once Chrome get the response from the DM Server. | ||
void OnReportUploaded(bool status); | ||
|
||
std::unique_ptr<policy::CloudPolicyClient> cloud_policy_client_; | ||
std::string dm_token_; | ||
std::string client_id_; | ||
|
||
DISALLOW_COPY_AND_ASSIGN( | ||
EnterpriseReportingPrivateUploadChromeDesktopReportFunction); | ||
}; | ||
|
||
} // namespace extensions | ||
|
||
#endif // CHROME_BROWSER_EXTENSIONS_API_ENTERPRISE_REPORTING_PRIVATE_ENTERPRISE_REPORTING_PRIVATE_API_H_ |
123 changes: 123 additions & 0 deletions
123
...wser/extensions/api/enterprise_reporting_private/enterprise_reporting_private_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,123 @@ | ||
// Copyright 2018 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/extensions/api/enterprise_reporting_private/enterprise_reporting_private_api.h" | ||
|
||
#include "base/macros.h" | ||
#include "base/strings/stringprintf.h" | ||
#include "chrome/browser/extensions/extension_api_unittest.h" | ||
#include "chrome/browser/extensions/extension_function_test_utils.h" | ||
#include "components/policy/core/common/cloud/mock_cloud_policy_client.h" | ||
#include "testing/gmock/include/gmock/gmock.h" | ||
|
||
using ::testing::_; | ||
using ::testing::Invoke; | ||
using ::testing::WithArgs; | ||
|
||
namespace extensions { | ||
namespace { | ||
|
||
const char kFakeDMToken[] = "fake-dm-token"; | ||
const char kFakeClientId[] = "fake-client-id"; | ||
const char kFakeMachineNameReport[] = "{\"computername\":\"name\"}"; | ||
const char kFakeInvalidMachineNameReport[] = "\"invalid\""; | ||
|
||
class MockCloudPolicyClient : public policy::MockCloudPolicyClient { | ||
public: | ||
MockCloudPolicyClient() = default; | ||
|
||
void UploadChromeDesktopReport( | ||
std::unique_ptr<enterprise_management::ChromeDesktopReportRequest> | ||
request, | ||
const StatusCallback& callback) { | ||
UploadChromeDesktopReportProxy(request.get(), callback); | ||
} | ||
MOCK_METHOD2(UploadChromeDesktopReportProxy, | ||
void(enterprise_management::ChromeDesktopReportRequest*, | ||
const StatusCallback&)); | ||
|
||
void OnReportUploadedFailed(const StatusCallback& callback) { | ||
base::ThreadTaskRunnerHandle::Get()->PostTask( | ||
FROM_HERE, base::BindOnce(callback, false)); | ||
} | ||
|
||
void OnReportUploadedSucceeded(const StatusCallback& callback) { | ||
base::ThreadTaskRunnerHandle::Get()->PostTask( | ||
FROM_HERE, base::BindOnce(callback, true)); | ||
} | ||
|
||
private: | ||
DISALLOW_COPY_AND_ASSIGN(MockCloudPolicyClient); | ||
}; | ||
|
||
} // namespace | ||
|
||
class EnterpriseReportingPrivateTest : public ExtensionApiUnittest { | ||
public: | ||
EnterpriseReportingPrivateTest() = default; | ||
|
||
UIThreadExtensionFunction* CreateChromeDesktopReportingFunction( | ||
const std::string& dm_token) { | ||
EnterpriseReportingPrivateUploadChromeDesktopReportFunction* function = | ||
new EnterpriseReportingPrivateUploadChromeDesktopReportFunction(); | ||
std::unique_ptr<MockCloudPolicyClient> client = | ||
std::make_unique<MockCloudPolicyClient>(); | ||
client_ = client.get(); | ||
function->SetCloudPolicyClientForTesting(std::move(client)); | ||
function->SetRegistrationInfoForTesting(dm_token, kFakeClientId); | ||
return function; | ||
} | ||
|
||
std::string GenerateArgs(const char* name) { | ||
return base::StringPrintf("[{\"machineName\":%s}]", name); | ||
} | ||
|
||
MockCloudPolicyClient* client_; | ||
|
||
private: | ||
DISALLOW_COPY_AND_ASSIGN(EnterpriseReportingPrivateTest); | ||
}; | ||
|
||
TEST_F(EnterpriseReportingPrivateTest, DeviceIsNotEnrolled) { | ||
ASSERT_EQ(enterprise_reporting::kDeviceNotEnrolled, | ||
RunFunctionAndReturnError( | ||
CreateChromeDesktopReportingFunction(std::string()), | ||
GenerateArgs(kFakeMachineNameReport))); | ||
} | ||
|
||
TEST_F(EnterpriseReportingPrivateTest, ReportIsNotValid) { | ||
ASSERT_EQ(enterprise_reporting::kInvalidInputErrorMessage, | ||
RunFunctionAndReturnError( | ||
CreateChromeDesktopReportingFunction(kFakeDMToken), | ||
GenerateArgs(kFakeInvalidMachineNameReport))); | ||
} | ||
|
||
TEST_F(EnterpriseReportingPrivateTest, UploadFailed) { | ||
UIThreadExtensionFunction* function = | ||
CreateChromeDesktopReportingFunction(kFakeDMToken); | ||
EXPECT_CALL(*client_, SetupRegistration(kFakeDMToken, kFakeClientId, _)) | ||
.Times(1); | ||
EXPECT_CALL(*client_, UploadChromeDesktopReportProxy(_, _)) | ||
.WillOnce(WithArgs<1>( | ||
Invoke(client_, &MockCloudPolicyClient::OnReportUploadedFailed))); | ||
ASSERT_EQ(enterprise_reporting::kUploadFailed, | ||
RunFunctionAndReturnError(function, | ||
GenerateArgs(kFakeMachineNameReport))); | ||
::testing::Mock::VerifyAndClearExpectations(client_); | ||
} | ||
|
||
TEST_F(EnterpriseReportingPrivateTest, UploadSucceeded) { | ||
UIThreadExtensionFunction* function = | ||
CreateChromeDesktopReportingFunction(kFakeDMToken); | ||
EXPECT_CALL(*client_, SetupRegistration(kFakeDMToken, kFakeClientId, _)) | ||
.Times(1); | ||
EXPECT_CALL(*client_, UploadChromeDesktopReportProxy(_, _)) | ||
.WillOnce(WithArgs<1>( | ||
Invoke(client_, &MockCloudPolicyClient::OnReportUploadedSucceeded))); | ||
ASSERT_EQ(nullptr, RunFunctionAndReturnValue( | ||
function, GenerateArgs(kFakeMachineNameReport))); | ||
::testing::Mock::VerifyAndClearExpectations(client_); | ||
} | ||
|
||
} // namespace extensions |
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.