1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #include "chrome/browser/webdata/web_apps_table.h" 6 7 #include "base/logging.h" 8 #include "chrome/browser/history/history_database.h" 9 #include "components/webdata/common/web_database.h" 10 #include "sql/statement.h" 11 #include "third_party/skia/include/core/SkBitmap.h" 12 #include "ui/gfx/codec/png_codec.h" 13 #include "url/gurl.h" 14 15 namespace { 16 17 WebDatabaseTable::TypeKey GetKey() { 18 // We just need a unique constant. Use the address of a static that 19 // COMDAT folding won't touch in an optimizing linker. 20 static int table_key = 0; 21 return reinterpret_cast<void*>(&table_key); 22 } 23 24 } // namespace 25 26 WebAppsTable* WebAppsTable::FromWebDatabase(WebDatabase* db) { 27 return static_cast<WebAppsTable*>(db->GetTable(GetKey())); 28 } 29 30 WebDatabaseTable::TypeKey WebAppsTable::GetTypeKey() const { 31 return GetKey(); 32 } 33 34 bool WebAppsTable::Init(sql::Connection* db, sql::MetaTable* meta_table) { 35 WebDatabaseTable::Init(db, meta_table); 36 37 return (InitWebAppIconsTable() && InitWebAppsTable()); 38 } 39 40 bool WebAppsTable::IsSyncable() { 41 return true; 42 } 43 44 bool WebAppsTable::MigrateToVersion(int version, 45 bool* update_compatible_version) { 46 return true; 47 } 48 49 bool WebAppsTable::InitWebAppIconsTable() { 50 if (!db_->DoesTableExist("web_app_icons")) { 51 if (!db_->Execute("CREATE TABLE web_app_icons (" 52 "url LONGVARCHAR," 53 "width int," 54 "height int," 55 "image BLOB, UNIQUE (url, width, height))")) { 56 NOTREACHED(); 57 return false; 58 } 59 } 60 return true; 61 } 62 63 bool WebAppsTable::InitWebAppsTable() { 64 if (!db_->DoesTableExist("web_apps")) { 65 if (!db_->Execute("CREATE TABLE web_apps (" 66 "url LONGVARCHAR UNIQUE," 67 "has_all_images INTEGER NOT NULL)")) { 68 NOTREACHED(); 69 return false; 70 } 71 if (!db_->Execute("CREATE INDEX web_apps_url_index ON web_apps (url)")) { 72 NOTREACHED(); 73 return false; 74 } 75 } 76 return true; 77 } 78 79 bool WebAppsTable::SetWebAppImage(const GURL& url, const SkBitmap& image) { 80 // Don't bother with a cached statement since this will be a relatively 81 // infrequent operation. 82 sql::Statement s(db_->GetUniqueStatement( 83 "INSERT OR REPLACE INTO web_app_icons " 84 "(url, width, height, image) VALUES (?, ?, ?, ?)")); 85 std::vector<unsigned char> image_data; 86 gfx::PNGCodec::EncodeBGRASkBitmap(image, false, &image_data); 87 s.BindString(0, history::HistoryDatabase::GURLToDatabaseURL(url)); 88 s.BindInt(1, image.width()); 89 s.BindInt(2, image.height()); 90 s.BindBlob(3, &image_data.front(), static_cast<int>(image_data.size())); 91 92 return s.Run(); 93 } 94 95 bool WebAppsTable::GetWebAppImages(const GURL& url, 96 std::vector<SkBitmap>* images) { 97 sql::Statement s(db_->GetUniqueStatement( 98 "SELECT image FROM web_app_icons WHERE url=?")); 99 s.BindString(0, history::HistoryDatabase::GURLToDatabaseURL(url)); 100 101 while (s.Step()) { 102 SkBitmap image; 103 int col_bytes = s.ColumnByteLength(0); 104 if (col_bytes > 0) { 105 if (gfx::PNGCodec::Decode( 106 reinterpret_cast<const unsigned char*>(s.ColumnBlob(0)), 107 col_bytes, &image)) { 108 images->push_back(image); 109 } else { 110 // Should only have valid image data in the db. 111 NOTREACHED(); 112 } 113 } 114 } 115 return s.Succeeded(); 116 } 117 118 bool WebAppsTable::SetWebAppHasAllImages(const GURL& url, 119 bool has_all_images) { 120 sql::Statement s(db_->GetUniqueStatement( 121 "INSERT OR REPLACE INTO web_apps (url, has_all_images) VALUES (?, ?)")); 122 s.BindString(0, history::HistoryDatabase::GURLToDatabaseURL(url)); 123 s.BindInt(1, has_all_images ? 1 : 0); 124 125 return s.Run(); 126 } 127 128 bool WebAppsTable::GetWebAppHasAllImages(const GURL& url) { 129 sql::Statement s(db_->GetUniqueStatement( 130 "SELECT has_all_images FROM web_apps WHERE url=?")); 131 s.BindString(0, history::HistoryDatabase::GURLToDatabaseURL(url)); 132 133 return (s.Step() && s.ColumnInt(0) == 1); 134 } 135 136 bool WebAppsTable::RemoveWebApp(const GURL& url) { 137 sql::Statement delete_s(db_->GetUniqueStatement( 138 "DELETE FROM web_app_icons WHERE url = ?")); 139 delete_s.BindString(0, history::HistoryDatabase::GURLToDatabaseURL(url)); 140 141 if (!delete_s.Run()) 142 return false; 143 144 sql::Statement delete_s2(db_->GetUniqueStatement( 145 "DELETE FROM web_apps WHERE url = ?")); 146 delete_s2.BindString(0, history::HistoryDatabase::GURLToDatabaseURL(url)); 147 148 return delete_s2.Run(); 149 } 150