Home | History | Annotate | Download | only in diagnostics
      1 // Copyright (c) 2011 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 #include "chrome/browser/diagnostics/diagnostics_model.h"
      6 
      7 #include <algorithm>
      8 #include <vector>
      9 
     10 #include "base/basictypes.h"
     11 #include "base/command_line.h"
     12 #include "base/files/file_path.h"
     13 #include "base/path_service.h"
     14 #include "base/stl_util.h"
     15 #include "base/strings/string_util.h"
     16 #include "chrome/browser/diagnostics/diagnostics_test.h"
     17 #include "chrome/browser/diagnostics/recon_diagnostics.h"
     18 #include "chrome/browser/diagnostics/sqlite_diagnostics.h"
     19 #include "chrome/common/chrome_paths.h"
     20 #include "chrome/common/chrome_switches.h"
     21 
     22 namespace diagnostics {
     23 
     24 // This is the count of diagnostic tests on each platform.  This should
     25 // only be used by testing code.
     26 #if defined(OS_WIN)
     27 const int DiagnosticsModel::kDiagnosticsTestCount = 17;
     28 #elif defined(OS_MACOSX)
     29 const int DiagnosticsModel::kDiagnosticsTestCount = 13;
     30 #elif defined(OS_POSIX)
     31 #if defined(OS_CHROMEOS)
     32 const int DiagnosticsModel::kDiagnosticsTestCount = 17;
     33 #else
     34 const int DiagnosticsModel::kDiagnosticsTestCount = 15;
     35 #endif
     36 #endif
     37 
     38 namespace {
     39 
     40 // Embodies the commonalities of the model across platforms. It manages the
     41 // list of tests and can loop over them. The main job of the platform specific
     42 // code becomes:
     43 // 1- Inserting the appropriate tests into |tests_|
     44 // 2- Overriding RunTest() to wrap it with the appropriate fatal exception
     45 //    handler for the OS.
     46 // This class owns the all the tests and will only delete them upon
     47 // destruction.
     48 class DiagnosticsModelImpl : public DiagnosticsModel {
     49  public:
     50   DiagnosticsModelImpl() : tests_run_(0) {}
     51 
     52   virtual ~DiagnosticsModelImpl() { STLDeleteElements(&tests_); }
     53 
     54   virtual int GetTestRunCount() const OVERRIDE { return tests_run_; }
     55 
     56   virtual int GetTestAvailableCount() const OVERRIDE { return tests_.size(); }
     57 
     58   virtual void RunAll(DiagnosticsModel::Observer* observer) OVERRIDE {
     59     size_t test_count = tests_.size();
     60     bool continue_running = true;
     61     for (size_t i = 0; i != test_count; ++i) {
     62       // If one of the diagnostic steps returns false, we want to
     63       // mark the rest of them as "skipped" in the UMA stats.
     64       if (continue_running) {
     65         continue_running = RunTest(tests_[i], observer, i);
     66         ++tests_run_;
     67       } else {
     68 #if defined(OS_CHROMEOS)  // Only collecting UMA stats on ChromeOS
     69         RecordUMATestResult(static_cast<DiagnosticsTestId>(tests_[i]->GetId()),
     70                             RESULT_SKIPPED);
     71 #else
     72         // On other platforms, we can just bail out if a diagnostic step returns
     73         // false.
     74         break;
     75 #endif
     76       }
     77     }
     78     if (observer)
     79       observer->OnAllTestsDone(this);
     80   }
     81 
     82   virtual void RecoverAll(DiagnosticsModel::Observer* observer) OVERRIDE {
     83     size_t test_count = tests_.size();
     84     bool continue_running = true;
     85     for (size_t i = 0; i != test_count; ++i) {
     86       // If one of the recovery steps returns false, we want to
     87       // mark the rest of them as "skipped" in the UMA stats.
     88       if (continue_running) {
     89         continue_running = RunRecovery(tests_[i], observer, i);
     90       } else {
     91 #if defined(OS_CHROMEOS)  // Only collecting UMA stats on ChromeOS
     92         RecordUMARecoveryResult(
     93             static_cast<DiagnosticsTestId>(tests_[i]->GetId()), RESULT_SKIPPED);
     94 #else
     95         // On other platforms, we can just bail out if a recovery step returns
     96         // false.
     97         break;
     98 #endif
     99       }
    100     }
    101     if (observer)
    102       observer->OnAllRecoveryDone(this);
    103   }
    104 
    105   virtual const TestInfo& GetTest(size_t index) const OVERRIDE {
    106     return *tests_[index];
    107   }
    108 
    109   virtual bool GetTestInfo(int id, const TestInfo** result) const OVERRIDE {
    110     DCHECK(id < DIAGNOSTICS_TEST_ID_COUNT);
    111     DCHECK(id >= 0);
    112     for (size_t i = 0; i < tests_.size(); i++) {
    113       if (tests_[i]->GetId() == id) {
    114         *result = tests_[i];
    115         return true;
    116       }
    117     }
    118     return false;
    119   }
    120 
    121  protected:
    122   // Run a particular diagnostic test. Return false if no other tests should be
    123   // run.
    124   virtual bool RunTest(DiagnosticsTest* test,
    125                        Observer* observer,
    126                        size_t index) {
    127     return test->Execute(observer, this, index);
    128   }
    129 
    130   // Recover from a particular diagnostic test. Return false if no further
    131   // recovery should be run.
    132   virtual bool RunRecovery(DiagnosticsTest* test,
    133                            Observer* observer,
    134                            size_t index) {
    135     return test->Recover(observer, this, index);
    136   }
    137 
    138   typedef std::vector<DiagnosticsTest*> TestArray;
    139   TestArray tests_;
    140   int tests_run_;
    141 
    142  private:
    143   DISALLOW_COPY_AND_ASSIGN(DiagnosticsModelImpl);
    144 };
    145 
    146 // Each platform can have their own tests. For the time being there is only
    147 // one test that works on all platforms.
    148 #if defined(OS_WIN)
    149 class DiagnosticsModelWin : public DiagnosticsModelImpl {
    150  public:
    151   DiagnosticsModelWin() {
    152     tests_.push_back(MakeOperatingSystemTest());
    153     tests_.push_back(MakeConflictingDllsTest());
    154     tests_.push_back(MakeInstallTypeTest());
    155     tests_.push_back(MakeVersionTest());
    156     tests_.push_back(MakeUserDirTest());
    157     tests_.push_back(MakeLocalStateFileTest());
    158     tests_.push_back(MakeDictonaryDirTest());
    159     tests_.push_back(MakeResourcesFileTest());
    160     tests_.push_back(MakeDiskSpaceTest());
    161     tests_.push_back(MakePreferencesTest());
    162     tests_.push_back(MakeLocalStateTest());
    163     tests_.push_back(MakeBookMarksTest());
    164     tests_.push_back(MakeSqliteWebDataDbTest());
    165     tests_.push_back(MakeSqliteCookiesDbTest());
    166     tests_.push_back(MakeSqliteHistoryDbTest());
    167     tests_.push_back(MakeSqliteThumbnailsDbTest());
    168     tests_.push_back(MakeSqliteWebDatabaseTrackerDbTest());
    169   }
    170 
    171  private:
    172   DISALLOW_COPY_AND_ASSIGN(DiagnosticsModelWin);
    173 };
    174 
    175 #elif defined(OS_MACOSX)
    176 class DiagnosticsModelMac : public DiagnosticsModelImpl {
    177  public:
    178   DiagnosticsModelMac() {
    179     tests_.push_back(MakeInstallTypeTest());
    180     tests_.push_back(MakeUserDirTest());
    181     tests_.push_back(MakeLocalStateFileTest());
    182     tests_.push_back(MakeDictonaryDirTest());
    183     tests_.push_back(MakeDiskSpaceTest());
    184     tests_.push_back(MakePreferencesTest());
    185     tests_.push_back(MakeLocalStateTest());
    186     tests_.push_back(MakeBookMarksTest());
    187     tests_.push_back(MakeSqliteWebDataDbTest());
    188     tests_.push_back(MakeSqliteCookiesDbTest());
    189     tests_.push_back(MakeSqliteHistoryDbTest());
    190     tests_.push_back(MakeSqliteThumbnailsDbTest());
    191     tests_.push_back(MakeSqliteWebDatabaseTrackerDbTest());
    192   }
    193 
    194  private:
    195   DISALLOW_COPY_AND_ASSIGN(DiagnosticsModelMac);
    196 };
    197 
    198 #elif defined(OS_POSIX)
    199 class DiagnosticsModelPosix : public DiagnosticsModelImpl {
    200  public:
    201   DiagnosticsModelPosix() {
    202     tests_.push_back(MakeInstallTypeTest());
    203     tests_.push_back(MakeVersionTest());
    204     tests_.push_back(MakeUserDirTest());
    205     tests_.push_back(MakeLocalStateFileTest());
    206     tests_.push_back(MakeDictonaryDirTest());
    207     tests_.push_back(MakeResourcesFileTest());
    208     tests_.push_back(MakeDiskSpaceTest());
    209     tests_.push_back(MakePreferencesTest());
    210     tests_.push_back(MakeLocalStateTest());
    211     tests_.push_back(MakeBookMarksTest());
    212     tests_.push_back(MakeSqliteWebDataDbTest());
    213     tests_.push_back(MakeSqliteCookiesDbTest());
    214     tests_.push_back(MakeSqliteHistoryDbTest());
    215     tests_.push_back(MakeSqliteThumbnailsDbTest());
    216     tests_.push_back(MakeSqliteWebDatabaseTrackerDbTest());
    217 #if defined(OS_CHROMEOS)
    218     tests_.push_back(MakeSqliteNssCertDbTest());
    219     tests_.push_back(MakeSqliteNssKeyDbTest());
    220 #endif
    221   }
    222 
    223  private:
    224   DISALLOW_COPY_AND_ASSIGN(DiagnosticsModelPosix);
    225 };
    226 
    227 #endif
    228 
    229 }  // namespace
    230 
    231 DiagnosticsModel* MakeDiagnosticsModel(const CommandLine& cmdline) {
    232   base::FilePath user_data_dir =
    233       cmdline.GetSwitchValuePath(switches::kUserDataDir);
    234   if (!user_data_dir.empty())
    235     PathService::Override(chrome::DIR_USER_DATA, user_data_dir);
    236 #if defined(OS_WIN)
    237   return new DiagnosticsModelWin();
    238 #elif defined(OS_MACOSX)
    239   return new DiagnosticsModelMac();
    240 #elif defined(OS_POSIX)
    241   return new DiagnosticsModelPosix();
    242 #endif
    243 }
    244 
    245 }  // namespace diagnostics
    246