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 3// found in the LICENSE file. 4 5#include "base/test/values_test_util.h" 6#include "chrome/common/extensions/api/identity/oauth2_manifest_handler.h" 7#include "chrome/common/extensions/manifest_tests/chrome_manifest_test.h" 8#include "extensions/common/manifest_constants.h" 9#include "testing/gtest/include/gtest/gtest.h" 10 11namespace extensions { 12 13namespace keys = manifest_keys; 14namespace errors = manifest_errors; 15 16namespace { 17 18// Produces extension ID = "mdbihdcgjmagbcapkhhkjbbdlkflmbfo". 19const char kExtensionKey[] = 20 "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCV9PlZjcTIXfnlB3HXo50OlM/CnIq0y7jm" 21 "KfPVyStaWsmFB7NaVnqUXoGb9swBDfVnZ6BrupwnxL76TWEJPo+KQMJ6uz0PPdJWi2jQfZiG" 22 "iheDiKH5Gv+dVd67qf7ly8QWW0o8qmFpqBZQpksm1hOGbfsupv9W4c42tMEIicDMLQIDAQAB"; 23const char kAutoApproveNotAllowedWarning[] = 24 "'oauth2.auto_approve' is not allowed for specified extension ID."; 25 26} // namespace 27 28class OAuth2ManifestTest : public ChromeManifestTest { 29 protected: 30 enum AutoApproveValue { 31 AUTO_APPROVE_NOT_SET, 32 AUTO_APPROVE_FALSE, 33 AUTO_APPROVE_TRUE, 34 AUTO_APPROVE_INVALID 35 }; 36 37 enum ClientIdValue { 38 CLIENT_ID_DEFAULT, 39 CLIENT_ID_NOT_SET, 40 CLIENT_ID_EMPTY 41 }; 42 43 base::DictionaryValue* CreateManifest( 44 AutoApproveValue auto_approve, 45 bool extension_id_whitelisted, 46 ClientIdValue client_id) { 47 parsed_manifest_.reset(base::test::ParseJson( 48 "{ \n" 49 " \"name\": \"test\", \n" 50 " \"version\": \"0.1\", \n" 51 " \"manifest_version\": 2, \n" 52 " \"oauth2\": { \n" 53 " \"scopes\": [ \"scope1\" ], \n" 54 " }, \n" 55 "} \n").release()); 56 base::DictionaryValue* ext_manifest; 57 EXPECT_TRUE(parsed_manifest_->GetAsDictionary(&ext_manifest)); 58 switch (auto_approve) { 59 case AUTO_APPROVE_NOT_SET: 60 break; 61 case AUTO_APPROVE_FALSE: 62 ext_manifest->SetBoolean(keys::kOAuth2AutoApprove, false); 63 break; 64 case AUTO_APPROVE_TRUE: 65 ext_manifest->SetBoolean(keys::kOAuth2AutoApprove, true); 66 break; 67 case AUTO_APPROVE_INVALID: 68 ext_manifest->SetString(keys::kOAuth2AutoApprove, "incorrect value"); 69 break; 70 } 71 switch (client_id) { 72 case CLIENT_ID_DEFAULT: 73 ext_manifest->SetString(keys::kOAuth2ClientId, "client1"); 74 break; 75 case CLIENT_ID_NOT_SET: 76 break; 77 case CLIENT_ID_EMPTY: 78 ext_manifest->SetString(keys::kOAuth2ClientId, ""); 79 } 80 if (extension_id_whitelisted) 81 ext_manifest->SetString(keys::kKey, kExtensionKey); 82 return ext_manifest; 83 } 84 85 private: 86 scoped_ptr<base::Value> parsed_manifest_; 87}; 88 89TEST_F(OAuth2ManifestTest, OAuth2SectionParsing) { 90 base::DictionaryValue base_manifest; 91 92 base_manifest.SetString(keys::kName, "test"); 93 base_manifest.SetString(keys::kVersion, "0.1"); 94 base_manifest.SetInteger(keys::kManifestVersion, 2); 95 base_manifest.SetString(keys::kOAuth2ClientId, "client1"); 96 base::ListValue* scopes = new base::ListValue(); 97 scopes->Append(new base::StringValue("scope1")); 98 scopes->Append(new base::StringValue("scope2")); 99 base_manifest.Set(keys::kOAuth2Scopes, scopes); 100 101 // OAuth2 section should be parsed for an extension. 102 { 103 base::DictionaryValue ext_manifest; 104 // Lack of "app" section representa an extension. So the base manifest 105 // itself represents an extension. 106 ext_manifest.MergeDictionary(&base_manifest); 107 ext_manifest.SetString(keys::kKey, kExtensionKey); 108 ext_manifest.SetBoolean(keys::kOAuth2AutoApprove, true); 109 110 ManifestData manifest(&ext_manifest, "test"); 111 scoped_refptr<extensions::Extension> extension = 112 LoadAndExpectSuccess(manifest); 113 EXPECT_TRUE(extension->install_warnings().empty()); 114 EXPECT_EQ("client1", OAuth2Info::GetOAuth2Info(extension.get()).client_id); 115 EXPECT_EQ(2U, OAuth2Info::GetOAuth2Info(extension.get()).scopes.size()); 116 EXPECT_EQ("scope1", OAuth2Info::GetOAuth2Info(extension.get()).scopes[0]); 117 EXPECT_EQ("scope2", OAuth2Info::GetOAuth2Info(extension.get()).scopes[1]); 118 EXPECT_TRUE(OAuth2Info::GetOAuth2Info(extension.get()).auto_approve); 119 } 120 121 // OAuth2 section should be parsed for a packaged app. 122 { 123 base::DictionaryValue app_manifest; 124 app_manifest.SetString(keys::kLaunchLocalPath, "launch.html"); 125 app_manifest.MergeDictionary(&base_manifest); 126 127 ManifestData manifest(&app_manifest, "test"); 128 scoped_refptr<extensions::Extension> extension = 129 LoadAndExpectSuccess(manifest); 130 EXPECT_TRUE(extension->install_warnings().empty()); 131 EXPECT_EQ("client1", OAuth2Info::GetOAuth2Info(extension.get()).client_id); 132 EXPECT_EQ(2U, OAuth2Info::GetOAuth2Info(extension.get()).scopes.size()); 133 EXPECT_EQ("scope1", OAuth2Info::GetOAuth2Info(extension.get()).scopes[0]); 134 EXPECT_EQ("scope2", OAuth2Info::GetOAuth2Info(extension.get()).scopes[1]); 135 EXPECT_FALSE(OAuth2Info::GetOAuth2Info(extension.get()).auto_approve); 136 } 137 138 // OAuth2 section should NOT be parsed for a hosted app. 139 { 140 base::DictionaryValue app_manifest; 141 app_manifest.SetString(keys::kLaunchWebURL, "http://www.google.com"); 142 app_manifest.MergeDictionary(&base_manifest); 143 144 ManifestData manifest(&app_manifest, "test"); 145 scoped_refptr<extensions::Extension> extension = 146 LoadAndExpectSuccess(manifest); 147 EXPECT_EQ(1U, extension->install_warnings().size()); 148 const extensions::InstallWarning& warning = 149 extension->install_warnings()[0]; 150 EXPECT_EQ("'oauth2' is only allowed for extensions, legacy packaged apps, " 151 "and packaged apps, but this is a hosted app.", 152 warning.message); 153 EXPECT_EQ("", OAuth2Info::GetOAuth2Info(extension.get()).client_id); 154 EXPECT_TRUE(OAuth2Info::GetOAuth2Info(extension.get()).scopes.empty()); 155 EXPECT_FALSE(OAuth2Info::GetOAuth2Info(extension.get()).auto_approve); 156 } 157} 158 159TEST_F(OAuth2ManifestTest, AutoApproveNotSetExtensionNotOnWhitelist) { 160 base::DictionaryValue* ext_manifest = 161 CreateManifest(AUTO_APPROVE_NOT_SET, false, CLIENT_ID_DEFAULT); 162 ManifestData manifest(ext_manifest, "test"); 163 scoped_refptr<extensions::Extension> extension = 164 LoadAndExpectSuccess(manifest); 165 EXPECT_TRUE(extension->install_warnings().empty()); 166 EXPECT_FALSE(OAuth2Info::GetOAuth2Info(extension.get()).auto_approve); 167} 168 169TEST_F(OAuth2ManifestTest, AutoApproveFalseExtensionNotOnWhitelist) { 170 base::DictionaryValue* ext_manifest = 171 CreateManifest(AUTO_APPROVE_FALSE, false, CLIENT_ID_DEFAULT); 172 ManifestData manifest(ext_manifest, "test"); 173 scoped_refptr<extensions::Extension> extension = 174 LoadAndExpectSuccess(manifest); 175 EXPECT_EQ(1U, extension->install_warnings().size()); 176 const extensions::InstallWarning& warning = 177 extension->install_warnings()[0]; 178 EXPECT_EQ(kAutoApproveNotAllowedWarning, warning.message); 179 EXPECT_FALSE(OAuth2Info::GetOAuth2Info(extension.get()).auto_approve); 180} 181 182TEST_F(OAuth2ManifestTest, AutoApproveTrueExtensionNotOnWhitelist) { 183 base::DictionaryValue* ext_manifest = 184 CreateManifest(AUTO_APPROVE_TRUE, false, CLIENT_ID_DEFAULT); 185 ManifestData manifest(ext_manifest, "test"); 186 scoped_refptr<extensions::Extension> extension = 187 LoadAndExpectSuccess(manifest); 188 EXPECT_EQ(1U, extension->install_warnings().size()); 189 const extensions::InstallWarning& warning = 190 extension->install_warnings()[0]; 191 EXPECT_EQ(kAutoApproveNotAllowedWarning, warning.message); 192 EXPECT_FALSE(OAuth2Info::GetOAuth2Info(extension.get()).auto_approve); 193} 194 195TEST_F(OAuth2ManifestTest, AutoApproveInvalidExtensionNotOnWhitelist) { 196 base::DictionaryValue* ext_manifest = 197 CreateManifest(AUTO_APPROVE_INVALID, false, CLIENT_ID_DEFAULT); 198 ManifestData manifest(ext_manifest, "test"); 199 scoped_refptr<extensions::Extension> extension = 200 LoadAndExpectSuccess(manifest); 201 EXPECT_EQ(1U, extension->install_warnings().size()); 202 const extensions::InstallWarning& warning = 203 extension->install_warnings()[0]; 204 EXPECT_EQ(kAutoApproveNotAllowedWarning, warning.message); 205 EXPECT_FALSE(OAuth2Info::GetOAuth2Info(extension.get()).auto_approve); 206} 207 208TEST_F(OAuth2ManifestTest, AutoApproveNotSetExtensionOnWhitelist) { 209 base::DictionaryValue* ext_manifest = 210 CreateManifest(AUTO_APPROVE_NOT_SET, true, CLIENT_ID_DEFAULT); 211 ManifestData manifest(ext_manifest, "test"); 212 scoped_refptr<extensions::Extension> extension = 213 LoadAndExpectSuccess(manifest); 214 EXPECT_TRUE(extension->install_warnings().empty()); 215 EXPECT_FALSE(OAuth2Info::GetOAuth2Info(extension.get()).auto_approve); 216} 217 218TEST_F(OAuth2ManifestTest, AutoApproveFalseExtensionOnWhitelist) { 219 base::DictionaryValue* ext_manifest = 220 CreateManifest(AUTO_APPROVE_FALSE, true, CLIENT_ID_DEFAULT); 221 ManifestData manifest(ext_manifest, "test"); 222 scoped_refptr<extensions::Extension> extension = 223 LoadAndExpectSuccess(manifest); 224 EXPECT_TRUE(extension->install_warnings().empty()); 225 EXPECT_FALSE(OAuth2Info::GetOAuth2Info(extension.get()).auto_approve); 226} 227 228TEST_F(OAuth2ManifestTest, AutoApproveTrueExtensionOnWhitelist) { 229 base::DictionaryValue* ext_manifest = 230 CreateManifest(AUTO_APPROVE_TRUE, true, CLIENT_ID_DEFAULT); 231 ManifestData manifest(ext_manifest, "test"); 232 scoped_refptr<extensions::Extension> extension = 233 LoadAndExpectSuccess(manifest); 234 EXPECT_TRUE(extension->install_warnings().empty()); 235 EXPECT_TRUE(OAuth2Info::GetOAuth2Info(extension.get()).auto_approve); 236} 237 238TEST_F(OAuth2ManifestTest, AutoApproveInvalidExtensionOnWhitelist) { 239 base::DictionaryValue* ext_manifest = 240 CreateManifest(AUTO_APPROVE_INVALID, true, CLIENT_ID_DEFAULT); 241 ManifestData manifest(ext_manifest, "test"); 242 std::string error; 243 scoped_refptr<extensions::Extension> extension = 244 LoadExtension(manifest, &error); 245 EXPECT_EQ( 246 "Invalid value for 'oauth2.auto_approve'. Value must be true or false.", 247 error); 248} 249 250TEST_F(OAuth2ManifestTest, InvalidClientId) { 251 { 252 base::DictionaryValue* ext_manifest = 253 CreateManifest(AUTO_APPROVE_NOT_SET, false, CLIENT_ID_NOT_SET); 254 ManifestData manifest(ext_manifest, "test"); 255 std::string error; 256 LoadAndExpectError(manifest, errors::kInvalidOAuth2ClientId); 257 } 258 259 { 260 base::DictionaryValue* ext_manifest = 261 CreateManifest(AUTO_APPROVE_NOT_SET, false, CLIENT_ID_EMPTY); 262 ManifestData manifest(ext_manifest, "test"); 263 std::string error; 264 LoadAndExpectError(manifest, errors::kInvalidOAuth2ClientId); 265 } 266} 267 268TEST_F(OAuth2ManifestTest, ComponentInvalidClientId) { 269 // Component Apps without auto_approve must include a client ID. 270 { 271 base::DictionaryValue* ext_manifest = 272 CreateManifest(AUTO_APPROVE_NOT_SET, false, CLIENT_ID_NOT_SET); 273 ManifestData manifest(ext_manifest, "test"); 274 std::string error; 275 LoadAndExpectError(manifest, 276 errors::kInvalidOAuth2ClientId, 277 extensions::Manifest::COMPONENT); 278 } 279 280 { 281 base::DictionaryValue* ext_manifest = 282 CreateManifest(AUTO_APPROVE_NOT_SET, false, CLIENT_ID_EMPTY); 283 ManifestData manifest(ext_manifest, "test"); 284 std::string error; 285 LoadAndExpectError(manifest, 286 errors::kInvalidOAuth2ClientId, 287 extensions::Manifest::COMPONENT); 288 } 289} 290 291TEST_F(OAuth2ManifestTest, ComponentWithChromeClientId) { 292 { 293 base::DictionaryValue* ext_manifest = 294 CreateManifest(AUTO_APPROVE_TRUE, true, CLIENT_ID_NOT_SET); 295 ManifestData manifest(ext_manifest, "test"); 296 scoped_refptr<extensions::Extension> extension = 297 LoadAndExpectSuccess(manifest, extensions::Manifest::COMPONENT); 298 EXPECT_TRUE(OAuth2Info::GetOAuth2Info(extension.get()).client_id.empty()); 299 300 } 301 302 { 303 base::DictionaryValue* ext_manifest = 304 CreateManifest(AUTO_APPROVE_TRUE, true, CLIENT_ID_EMPTY); 305 ManifestData manifest(ext_manifest, "test"); 306 scoped_refptr<extensions::Extension> extension = 307 LoadAndExpectSuccess(manifest, extensions::Manifest::COMPONENT); 308 EXPECT_TRUE(OAuth2Info::GetOAuth2Info(extension.get()).client_id.empty()); 309 310 } 311} 312 313TEST_F(OAuth2ManifestTest, ComponentWithStandardClientId) { 314 base::DictionaryValue* ext_manifest = 315 CreateManifest(AUTO_APPROVE_TRUE, true, CLIENT_ID_DEFAULT); 316 ManifestData manifest(ext_manifest, "test"); 317 scoped_refptr<extensions::Extension> extension = 318 LoadAndExpectSuccess(manifest, extensions::Manifest::COMPONENT); 319 EXPECT_EQ("client1", OAuth2Info::GetOAuth2Info(extension.get()).client_id); 320} 321 322} // namespace extensions 323