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 21namespace { 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. 26bool 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. 42void 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 58namespace history { 59 60const wchar_t* const HistoryPublisher::kRegKeyRegisteredIndexersInfo = 61 L"Software\\Google\\Google Chrome\\IndexerPlugins"; 62 63// static 64double 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 86HistoryPublisher::HistoryPublisher() { 87 CoInitialize(NULL); 88} 89 90HistoryPublisher::~HistoryPublisher() { 91 CoUninitialize(); 92} 93 94bool 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. 101bool HistoryPublisher::ReadRegisteredIndexersFromRegistry() { 102 AddRegisteredIndexers(HKEY_CURRENT_USER, 103 kRegKeyRegisteredIndexersInfo, &indexers_); 104 AddRegisteredIndexers(HKEY_LOCAL_MACHINE, 105 kRegKeyRegisteredIndexersInfo, &indexers_); 106 return !indexers_.empty(); 107} 108 109void 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 134void 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