| OLD | NEW |
| 1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "chrome/browser/webdata/web_database.h" | 5 #include "chrome/browser/webdata/web_database.h" |
| 6 | 6 |
| 7 #include <algorithm> | 7 #include <algorithm> |
| 8 #include <limits> | 8 #include <limits> |
| 9 #include <set> | 9 #include <set> |
| 10 #include <string> | 10 #include <string> |
| (...skipping 429 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 440 | 440 |
| 441 // Version check. | 441 // Version check. |
| 442 if (!meta_table_.Init(&db_, kCurrentVersionNumber, kCompatibleVersionNumber)) | 442 if (!meta_table_.Init(&db_, kCurrentVersionNumber, kCompatibleVersionNumber)) |
| 443 return sql::INIT_FAILURE; | 443 return sql::INIT_FAILURE; |
| 444 if (meta_table_.GetCompatibleVersionNumber() > kCurrentVersionNumber) { | 444 if (meta_table_.GetCompatibleVersionNumber() > kCurrentVersionNumber) { |
| 445 LOG(WARNING) << "Web database is too new."; | 445 LOG(WARNING) << "Web database is too new."; |
| 446 return sql::INIT_TOO_NEW; | 446 return sql::INIT_TOO_NEW; |
| 447 } | 447 } |
| 448 | 448 |
| 449 // Initialize the tables. | 449 // Initialize the tables. |
| 450 bool credit_card_table_created = false; | |
| 451 if (!InitKeywordsTable() || !InitLoginsTable() || !InitWebAppIconsTable() || | 450 if (!InitKeywordsTable() || !InitLoginsTable() || !InitWebAppIconsTable() || |
| 452 !InitWebAppsTable() || !InitAutofillTable() || | 451 !InitWebAppsTable() || !InitAutofillTable() || |
| 453 !InitAutofillDatesTable() || !InitAutoFillProfilesTable() || | 452 !InitAutofillDatesTable() || !InitAutoFillProfilesTable() || |
| 454 !InitCreditCardsTable(&credit_card_table_created) || | 453 !InitCreditCardsTable() || !InitTokenServiceTable()) { |
| 455 !InitTokenServiceTable()) { | |
| 456 LOG(WARNING) << "Unable to initialize the web database."; | 454 LOG(WARNING) << "Unable to initialize the web database."; |
| 457 return sql::INIT_FAILURE; | 455 return sql::INIT_FAILURE; |
| 458 } | 456 } |
| 459 | 457 |
| 460 // If the file on disk is an older database version, bring it up to date. | 458 // If the file on disk is an older database version, bring it up to date. |
| 461 MigrateOldVersionsAsNeeded(credit_card_table_created); | 459 MigrateOldVersionsAsNeeded(); |
| 462 | 460 |
| 463 return transaction.Commit() ? sql::INIT_OK : sql::INIT_FAILURE; | 461 return transaction.Commit() ? sql::INIT_OK : sql::INIT_FAILURE; |
| 464 } | 462 } |
| 465 | 463 |
| 466 bool WebDatabase::SetWebAppImage(const GURL& url, const SkBitmap& image) { | 464 bool WebDatabase::SetWebAppImage(const GURL& url, const SkBitmap& image) { |
| 467 // Don't bother with a cached statement since this will be a relatively | 465 // Don't bother with a cached statement since this will be a relatively |
| 468 // infrequent operation. | 466 // infrequent operation. |
| 469 sql::Statement s(db_.GetUniqueStatement( | 467 sql::Statement s(db_.GetUniqueStatement( |
| 470 "INSERT OR REPLACE INTO web_app_icons " | 468 "INSERT OR REPLACE INTO web_app_icons " |
| 471 "(url, width, height, image) VALUES (?, ?, ?, ?)")); | 469 "(url, width, height, image) VALUES (?, ?, ?, ?)")); |
| (...skipping 283 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 755 } | 753 } |
| 756 if (!db_.Execute("CREATE INDEX autofill_profiles_label_index " | 754 if (!db_.Execute("CREATE INDEX autofill_profiles_label_index " |
| 757 "ON autofill_profiles (label)")) { | 755 "ON autofill_profiles (label)")) { |
| 758 NOTREACHED(); | 756 NOTREACHED(); |
| 759 return false; | 757 return false; |
| 760 } | 758 } |
| 761 } | 759 } |
| 762 return true; | 760 return true; |
| 763 } | 761 } |
| 764 | 762 |
| 765 bool WebDatabase::InitCreditCardsTable(bool* table_was_created) { | 763 bool WebDatabase::InitCreditCardsTable() { |
| 766 if (!db_.DoesTableExist("credit_cards")) { | 764 if (!db_.DoesTableExist("credit_cards")) { |
| 767 if (!db_.Execute("CREATE TABLE credit_cards ( " | 765 if (!db_.Execute("CREATE TABLE credit_cards ( " |
| 768 "label VARCHAR, " | 766 "label VARCHAR, " |
| 769 "unique_id INTEGER PRIMARY KEY, " | 767 "unique_id INTEGER PRIMARY KEY, " |
| 770 "name_on_card VARCHAR, " | 768 "name_on_card VARCHAR, " |
| 771 "type VARCHAR, " | 769 "type VARCHAR, " |
| 772 "card_number VARCHAR, " | 770 "card_number VARCHAR, " |
| 773 "expiration_month INTEGER, " | 771 "expiration_month INTEGER, " |
| 774 "expiration_year INTEGER, " | 772 "expiration_year INTEGER, " |
| 775 "verification_code VARCHAR, " | 773 "verification_code VARCHAR, " |
| 776 "billing_address VARCHAR, " | 774 "billing_address VARCHAR, " |
| 777 "shipping_address VARCHAR, " | 775 "shipping_address VARCHAR, " |
| 778 "card_number_encrypted BLOB, " | 776 "card_number_encrypted BLOB, " |
| 779 "verification_code_encrypted BLOB)")) { | 777 "verification_code_encrypted BLOB)")) { |
| 780 NOTREACHED(); | 778 NOTREACHED(); |
| 781 return false; | 779 return false; |
| 782 } | 780 } |
| 783 *table_was_created = true; | |
| 784 if (!db_.Execute("CREATE INDEX credit_cards_label_index " | 781 if (!db_.Execute("CREATE INDEX credit_cards_label_index " |
| 785 "ON credit_cards (label)")) { | 782 "ON credit_cards (label)")) { |
| 786 NOTREACHED(); | 783 NOTREACHED(); |
| 787 return false; | 784 return false; |
| 788 } | 785 } |
| 789 } | 786 } |
| 790 return true; | 787 return true; |
| 791 } | 788 } |
| 792 | 789 |
| 793 bool WebDatabase::InitWebAppIconsTable() { | 790 bool WebDatabase::InitWebAppIconsTable() { |
| (...skipping 1073 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1867 return false; | 1864 return false; |
| 1868 } | 1865 } |
| 1869 s.BindInt64(0, pair_id); | 1866 s.BindInt64(0, pair_id); |
| 1870 if (s.Run()) { | 1867 if (s.Run()) { |
| 1871 return RemoveFormElementForTimeRange(pair_id, base::Time(), base::Time(), | 1868 return RemoveFormElementForTimeRange(pair_id, base::Time(), base::Time(), |
| 1872 NULL); | 1869 NULL); |
| 1873 } | 1870 } |
| 1874 return false; | 1871 return false; |
| 1875 } | 1872 } |
| 1876 | 1873 |
| 1877 void WebDatabase::MigrateOldVersionsAsNeeded(bool credit_card_table_created) { | 1874 void WebDatabase::MigrateOldVersionsAsNeeded(){ |
| 1878 // Migrate if necessary. | 1875 // Migrate if necessary. |
| 1879 int current_version = meta_table_.GetVersionNumber(); | 1876 int current_version = meta_table_.GetVersionNumber(); |
| 1880 switch (current_version) { | 1877 switch (current_version) { |
| 1881 // Versions 1 - 19 are unhandled. Version numbers greater than | 1878 // Versions 1 - 19 are unhandled. Version numbers greater than |
| 1882 // kCurrentVersionNumber should have already been weeded out by the caller. | 1879 // kCurrentVersionNumber should have already been weeded out by the caller. |
| 1883 default: | 1880 default: |
| 1884 // When the version is too old, we just try to continue anyway. There | 1881 // When the version is too old, we just try to continue anyway. There |
| 1885 // should not be a released product that makes a database too old for us | 1882 // should not be a released product that makes a database too old for us |
| 1886 // to handle. | 1883 // to handle. |
| 1887 LOG(WARNING) << "Web database version " << current_version << | 1884 LOG(WARNING) << "Web database version " << current_version << |
| (...skipping 17 matching lines...) Expand all Loading... |
| 1905 if (!ClearAutofillEmptyValueElements()) { | 1902 if (!ClearAutofillEmptyValueElements()) { |
| 1906 NOTREACHED() << "Failed to clean-up autofill DB."; | 1903 NOTREACHED() << "Failed to clean-up autofill DB."; |
| 1907 } | 1904 } |
| 1908 meta_table_.SetVersionNumber(22); | 1905 meta_table_.SetVersionNumber(22); |
| 1909 // No change in the compatibility version number. | 1906 // No change in the compatibility version number. |
| 1910 | 1907 |
| 1911 // FALL THROUGH | 1908 // FALL THROUGH |
| 1912 | 1909 |
| 1913 case 22: | 1910 case 22: |
| 1914 // Add the card_number_encrypted column if credit card table was not | 1911 // Add the card_number_encrypted column if credit card table was not |
| 1915 // created in this build. | 1912 // created in this build (otherwise the column already exists). |
| 1916 if (!credit_card_table_created) { | 1913 // WARNING: Do not change the order of the execution of the SQL |
| 1917 if (!db_.Execute("ALTER TABLE credit_cards ADD COLUMN " | 1914 // statements in this case! Profile corruption and data migration |
| 1918 "card_number_encrypted BLOB DEFAULT NULL")) { | 1915 // issues WILL OCCUR. (see http://crbug.com/10913) |
| 1919 NOTREACHED(); | 1916 // |
| 1920 LOG(WARNING) << "Unable to update web database to version 23."; | 1917 // The problem is that if a user has a profile which was created before |
| 1921 return; | 1918 // r37036, when the credit_cards table was added, and then failed to |
| 1922 } | 1919 // update this profile between the credit card addition and the addition |
| 1923 if (!db_.Execute("ALTER TABLE credit_cards ADD COLUMN " | 1920 // of the "encrypted" columns (44963), the next data migration will put |
| 1924 "verification_code_encrypted BLOB DEFAULT NULL")) { | 1921 // the user's profile in an incoherent state: The user will update from |
| 1925 NOTREACHED(); | 1922 // a data profile set to be earlier than 22, and therefore pass through |
| 1926 LOG(WARNING) << "Unable to update web database to version 23."; | 1923 // this update case. But because the user did not have a credit_cards |
| 1927 return; | 1924 // table before starting Chrome, it will have just been initialized |
| 1928 } | 1925 // above, and so already have these columns -- and thus this data |
| 1926 // update step will have failed. |
| 1927 // |
| 1928 // The false assumption in this case is that at this step in the |
| 1929 // migration, the user has a credit card table, and that this |
| 1930 // table does not include encrypted columns! |
| 1931 // Because this case does not roll back the complete set of SQL |
| 1932 // transactions properly in case of failure (that is, it does not |
| 1933 // roll back the table initialization done above), the incoherent |
| 1934 // profile will now see itself as being at version 22 -- but include a |
| 1935 // fully initialized credit_cards table. Every time Chrome runs, it |
| 1936 // will try to update the web database and fail at this step, unless |
| 1937 // we allow for the faulty assumption described above by checking for |
| 1938 // the existence of the columns only AFTER we've executed the commands |
| 1939 // to add them. |
| 1940 if (!db_.Execute("ALTER TABLE credit_cards ADD COLUMN " |
| 1941 "card_number_encrypted BLOB DEFAULT NULL")) { |
| 1942 LOG(WARNING) << "Could not add card_number_encrypted to " |
| 1943 "credit_cards table."; |
| 1944 } |
| 1945 if (!db_.Execute("ALTER TABLE credit_cards ADD COLUMN " |
| 1946 "verification_code_encrypted BLOB DEFAULT NULL")) { |
| 1947 LOG(WARNING) << "Could not add verification_code_encrypted to " |
| 1948 "credit_cards table."; |
| 1949 } |
| 1950 if (!db_.Execute( |
| 1951 "SELECT card_number_encrypted FROM credit_cards limit 1") || |
| 1952 !db_.Execute( |
| 1953 "SELECT verification_code_encrypted FROM credit_cards limit 1")) { |
| 1954 NOTREACHED(); |
| 1955 LOG(WARNING) << "Unable to update web database to version 23."; |
| 1956 return; |
| 1929 } | 1957 } |
| 1930 meta_table_.SetVersionNumber(23); | 1958 meta_table_.SetVersionNumber(23); |
| 1931 | |
| 1932 // FALL THROUGH | 1959 // FALL THROUGH |
| 1933 | 1960 |
| 1934 case 23: { | 1961 case 23: { |
| 1935 // One-time cleanup for Chromium bug 38364. In the presence of | 1962 // One-time cleanup for Chromium bug 38364. In the presence of |
| 1936 // multi-byte UTF-8 characters, that bug could cause AutoFill strings | 1963 // multi-byte UTF-8 characters, that bug could cause AutoFill strings |
| 1937 // to grow larger and more corrupt with each save. The cleanup removes | 1964 // to grow larger and more corrupt with each save. The cleanup removes |
| 1938 // any row with a string field larger than a reasonable size. The string | 1965 // any row with a string field larger than a reasonable size. The string |
| 1939 // fields examined here are precisely the ones that were subject to | 1966 // fields examined here are precisely the ones that were subject to |
| 1940 // corruption by the original bug. | 1967 // corruption by the original bug. |
| 1941 const std::string autofill_is_too_big = | 1968 const std::string autofill_is_too_big = |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1983 LOG(WARNING) << "Unable to update web database to version 24."; | 2010 LOG(WARNING) << "Unable to update web database to version 24."; |
| 1984 return; | 2011 return; |
| 1985 } | 2012 } |
| 1986 | 2013 |
| 1987 meta_table_.SetVersionNumber(24); | 2014 meta_table_.SetVersionNumber(24); |
| 1988 | 2015 |
| 1989 // FALL THROUGH | 2016 // FALL THROUGH |
| 1990 } | 2017 } |
| 1991 | 2018 |
| 1992 case 24: | 2019 case 24: |
| 1993 // Add the logo_id column. | 2020 // Add the logo_id column if keyword table was not created in this build. |
| 1994 if (!db_.Execute("ALTER TABLE keywords ADD COLUMN logo_id " | 2021 if (!db_.Execute("ALTER TABLE keywords ADD COLUMN logo_id " |
| 1995 "INTEGER DEFAULT 0")) { | 2022 "INTEGER DEFAULT 0")) { |
| 1996 NOTREACHED(); | 2023 NOTREACHED(); |
| 1997 LOG(WARNING) << "Unable to update web database to version 25."; | 2024 LOG(WARNING) << "Unable to update web database to version 25."; |
| 1998 return; | 2025 return; |
| 1999 } | 2026 } |
| 2000 meta_table_.SetVersionNumber(25); | 2027 meta_table_.SetVersionNumber(25); |
| 2001 meta_table_.SetCompatibleVersionNumber( | 2028 meta_table_.SetCompatibleVersionNumber( |
| 2002 std::min(25, kCompatibleVersionNumber)); | 2029 std::min(25, kCompatibleVersionNumber)); |
| 2003 // FALL THROUGH | 2030 // FALL THROUGH |
| 2004 | 2031 |
| 2005 // Add successive versions here. Each should set the version number and | 2032 // Add successive versions here. Each should set the version number and |
| 2006 // compatible version number as appropriate, then fall through to the next | 2033 // compatible version number as appropriate, then fall through to the next |
| 2007 // case. | 2034 // case. |
| 2008 | 2035 |
| 2009 case kCurrentVersionNumber: | 2036 case kCurrentVersionNumber: |
| 2010 // No migration needed. | 2037 // No migration needed. |
| 2011 return; | 2038 return; |
| 2012 } | 2039 } |
| 2013 } | 2040 } |
| OLD | NEW |