| Index: chrome/installer/util/installer_state.cc
 | 
| ===================================================================
 | 
| --- chrome/installer/util/installer_state.cc	(revision 91508)
 | 
| +++ chrome/installer/util/installer_state.cc	(working copy)
 | 
| @@ -15,6 +15,7 @@
 | 
|  #include "base/string_util.h"
 | 
|  #include "base/utf_string_conversions.h"
 | 
|  #include "base/win/registry.h"
 | 
| +#include "base/win/scoped_handle.h"
 | 
|  #include "chrome/installer/util/delete_tree_work_item.h"
 | 
|  #include "chrome/installer/util/helper.h"
 | 
|  #include "chrome/installer/util/install_util.h"
 | 
| @@ -75,7 +76,8 @@
 | 
|        state_type_(BrowserDistribution::CHROME_BROWSER),
 | 
|        root_key_(NULL),
 | 
|        msi_(false),
 | 
| -      verbose_logging_(false) {
 | 
| +      verbose_logging_(false),
 | 
| +      is_chrome_frame_running_(false) {
 | 
|  }
 | 
|  
 | 
|  InstallerState::InstallerState(Level level)
 | 
| @@ -86,7 +88,8 @@
 | 
|        state_type_(BrowserDistribution::CHROME_BROWSER),
 | 
|        root_key_(NULL),
 | 
|        msi_(false),
 | 
| -      verbose_logging_(false) {
 | 
| +      verbose_logging_(false),
 | 
| +      is_chrome_frame_running_(false) {
 | 
|    // Use set_level() so that root_key_ is updated properly.
 | 
|    set_level(level);
 | 
|  }
 | 
| @@ -155,6 +158,8 @@
 | 
|  
 | 
|    state_key_ = operand->GetStateKey();
 | 
|    state_type_ = operand->GetType();
 | 
| +
 | 
| +  is_chrome_frame_running_ = DetectChromeFrameInUse(machine_state);
 | 
|  }
 | 
|  
 | 
|  void InstallerState::set_level(Level level) {
 | 
| @@ -417,6 +422,32 @@
 | 
|        .Append(kInstallerDir);
 | 
|  }
 | 
|  
 | 
| +// static
 | 
| +bool InstallerState::IsFileInUse(const FilePath& file) {
 | 
| +  // Call CreateFile with a share mode of 0 which should cause this to fail
 | 
| +  // with ERROR_SHARING_VIOLATION if the file exists and is in-use.
 | 
| +  return !base::win::ScopedHandle(CreateFile(file.value().c_str(),
 | 
| +                                             GENERIC_WRITE, 0, NULL,
 | 
| +                                             OPEN_EXISTING, 0, 0)).IsValid();
 | 
| +}
 | 
| +
 | 
| +bool InstallerState::DetectChromeFrameInUse(
 | 
| +    const InstallationState& machine_state) {
 | 
| +  // We check only for the current version (e.g. the version we are upgrading
 | 
| +  // _from_). We don't need to check interstitial versions if any (as would
 | 
| +  // occur in the case of multiple updates) since if they are in use, we are
 | 
| +  // guaranteed that the current version is in use too.
 | 
| +  bool in_use = false;
 | 
| +  scoped_ptr<Version> current_version(GetCurrentVersion(machine_state));
 | 
| +  if (current_version != NULL) {
 | 
| +    FilePath cf_install_path(
 | 
| +        target_path().AppendASCII(current_version->GetString())
 | 
| +                     .Append(kChromeFrameDll));
 | 
| +    in_use = IsFileInUse(cf_install_path);
 | 
| +  }
 | 
| +  return in_use;
 | 
| +}
 | 
| +
 | 
|  void InstallerState::RemoveOldVersionDirectories(
 | 
|      const Version& new_version,
 | 
|      Version* existing_version,
 | 
| 
 |