| 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; |
| 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 |