michael@0: /* This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this file, michael@0: * You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: #include "nsIEHistoryEnumerator.h" michael@0: michael@0: #include michael@0: #include michael@0: michael@0: #include "nsStringAPI.h" michael@0: #include "nsNetUtil.h" michael@0: #include "nsIVariant.h" michael@0: #include "nsCOMArray.h" michael@0: #include "nsArrayEnumerator.h" michael@0: michael@0: namespace { michael@0: michael@0: PRTime FileTimeToPRTime(FILETIME* filetime) michael@0: { michael@0: SYSTEMTIME st; michael@0: ::FileTimeToSystemTime(filetime, &st); michael@0: PRExplodedTime prt; michael@0: prt.tm_year = st.wYear; michael@0: // SYSTEMTIME's day-of-month parameter is 1-based, michael@0: // PRExplodedTime's is 0-based. michael@0: prt.tm_month = st.wMonth - 1; michael@0: prt.tm_mday = st.wDay; michael@0: prt.tm_hour = st.wHour; michael@0: prt.tm_min = st.wMinute; michael@0: prt.tm_sec = st.wSecond; michael@0: prt.tm_usec = st.wMilliseconds * 1000; michael@0: prt.tm_wday = 0; michael@0: prt.tm_yday = 0; michael@0: prt.tm_params.tp_gmt_offset = 0; michael@0: prt.tm_params.tp_dst_offset = 0; michael@0: return PR_ImplodeTime(&prt); michael@0: } michael@0: michael@0: } // Anonymous namespace. michael@0: michael@0: //////////////////////////////////////////////////////////////////////////////// michael@0: //// nsIEHistoryEnumerator michael@0: michael@0: NS_IMPL_ISUPPORTS(nsIEHistoryEnumerator, nsISimpleEnumerator) michael@0: michael@0: nsIEHistoryEnumerator::nsIEHistoryEnumerator() michael@0: { michael@0: ::CoInitialize(nullptr); michael@0: } michael@0: michael@0: nsIEHistoryEnumerator::~nsIEHistoryEnumerator() michael@0: { michael@0: ::CoUninitialize(); michael@0: } michael@0: michael@0: void michael@0: nsIEHistoryEnumerator::EnsureInitialized() michael@0: { michael@0: if (mURLEnumerator) michael@0: return; michael@0: michael@0: HRESULT hr = ::CoCreateInstance(CLSID_CUrlHistory, michael@0: nullptr, michael@0: CLSCTX_INPROC_SERVER, michael@0: IID_IUrlHistoryStg2, michael@0: getter_AddRefs(mIEHistory)); michael@0: if (FAILED(hr)) michael@0: return; michael@0: michael@0: hr = mIEHistory->EnumUrls(getter_AddRefs(mURLEnumerator)); michael@0: if (FAILED(hr)) michael@0: return; michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: nsIEHistoryEnumerator::HasMoreElements(bool* _retval) michael@0: { michael@0: *_retval = false; michael@0: michael@0: EnsureInitialized(); michael@0: MOZ_ASSERT(mURLEnumerator, "Should have instanced an IE History URLEnumerator"); michael@0: if (!mURLEnumerator) michael@0: return NS_OK; michael@0: michael@0: STATURL statURL; michael@0: ULONG fetched; michael@0: michael@0: // First argument is not implemented, so doesn't matter what we pass. michael@0: HRESULT hr = mURLEnumerator->Next(1, &statURL, &fetched); michael@0: if (FAILED(hr) || fetched != 1UL) { michael@0: // Reached the last entry. michael@0: return NS_OK; michael@0: } michael@0: michael@0: nsCOMPtr uri; michael@0: if (statURL.pwcsUrl) { michael@0: nsDependentString url(statURL.pwcsUrl); michael@0: nsresult rv = NS_NewURI(getter_AddRefs(uri), url); michael@0: ::CoTaskMemFree(statURL.pwcsUrl); michael@0: if (NS_FAILED(rv)) { michael@0: // Got a corrupt or invalid URI, continue to the next entry. michael@0: return HasMoreElements(_retval); michael@0: } michael@0: } michael@0: michael@0: nsDependentString title(statURL.pwcsTitle); michael@0: michael@0: PRTime lastVisited = FileTimeToPRTime(&(statURL.ftLastVisited)); michael@0: michael@0: mCachedNextEntry = do_CreateInstance("@mozilla.org/hash-property-bag;1"); michael@0: MOZ_ASSERT(mCachedNextEntry, "Should have instanced a new property bag"); michael@0: if (mCachedNextEntry) { michael@0: mCachedNextEntry->SetPropertyAsInterface(NS_LITERAL_STRING("uri"), uri); michael@0: mCachedNextEntry->SetPropertyAsAString(NS_LITERAL_STRING("title"), title); michael@0: mCachedNextEntry->SetPropertyAsInt64(NS_LITERAL_STRING("time"), lastVisited); michael@0: michael@0: *_retval = true; michael@0: } michael@0: michael@0: if (statURL.pwcsTitle) michael@0: ::CoTaskMemFree(statURL.pwcsTitle); michael@0: michael@0: return NS_OK; michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: nsIEHistoryEnumerator::GetNext(nsISupports** _retval) michael@0: { michael@0: *_retval = nullptr; michael@0: michael@0: if (!mCachedNextEntry) michael@0: return NS_ERROR_FAILURE; michael@0: michael@0: NS_ADDREF(*_retval = mCachedNextEntry); michael@0: // Release the cached entry, so it can't be returned twice. michael@0: mCachedNextEntry = nullptr; michael@0: michael@0: return NS_OK; michael@0: }