|
1 /* This Source Code Form is subject to the terms of the Mozilla Public |
|
2 * License, v. 2.0. If a copy of the MPL was not distributed with this file, |
|
3 * You can obtain one at http://mozilla.org/MPL/2.0/. */ |
|
4 |
|
5 #include "nsIEHistoryEnumerator.h" |
|
6 |
|
7 #include <urlhist.h> |
|
8 #include <shlguid.h> |
|
9 |
|
10 #include "nsStringAPI.h" |
|
11 #include "nsNetUtil.h" |
|
12 #include "nsIVariant.h" |
|
13 #include "nsCOMArray.h" |
|
14 #include "nsArrayEnumerator.h" |
|
15 |
|
16 namespace { |
|
17 |
|
18 PRTime FileTimeToPRTime(FILETIME* filetime) |
|
19 { |
|
20 SYSTEMTIME st; |
|
21 ::FileTimeToSystemTime(filetime, &st); |
|
22 PRExplodedTime prt; |
|
23 prt.tm_year = st.wYear; |
|
24 // SYSTEMTIME's day-of-month parameter is 1-based, |
|
25 // PRExplodedTime's is 0-based. |
|
26 prt.tm_month = st.wMonth - 1; |
|
27 prt.tm_mday = st.wDay; |
|
28 prt.tm_hour = st.wHour; |
|
29 prt.tm_min = st.wMinute; |
|
30 prt.tm_sec = st.wSecond; |
|
31 prt.tm_usec = st.wMilliseconds * 1000; |
|
32 prt.tm_wday = 0; |
|
33 prt.tm_yday = 0; |
|
34 prt.tm_params.tp_gmt_offset = 0; |
|
35 prt.tm_params.tp_dst_offset = 0; |
|
36 return PR_ImplodeTime(&prt); |
|
37 } |
|
38 |
|
39 } // Anonymous namespace. |
|
40 |
|
41 //////////////////////////////////////////////////////////////////////////////// |
|
42 //// nsIEHistoryEnumerator |
|
43 |
|
44 NS_IMPL_ISUPPORTS(nsIEHistoryEnumerator, nsISimpleEnumerator) |
|
45 |
|
46 nsIEHistoryEnumerator::nsIEHistoryEnumerator() |
|
47 { |
|
48 ::CoInitialize(nullptr); |
|
49 } |
|
50 |
|
51 nsIEHistoryEnumerator::~nsIEHistoryEnumerator() |
|
52 { |
|
53 ::CoUninitialize(); |
|
54 } |
|
55 |
|
56 void |
|
57 nsIEHistoryEnumerator::EnsureInitialized() |
|
58 { |
|
59 if (mURLEnumerator) |
|
60 return; |
|
61 |
|
62 HRESULT hr = ::CoCreateInstance(CLSID_CUrlHistory, |
|
63 nullptr, |
|
64 CLSCTX_INPROC_SERVER, |
|
65 IID_IUrlHistoryStg2, |
|
66 getter_AddRefs(mIEHistory)); |
|
67 if (FAILED(hr)) |
|
68 return; |
|
69 |
|
70 hr = mIEHistory->EnumUrls(getter_AddRefs(mURLEnumerator)); |
|
71 if (FAILED(hr)) |
|
72 return; |
|
73 } |
|
74 |
|
75 NS_IMETHODIMP |
|
76 nsIEHistoryEnumerator::HasMoreElements(bool* _retval) |
|
77 { |
|
78 *_retval = false; |
|
79 |
|
80 EnsureInitialized(); |
|
81 MOZ_ASSERT(mURLEnumerator, "Should have instanced an IE History URLEnumerator"); |
|
82 if (!mURLEnumerator) |
|
83 return NS_OK; |
|
84 |
|
85 STATURL statURL; |
|
86 ULONG fetched; |
|
87 |
|
88 // First argument is not implemented, so doesn't matter what we pass. |
|
89 HRESULT hr = mURLEnumerator->Next(1, &statURL, &fetched); |
|
90 if (FAILED(hr) || fetched != 1UL) { |
|
91 // Reached the last entry. |
|
92 return NS_OK; |
|
93 } |
|
94 |
|
95 nsCOMPtr<nsIURI> uri; |
|
96 if (statURL.pwcsUrl) { |
|
97 nsDependentString url(statURL.pwcsUrl); |
|
98 nsresult rv = NS_NewURI(getter_AddRefs(uri), url); |
|
99 ::CoTaskMemFree(statURL.pwcsUrl); |
|
100 if (NS_FAILED(rv)) { |
|
101 // Got a corrupt or invalid URI, continue to the next entry. |
|
102 return HasMoreElements(_retval); |
|
103 } |
|
104 } |
|
105 |
|
106 nsDependentString title(statURL.pwcsTitle); |
|
107 |
|
108 PRTime lastVisited = FileTimeToPRTime(&(statURL.ftLastVisited)); |
|
109 |
|
110 mCachedNextEntry = do_CreateInstance("@mozilla.org/hash-property-bag;1"); |
|
111 MOZ_ASSERT(mCachedNextEntry, "Should have instanced a new property bag"); |
|
112 if (mCachedNextEntry) { |
|
113 mCachedNextEntry->SetPropertyAsInterface(NS_LITERAL_STRING("uri"), uri); |
|
114 mCachedNextEntry->SetPropertyAsAString(NS_LITERAL_STRING("title"), title); |
|
115 mCachedNextEntry->SetPropertyAsInt64(NS_LITERAL_STRING("time"), lastVisited); |
|
116 |
|
117 *_retval = true; |
|
118 } |
|
119 |
|
120 if (statURL.pwcsTitle) |
|
121 ::CoTaskMemFree(statURL.pwcsTitle); |
|
122 |
|
123 return NS_OK; |
|
124 } |
|
125 |
|
126 NS_IMETHODIMP |
|
127 nsIEHistoryEnumerator::GetNext(nsISupports** _retval) |
|
128 { |
|
129 *_retval = nullptr; |
|
130 |
|
131 if (!mCachedNextEntry) |
|
132 return NS_ERROR_FAILURE; |
|
133 |
|
134 NS_ADDREF(*_retval = mCachedNextEntry); |
|
135 // Release the cached entry, so it can't be returned twice. |
|
136 mCachedNextEntry = nullptr; |
|
137 |
|
138 return NS_OK; |
|
139 } |