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
15namespace {
16
17WebDatabaseTable::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
26WebAppsTable* WebAppsTable::FromWebDatabase(WebDatabase* db) {
27  return static_cast<WebAppsTable*>(db->GetTable(GetKey()));
28}
29
30WebDatabaseTable::TypeKey WebAppsTable::GetTypeKey() const {
31  return GetKey();
32}
33
34bool WebAppsTable::CreateTablesIfNecessary() {
35  return (InitWebAppIconsTable() && InitWebAppsTable());
36}
37
38bool WebAppsTable::IsSyncable() {
39  return true;
40}
41
42bool WebAppsTable::MigrateToVersion(int version,
43                                    bool* update_compatible_version) {
44  return true;
45}
46
47bool WebAppsTable::InitWebAppIconsTable() {
48  if (!db_->DoesTableExist("web_app_icons")) {
49    if (!db_->Execute("CREATE TABLE web_app_icons ("
50                      "url LONGVARCHAR,"
51                      "width int,"
52                      "height int,"
53                      "image BLOB, UNIQUE (url, width, height))")) {
54      NOTREACHED();
55      return false;
56    }
57  }
58  return true;
59}
60
61bool WebAppsTable::InitWebAppsTable() {
62  if (!db_->DoesTableExist("web_apps")) {
63    if (!db_->Execute("CREATE TABLE web_apps ("
64                      "url LONGVARCHAR UNIQUE,"
65                      "has_all_images INTEGER NOT NULL)")) {
66      NOTREACHED();
67      return false;
68    }
69    if (!db_->Execute("CREATE INDEX web_apps_url_index ON web_apps (url)")) {
70      NOTREACHED();
71      return false;
72    }
73  }
74  return true;
75}
76
77bool WebAppsTable::SetWebAppImage(const GURL& url, const SkBitmap& image) {
78  // Don't bother with a cached statement since this will be a relatively
79  // infrequent operation.
80  sql::Statement s(db_->GetUniqueStatement(
81      "INSERT OR REPLACE INTO web_app_icons "
82      "(url, width, height, image) VALUES (?, ?, ?, ?)"));
83  std::vector<unsigned char> image_data;
84  gfx::PNGCodec::EncodeBGRASkBitmap(image, false, &image_data);
85  s.BindString(0, history::HistoryDatabase::GURLToDatabaseURL(url));
86  s.BindInt(1, image.width());
87  s.BindInt(2, image.height());
88  s.BindBlob(3, &image_data.front(), static_cast<int>(image_data.size()));
89
90  return s.Run();
91}
92
93bool WebAppsTable::GetWebAppImages(const GURL& url,
94                                  std::vector<SkBitmap>* images) {
95  sql::Statement s(db_->GetUniqueStatement(
96      "SELECT image FROM web_app_icons WHERE url=?"));
97  s.BindString(0, history::HistoryDatabase::GURLToDatabaseURL(url));
98
99  while (s.Step()) {
100    SkBitmap image;
101    int col_bytes = s.ColumnByteLength(0);
102    if (col_bytes > 0) {
103      if (gfx::PNGCodec::Decode(
104              reinterpret_cast<const unsigned char*>(s.ColumnBlob(0)),
105              col_bytes, &image)) {
106        images->push_back(image);
107      } else {
108        // Should only have valid image data in the db.
109        NOTREACHED();
110      }
111    }
112  }
113  return s.Succeeded();
114}
115
116bool WebAppsTable::SetWebAppHasAllImages(const GURL& url,
117                                        bool has_all_images) {
118  sql::Statement s(db_->GetUniqueStatement(
119      "INSERT OR REPLACE INTO web_apps (url, has_all_images) VALUES (?, ?)"));
120  s.BindString(0, history::HistoryDatabase::GURLToDatabaseURL(url));
121  s.BindInt(1, has_all_images ? 1 : 0);
122
123  return s.Run();
124}
125
126bool WebAppsTable::GetWebAppHasAllImages(const GURL& url) {
127  sql::Statement s(db_->GetUniqueStatement(
128      "SELECT has_all_images FROM web_apps WHERE url=?"));
129  s.BindString(0, history::HistoryDatabase::GURLToDatabaseURL(url));
130
131  return (s.Step() && s.ColumnInt(0) == 1);
132}
133
134bool WebAppsTable::RemoveWebApp(const GURL& url) {
135  sql::Statement delete_s(db_->GetUniqueStatement(
136      "DELETE FROM web_app_icons WHERE url = ?"));
137  delete_s.BindString(0, history::HistoryDatabase::GURLToDatabaseURL(url));
138
139  if (!delete_s.Run())
140    return false;
141
142  sql::Statement delete_s2(db_->GetUniqueStatement(
143      "DELETE FROM web_apps WHERE url = ?"));
144  delete_s2.BindString(0, history::HistoryDatabase::GURLToDatabaseURL(url));
145
146  return delete_s2.Run();
147}
148