| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "chrome/browser/chromeos/policy/device_status_collector.h" | 5 #include "chrome/browser/chromeos/policy/device_status_collector.h" |
| 6 | 6 |
| 7 #include <stddef.h> | 7 #include <stddef.h> |
| 8 #include <stdint.h> | 8 #include <stdint.h> |
| 9 |
| 10 #include <memory> |
| 9 #include <string> | 11 #include <string> |
| 10 #include <utility> | 12 #include <utility> |
| 11 #include <vector> | 13 #include <vector> |
| 12 | 14 |
| 13 #include "base/bind.h" | 15 #include "base/bind.h" |
| 14 #include "base/environment.h" | 16 #include "base/environment.h" |
| 15 #include "base/logging.h" | 17 #include "base/logging.h" |
| 16 #include "base/macros.h" | 18 #include "base/macros.h" |
| 17 #include "base/memory/scoped_ptr.h" | 19 #include "base/memory/ptr_util.h" |
| 18 #include "base/message_loop/message_loop.h" | 20 #include "base/message_loop/message_loop.h" |
| 19 #include "base/run_loop.h" | 21 #include "base/run_loop.h" |
| 20 #include "base/strings/stringprintf.h" | 22 #include "base/strings/stringprintf.h" |
| 21 #include "base/threading/sequenced_worker_pool.h" | 23 #include "base/threading/sequenced_worker_pool.h" |
| 22 #include "chrome/browser/chromeos/login/users/mock_user_manager.h" | 24 #include "chrome/browser/chromeos/login/users/mock_user_manager.h" |
| 23 #include "chrome/browser/chromeos/login/users/scoped_user_manager_enabler.h" | 25 #include "chrome/browser/chromeos/login/users/scoped_user_manager_enabler.h" |
| 24 #include "chrome/browser/chromeos/ownership/fake_owner_settings_service.h" | 26 #include "chrome/browser/chromeos/ownership/fake_owner_settings_service.h" |
| 25 #include "chrome/browser/chromeos/policy/browser_policy_connector_chromeos.h" | 27 #include "chrome/browser/chromeos/policy/browser_policy_connector_chromeos.h" |
| 26 #include "chrome/browser/chromeos/policy/device_local_account.h" | 28 #include "chrome/browser/chromeos/policy/device_local_account.h" |
| 27 #include "chrome/browser/chromeos/policy/stub_enterprise_install_attributes.h" | 29 #include "chrome/browser/chromeos/policy/stub_enterprise_install_attributes.h" |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 64 namespace em = enterprise_management; | 66 namespace em = enterprise_management; |
| 65 | 67 |
| 66 namespace { | 68 namespace { |
| 67 | 69 |
| 68 const int64_t kMillisecondsPerDay = Time::kMicrosecondsPerDay / 1000; | 70 const int64_t kMillisecondsPerDay = Time::kMicrosecondsPerDay / 1000; |
| 69 const char kKioskAccountId[] = "kiosk_user@localhost"; | 71 const char kKioskAccountId[] = "kiosk_user@localhost"; |
| 70 const char kKioskAppId[] = "kiosk_app_id"; | 72 const char kKioskAppId[] = "kiosk_app_id"; |
| 71 const char kExternalMountPoint[] = "/a/b/c"; | 73 const char kExternalMountPoint[] = "/a/b/c"; |
| 72 const char kPublicAccountId[] = "public_user@localhost"; | 74 const char kPublicAccountId[] = "public_user@localhost"; |
| 73 | 75 |
| 74 scoped_ptr<content::Geoposition> mock_position_to_return_next; | 76 std::unique_ptr<content::Geoposition> mock_position_to_return_next; |
| 75 | 77 |
| 76 void SetMockPositionToReturnNext(const content::Geoposition &position) { | 78 void SetMockPositionToReturnNext(const content::Geoposition &position) { |
| 77 mock_position_to_return_next.reset(new content::Geoposition(position)); | 79 mock_position_to_return_next.reset(new content::Geoposition(position)); |
| 78 } | 80 } |
| 79 | 81 |
| 80 void MockPositionUpdateRequester( | 82 void MockPositionUpdateRequester( |
| 81 const content::GeolocationProvider::LocationUpdateCallback& callback) { | 83 const content::GeolocationProvider::LocationUpdateCallback& callback) { |
| 82 if (!mock_position_to_return_next.get()) | 84 if (!mock_position_to_return_next.get()) |
| 83 return; | 85 return; |
| 84 | 86 |
| 85 // If the fix is invalid, the DeviceStatusCollector will immediately request | 87 // If the fix is invalid, the DeviceStatusCollector will immediately request |
| 86 // another update when it receives the callback. This is desirable and safe in | 88 // another update when it receives the callback. This is desirable and safe in |
| 87 // real life where geolocation updates arrive asynchronously. In this testing | 89 // real life where geolocation updates arrive asynchronously. In this testing |
| 88 // harness, the callback is invoked synchronously upon request, leading to a | 90 // harness, the callback is invoked synchronously upon request, leading to a |
| 89 // request-callback loop. The loop is broken by returning the mock position | 91 // request-callback loop. The loop is broken by returning the mock position |
| 90 // only once. | 92 // only once. |
| 91 scoped_ptr<content::Geoposition> position( | 93 std::unique_ptr<content::Geoposition> position( |
| 92 mock_position_to_return_next.release()); | 94 mock_position_to_return_next.release()); |
| 93 callback.Run(*position); | 95 callback.Run(*position); |
| 94 } | 96 } |
| 95 | 97 |
| 96 class TestingDeviceStatusCollector : public policy::DeviceStatusCollector { | 98 class TestingDeviceStatusCollector : public policy::DeviceStatusCollector { |
| 97 public: | 99 public: |
| 98 TestingDeviceStatusCollector( | 100 TestingDeviceStatusCollector( |
| 99 PrefService* local_state, | 101 PrefService* local_state, |
| 100 chromeos::system::StatisticsProvider* provider, | 102 chromeos::system::StatisticsProvider* provider, |
| 101 const policy::DeviceStatusCollector::LocationUpdateRequester& | 103 const policy::DeviceStatusCollector::LocationUpdateRequester& |
| (...skipping 25 matching lines...) Expand all Loading... |
| 127 void set_max_stored_future_activity_days(unsigned int value) { | 129 void set_max_stored_future_activity_days(unsigned int value) { |
| 128 max_stored_future_activity_days_ = value; | 130 max_stored_future_activity_days_ = value; |
| 129 } | 131 } |
| 130 | 132 |
| 131 // Reset the baseline time. | 133 // Reset the baseline time. |
| 132 void SetBaselineTime(Time time) { | 134 void SetBaselineTime(Time time) { |
| 133 baseline_time_ = time; | 135 baseline_time_ = time; |
| 134 baseline_offset_periods_ = 0; | 136 baseline_offset_periods_ = 0; |
| 135 } | 137 } |
| 136 | 138 |
| 137 void set_kiosk_account(scoped_ptr<policy::DeviceLocalAccount> account) { | 139 void set_kiosk_account(std::unique_ptr<policy::DeviceLocalAccount> account) { |
| 138 kiosk_account_ = std::move(account); | 140 kiosk_account_ = std::move(account); |
| 139 } | 141 } |
| 140 | 142 |
| 141 scoped_ptr<policy::DeviceLocalAccount> | 143 std::unique_ptr<policy::DeviceLocalAccount> GetAutoLaunchedKioskSessionInfo() |
| 142 GetAutoLaunchedKioskSessionInfo() override { | 144 override { |
| 143 if (kiosk_account_) | 145 if (kiosk_account_) |
| 144 return make_scoped_ptr(new policy::DeviceLocalAccount(*kiosk_account_)); | 146 return base::WrapUnique(new policy::DeviceLocalAccount(*kiosk_account_)); |
| 145 return scoped_ptr<policy::DeviceLocalAccount>(); | 147 return std::unique_ptr<policy::DeviceLocalAccount>(); |
| 146 } | 148 } |
| 147 | 149 |
| 148 std::string GetAppVersion(const std::string& app_id) override { | 150 std::string GetAppVersion(const std::string& app_id) override { |
| 149 // Just return the app_id as the version - this makes it easy for tests | 151 // Just return the app_id as the version - this makes it easy for tests |
| 150 // to confirm that the correct app's version was requested. | 152 // to confirm that the correct app's version was requested. |
| 151 return app_id; | 153 return app_id; |
| 152 } | 154 } |
| 153 | 155 |
| 154 void RefreshSampleResourceUsage() { | 156 void RefreshSampleResourceUsage() { |
| 155 SampleHardwareStatus(); | 157 SampleHardwareStatus(); |
| (...skipping 14 matching lines...) Expand all Loading... |
| 170 TimeDelta::FromSeconds(poll_interval * baseline_offset_periods_++); | 172 TimeDelta::FromSeconds(poll_interval * baseline_offset_periods_++); |
| 171 } | 173 } |
| 172 | 174 |
| 173 private: | 175 private: |
| 174 // Baseline time for the fake times returned from GetCurrentTime(). | 176 // Baseline time for the fake times returned from GetCurrentTime(). |
| 175 Time baseline_time_; | 177 Time baseline_time_; |
| 176 | 178 |
| 177 // The number of simulated periods since the baseline time. | 179 // The number of simulated periods since the baseline time. |
| 178 int baseline_offset_periods_; | 180 int baseline_offset_periods_; |
| 179 | 181 |
| 180 scoped_ptr<policy::DeviceLocalAccount> kiosk_account_; | 182 std::unique_ptr<policy::DeviceLocalAccount> kiosk_account_; |
| 181 }; | 183 }; |
| 182 | 184 |
| 183 // Return the total number of active milliseconds contained in a device | 185 // Return the total number of active milliseconds contained in a device |
| 184 // status report. | 186 // status report. |
| 185 int64_t GetActiveMilliseconds(em::DeviceStatusReportRequest& status) { | 187 int64_t GetActiveMilliseconds(em::DeviceStatusReportRequest& status) { |
| 186 int64_t active_milliseconds = 0; | 188 int64_t active_milliseconds = 0; |
| 187 for (int i = 0; i < status.active_period_size(); i++) { | 189 for (int i = 0; i < status.active_period_size(); i++) { |
| 188 active_milliseconds += status.active_period(i).active_duration(); | 190 active_milliseconds += status.active_period(i).active_duration(); |
| 189 } | 191 } |
| 190 return active_milliseconds; | 192 return active_milliseconds; |
| (...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 254 DEVICE_MODE_ENTERPRISE), | 256 DEVICE_MODE_ENTERPRISE), |
| 255 settings_helper_(false), | 257 settings_helper_(false), |
| 256 user_manager_(new chromeos::MockUserManager()), | 258 user_manager_(new chromeos::MockUserManager()), |
| 257 user_manager_enabler_(user_manager_), | 259 user_manager_enabler_(user_manager_), |
| 258 fake_device_local_account_(policy::DeviceLocalAccount::TYPE_KIOSK_APP, | 260 fake_device_local_account_(policy::DeviceLocalAccount::TYPE_KIOSK_APP, |
| 259 kKioskAccountId, | 261 kKioskAccountId, |
| 260 kKioskAppId, | 262 kKioskAppId, |
| 261 std::string() /* kiosk_app_update_url */) { | 263 std::string() /* kiosk_app_update_url */) { |
| 262 // Run this test with a well-known timezone so that Time::LocalMidnight() | 264 // Run this test with a well-known timezone so that Time::LocalMidnight() |
| 263 // returns the same values on all machines. | 265 // returns the same values on all machines. |
| 264 scoped_ptr<base::Environment> env(base::Environment::Create()); | 266 std::unique_ptr<base::Environment> env(base::Environment::Create()); |
| 265 env->SetVar("TZ", "UTC"); | 267 env->SetVar("TZ", "UTC"); |
| 266 | 268 |
| 267 // Initialize our mock mounted disk volumes. | 269 // Initialize our mock mounted disk volumes. |
| 268 scoped_ptr<chromeos::disks::MockDiskMountManager> mock_disk_mount_manager = | 270 std::unique_ptr<chromeos::disks::MockDiskMountManager> |
| 269 make_scoped_ptr(new chromeos::disks::MockDiskMountManager()); | 271 mock_disk_mount_manager = |
| 272 base::WrapUnique(new chromeos::disks::MockDiskMountManager()); |
| 270 AddMountPoint("/mount/volume1"); | 273 AddMountPoint("/mount/volume1"); |
| 271 AddMountPoint("/mount/volume2"); | 274 AddMountPoint("/mount/volume2"); |
| 272 EXPECT_CALL(*mock_disk_mount_manager, mount_points()) | 275 EXPECT_CALL(*mock_disk_mount_manager, mount_points()) |
| 273 .WillRepeatedly(ReturnRef(mount_point_map_)); | 276 .WillRepeatedly(ReturnRef(mount_point_map_)); |
| 274 | 277 |
| 275 // Setup a fake file system that should show up in mount points. | 278 // Setup a fake file system that should show up in mount points. |
| 276 storage::ExternalMountPoints::GetSystemInstance()->RevokeAllFileSystems(); | 279 storage::ExternalMountPoints::GetSystemInstance()->RevokeAllFileSystems(); |
| 277 storage::ExternalMountPoints::GetSystemInstance()->RegisterFileSystem( | 280 storage::ExternalMountPoints::GetSystemInstance()->RegisterFileSystem( |
| 278 "c", storage::kFileSystemTypeNativeLocal, | 281 "c", storage::kFileSystemTypeNativeLocal, |
| 279 storage::FileSystemMountOption(), | 282 storage::FileSystemMountOption(), |
| (...skipping 122 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 402 content::TestBrowserThread file_thread_; | 405 content::TestBrowserThread file_thread_; |
| 403 content::TestBrowserThread io_thread_; | 406 content::TestBrowserThread io_thread_; |
| 404 | 407 |
| 405 ScopedStubEnterpriseInstallAttributes install_attributes_; | 408 ScopedStubEnterpriseInstallAttributes install_attributes_; |
| 406 TestingPrefServiceSimple prefs_; | 409 TestingPrefServiceSimple prefs_; |
| 407 chromeos::system::ScopedFakeStatisticsProvider fake_statistics_provider_; | 410 chromeos::system::ScopedFakeStatisticsProvider fake_statistics_provider_; |
| 408 DiskMountManager::MountPointMap mount_point_map_; | 411 DiskMountManager::MountPointMap mount_point_map_; |
| 409 chromeos::ScopedTestDeviceSettingsService test_device_settings_service_; | 412 chromeos::ScopedTestDeviceSettingsService test_device_settings_service_; |
| 410 chromeos::ScopedTestCrosSettings test_cros_settings_; | 413 chromeos::ScopedTestCrosSettings test_cros_settings_; |
| 411 chromeos::ScopedCrosSettingsTestHelper settings_helper_; | 414 chromeos::ScopedCrosSettingsTestHelper settings_helper_; |
| 412 scoped_ptr<chromeos::FakeOwnerSettingsService> owner_settings_service_; | 415 std::unique_ptr<chromeos::FakeOwnerSettingsService> owner_settings_service_; |
| 413 chromeos::MockUserManager* user_manager_; | 416 chromeos::MockUserManager* user_manager_; |
| 414 chromeos::ScopedUserManagerEnabler user_manager_enabler_; | 417 chromeos::ScopedUserManagerEnabler user_manager_enabler_; |
| 415 em::DeviceStatusReportRequest status_; | 418 em::DeviceStatusReportRequest status_; |
| 416 scoped_ptr<TestingDeviceStatusCollector> status_collector_; | 419 std::unique_ptr<TestingDeviceStatusCollector> status_collector_; |
| 417 const policy::DeviceLocalAccount fake_device_local_account_; | 420 const policy::DeviceLocalAccount fake_device_local_account_; |
| 418 }; | 421 }; |
| 419 | 422 |
| 420 TEST_F(DeviceStatusCollectorTest, AllIdle) { | 423 TEST_F(DeviceStatusCollectorTest, AllIdle) { |
| 421 ui::IdleState test_states[] = { | 424 ui::IdleState test_states[] = { |
| 422 ui::IDLE_STATE_IDLE, | 425 ui::IDLE_STATE_IDLE, |
| 423 ui::IDLE_STATE_IDLE, | 426 ui::IDLE_STATE_IDLE, |
| 424 ui::IDLE_STATE_IDLE | 427 ui::IDLE_STATE_IDLE |
| 425 }; | 428 }; |
| 426 settings_helper_.SetBoolean(chromeos::kReportDeviceActivityTimes, true); | 429 settings_helper_.SetBoolean(chromeos::kReportDeviceActivityTimes, true); |
| (...skipping 552 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 979 TEST_F(DeviceStatusCollectorTest, NoSessionStatusIfNotKioskMode) { | 982 TEST_F(DeviceStatusCollectorTest, NoSessionStatusIfNotKioskMode) { |
| 980 // Should not report session status if we don't have an active kiosk app. | 983 // Should not report session status if we don't have an active kiosk app. |
| 981 settings_helper_.SetBoolean(chromeos::kReportDeviceSessionStatus, true); | 984 settings_helper_.SetBoolean(chromeos::kReportDeviceSessionStatus, true); |
| 982 em::SessionStatusReportRequest session_status; | 985 em::SessionStatusReportRequest session_status; |
| 983 EXPECT_FALSE(status_collector_->GetDeviceSessionStatus(&session_status)); | 986 EXPECT_FALSE(status_collector_->GetDeviceSessionStatus(&session_status)); |
| 984 } | 987 } |
| 985 | 988 |
| 986 TEST_F(DeviceStatusCollectorTest, NoSessionStatusIfSessionReportingDisabled) { | 989 TEST_F(DeviceStatusCollectorTest, NoSessionStatusIfSessionReportingDisabled) { |
| 987 // Should not report session status if session status reporting is disabled. | 990 // Should not report session status if session status reporting is disabled. |
| 988 settings_helper_.SetBoolean(chromeos::kReportDeviceSessionStatus, false); | 991 settings_helper_.SetBoolean(chromeos::kReportDeviceSessionStatus, false); |
| 989 status_collector_->set_kiosk_account(make_scoped_ptr( | 992 status_collector_->set_kiosk_account(base::WrapUnique( |
| 990 new policy::DeviceLocalAccount(fake_device_local_account_))); | 993 new policy::DeviceLocalAccount(fake_device_local_account_))); |
| 991 // Set up a device-local account for single-app kiosk mode. | 994 // Set up a device-local account for single-app kiosk mode. |
| 992 MockRunningKioskApp(fake_device_local_account_); | 995 MockRunningKioskApp(fake_device_local_account_); |
| 993 | 996 |
| 994 em::SessionStatusReportRequest session_status; | 997 em::SessionStatusReportRequest session_status; |
| 995 EXPECT_FALSE(status_collector_->GetDeviceSessionStatus(&session_status)); | 998 EXPECT_FALSE(status_collector_->GetDeviceSessionStatus(&session_status)); |
| 996 } | 999 } |
| 997 | 1000 |
| 998 TEST_F(DeviceStatusCollectorTest, ReportSessionStatus) { | 1001 TEST_F(DeviceStatusCollectorTest, ReportSessionStatus) { |
| 999 settings_helper_.SetBoolean(chromeos::kReportDeviceSessionStatus, true); | 1002 settings_helper_.SetBoolean(chromeos::kReportDeviceSessionStatus, true); |
| 1000 status_collector_->set_kiosk_account(make_scoped_ptr( | 1003 status_collector_->set_kiosk_account(base::WrapUnique( |
| 1001 new policy::DeviceLocalAccount(fake_device_local_account_))); | 1004 new policy::DeviceLocalAccount(fake_device_local_account_))); |
| 1002 | 1005 |
| 1003 // Set up a device-local account for single-app kiosk mode. | 1006 // Set up a device-local account for single-app kiosk mode. |
| 1004 MockRunningKioskApp(fake_device_local_account_); | 1007 MockRunningKioskApp(fake_device_local_account_); |
| 1005 | 1008 |
| 1006 em::SessionStatusReportRequest session_status; | 1009 em::SessionStatusReportRequest session_status; |
| 1007 EXPECT_TRUE(status_collector_->GetDeviceSessionStatus(&session_status)); | 1010 EXPECT_TRUE(status_collector_->GetDeviceSessionStatus(&session_status)); |
| 1008 ASSERT_EQ(1, session_status.installed_apps_size()); | 1011 ASSERT_EQ(1, session_status.installed_apps_size()); |
| 1009 EXPECT_EQ(kKioskAccountId, session_status.device_local_account_id()); | 1012 EXPECT_EQ(kKioskAccountId, session_status.device_local_account_id()); |
| 1010 const em::AppStatus app = session_status.installed_apps(0); | 1013 const em::AppStatus app = session_status.installed_apps(0); |
| (...skipping 266 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1277 TEST_F(DeviceStatusCollectorNetworkInterfacesTest, NoNetworkStateIfNotKiosk) { | 1280 TEST_F(DeviceStatusCollectorNetworkInterfacesTest, NoNetworkStateIfNotKiosk) { |
| 1278 // If not in an active kiosk session, there should be network interfaces | 1281 // If not in an active kiosk session, there should be network interfaces |
| 1279 // reported, but no network state. | 1282 // reported, but no network state. |
| 1280 GetStatus(); | 1283 GetStatus(); |
| 1281 EXPECT_LT(0, status_.network_interface_size()); | 1284 EXPECT_LT(0, status_.network_interface_size()); |
| 1282 EXPECT_EQ(0, status_.network_state_size()); | 1285 EXPECT_EQ(0, status_.network_state_size()); |
| 1283 } | 1286 } |
| 1284 | 1287 |
| 1285 TEST_F(DeviceStatusCollectorNetworkInterfacesTest, NetworkInterfaces) { | 1288 TEST_F(DeviceStatusCollectorNetworkInterfacesTest, NetworkInterfaces) { |
| 1286 // Mock that we are in kiosk mode so we report network state. | 1289 // Mock that we are in kiosk mode so we report network state. |
| 1287 status_collector_->set_kiosk_account(make_scoped_ptr( | 1290 status_collector_->set_kiosk_account(base::WrapUnique( |
| 1288 new policy::DeviceLocalAccount(fake_device_local_account_))); | 1291 new policy::DeviceLocalAccount(fake_device_local_account_))); |
| 1289 | 1292 |
| 1290 // Interfaces should be reported by default. | 1293 // Interfaces should be reported by default. |
| 1291 GetStatus(); | 1294 GetStatus(); |
| 1292 EXPECT_LT(0, status_.network_interface_size()); | 1295 EXPECT_LT(0, status_.network_interface_size()); |
| 1293 EXPECT_LT(0, status_.network_state_size()); | 1296 EXPECT_LT(0, status_.network_state_size()); |
| 1294 | 1297 |
| 1295 // No interfaces should be reported if the policy is off. | 1298 // No interfaces should be reported if the policy is off. |
| 1296 settings_helper_.SetBoolean(chromeos::kReportDeviceNetworkInterfaces, false); | 1299 settings_helper_.SetBoolean(chromeos::kReportDeviceNetworkInterfaces, false); |
| 1297 GetStatus(); | 1300 GetStatus(); |
| (...skipping 13 matching lines...) Expand all Loading... |
| 1311 AccountId::FromUserEmail(kPublicAccountId)); | 1314 AccountId::FromUserEmail(kPublicAccountId)); |
| 1312 EXPECT_CALL(*user_manager_, IsLoggedInAsPublicAccount()) | 1315 EXPECT_CALL(*user_manager_, IsLoggedInAsPublicAccount()) |
| 1313 .WillRepeatedly(Return(true)); | 1316 .WillRepeatedly(Return(true)); |
| 1314 | 1317 |
| 1315 settings_helper_.SetBoolean(chromeos::kReportDeviceNetworkInterfaces, true); | 1318 settings_helper_.SetBoolean(chromeos::kReportDeviceNetworkInterfaces, true); |
| 1316 GetStatus(); | 1319 GetStatus(); |
| 1317 VerifyNetworkReporting(); | 1320 VerifyNetworkReporting(); |
| 1318 } | 1321 } |
| 1319 | 1322 |
| 1320 } // namespace policy | 1323 } // namespace policy |
| OLD | NEW |