• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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
3 // found in the LICENSE file.
4 
5 #ifndef CHROME_BROWSER_PROFILES_PROFILE_IO_DATA_H_
6 #define CHROME_BROWSER_PROFILES_PROFILE_IO_DATA_H_
7 
8 #include <string>
9 
10 #include "base/basictypes.h"
11 #include "base/callback_forward.h"
12 #include "base/files/file_path.h"
13 #include "base/memory/ref_counted.h"
14 #include "base/memory/scoped_ptr.h"
15 #include "base/memory/weak_ptr.h"
16 #include "base/prefs/pref_member.h"
17 #include "base/synchronization/lock.h"
18 #include "chrome/browser/custom_handlers/protocol_handler_registry.h"
19 #include "chrome/browser/io_thread.h"
20 #include "chrome/browser/net/chrome_url_request_context.h"
21 #include "chrome/browser/profiles/profile.h"
22 #include "chrome/browser/profiles/storage_partition_descriptor.h"
23 #include "chrome/common/content_settings_types.h"
24 #include "content/public/browser/content_browser_client.h"
25 #include "content/public/browser/resource_context.h"
26 #include "net/cookies/cookie_monster.h"
27 #include "net/http/http_cache.h"
28 #include "net/http/http_network_session.h"
29 #include "net/url_request/url_request_job_factory.h"
30 
31 class ChromeHttpUserAgentSettings;
32 class ChromeNetworkDelegate;
33 class CookieSettings;
34 class DevToolsNetworkController;
35 class HostContentSettingsMap;
36 class MediaDeviceIDSalt;
37 class ProtocolHandlerRegistry;
38 class SigninNamesOnIOThread;
39 class SupervisedUserURLFilter;
40 
41 namespace extensions {
42 class InfoMap;
43 }
44 
45 namespace net {
46 class CookieStore;
47 class FraudulentCertificateReporter;
48 class FtpTransactionFactory;
49 class HttpServerProperties;
50 class HttpTransactionFactory;
51 class ServerBoundCertService;
52 class ProxyConfigService;
53 class ProxyService;
54 class SSLConfigService;
55 class TransportSecurityPersister;
56 class TransportSecurityState;
57 class URLRequestJobFactoryImpl;
58 }  // namespace net
59 
60 namespace policy {
61 class PolicyCertVerifier;
62 class PolicyHeaderIOHelper;
63 class URLBlacklistManager;
64 }  // namespace policy
65 
66 namespace prerender {
67 class PrerenderTracker;
68 }
69 
70 // Conceptually speaking, the ProfileIOData represents data that lives on the IO
71 // thread that is owned by a Profile, such as, but not limited to, network
72 // objects like CookieMonster, HttpTransactionFactory, etc.  Profile owns
73 // ProfileIOData, but will make sure to delete it on the IO thread (except
74 // possibly in unit tests where there is no IO thread).
75 class ProfileIOData {
76  public:
77   virtual ~ProfileIOData();
78 
79   static ProfileIOData* FromResourceContext(content::ResourceContext* rc);
80 
81   // Returns true if |scheme| is handled in Chrome, or by default handlers in
82   // net::URLRequest.
83   static bool IsHandledProtocol(const std::string& scheme);
84 
85   // Returns true if |url| is handled in Chrome, or by default handlers in
86   // net::URLRequest.
87   static bool IsHandledURL(const GURL& url);
88 
89   // Utility to install additional WebUI handlers into the |job_factory|.
90   // Ownership of the handlers is transfered from |protocol_handlers|
91   // to the |job_factory|.
92   static void InstallProtocolHandlers(
93       net::URLRequestJobFactoryImpl* job_factory,
94       content::ProtocolHandlerMap* protocol_handlers);
95 
96   // Called by Profile.
97   content::ResourceContext* GetResourceContext() const;
98 
99   // Initializes the ProfileIOData object and primes the RequestContext
100   // generation. Must be called prior to any of the Get*() methods other than
101   // GetResouceContext or GetMetricsEnabledStateOnIOThread.
102   void Init(
103       content::ProtocolHandlerMap* protocol_handlers,
104       content::URLRequestInterceptorScopedVector request_interceptors) const;
105 
106   ChromeURLRequestContext* GetMainRequestContext() const;
107   ChromeURLRequestContext* GetMediaRequestContext() const;
108   ChromeURLRequestContext* GetExtensionsRequestContext() const;
109   ChromeURLRequestContext* GetIsolatedAppRequestContext(
110       ChromeURLRequestContext* main_context,
111       const StoragePartitionDescriptor& partition_descriptor,
112       scoped_ptr<ProtocolHandlerRegistry::JobInterceptorFactory>
113           protocol_handler_interceptor,
114       content::ProtocolHandlerMap* protocol_handlers,
115       content::URLRequestInterceptorScopedVector request_interceptors) const;
116   ChromeURLRequestContext* GetIsolatedMediaRequestContext(
117       ChromeURLRequestContext* app_context,
118       const StoragePartitionDescriptor& partition_descriptor) const;
119 
120   // These are useful when the Chrome layer is called from the content layer
121   // with a content::ResourceContext, and they want access to Chrome data for
122   // that profile.
123   extensions::InfoMap* GetExtensionInfoMap() const;
124   CookieSettings* GetCookieSettings() const;
125   HostContentSettingsMap* GetHostContentSettingsMap() const;
126 
session_startup_pref()127   IntegerPrefMember* session_startup_pref() const {
128     return &session_startup_pref_;
129   }
130 
signin_names()131   SigninNamesOnIOThread* signin_names() const {
132     return signin_names_.get();
133   }
134 
google_services_account_id()135   StringPrefMember* google_services_account_id() const {
136     return &google_services_user_account_id_;
137   }
138 
google_services_username()139   StringPrefMember* google_services_username() const {
140     return &google_services_username_;
141   }
142 
google_services_username_pattern()143   StringPrefMember* google_services_username_pattern() const {
144     return &google_services_username_pattern_;
145   }
146 
reverse_autologin_enabled()147   BooleanPrefMember* reverse_autologin_enabled() const {
148     return &reverse_autologin_enabled_;
149   }
150 
reverse_autologin_pending_email()151   const std::string& reverse_autologin_pending_email() const {
152     return reverse_autologin_pending_email_;
153   }
154 
set_reverse_autologin_pending_email(const std::string & email)155   void set_reverse_autologin_pending_email(const std::string& email) {
156     reverse_autologin_pending_email_ = email;
157   }
158 
one_click_signin_rejected_email_list()159   StringListPrefMember* one_click_signin_rejected_email_list() const {
160     return &one_click_signin_rejected_email_list_;
161   }
162 
extensions_request_context()163   ChromeURLRequestContext* extensions_request_context() const {
164     return extensions_request_context_.get();
165   }
166 
safe_browsing_enabled()167   BooleanPrefMember* safe_browsing_enabled() const {
168     return &safe_browsing_enabled_;
169   }
170 
data_reduction_proxy_enabled()171   BooleanPrefMember* data_reduction_proxy_enabled() const {
172     return &data_reduction_proxy_enabled_;
173   }
174 
printing_enabled()175   BooleanPrefMember* printing_enabled() const {
176     return &printing_enabled_;
177   }
178 
sync_disabled()179   BooleanPrefMember* sync_disabled() const {
180     return &sync_disabled_;
181   }
182 
signin_allowed()183   BooleanPrefMember* signin_allowed() const {
184     return &signin_allowed_;
185   }
186 
network_prediction_enabled()187   BooleanPrefMember* network_prediction_enabled() const {
188     return &network_prediction_enabled_;
189   }
190 
191   content::ResourceContext::SaltCallback GetMediaDeviceIDSalt() const;
192 
network_controller()193   DevToolsNetworkController* network_controller() const {
194     return network_controller_.get();
195   }
196 
transport_security_state()197   net::TransportSecurityState* transport_security_state() const {
198     return transport_security_state_.get();
199   }
200 
201 #if defined(OS_CHROMEOS)
username_hash()202   std::string username_hash() const {
203     return username_hash_;
204   }
205 #endif
206 
profile_type()207   Profile::ProfileType profile_type() const {
208     return profile_type_;
209   }
210 
211   bool IsOffTheRecord() const;
212 
incognito_availibility()213   IntegerPrefMember* incognito_availibility() const {
214     return &incognito_availibility_pref_;
215   }
216 
217 #if defined(ENABLE_CONFIGURATION_POLICY)
policy_header_helper()218   policy::PolicyHeaderIOHelper* policy_header_helper() const {
219     return policy_header_helper_.get();
220   }
221 #endif
222 
223 #if defined(ENABLE_MANAGED_USERS)
supervised_user_url_filter()224   const SupervisedUserURLFilter* supervised_user_url_filter() const {
225     return supervised_user_url_filter_.get();
226   }
227 #endif
228 
229   // Initialize the member needed to track the metrics enabled state. This is
230   // only to be called on the UI thread.
231   void InitializeMetricsEnabledStateOnUIThread();
232 
233   // Returns whether or not metrics reporting is enabled in the browser instance
234   // on which this profile resides. This is safe for use from the IO thread, and
235   // should only be called from there.
236   bool GetMetricsEnabledStateOnIOThread() const;
237 
set_client_cert_store_factory_for_testing(const base::Callback<scoped_ptr<net::ClientCertStore> ()> & factory)238   void set_client_cert_store_factory_for_testing(
239     const base::Callback<scoped_ptr<net::ClientCertStore>()>& factory) {
240       client_cert_store_factory_ = factory;
241   }
242 
243  protected:
244   // A URLRequestContext for media that owns its HTTP factory, to ensure
245   // it is deleted.
246   class MediaRequestContext : public ChromeURLRequestContext {
247    public:
248     MediaRequestContext();
249 
250     void SetHttpTransactionFactory(
251         scoped_ptr<net::HttpTransactionFactory> http_factory);
252 
253    private:
254     virtual ~MediaRequestContext();
255 
256     scoped_ptr<net::HttpTransactionFactory> http_factory_;
257   };
258 
259   // A URLRequestContext for apps that owns its cookie store and HTTP factory,
260   // to ensure they are deleted.
261   class AppRequestContext : public ChromeURLRequestContext {
262    public:
263     AppRequestContext();
264 
265     void SetCookieStore(net::CookieStore* cookie_store);
266     void SetHttpTransactionFactory(
267         scoped_ptr<net::HttpTransactionFactory> http_factory);
268     void SetJobFactory(scoped_ptr<net::URLRequestJobFactory> job_factory);
269 
270    private:
271     virtual ~AppRequestContext();
272 
273     scoped_refptr<net::CookieStore> cookie_store_;
274     scoped_ptr<net::HttpTransactionFactory> http_factory_;
275     scoped_ptr<net::URLRequestJobFactory> job_factory_;
276   };
277 
278   // Created on the UI thread, read on the IO thread during ProfileIOData lazy
279   // initialization.
280   struct ProfileParams {
281     ProfileParams();
282     ~ProfileParams();
283 
284     base::FilePath path;
285     IOThread* io_thread;
286     scoped_refptr<CookieSettings> cookie_settings;
287     scoped_refptr<HostContentSettingsMap> host_content_settings_map;
288     scoped_refptr<net::SSLConfigService> ssl_config_service;
289     scoped_refptr<net::CookieMonster::Delegate> cookie_monster_delegate;
290     scoped_refptr<extensions::InfoMap> extension_info_map;
291 
292     // This pointer exists only as a means of conveying a url job factory
293     // pointer from the protocol handler registry on the UI thread to the
294     // the URLRequestContext on the IO thread. The consumer MUST take
295     // ownership of the object by calling release() on this pointer.
296     scoped_ptr<ProtocolHandlerRegistry::JobInterceptorFactory>
297         protocol_handler_interceptor;
298 
299     // We need to initialize the ProxyConfigService from the UI thread
300     // because on linux it relies on initializing things through gconf,
301     // and needs to be on the main thread.
302     scoped_ptr<net::ProxyConfigService> proxy_config_service;
303 
304 #if defined(ENABLE_MANAGED_USERS)
305     scoped_refptr<const SupervisedUserURLFilter> supervised_user_url_filter;
306 #endif
307 
308 #if defined(OS_CHROMEOS)
309     std::string username_hash;
310 #endif
311 
312     // The profile this struct was populated from. It's passed as a void* to
313     // ensure it's not accidently used on the IO thread. Before using it on the
314     // UI thread, call ProfileManager::IsValidProfile to ensure it's alive.
315     void* profile;
316 
317     prerender::PrerenderTracker* prerender_tracker;
318   };
319 
320   explicit ProfileIOData(Profile::ProfileType profile_type);
321 
322   static std::string GetSSLSessionCacheShard();
323 
324   void InitializeOnUIThread(Profile* profile);
325   void ApplyProfileParamsToContext(ChromeURLRequestContext* context) const;
326 
327   scoped_ptr<net::URLRequestJobFactory> SetUpJobFactoryDefaults(
328       scoped_ptr<net::URLRequestJobFactoryImpl> job_factory,
329       content::URLRequestInterceptorScopedVector request_interceptors,
330       scoped_ptr<ProtocolHandlerRegistry::JobInterceptorFactory>
331           protocol_handler_interceptor,
332       net::NetworkDelegate* network_delegate,
333       net::FtpTransactionFactory* ftp_transaction_factory) const;
334 
335   // Called when the profile is destroyed.
336   void ShutdownOnUIThread();
337 
338   // A ServerBoundCertService object is created by a derived class of
339   // ProfileIOData, and the derived class calls this method to set the
340   // server_bound_cert_service_ member and transfers ownership to the base
341   // class.
342   void set_server_bound_cert_service(
343       net::ServerBoundCertService* server_bound_cert_service) const;
344 
network_delegate()345   ChromeNetworkDelegate* network_delegate() const {
346     return network_delegate_.get();
347   }
348 
fraudulent_certificate_reporter()349   net::FraudulentCertificateReporter* fraudulent_certificate_reporter() const {
350     return fraudulent_certificate_reporter_.get();
351   }
352 
proxy_service()353   net::ProxyService* proxy_service() const {
354     return proxy_service_.get();
355   }
356 
357   base::WeakPtr<net::HttpServerProperties> http_server_properties() const;
358 
359   void set_http_server_properties(
360       scoped_ptr<net::HttpServerProperties> http_server_properties) const;
361 
main_request_context()362   ChromeURLRequestContext* main_request_context() const {
363     return main_request_context_.get();
364   }
365 
initialized()366   bool initialized() const {
367     return initialized_;
368   }
369 
370   // Destroys the ResourceContext first, to cancel any URLRequests that are
371   // using it still, before we destroy the member variables that those
372   // URLRequests may be accessing.
373   void DestroyResourceContext();
374 
375   // Creates network session and main network transaction factory.
376   scoped_ptr<net::HttpCache> CreateMainHttpFactory(
377       const ProfileParams* profile_params,
378       net::HttpCache::BackendFactory* main_backend) const;
379 
380   // Creates network transaction factory.
381   scoped_ptr<net::HttpCache> CreateHttpFactory(
382       net::HttpNetworkSession* shared_session,
383       net::HttpCache::BackendFactory* backend) const;
384 
385   void SetCookieSettingsForTesting(CookieSettings* cookie_settings);
386 
387   void set_signin_names_for_testing(SigninNamesOnIOThread* signin_names);
388 
389  private:
390   class ResourceContext : public content::ResourceContext {
391    public:
392     explicit ResourceContext(ProfileIOData* io_data);
393     virtual ~ResourceContext();
394 
395     // ResourceContext implementation:
396     virtual net::HostResolver* GetHostResolver() OVERRIDE;
397     virtual net::URLRequestContext* GetRequestContext() OVERRIDE;
398     virtual scoped_ptr<net::ClientCertStore> CreateClientCertStore() OVERRIDE;
399     virtual void CreateKeygenHandler(
400         uint32 key_size_in_bits,
401         const std::string& challenge_string,
402         const GURL& url,
403         const base::Callback<void(scoped_ptr<net::KeygenHandler>)>& callback)
404         OVERRIDE;
405     virtual bool AllowMicAccess(const GURL& origin) OVERRIDE;
406     virtual bool AllowCameraAccess(const GURL& origin) OVERRIDE;
407     virtual SaltCallback GetMediaDeviceIDSalt() OVERRIDE;
408 
409    private:
410     friend class ProfileIOData;
411 
412     // Helper method that returns true if |type| is allowed for |origin|, false
413     // otherwise.
414     bool AllowContentAccess(const GURL& origin, ContentSettingsType type);
415 
416     ProfileIOData* const io_data_;
417 
418     net::HostResolver* host_resolver_;
419     net::URLRequestContext* request_context_;
420   };
421 
422   typedef std::map<StoragePartitionDescriptor,
423                    ChromeURLRequestContext*,
424                    StoragePartitionDescriptorLess>
425       URLRequestContextMap;
426 
427   // --------------------------------------------
428   // Virtual interface for subtypes to implement:
429   // --------------------------------------------
430 
431   // Does the actual initialization of the ProfileIOData subtype. Subtypes
432   // should use the static helper functions above to implement this.
433   virtual void InitializeInternal(
434       ProfileParams* profile_params,
435       content::ProtocolHandlerMap* protocol_handlers,
436       content::URLRequestInterceptorScopedVector
437           request_interceptors) const = 0;
438 
439   // Initializes the RequestContext for extensions.
440   virtual void InitializeExtensionsRequestContext(
441       ProfileParams* profile_params) const = 0;
442   // Does an on-demand initialization of a RequestContext for the given
443   // isolated app.
444   virtual ChromeURLRequestContext* InitializeAppRequestContext(
445       ChromeURLRequestContext* main_context,
446       const StoragePartitionDescriptor& details,
447       scoped_ptr<ProtocolHandlerRegistry::JobInterceptorFactory>
448           protocol_handler_interceptor,
449       content::ProtocolHandlerMap* protocol_handlers,
450       content::URLRequestInterceptorScopedVector
451           request_interceptors) const = 0;
452 
453   // Does an on-demand initialization of a media RequestContext for the given
454   // isolated app.
455   virtual ChromeURLRequestContext* InitializeMediaRequestContext(
456       ChromeURLRequestContext* original_context,
457       const StoragePartitionDescriptor& details) const = 0;
458 
459   // These functions are used to transfer ownership of the lazily initialized
460   // context from ProfileIOData to the URLRequestContextGetter.
461   virtual ChromeURLRequestContext*
462       AcquireMediaRequestContext() const = 0;
463   virtual ChromeURLRequestContext* AcquireIsolatedAppRequestContext(
464       ChromeURLRequestContext* main_context,
465       const StoragePartitionDescriptor& partition_descriptor,
466       scoped_ptr<ProtocolHandlerRegistry::JobInterceptorFactory>
467           protocol_handler_interceptor,
468       content::ProtocolHandlerMap* protocol_handlers,
469       content::URLRequestInterceptorScopedVector
470           request_interceptors) const = 0;
471   virtual ChromeURLRequestContext*
472       AcquireIsolatedMediaRequestContext(
473           ChromeURLRequestContext* app_context,
474           const StoragePartitionDescriptor& partition_descriptor) const = 0;
475 
476   // The order *DOES* matter for the majority of these member variables, so
477   // don't move them around unless you know what you're doing!
478   // General rules:
479   //   * ResourceContext references the URLRequestContexts, so
480   //   URLRequestContexts must outlive ResourceContext, hence ResourceContext
481   //   should be destroyed first.
482   //   * URLRequestContexts reference a whole bunch of members, so
483   //   URLRequestContext needs to be destroyed before them.
484   //   * Therefore, ResourceContext should be listed last, and then the
485   //   URLRequestContexts, and then the URLRequestContext members.
486   //   * Note that URLRequestContext members have a directed dependency graph
487   //   too, so they must themselves be ordered correctly.
488 
489   // Tracks whether or not we've been lazily initialized.
490   mutable bool initialized_;
491 
492   // Data from the UI thread from the Profile, used to initialize ProfileIOData.
493   // Deleted after lazy initialization.
494   mutable scoped_ptr<ProfileParams> profile_params_;
495 
496   // Provides access to the email addresses of all signed in profiles.
497   mutable scoped_ptr<SigninNamesOnIOThread> signin_names_;
498 
499   // Used for testing.
500   mutable base::Callback<scoped_ptr<net::ClientCertStore>()>
501       client_cert_store_factory_;
502 
503   mutable StringPrefMember google_services_user_account_id_;
504   mutable StringPrefMember google_services_username_;
505   mutable StringPrefMember google_services_username_pattern_;
506   mutable BooleanPrefMember reverse_autologin_enabled_;
507 
508   // During the reverse autologin request chain processing, this member saves
509   // the email of the google account that is being signed into.
510   std::string reverse_autologin_pending_email_;
511 
512   mutable StringListPrefMember one_click_signin_rejected_email_list_;
513 
514   mutable scoped_refptr<MediaDeviceIDSalt> media_device_id_salt_;
515 
516   // Member variables which are pointed to by the various context objects.
517   mutable BooleanPrefMember enable_referrers_;
518   mutable BooleanPrefMember enable_do_not_track_;
519   mutable BooleanPrefMember force_safesearch_;
520   mutable BooleanPrefMember safe_browsing_enabled_;
521   mutable BooleanPrefMember data_reduction_proxy_enabled_;
522   mutable BooleanPrefMember printing_enabled_;
523   mutable BooleanPrefMember sync_disabled_;
524   mutable BooleanPrefMember signin_allowed_;
525   mutable BooleanPrefMember network_prediction_enabled_;
526   // TODO(marja): Remove session_startup_pref_ if no longer needed.
527   mutable IntegerPrefMember session_startup_pref_;
528   mutable BooleanPrefMember quick_check_enabled_;
529   mutable IntegerPrefMember incognito_availibility_pref_;
530 
531   // The state of metrics reporting in the browser that this profile runs on.
532   // Unfortunately, since ChromeOS has a separate representation of this state,
533   // we need to make one available based on the platform.
534 #if defined(OS_CHROMEOS)
535   bool enable_metrics_;
536 #else
537   BooleanPrefMember enable_metrics_;
538 #endif
539 
540 #if defined(ENABLE_CONFIGURATION_POLICY)
541   // Pointed to by NetworkDelegate.
542   mutable scoped_ptr<policy::URLBlacklistManager> url_blacklist_manager_;
543   mutable scoped_ptr<policy::PolicyHeaderIOHelper> policy_header_helper_;
544 #endif
545 
546   // Pointed to by URLRequestContext.
547   mutable scoped_refptr<extensions::InfoMap> extension_info_map_;
548   mutable scoped_ptr<net::ServerBoundCertService> server_bound_cert_service_;
549   mutable scoped_ptr<ChromeNetworkDelegate> network_delegate_;
550   mutable scoped_ptr<net::FraudulentCertificateReporter>
551       fraudulent_certificate_reporter_;
552   mutable scoped_ptr<net::ProxyService> proxy_service_;
553   mutable scoped_ptr<net::TransportSecurityState> transport_security_state_;
554   mutable scoped_ptr<net::HttpServerProperties>
555       http_server_properties_;
556 #if defined(OS_CHROMEOS)
557   mutable scoped_ptr<policy::PolicyCertVerifier> cert_verifier_;
558   mutable std::string username_hash_;
559 #endif
560 
561   mutable scoped_ptr<net::TransportSecurityPersister>
562       transport_security_persister_;
563 
564   // These are only valid in between LazyInitialize() and their accessor being
565   // called.
566   mutable scoped_ptr<ChromeURLRequestContext> main_request_context_;
567   mutable scoped_ptr<ChromeURLRequestContext> extensions_request_context_;
568   // One URLRequestContext per isolated app for main and media requests.
569   mutable URLRequestContextMap app_request_context_map_;
570   mutable URLRequestContextMap isolated_media_request_context_map_;
571 
572   mutable scoped_ptr<ResourceContext> resource_context_;
573 
574   mutable scoped_refptr<CookieSettings> cookie_settings_;
575 
576   mutable scoped_refptr<HostContentSettingsMap> host_content_settings_map_;
577 
578   mutable scoped_ptr<ChromeHttpUserAgentSettings>
579       chrome_http_user_agent_settings_;
580 
581 #if defined(ENABLE_MANAGED_USERS)
582   mutable scoped_refptr<const SupervisedUserURLFilter>
583       supervised_user_url_filter_;
584 #endif
585 
586   mutable scoped_ptr<DevToolsNetworkController> network_controller_;
587 
588   // TODO(jhawkins): Remove once crbug.com/102004 is fixed.
589   bool initialized_on_UI_thread_;
590 
591   const Profile::ProfileType profile_type_;
592 
593   DISALLOW_COPY_AND_ASSIGN(ProfileIOData);
594 };
595 
596 #endif  // CHROME_BROWSER_PROFILES_PROFILE_IO_DATA_H_
597