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