Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1516)

Unified Diff: chrome/utility/importer/edge_database_reader_win.cc

Issue 1465853002: Implement support for importing favorites from Edge on Windows 10. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Added missing include files Created 5 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: chrome/utility/importer/edge_database_reader_win.cc
diff --git a/chrome/utility/importer/edge_database_reader_win.cc b/chrome/utility/importer/edge_database_reader_win.cc
new file mode 100644
index 0000000000000000000000000000000000000000..58f4b2024d4f349124b17195fff168d43ea65406
--- /dev/null
+++ b/chrome/utility/importer/edge_database_reader_win.cc
@@ -0,0 +1,257 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/utility/importer/edge_database_reader_win.h"
+
+#include <windows.h>
+
+#include <vector>
+
+namespace {
+
+// This is an arbitary size chosen for the database error message buffer.
+const size_t kErrorMessageSize = 1024;
+// This is the page size of the Edge data. It's unlikely to change.
+const JET_API_PTR kEdgeDatabasePageSize = 8192;
+// This is the code page value for a Unicode (UCS-2) column.
+const unsigned short kJetUnicodeCodePage = 1200;
+
+template <typename T>
+bool ValidateAndConvertValueGeneric(const JET_COLTYP match_column_type,
+ const JET_COLTYP column_type,
+ const std::vector<uint8_t>& column_data,
+ T* value) {
+ if ((column_type == match_column_type) && (column_data.size() == sizeof(T))) {
+ memcpy(value, &column_data[0], sizeof(T));
+ return true;
+ }
+ return false;
+}
+
+bool ValidateAndConvertValue(const JET_COLTYP column_type,
+ const std::vector<uint8_t>& column_data,
+ bool* value) {
+ if ((column_type == JET_coltypBit) && (column_data.size() == 1)) {
+ *value = (column_data[0] & 1) == 1;
+ return true;
+ }
+ return false;
+}
+
+bool ValidateAndConvertValue(const JET_COLTYP column_type,
+ const std::vector<uint8_t>& column_data,
+ base::string16* value) {
+ if ((column_type == JET_coltypLongText) &&
+ ((column_data.size() % sizeof(base::char16)) == 0)) {
+ base::string16& value_ref = *value;
+ size_t char_length = column_data.size() / sizeof(base::char16);
+ value_ref.resize(char_length);
+ memcpy(&value_ref[0], &column_data[0], column_data.size());
+ // Remove any trailing NUL characters.
+ while (char_length > 0) {
+ if (value_ref[char_length - 1])
+ break;
+ char_length--;
+ }
+ value_ref.resize(char_length);
+ return true;
+ }
+ return false;
+}
+
+bool ValidateAndConvertValue(const JET_COLTYP column_type,
+ const std::vector<uint8_t>& column_data,
+ GUID* value) {
+ return ValidateAndConvertValueGeneric(JET_coltypGUID, column_type,
+ column_data, value);
+}
+
+bool ValidateAndConvertValue(const JET_COLTYP column_type,
+ const std::vector<uint8_t>& column_data,
+ int32_t* value) {
+ return ValidateAndConvertValueGeneric(JET_coltypLong, column_type,
+ column_data, value);
+}
+
+bool ValidateAndConvertValue(const JET_COLTYP column_type,
+ const std::vector<uint8_t>& column_data,
+ int64_t* value) {
+ return ValidateAndConvertValueGeneric(JET_coltypLongLong, column_type,
+ column_data, value);
+}
+
+bool ValidateAndConvertValue(const JET_COLTYP column_type,
+ const std::vector<uint8_t>& column_data,
+ FILETIME* value) {
+ return ValidateAndConvertValueGeneric(JET_coltypLongLong, column_type,
+ column_data, value);
+}
+
+bool ValidateAndConvertValue(const JET_COLTYP column_type,
+ const std::vector<uint8_t>& column_data,
+ uint32_t* value) {
+ return ValidateAndConvertValueGeneric(JET_coltypUnsignedLong, column_type,
+ column_data, value);
+}
+
+} // namespace
+
+base::string16 EdgeErrorObject::GetErrorMessage() const {
+ WCHAR error_message[kErrorMessageSize] = {};
+ JET_API_PTR err = last_error_;
+ JET_ERR result = JetGetSystemParameter(JET_instanceNil, JET_sesidNil,
+ JET_paramErrorToString, &err,
+ error_message, sizeof(error_message));
+ if (result != JET_errSuccess)
+ return L"";
+
+ return error_message;
+}
+
+bool EdgeErrorObject::SetLastError(JET_ERR error) {
+ last_error_ = error;
+ return error == JET_errSuccess;
+}
+
+EdgeDatabaseTableEnumerator::EdgeDatabaseTableEnumerator(
+ const base::string16& table_name,
+ JET_SESID session_id,
+ JET_TABLEID table_id)
+ : table_id_(table_id), table_name_(table_name), session_id_(session_id) {}
+
+EdgeDatabaseTableEnumerator::~EdgeDatabaseTableEnumerator() {
+ if (table_id_ != JET_tableidNil)
+ JetCloseTable(session_id_, table_id_);
+}
+
+bool EdgeDatabaseTableEnumerator::Reset() {
+ return SetLastError(JetMove(session_id_, table_id_, JET_MoveFirst, 0));
+}
+
+bool EdgeDatabaseTableEnumerator::Next() {
+ return SetLastError(JetMove(session_id_, table_id_, JET_MoveNext, 0));
+}
+
+template <typename T>
+bool EdgeDatabaseTableEnumerator::RetrieveColumn(
+ const base::string16& column_name,
+ T* value) {
+ const JET_COLUMNBASE& column_base = GetColumnByName(column_name);
+ if (column_base.cbMax == 0) {
+ SetLastError(JET_errColumnNotFound);
+ return false;
+ }
+ if (column_base.coltyp == JET_coltypLongText &&
+ column_base.cp != kJetUnicodeCodePage) {
+ SetLastError(JET_errInvalidColumnType);
+ return false;
+ }
+ std::vector<uint8_t> column_data(column_base.cbMax);
+ unsigned long actual_size = 0;
+ JET_ERR err = JetRetrieveColumn(session_id_, table_id_, column_base.columnid,
+ &column_data[0], column_data.size(),
+ &actual_size, 0, nullptr);
+ SetLastError(err);
+ if (err != JET_errSuccess && err != JET_wrnColumnNull) {
+ return false;
+ }
+
+ if (err == JET_errSuccess) {
+ column_data.resize(actual_size);
+ if (!ValidateAndConvertValue(column_base.coltyp, column_data, value)) {
+ SetLastError(JET_errInvalidColumnType);
ananta 2015/12/02 21:33:11 Should there be a trace error here?
forshaw 2015/12/02 21:56:11 I expect if this fails then the entire import woul
+ return false;
+ }
+ } else {
+ *value = T();
+ }
+
+ return true;
+}
+
+// Explicitly instantiate implementations of RetrieveColumn for various types.
+template bool EdgeDatabaseTableEnumerator::RetrieveColumn(const base::string16&,
+ bool*);
+template bool EdgeDatabaseTableEnumerator::RetrieveColumn(const base::string16&,
+ FILETIME*);
+template bool EdgeDatabaseTableEnumerator::RetrieveColumn(const base::string16&,
+ GUID*);
+template bool EdgeDatabaseTableEnumerator::RetrieveColumn(const base::string16&,
+ int32_t*);
+template bool EdgeDatabaseTableEnumerator::RetrieveColumn(const base::string16&,
+ int64_t*);
+template bool EdgeDatabaseTableEnumerator::RetrieveColumn(const base::string16&,
+ base::string16*);
+template bool EdgeDatabaseTableEnumerator::RetrieveColumn(const base::string16&,
+ uint32_t*);
+
+const JET_COLUMNBASE& EdgeDatabaseTableEnumerator::GetColumnByName(
+ const base::string16& column_name) {
+ auto found_col = columns_by_name_.find(column_name);
+ if (found_col == columns_by_name_.end()) {
+ JET_COLUMNBASE column_base = {};
+ column_base.cbStruct = sizeof(JET_COLUMNBASE);
+ if (!SetLastError(JetGetTableColumnInfo(
+ session_id_, table_id_, column_name.c_str(), &column_base,
+ sizeof(column_base), JET_ColInfoBase))) {
+ // 0 indicates an invalid column.
+ column_base.cbMax = 0;
+ }
+ columns_by_name_[column_name] = column_base;
+ found_col = columns_by_name_.find(column_name);
+ }
+ return found_col->second;
+}
+
+EdgeDatabaseReader::~EdgeDatabaseReader() {
+ // We don't need to collect other ID handles, terminating instance
+ // is enough to shut the entire session down.
+ if (instance_id_ != JET_instanceNil)
+ JetTerm(instance_id_);
+}
+
+bool EdgeDatabaseReader::OpenDatabase(const base::string16& database_file) {
+ if (IsOpen()) {
+ SetLastError(JET_errOneDatabasePerSession);
+ return false;
+ }
+ if (!SetLastError(JetSetSystemParameter(nullptr, JET_sesidNil,
+ JET_paramDatabasePageSize,
+ kEdgeDatabasePageSize, nullptr)))
+ return false;
+ if (!SetLastError(JetCreateInstance(&instance_id_, L"EdgeDataImporter")))
+ return false;
+ if (!SetLastError(JetSetSystemParameter(&instance_id_, JET_sesidNil,
+ JET_paramRecovery, 0, L"Off")))
+ return false;
+ if (!SetLastError(JetInit(&instance_id_)))
+ return false;
+ if (!SetLastError(
+ JetBeginSession(instance_id_, &session_id_, nullptr, nullptr)))
+ return false;
+ if (!SetLastError(JetAttachDatabase2(session_id_, database_file.c_str(), 0,
+ JET_bitDbReadOnly)))
+ return false;
+ if (!SetLastError(JetOpenDatabase(session_id_, database_file.c_str(), nullptr,
+ &db_id_, JET_bitDbReadOnly)))
+ return false;
+ return true;
+}
+
+scoped_ptr<EdgeDatabaseTableEnumerator> EdgeDatabaseReader::OpenTableEnumerator(
+ const base::string16& table_name) {
+ JET_TABLEID table_id;
+
+ if (!IsOpen()) {
+ SetLastError(JET_errDatabaseNotFound);
+ return nullptr;
+ }
+
+ if (!SetLastError(JetOpenTable(session_id_, db_id_, table_name.c_str(),
+ nullptr, 0, JET_bitTableReadOnly, &table_id)))
+ return nullptr;
+
+ return make_scoped_ptr(
+ new EdgeDatabaseTableEnumerator(table_name, session_id_, table_id));
+}

Powered by Google App Engine
This is Rietveld 408576698