| 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 426 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 437 | 437 |
| 438 // Version check. | 438 // Version check. |
| 439 if (!meta_table_.Init(&db_, kCurrentVersionNumber, kCompatibleVersionNumber)) | 439 if (!meta_table_.Init(&db_, kCurrentVersionNumber, kCompatibleVersionNumber)) |
| 440 return sql::INIT_FAILURE; | 440 return sql::INIT_FAILURE; |
| 441 if (meta_table_.GetCompatibleVersionNumber() > kCurrentVersionNumber) { | 441 if (meta_table_.GetCompatibleVersionNumber() > kCurrentVersionNumber) { |
| 442 LOG(WARNING) << "Web database is too new."; | 442 LOG(WARNING) << "Web database is too new."; |
| 443 return sql::INIT_TOO_NEW; | 443 return sql::INIT_TOO_NEW; |
| 444 } | 444 } |
| 445 | 445 |
| 446 // Initialize the tables. | 446 // Initialize the tables. |
| 447 bool credit_card_table_created = false; | |
| 448 if (!InitKeywordsTable() || !InitLoginsTable() || !InitWebAppIconsTable() || | 447 if (!InitKeywordsTable() || !InitLoginsTable() || !InitWebAppIconsTable() || |
| 449 !InitWebAppsTable() || !InitAutofillTable() || | 448 !InitWebAppsTable() || !InitAutofillTable() || |
| 450 !InitAutofillDatesTable() || !InitAutoFillProfilesTable() || | 449 !InitAutofillDatesTable() || !InitAutoFillProfilesTable() || |
| 451 !InitCreditCardsTable(&credit_card_table_created)) { | 450 !InitCreditCardsTable()) { |
| 452 LOG(WARNING) << "Unable to initialize the web database."; | 451 LOG(WARNING) << "Unable to initialize the web database."; |
| 453 return sql::INIT_FAILURE; | 452 return sql::INIT_FAILURE; |
| 454 } | 453 } |
| 455 | 454 |
| 456 // If the file on disk is an older database version, bring it up to date. | 455 // If the file on disk is an older database version, bring it up to date. |
| 457 MigrateOldVersionsAsNeeded(credit_card_table_created); | 456 MigrateOldVersionsAsNeeded(); |
| 458 | 457 |
| 459 return transaction.Commit() ? sql::INIT_OK : sql::INIT_FAILURE; | 458 return transaction.Commit() ? sql::INIT_OK : sql::INIT_FAILURE; |
| 460 } | 459 } |
| 461 | 460 |
| 462 bool WebDatabase::SetWebAppImage(const GURL& url, const SkBitmap& image) { | 461 bool WebDatabase::SetWebAppImage(const GURL& url, const SkBitmap& image) { |
| 463 // Don't bother with a cached statement since this will be a relatively | 462 // Don't bother with a cached statement since this will be a relatively |
| 464 // infrequent operation. | 463 // infrequent operation. |
| 465 sql::Statement s(db_.GetUniqueStatement( | 464 sql::Statement s(db_.GetUniqueStatement( |
| 466 "INSERT OR REPLACE INTO web_app_icons " | 465 "INSERT OR REPLACE INTO web_app_icons " |
| 467 "(url, width, height, image) VALUES (?, ?, ?, ?)")); | 466 "(url, width, height, image) VALUES (?, ?, ?, ?)")); |
| (...skipping 221 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 689 } | 688 } |
| 690 if (!db_.Execute("CREATE INDEX autofill_profiles_label_index " | 689 if (!db_.Execute("CREATE INDEX autofill_profiles_label_index " |
| 691 "ON autofill_profiles (label)")) { | 690 "ON autofill_profiles (label)")) { |
| 692 NOTREACHED(); | 691 NOTREACHED(); |
| 693 return false; | 692 return false; |
| 694 } | 693 } |
| 695 } | 694 } |
| 696 return true; | 695 return true; |
| 697 } | 696 } |
| 698 | 697 |
| 699 bool WebDatabase::InitCreditCardsTable(bool* table_was_created) { | 698 bool WebDatabase::InitCreditCardsTable() { |
| 700 if (!db_.DoesTableExist("credit_cards")) { | 699 if (!db_.DoesTableExist("credit_cards")) { |
| 701 if (!db_.Execute("CREATE TABLE credit_cards ( " | 700 if (!db_.Execute("CREATE TABLE credit_cards ( " |
| 702 "label VARCHAR, " | 701 "label VARCHAR, " |
| 703 "unique_id INTEGER PRIMARY KEY, " | 702 "unique_id INTEGER PRIMARY KEY, " |
| 704 "name_on_card VARCHAR, " | 703 "name_on_card VARCHAR, " |
| 705 "type VARCHAR, " | 704 "type VARCHAR, " |
| 706 "card_number VARCHAR, " | 705 "card_number VARCHAR, " |
| 707 "expiration_month INTEGER, " | 706 "expiration_month INTEGER, " |
| 708 "expiration_year INTEGER, " | 707 "expiration_year INTEGER, " |
| 709 "verification_code VARCHAR, " | 708 "verification_code VARCHAR, " |
| 710 "billing_address VARCHAR, " | 709 "billing_address VARCHAR, " |
| 711 "shipping_address VARCHAR, " | 710 "shipping_address VARCHAR, " |
| 712 "card_number_encrypted BLOB, " | 711 "card_number_encrypted BLOB, " |
| 713 "verification_code_encrypted BLOB)")) { | 712 "verification_code_encrypted BLOB)")) { |
| 714 NOTREACHED(); | 713 NOTREACHED(); |
| 715 return false; | 714 return false; |
| 716 } | 715 } |
| 717 *table_was_created = true; | |
| 718 if (!db_.Execute("CREATE INDEX credit_cards_label_index " | 716 if (!db_.Execute("CREATE INDEX credit_cards_label_index " |
| 719 "ON credit_cards (label)")) { | 717 "ON credit_cards (label)")) { |
| 720 NOTREACHED(); | 718 NOTREACHED(); |
| 721 return false; | 719 return false; |
| 722 } | 720 } |
| 723 } | 721 } |
| 724 return true; | 722 return true; |
| 725 } | 723 } |
| 726 | 724 |
| 727 bool WebDatabase::InitWebAppIconsTable() { | 725 bool WebDatabase::InitWebAppIconsTable() { |
| (...skipping 1061 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1789 return false; | 1787 return false; |
| 1790 } | 1788 } |
| 1791 s.BindInt64(0, pair_id); | 1789 s.BindInt64(0, pair_id); |
| 1792 if (s.Run()) { | 1790 if (s.Run()) { |
| 1793 return RemoveFormElementForTimeRange(pair_id, base::Time(), base::Time(), | 1791 return RemoveFormElementForTimeRange(pair_id, base::Time(), base::Time(), |
| 1794 NULL); | 1792 NULL); |
| 1795 } | 1793 } |
| 1796 return false; | 1794 return false; |
| 1797 } | 1795 } |
| 1798 | 1796 |
| 1799 void WebDatabase::MigrateOldVersionsAsNeeded(bool credit_card_table_created) { | 1797 void WebDatabase::MigrateOldVersionsAsNeeded() { |
| 1800 // Migrate if necessary. | 1798 // Migrate if necessary. |
| 1801 int current_version = meta_table_.GetVersionNumber(); | 1799 int current_version = meta_table_.GetVersionNumber(); |
| 1802 switch (current_version) { | 1800 switch (current_version) { |
| 1803 // Versions 1 - 19 are unhandled. Version numbers greater than | 1801 // Versions 1 - 19 are unhandled. Version numbers greater than |
| 1804 // kCurrentVersionNumber should have already been weeded out by the caller. | 1802 // kCurrentVersionNumber should have already been weeded out by the caller. |
| 1805 default: | 1803 default: |
| 1806 // When the version is too old, we just try to continue anyway. There | 1804 // When the version is too old, we just try to continue anyway. There |
| 1807 // should not be a released product that makes a database too old for us | 1805 // should not be a released product that makes a database too old for us |
| 1808 // to handle. | 1806 // to handle. |
| 1809 LOG(WARNING) << "Web database version " << current_version << | 1807 LOG(WARNING) << "Web database version " << current_version << |
| (...skipping 18 matching lines...) Expand all Loading... |
| 1828 NOTREACHED() << "Failed to clean-up autofill DB."; | 1826 NOTREACHED() << "Failed to clean-up autofill DB."; |
| 1829 } | 1827 } |
| 1830 meta_table_.SetVersionNumber(22); | 1828 meta_table_.SetVersionNumber(22); |
| 1831 // No change in the compatibility version number. | 1829 // No change in the compatibility version number. |
| 1832 | 1830 |
| 1833 // FALL THROUGH | 1831 // FALL THROUGH |
| 1834 | 1832 |
| 1835 case 22: | 1833 case 22: |
| 1836 // Add the card_number_encrypted column if credit card table was not | 1834 // Add the card_number_encrypted column if credit card table was not |
| 1837 // created in this build (otherwise the column already exists). | 1835 // created in this build (otherwise the column already exists). |
| 1838 if (!credit_card_table_created) { | 1836 // WARNING: Do not change the order of the execution of the SQL |
| 1839 if (!db_.Execute("ALTER TABLE credit_cards ADD COLUMN " | 1837 // statements in this case! Profile corruption and data migration |
| 1840 "card_number_encrypted BLOB DEFAULT NULL")) { | 1838 // issues WILL OCCUR. (see http://crbug.com/10913)! |
| 1841 NOTREACHED(); | 1839 // |
| 1842 LOG(WARNING) << "Unable to update web database to version 23."; | 1840 // The problem is that if a user has a profile which was created before |
| 1843 return; | 1841 // r37036, when the credit_cards table was added, and then failed to |
| 1844 } | 1842 // update this profile between the credit card addition and the addition |
| 1845 if (!db_.Execute("ALTER TABLE credit_cards ADD COLUMN " | 1843 // of the "encrypted" columns (44963), the next data migration will put |
| 1846 "verification_code_encrypted BLOB DEFAULT NULL")) { | 1844 // the user's profile in an incoherent state: The user will update from |
| 1847 NOTREACHED(); | 1845 // a data profile set to be earlier than 22, and therefore pass through |
| 1848 LOG(WARNING) << "Unable to update web database to version 23."; | 1846 // this update case. But because the user did not have a credit_cards |
| 1849 return; | 1847 // table before starting Chrome, it will have just been initialized |
| 1850 } | 1848 // above, and so already have these columns -- and thus this data |
| 1849 // update step will have failed. |
| 1850 // |
| 1851 // The false assumption in this case is that at this step in the |
| 1852 // migration, the user has a credit card table, and that this |
| 1853 // table does not include encrypted columns! |
| 1854 // Because this case does not roll back the complete set of SQL |
| 1855 // transactions properly in case of failure (that is, it does not |
| 1856 // roll back the table initialization done above), the incoherent |
| 1857 // profile will now see itself as being at version 22 -- but include a |
| 1858 // fully initialized credit_cards table. Every time Chrome runs, it |
| 1859 // will try to update the web database and fail at this step, unless |
| 1860 // we allow for the faulty assumption described above by checking for |
| 1861 // the existence of the columns only AFTER we've executed the commands |
| 1862 // to add them. |
| 1863 if (!db_.Execute("ALTER TABLE credit_cards ADD COLUMN " |
| 1864 "card_number_encrypted BLOB DEFAULT NULL")) { |
| 1865 LOG(WARNING) << "Could not add card_number_encrypted to " |
| 1866 "credit_cards table."; |
| 1867 } |
| 1868 if (!db_.Execute("ALTER TABLE credit_cards ADD COLUMN " |
| 1869 "verification_code_encrypted BLOB DEFAULT NULL")) { |
| 1870 LOG(WARNING) << "Could not add verification_code_encrypted to " |
| 1871 "credit_cards table."; |
| 1872 } |
| 1873 if (!db_.Execute( |
| 1874 "SELECT card_number_encrypted FROM credit_cards limit 1") || |
| 1875 !db_.Execute( |
| 1876 "SELECT verification_code_encrypted FROM credit_cards limit 1")) { |
| 1877 NOTREACHED(); |
| 1878 LOG(WARNING) << "Unable to update web database to version 23."; |
| 1879 return; |
| 1851 } | 1880 } |
| 1852 meta_table_.SetVersionNumber(23); | 1881 meta_table_.SetVersionNumber(23); |
| 1853 | 1882 |
| 1854 // FALL THROUGH | 1883 // FALL THROUGH |
| 1855 | 1884 |
| 1856 case 23: { | 1885 case 23: { |
| 1857 // One-time cleanup for Chromium bug 38364. In the presence of | 1886 // One-time cleanup for Chromium bug 38364. In the presence of |
| 1858 // multi-byte UTF-8 characters, that bug could cause AutoFill strings | 1887 // multi-byte UTF-8 characters, that bug could cause AutoFill strings |
| 1859 // to grow larger and more corrupt with each save. The cleanup removes | 1888 // to grow larger and more corrupt with each save. The cleanup removes |
| 1860 // any row with a string field larger than a reasonable size. The string | 1889 // any row with a string field larger than a reasonable size. The string |
| (...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1926 | 1955 |
| 1927 // Add successive versions here. Each should set the version number and | 1956 // Add successive versions here. Each should set the version number and |
| 1928 // compatible version number as appropriate, then fall through to the next | 1957 // compatible version number as appropriate, then fall through to the next |
| 1929 // case. | 1958 // case. |
| 1930 | 1959 |
| 1931 case kCurrentVersionNumber: | 1960 case kCurrentVersionNumber: |
| 1932 // No migration needed. | 1961 // No migration needed. |
| 1933 return; | 1962 return; |
| 1934 } | 1963 } |
| 1935 } | 1964 } |
| OLD | NEW |