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