15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 52a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#ifndef CHROME_BROWSER_CHROMEOS_POLICY_DEVICE_STATUS_COLLECTOR_H_ 62a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#define CHROME_BROWSER_CHROMEOS_POLICY_DEVICE_STATUS_COLLECTOR_H_ 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <string> 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/basictypes.h" 11cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "base/callback_list.h" 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/compiler_specific.h" 13b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)#include "base/memory/ref_counted.h" 1468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)#include "base/memory/scoped_ptr.h" 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/memory/weak_ptr.h" 165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "base/task/cancelable_task_tracker.h" 17eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "base/time/time.h" 18eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "base/timer/timer.h" 1968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)#include "chrome/browser/chromeos/settings/cros_settings.h" 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/chromeos/version_loader.h" 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/idle.h" 22a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "components/policy/core/common/cloud/cloud_policy_client.h" 23b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)#include "content/public/browser/geolocation_provider.h" 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/common/geoposition.h" 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace chromeos { 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class CrosSettings; 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace system { 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class StatisticsProvider; 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace content { 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class NotificationDetails; 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class NotificationSource; 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace enterprise_management { 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class DeviceStatusReportRequest; 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)class PrefRegistrySimple; 437dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochclass PrefService; 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace policy { 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Collects and summarizes the status of an enterprised-managed ChromeOS device. 4868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)class DeviceStatusCollector : public CloudPolicyClient::StatusProvider { 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public: 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // TODO(bartfab): Remove this once crbug.com/125931 is addressed and a proper 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // way to mock geolocation exists. 52b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) typedef base::Callback<void( 53b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) const content::GeolocationProvider::LocationUpdateCallback& callback)> 54b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) LocationUpdateRequester; 55b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 56b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) DeviceStatusCollector( 57b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) PrefService* local_state, 58b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) chromeos::system::StatisticsProvider* provider, 59b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) LocationUpdateRequester* location_update_requester); 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual ~DeviceStatusCollector(); 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void GetStatus(enterprise_management::DeviceStatusReportRequest* request); 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // CloudPolicyClient::StatusProvider: 652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) virtual bool GetDeviceStatus( 662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) enterprise_management::DeviceStatusReportRequest* status) OVERRIDE; 672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) virtual bool GetSessionStatus( 682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) enterprise_management::SessionStatusReportRequest* status) OVERRIDE; 692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) virtual void OnSubmittedSuccessfully() OVERRIDE; 702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) static void RegisterPrefs(PrefRegistrySimple* registry); 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // How often, in seconds, to poll to see if the user is idle. 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static const unsigned int kIdlePollIntervalSeconds = 30; 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) protected: 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Check whether the user has been idle for a certain period of time. 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual void CheckIdleState(); 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Used instead of base::Time::Now(), to make testing possible. 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual base::Time GetCurrentTime(); 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Callback which receives the results of the idle state check. 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void IdleStateCallback(IdleState state); 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The number of days in the past to store device activity. 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // This is kept in case device status uploads fail for a number of days. 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) unsigned int max_stored_past_activity_days_; 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The number of days in the future to store device activity. 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // When changing the system time and/or timezones, it's possible to record 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // activity time that is slightly in the future. 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) unsigned int max_stored_future_activity_days_; 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private: 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Prevents the local store of activity periods from growing too large by 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // removing entries that are outside the reporting window. 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void PruneStoredActivityPeriods(base::Time base_time); 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Trims the store activity periods to only retain data within the 1012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // [|min_day_key|, |max_day_key|). The record for |min_day_key| will be 1022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // adjusted by subtracting |min_day_trim_duration|. 1032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) void TrimStoredActivityPeriods(int64 min_day_key, 1042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int min_day_trim_duration, 1052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int64 max_day_key); 1062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void AddActivePeriod(base::Time start, base::Time end); 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Callbacks from chromeos::VersionLoader. 1102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) void OnOSVersion(const std::string& version); 1112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) void OnOSFirmware(const std::string& version); 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Helpers for the various portions of the status. 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void GetActivityTimes( 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) enterprise_management::DeviceStatusReportRequest* request); 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void GetVersionInfo( 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) enterprise_management::DeviceStatusReportRequest* request); 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void GetBootMode( 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) enterprise_management::DeviceStatusReportRequest* request); 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void GetLocation( 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) enterprise_management::DeviceStatusReportRequest* request); 1227dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch void GetNetworkInterfaces( 1237dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch enterprise_management::DeviceStatusReportRequest* request); 1241e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) void GetUsers( 1251e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) enterprise_management::DeviceStatusReportRequest* request); 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Update the cached values of the reporting settings. 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void UpdateReportingSettings(); 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void ScheduleGeolocationUpdateRequest(); 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // content::GeolocationUpdateCallback implementation. 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void ReceiveGeolocationUpdate(const content::Geoposition&); 1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // How often to poll to see if the user is idle. 1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int poll_interval_seconds_; 1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PrefService* local_state_; 1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The last time an idle state check was performed. 1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Time last_idle_check_; 1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // The maximum key that went into the last report generated by 1442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // GetDeviceStatus(), and the duration for it. This is used to trim the 1452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // stored data in OnSubmittedSuccessfully(). Trimming is delayed so 1462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // unsuccessful uploads don't result in dropped data. 1472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int64 last_reported_day_; 1482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int duration_for_last_reported_day_; 1492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Whether a geolocation update is currently in progress. 1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool geolocation_update_in_progress_; 1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::RepeatingTimer<DeviceStatusCollector> idle_poll_timer_; 1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::OneShotTimer<DeviceStatusCollector> geolocation_update_timer_; 1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) chromeos::VersionLoader version_loader_; 1575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::CancelableTaskTracker tracker_; 1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string os_version_; 1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string firmware_version_; 1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) content::Geoposition position_; 1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) chromeos::system::StatisticsProvider* statistics_provider_; 1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) chromeos::CrosSettings* cros_settings_; 1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // TODO(bartfab): Remove this once crbug.com/125931 is addressed and a proper 1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // way to mock geolocation exists. 1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LocationUpdateRequester location_update_requester_; 1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 172cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) scoped_ptr<content::GeolocationProvider::Subscription> 173cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) geolocation_subscription_; 174cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Cached values of the reporting settings from the device policy. 1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool report_version_info_; 1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool report_activity_times_; 1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool report_boot_mode_; 1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool report_location_; 1807dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch bool report_network_interfaces_; 1811e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) bool report_users_; 1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 18368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) scoped_ptr<chromeos::CrosSettings::ObserverSubscription> 18468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) version_info_subscription_; 18568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) scoped_ptr<chromeos::CrosSettings::ObserverSubscription> 18668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) activity_times_subscription_; 18768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) scoped_ptr<chromeos::CrosSettings::ObserverSubscription> 18868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) boot_mode_subscription_; 18968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) scoped_ptr<chromeos::CrosSettings::ObserverSubscription> 19068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) location_subscription_; 19168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) scoped_ptr<chromeos::CrosSettings::ObserverSubscription> 19268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) network_interfaces_subscription_; 1931e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) scoped_ptr<chromeos::CrosSettings::ObserverSubscription> 1941e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) users_subscription_; 19568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) 1961320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci base::WeakPtrFactory<DeviceStatusCollector> weak_factory_; 1971320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DISALLOW_COPY_AND_ASSIGN(DeviceStatusCollector); 1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace policy 2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#endif // CHROME_BROWSER_CHROMEOS_POLICY_DEVICE_STATUS_COLLECTOR_H_ 204