Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1542)

Side by Side Diff: chrome/browser/extensions/convert_web_app.cc

Issue 4471001: Reland http://codereview.chromium.org/4139008, with a different (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: this crap still does not work Created 10 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
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
3 // found in the LICENSE file.
4
5 #include "chrome/browser/extensions/convert_web_app.h"
6
7 #include <cmath>
8 #include <limits>
9 #include <string>
10 #include <vector>
11
12 #include "base/base64.h"
13 #include "base/file_path.h"
14 #include "base/file_util.h"
15 #include "base/path_service.h"
16 #include "base/scoped_temp_dir.h"
17 #include "base/sha2.h"
18 #include "base/stringprintf.h"
19 #include "base/time.h"
20 #include "base/utf_string_conversions.h"
21 #include "chrome/common/chrome_paths.h"
22 #include "chrome/common/extensions/extension.h"
23 #include "chrome/common/extensions/extension_constants.h"
24 #include "chrome/common/json_value_serializer.h"
25 #include "gfx/codec/png_codec.h"
26 #include "googleurl/src/gurl.h"
27 #include "third_party/skia/include/core/SkBitmap.h"
28 #include "webkit/glue/dom_operations.h"
29
30 namespace keys = extension_manifest_keys;
31
32 using base::Time;
33
34 namespace {
35
36 const char kIconsDirName[] = "_icons";
37
38 // Create the public key for the converted web app.
39 //
40 // Web apps are not signed, but the public key for an extension doubles as
41 // its unique identity, and we need one of those. A web app's unique identity
42 // is its manifest URL, so we hash that to create a public key. There will be
43 // no corresponding private key, which means that these extensions cannot be
44 // auto-updated using ExtensionUpdater. But Chrome does notice updates to the
45 // manifest and regenerates these extensions.
46 std::string GenerateKey(const GURL& manifest_url) {
47 char raw[base::SHA256_LENGTH] = {0};
48 std::string key;
49 base::SHA256HashString(manifest_url.spec().c_str(),
50 raw,
51 base::SHA256_LENGTH);
52 base::Base64Encode(std::string(raw, base::SHA256_LENGTH), &key);
53 return key;
54 }
55
56 }
57
58
59 // Generates a version for the converted app using the current date. This isn't
60 // really needed, but it seems like useful information.
61 std::string ConvertTimeToExtensionVersion(const Time& create_time) {
62 Time::Exploded create_time_exploded;
63 create_time.UTCExplode(&create_time_exploded);
64
65 double micros =
66 (create_time_exploded.millisecond * Time::kMicrosecondsPerMillisecond) +
67 (create_time_exploded.second * Time::kMicrosecondsPerSecond) +
68 (create_time_exploded.minute * Time::kMicrosecondsPerMinute) +
69 (create_time_exploded.hour * Time::kMicrosecondsPerHour);
70 LOG(ERROR) << "micros: " << micros;
71 double day_fraction = micros / Time::kMicrosecondsPerDay;
72 LOG(ERROR) << "day_fraction: " << day_fraction;
73 double stamp = round(day_fraction * std::numeric_limits<uint16>::max());
74 LOG(ERROR) << "stamp: " << stamp;
75
76 return base::StringPrintf("%i.%i.%i.%i",
77 create_time_exploded.year,
78 create_time_exploded.month,
79 create_time_exploded.day_of_month,
80 static_cast<uint16>(stamp));
81 }
82
83 scoped_refptr<Extension> ConvertWebAppToExtension(
84 const webkit_glue::WebApplicationInfo& web_app,
85 const Time& create_time) {
86 FilePath user_data_temp_dir;
87 CHECK(PathService::Get(chrome::DIR_USER_DATA_TEMP, &user_data_temp_dir));
88
89 ScopedTempDir temp_dir;
90 if (!temp_dir.CreateUniqueTempDirUnderPath(user_data_temp_dir)) {
91 LOG(ERROR) << "Could not create temporary directory.";
92 return NULL;
93 }
94
95 // Create the manifest
96 scoped_ptr<DictionaryValue> root(new DictionaryValue);
97 root->SetString(keys::kPublicKey, GenerateKey(web_app.manifest_url));
98 root->SetString(keys::kName, UTF16ToUTF8(web_app.title));
99 root->SetString(keys::kVersion, ConvertTimeToExtensionVersion(create_time));
100 root->SetString(keys::kDescription, UTF16ToUTF8(web_app.description));
101 root->SetString(keys::kLaunchWebURL, web_app.app_url.spec());
102
103 // Add the icons.
104 DictionaryValue* icons = new DictionaryValue();
105 root->Set(keys::kIcons, icons);
106 for (size_t i = 0; i < web_app.icons.size(); ++i) {
107 std::string size = StringPrintf("%i", web_app.icons[i].width);
108 std::string icon_path = StringPrintf("%s/%s.png", kIconsDirName,
109 size.c_str());
110 icons->SetString(size, icon_path);
111 }
112
113 // Add the permissions.
114 ListValue* permissions = new ListValue();
115 root->Set(keys::kPermissions, permissions);
116 for (size_t i = 0; i < web_app.permissions.size(); ++i) {
117 permissions->Append(Value::CreateStringValue(web_app.permissions[i]));
118 }
119
120 // Add the URLs.
121 ListValue* urls = new ListValue();
122 root->Set(keys::kWebURLs, urls);
123 for (size_t i = 0; i < web_app.urls.size(); ++i) {
124 urls->Append(Value::CreateStringValue(web_app.urls[i].spec()));
125 }
126
127 // Write the manifest.
128 FilePath manifest_path = temp_dir.path().Append(
129 Extension::kManifestFilename);
130 JSONFileValueSerializer serializer(manifest_path);
131 if (!serializer.Serialize(*root)) {
132 LOG(ERROR) << "Could not serialize manifest.";
133 return NULL;
134 }
135
136 // Write the icon files.
137 FilePath icons_dir = temp_dir.path().AppendASCII(kIconsDirName);
138 if (!file_util::CreateDirectory(icons_dir)) {
139 LOG(ERROR) << "Could not create icons directory.";
140 return NULL;
141 }
142 for (size_t i = 0; i < web_app.icons.size(); ++i) {
143 FilePath icon_file = icons_dir.AppendASCII(
144 StringPrintf("%i.png", web_app.icons[i].width));
145 std::vector<unsigned char> image_data;
146 if (!gfx::PNGCodec::EncodeBGRASkBitmap(web_app.icons[i].data,
147 false,
148 &image_data)) {
149 LOG(ERROR) << "Could not create icon file.";
150 return NULL;
151 }
152
153 const char* image_data_ptr = reinterpret_cast<const char*>(&image_data[0]);
154 if (!file_util::WriteFile(icon_file, image_data_ptr, image_data.size())) {
155 LOG(ERROR) << "Could not write icon file.";
156 return NULL;
157 }
158 }
159
160 // Finally, create the extension object to represent the unpacked directory.
161 std::string error;
162 scoped_refptr<Extension> extension = Extension::Create(
163 temp_dir.path(), Extension::INTERNAL, *root, false, &error);
164 if (!extension) {
165 LOG(ERROR) << error;
166 return NULL;
167 }
168
169 temp_dir.Take(); // The caller takes ownership of the directory.
170 return extension;
171 }
OLDNEW
« no previous file with comments | « chrome/browser/extensions/convert_web_app.h ('k') | chrome/browser/extensions/convert_web_app_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698