// Copyright (c) 2012 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/protector/protector_service.h" #include "base/command_line.h" #include "base/logging.h" #include "chrome/browser/browser_process.h" #include "chrome/browser/prefs/pref_service.h" #include "chrome/browser/protector/settings_change_global_error.h" #include "chrome/browser/protector/keys.h" #include "chrome/browser/ui/browser.h" #include "chrome/common/chrome_notification_types.h" #include "chrome/common/chrome_switches.h" #include "chrome/common/pref_names.h" #include "content/public/browser/notification_source.h" #include "crypto/hmac.h" namespace protector { ProtectorService::ProtectorService(Profile* profile) : profile_(profile) { } ProtectorService::~ProtectorService() { DCHECK(!IsShowingChange()); // Should have been dismissed by Shutdown. } void ProtectorService::ShowChange(BaseSettingChange* change) { DCHECK(change); Item new_item; new_item.change.reset(change); DVLOG(1) << "Init change"; if (!change->Init(profile_)) { LOG(WARNING) << "Error while initializing, dismissing change"; return; } SettingsChangeGlobalError* error = new SettingsChangeGlobalError(change, this); new_item.error.reset(error); items_.push_back(new_item); error->ShowForProfile(profile_); } bool ProtectorService::IsShowingChange() const { return !items_.empty(); } void ProtectorService::ApplyChange(BaseSettingChange* change, Browser* browser) { change->Apply(browser); DismissChange(change); } void ProtectorService::DiscardChange(BaseSettingChange* change, Browser* browser) { change->Discard(browser); DismissChange(change); } void ProtectorService::DismissChange(BaseSettingChange* change) { std::vector::iterator item = std::find_if(items_.begin(), items_.end(), MatchItemByChange(change)); DCHECK(item != items_.end()); item->error->RemoveFromProfile(); } void ProtectorService::OpenTab(const GURL& url, Browser* browser) { DCHECK(browser); browser->ShowSingletonTab(url); } void ProtectorService::Shutdown() { while (IsShowingChange()) items_[0].error->RemoveFromProfile(); } void ProtectorService::OnApplyChange(SettingsChangeGlobalError* error, Browser* browser) { DVLOG(1) << "Apply change"; error->change()->Apply(browser); } void ProtectorService::OnDiscardChange(SettingsChangeGlobalError* error, Browser* browser) { DVLOG(1) << "Discard change"; error->change()->Discard(browser); } void ProtectorService::OnDecisionTimeout(SettingsChangeGlobalError* error) { DVLOG(1) << "Timeout"; error->change()->Timeout(); } void ProtectorService::OnRemovedFromProfile(SettingsChangeGlobalError* error) { std::vector::iterator item = std::find_if(items_.begin(), items_.end(), MatchItemByError(error)); DCHECK(item != items_.end()); items_.erase(item); } BaseSettingChange* ProtectorService::GetLastChange() { return items_.empty() ? NULL : items_.back().change.get(); } ProtectorService::Item::Item() { } ProtectorService::Item::~Item() { } ProtectorService::MatchItemByChange::MatchItemByChange( const BaseSettingChange* other) : other_(other) { } bool ProtectorService::MatchItemByChange::operator()( const ProtectorService::Item& item) { return other_ == item.change.get(); } ProtectorService::MatchItemByError::MatchItemByError( const SettingsChangeGlobalError* other) : other_(other) { } bool ProtectorService::MatchItemByError::operator()( const ProtectorService::Item& item) { return other_ == item.error.get(); } std::string SignSetting(const std::string& value) { crypto::HMAC hmac(crypto::HMAC::SHA256); if (!hmac.Init(kProtectorSigningKey)) { LOG(WARNING) << "Failed to initialize HMAC algorithm for signing"; return std::string(); } std::vector digest(hmac.DigestLength()); if (!hmac.Sign(value, &digest[0], digest.size())) { LOG(WARNING) << "Failed to sign setting"; return std::string(); } return std::string(&digest[0], &digest[0] + digest.size()); } bool IsSettingValid(const std::string& value, const std::string& signature) { crypto::HMAC hmac(crypto::HMAC::SHA256); if (!hmac.Init(kProtectorSigningKey)) { LOG(WARNING) << "Failed to initialize HMAC algorithm for verification."; return false; } return hmac.Verify(value, signature); } bool IsEnabled() { return !CommandLine::ForCurrentProcess()->HasSwitch(switches::kNoProtector); } } // namespace protector