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