OLD | NEW |
---|---|
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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/extensions/convert_web_app.h" | 5 #include "chrome/browser/extensions/convert_web_app.h" |
6 | 6 |
7 #include <cmath> | 7 #include <cmath> |
8 #include <limits> | 8 #include <limits> |
9 #include <string> | 9 #include <string> |
10 #include <vector> | 10 #include <vector> |
(...skipping 29 matching lines...) Expand all Loading... | |
40 namespace { | 40 namespace { |
41 | 41 |
42 const char kIconsDirName[] = "icons"; | 42 const char kIconsDirName[] = "icons"; |
43 | 43 |
44 // Create the public key for the converted web app. | 44 // Create the public key for the converted web app. |
45 // | 45 // |
46 // Web apps are not signed, but the public key for an extension doubles as | 46 // Web apps are not signed, but the public key for an extension doubles as |
47 // its unique identity, and we need one of those. A web app's unique identity | 47 // its unique identity, and we need one of those. A web app's unique identity |
48 // is its manifest URL, so we hash that to create a public key. There will be | 48 // is its manifest URL, so we hash that to create a public key. There will be |
49 // no corresponding private key, which means that these extensions cannot be | 49 // no corresponding private key, which means that these extensions cannot be |
50 // auto-updated using ExtensionUpdater. But Chrome does notice updates to the | 50 // auto-updated using ExtensionUpdater. |
51 // manifest and regenerates these extensions. | 51 std::string GenerateKey(const GURL& app_url) { |
52 std::string GenerateKey(const GURL& manifest_url) { | |
53 char raw[crypto::kSHA256Length] = {0}; | 52 char raw[crypto::kSHA256Length] = {0}; |
54 std::string key; | 53 std::string key; |
55 crypto::SHA256HashString(manifest_url.spec().c_str(), raw, | 54 crypto::SHA256HashString(app_url.spec().c_str(), raw, |
56 crypto::kSHA256Length); | 55 crypto::kSHA256Length); |
57 base::Base64Encode(std::string(raw, crypto::kSHA256Length), &key); | 56 base::Base64Encode(std::string(raw, crypto::kSHA256Length), &key); |
58 return key; | 57 return key; |
59 } | 58 } |
60 | 59 |
61 } // namespace | 60 } // namespace |
62 | 61 |
63 // Generates a version for the converted app using the current date. This isn't | 62 // Generates a version for the converted app using the current date. This isn't |
64 // really needed, but it seems like useful information. | 63 // really needed, but it seems like useful information. |
65 std::string ConvertTimeToExtensionVersion(const Time& create_time) { | 64 std::string ConvertTimeToExtensionVersion(const Time& create_time) { |
(...skipping 30 matching lines...) Expand all Loading... | |
96 } | 95 } |
97 | 96 |
98 base::ScopedTempDir temp_dir; | 97 base::ScopedTempDir temp_dir; |
99 if (!temp_dir.CreateUniqueTempDirUnderPath(install_temp_dir)) { | 98 if (!temp_dir.CreateUniqueTempDirUnderPath(install_temp_dir)) { |
100 LOG(ERROR) << "Could not create temporary directory."; | 99 LOG(ERROR) << "Could not create temporary directory."; |
101 return NULL; | 100 return NULL; |
102 } | 101 } |
103 | 102 |
104 // Create the manifest | 103 // Create the manifest |
105 scoped_ptr<base::DictionaryValue> root(new base::DictionaryValue); | 104 scoped_ptr<base::DictionaryValue> root(new base::DictionaryValue); |
106 if (!web_app.is_bookmark_app) | 105 root->SetString(keys::kPublicKey, GenerateKey(web_app.app_url)); |
107 root->SetString(keys::kPublicKey, GenerateKey(web_app.manifest_url)); | |
108 else | |
109 root->SetString(keys::kPublicKey, GenerateKey(web_app.app_url)); | |
110 | |
111 if (web_app.is_offline_enabled) | |
112 root->SetBoolean(keys::kOfflineEnabled, true); | |
113 | |
114 root->SetString(keys::kName, base::UTF16ToUTF8(web_app.title)); | 106 root->SetString(keys::kName, base::UTF16ToUTF8(web_app.title)); |
115 root->SetString(keys::kVersion, ConvertTimeToExtensionVersion(create_time)); | 107 root->SetString(keys::kVersion, ConvertTimeToExtensionVersion(create_time)); |
116 root->SetString(keys::kDescription, base::UTF16ToUTF8(web_app.description)); | 108 root->SetString(keys::kDescription, base::UTF16ToUTF8(web_app.description)); |
117 root->SetString(keys::kLaunchWebURL, web_app.app_url.spec()); | 109 root->SetString(keys::kLaunchWebURL, web_app.app_url.spec()); |
118 | 110 |
119 if (!web_app.launch_container.empty()) | |
120 root->SetString(keys::kLaunchContainer, web_app.launch_container); | |
121 | |
122 // Add the icons. | 111 // Add the icons. |
123 base::DictionaryValue* icons = new base::DictionaryValue(); | 112 base::DictionaryValue* icons = new base::DictionaryValue(); |
124 root->Set(keys::kIcons, icons); | 113 root->Set(keys::kIcons, icons); |
125 for (size_t i = 0; i < web_app.icons.size(); ++i) { | 114 for (size_t i = 0; i < web_app.icons.size(); ++i) { |
126 std::string size = base::StringPrintf("%i", web_app.icons[i].width); | 115 std::string size = base::StringPrintf("%i", web_app.icons[i].width); |
127 std::string icon_path = base::StringPrintf("%s/%s.png", kIconsDirName, | 116 std::string icon_path = base::StringPrintf("%s/%s.png", kIconsDirName, |
128 size.c_str()); | 117 size.c_str()); |
129 icons->SetString(size, icon_path); | 118 icons->SetString(size, icon_path); |
130 } | 119 } |
131 | 120 |
132 // Add the permissions. | |
133 base::ListValue* permissions = new base::ListValue(); | |
134 root->Set(keys::kPermissions, permissions); | |
135 for (size_t i = 0; i < web_app.permissions.size(); ++i) { | |
136 permissions->Append(new base::StringValue(web_app.permissions[i])); | |
137 } | |
138 | |
139 // Add the URLs. | |
140 base::ListValue* urls = new base::ListValue(); | |
141 root->Set(keys::kWebURLs, urls); | |
142 for (size_t i = 0; i < web_app.urls.size(); ++i) { | |
143 urls->Append(new base::StringValue(web_app.urls[i].spec())); | |
144 } | |
145 | |
146 // Write the manifest. | 121 // Write the manifest. |
147 base::FilePath manifest_path = temp_dir.path().Append(kManifestFilename); | 122 base::FilePath manifest_path = temp_dir.path().Append(kManifestFilename); |
148 JSONFileValueSerializer serializer(manifest_path); | 123 JSONFileValueSerializer serializer(manifest_path); |
149 if (!serializer.Serialize(*root)) { | 124 if (!serializer.Serialize(*root)) { |
150 LOG(ERROR) << "Could not serialize manifest."; | 125 LOG(ERROR) << "Could not serialize manifest."; |
151 return NULL; | 126 return NULL; |
152 } | 127 } |
153 | 128 |
154 // Write the icon files. | 129 // Write the icon files. |
155 base::FilePath icons_dir = temp_dir.path().AppendASCII(kIconsDirName); | 130 base::FilePath icons_dir = temp_dir.path().AppendASCII(kIconsDirName); |
(...skipping 20 matching lines...) Expand all Loading... | |
176 int size = base::checked_numeric_cast<int>(image_data.size()); | 151 int size = base::checked_numeric_cast<int>(image_data.size()); |
177 if (file_util::WriteFile(icon_file, image_data_ptr, size) != size) { | 152 if (file_util::WriteFile(icon_file, image_data_ptr, size) != size) { |
178 LOG(ERROR) << "Could not write icon file."; | 153 LOG(ERROR) << "Could not write icon file."; |
179 return NULL; | 154 return NULL; |
180 } | 155 } |
181 } | 156 } |
182 | 157 |
183 // Finally, create the extension object to represent the unpacked directory. | 158 // Finally, create the extension object to represent the unpacked directory. |
184 std::string error; | 159 std::string error; |
185 int extension_flags = Extension::NO_FLAGS; | 160 int extension_flags = Extension::NO_FLAGS; |
186 if (web_app.is_bookmark_app) | 161 extension_flags |= Extension::FROM_BOOKMARK; |
benwells
2014/01/27 10:30:16
nit: above two lines can be combined.
| |
187 extension_flags |= Extension::FROM_BOOKMARK; | |
188 scoped_refptr<Extension> extension = Extension::Create( | 162 scoped_refptr<Extension> extension = Extension::Create( |
189 temp_dir.path(), | 163 temp_dir.path(), |
190 Manifest::INTERNAL, | 164 Manifest::INTERNAL, |
191 *root, | 165 *root, |
192 extension_flags, | 166 extension_flags, |
193 &error); | 167 &error); |
194 if (!extension.get()) { | 168 if (!extension.get()) { |
195 LOG(ERROR) << error; | 169 LOG(ERROR) << error; |
196 return NULL; | 170 return NULL; |
197 } | 171 } |
198 | 172 |
199 temp_dir.Take(); // The caller takes ownership of the directory. | 173 temp_dir.Take(); // The caller takes ownership of the directory. |
200 return extension; | 174 return extension; |
201 } | 175 } |
202 | 176 |
203 } // namespace extensions | 177 } // namespace extensions |
OLD | NEW |