Home | History | Annotate | Download | only in history
      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/history/history_publisher.h"
      6 
      7 #include <atlsafe.h>
      8 #include <objbase.h>
      9 #include <oleauto.h>
     10 #include <wtypes.h>
     11 
     12 #include "base/string_util.h"
     13 #include "base/time.h"
     14 #include "base/utf_string_conversions.h"
     15 #include "base/win/registry.h"
     16 #include "base/win/scoped_bstr.h"
     17 #include "base/win/scoped_comptr.h"
     18 #include "base/win/scoped_variant.h"
     19 #include "googleurl/src/gurl.h"
     20 
     21 namespace {
     22 
     23 // Instantiates a IChromeHistoryIndexer COM object. Takes a COM class id
     24 // in |name| and returns the object in |indexer|. Returns false if the
     25 // operation fails.
     26 bool CoCreateIndexerFromName(const wchar_t* name,
     27                              IChromeHistoryIndexer** indexer) {
     28   CLSID clsid;
     29   HRESULT hr = CLSIDFromString(const_cast<wchar_t*>(name), &clsid);
     30   if (FAILED(hr))
     31     return false;
     32   hr = CoCreateInstance(clsid, NULL, CLSCTX_INPROC,
     33                         __uuidof(IChromeHistoryIndexer),
     34                         reinterpret_cast<void**>(indexer));
     35   if (FAILED(hr))
     36     return false;
     37   return true;
     38 }
     39 
     40 // Instantiates the registered indexers from the registry |root| + |path| key
     41 // and adds them to the |indexers| list.
     42 void AddRegisteredIndexers(HKEY root, const wchar_t* path,
     43     std::vector< base::win::ScopedComPtr<IChromeHistoryIndexer> >* indexers) {
     44   IChromeHistoryIndexer* indexer;
     45   base::win::RegistryKeyIterator r_iter(root, path);
     46   while (r_iter.Valid()) {
     47     if (CoCreateIndexerFromName(r_iter.Name(), &indexer)) {
     48       indexers->push_back(
     49           base::win::ScopedComPtr<IChromeHistoryIndexer>(indexer));
     50       indexer->Release();
     51     }
     52     ++r_iter;
     53   }
     54 }
     55 
     56 }  // namespace
     57 
     58 namespace history {
     59 
     60 const wchar_t* const HistoryPublisher::kRegKeyRegisteredIndexersInfo =
     61     L"Software\\Google\\Google Chrome\\IndexerPlugins";
     62 
     63 // static
     64 double HistoryPublisher::TimeToUTCVariantTime(const base::Time& time) {
     65   double var_time = 0;
     66   if (!time.is_null()) {
     67     base::Time::Exploded exploded;
     68     time.UTCExplode(&exploded);
     69 
     70     // Create the system time struct representing our exploded time.
     71     SYSTEMTIME system_time;
     72     system_time.wYear = exploded.year;
     73     system_time.wMonth = exploded.month;
     74     system_time.wDayOfWeek = exploded.day_of_week;
     75     system_time.wDay = exploded.day_of_month;
     76     system_time.wHour = exploded.hour;
     77     system_time.wMinute = exploded.minute;
     78     system_time.wSecond = exploded.second;
     79     system_time.wMilliseconds = exploded.millisecond;
     80     SystemTimeToVariantTime(&system_time, &var_time);
     81   }
     82 
     83   return var_time;
     84 }
     85 
     86 HistoryPublisher::HistoryPublisher() {
     87   CoInitialize(NULL);
     88 }
     89 
     90 HistoryPublisher::~HistoryPublisher() {
     91   CoUninitialize();
     92 }
     93 
     94 bool HistoryPublisher::Init() {
     95   return ReadRegisteredIndexersFromRegistry();
     96 }
     97 
     98 // Peruse the registry for Indexer to instantiate and store in |indexers_|.
     99 // Return true if we found at least one indexer object. We look both in HKCU
    100 // and HKLM.
    101 bool HistoryPublisher::ReadRegisteredIndexersFromRegistry() {
    102   AddRegisteredIndexers(HKEY_CURRENT_USER,
    103                         kRegKeyRegisteredIndexersInfo, &indexers_);
    104   AddRegisteredIndexers(HKEY_LOCAL_MACHINE,
    105                         kRegKeyRegisteredIndexersInfo, &indexers_);
    106   return !indexers_.empty();
    107 }
    108 
    109 void HistoryPublisher::PublishDataToIndexers(const PageData& page_data)
    110     const {
    111   double var_time = TimeToUTCVariantTime(page_data.time);
    112 
    113   CComSafeArray<unsigned char> thumbnail_arr;
    114   if (page_data.thumbnail) {
    115     for (size_t i = 0; i < page_data.thumbnail->size(); ++i)
    116       thumbnail_arr.Add((*page_data.thumbnail)[i]);
    117   }
    118 
    119   // Send data to registered indexers.
    120   base::win::ScopedVariant time(var_time, VT_DATE);
    121   base::win::ScopedBstr url(ASCIIToWide(page_data.url.spec()).c_str());
    122   base::win::ScopedBstr html(page_data.html);
    123   base::win::ScopedBstr title(page_data.title);
    124   // Don't send a NULL string through ASCIIToWide.
    125   base::win::ScopedBstr format(page_data.thumbnail_format ?
    126       ASCIIToWide(page_data.thumbnail_format).c_str() :
    127       NULL);
    128   base::win::ScopedVariant psa(thumbnail_arr.m_psa);
    129   for (size_t i = 0; i < indexers_.size(); ++i) {
    130     indexers_[i]->SendPageData(time, url, html, title, format, psa);
    131   }
    132 }
    133 
    134 void HistoryPublisher::DeleteUserHistoryBetween(const base::Time& begin_time,
    135                                                 const base::Time& end_time)
    136     const {
    137   base::win::ScopedVariant var_begin_time(TimeToUTCVariantTime(begin_time),
    138                                           VT_DATE);
    139   base::win::ScopedVariant var_end_time(TimeToUTCVariantTime(end_time),
    140                                         VT_DATE);
    141   for (size_t i = 0; i < indexers_.size(); ++i) {
    142     indexers_[i]->DeleteUserHistoryBetween(var_begin_time, var_end_time);
    143   }
    144 }
    145 
    146 }  // namespace history
    147