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.
CoCreateIndexerFromName(const wchar_t * name,IChromeHistoryIndexer ** indexer)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.
AddRegisteredIndexers(HKEY root,const wchar_t * path,std::vector<base::win::ScopedComPtr<IChromeHistoryIndexer>> * indexers)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
TimeToUTCVariantTime(const base::Time & time)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
HistoryPublisher()86 HistoryPublisher::HistoryPublisher() {
87 CoInitialize(NULL);
88 }
89
~HistoryPublisher()90 HistoryPublisher::~HistoryPublisher() {
91 CoUninitialize();
92 }
93
Init()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.
ReadRegisteredIndexersFromRegistry()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
PublishDataToIndexers(const PageData & page_data) const109 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
DeleteUserHistoryBetween(const base::Time & begin_time,const base::Time & end_time) const134 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