text: // Copyright (c) 2012 The Chromium Authors. All rights reserved.
  // Use of this source code is governed by a BSD-style license that can be
  // found in the LICENSE file.
  
  #include "base/test/values_test_util.h"
  #include "chrome/common/extensions/api/identity/oauth2_manifest_handler.h"
  #include "chrome/common/extensions/extension_manifest_constants.h"
  #include "chrome/common/extensions/manifest_tests/extension_manifest_test.h"
  #include "testing/gtest/include/gtest/gtest.h"
  
  namespace keys = extension_manifest_keys;
  
  namespace {
  
  // Produces extension ID = "mdbihdcgjmagbcapkhhkjbbdlkflmbfo".
  const char kExtensionKey[] =
      "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCV9PlZjcTIXfnlB3HXo50OlM/CnIq0y7jm"
      "KfPVyStaWsmFB7NaVnqUXoGb9swBDfVnZ6BrupwnxL76TWEJPo+KQMJ6uz0PPdJWi2jQfZiG"
      "iheDiKH5Gv+dVd67qf7ly8QWW0o8qmFpqBZQpksm1hOGbfsupv9W4c42tMEIicDMLQIDAQAB";
  const char kAutoApproveNotAllowedWarning[] =
      "'oauth2.auto_approve' is not allowed for specified extension ID.";
  
  }  // namespace
  
  namespace extensions {
  
  class OAuth2ManifestTest : public ExtensionManifestTest {
   protected:
    enum AutoApproveValue {
      AUTO_APPROVE_NOT_SET,
      AUTO_APPROVE_FALSE,
      AUTO_APPROVE_TRUE,
      AUTO_APPROVE_INVALID
    };
  
    base::DictionaryValue* CreateManifest(
        AutoApproveValue auto_approve,
        bool extension_id_whitelisted) {
      parsed_manifest_.reset(base::test::ParseJson(
          "{ \n"
          "  \"name\": \"test\", \n"
          "  \"version\": \"0.1\", \n"
          "  \"manifest_version\": 2, \n"
          "  \"oauth2\": { \n"
          "    \"client_id\": \"client1\", \n"
          "    \"scopes\": [ \"scope1\" ], \n"
          "  }, \n"
          "} \n").release());
      base::DictionaryValue* ext_manifest;
      EXPECT_TRUE(parsed_manifest_->GetAsDictionary(&ext_manifest));
      switch (auto_approve) {
        case AUTO_APPROVE_NOT_SET:
          break;
        case AUTO_APPROVE_FALSE:
          ext_manifest->SetBoolean(keys::kOAuth2AutoApprove, false);
          break;
        case AUTO_APPROVE_TRUE:
          ext_manifest->SetBoolean(keys::kOAuth2AutoApprove, true);
          break;
        case AUTO_APPROVE_INVALID:
          ext_manifest->SetString(keys::kOAuth2AutoApprove, "incorrect value");
          break;
      }
      if (extension_id_whitelisted)
        ext_manifest->SetString(keys::kKey, kExtensionKey);
      return ext_manifest;
    }
  
   private:
    scoped_ptr<Value> parsed_manifest_;
  };
  
  TEST_F(OAuth2ManifestTest, OAuth2SectionParsing) {
    base::DictionaryValue base_manifest;
  
    base_manifest.SetString(keys::kName, "test");
    base_manifest.SetString(keys::kVersion, "0.1");
    base_manifest.SetInteger(keys::kManifestVersion, 2);
    base_manifest.SetString(keys::kOAuth2ClientId, "client1");
    base::ListValue* scopes = new base::ListValue();
    scopes->Append(new base::StringValue("scope1"));
    scopes->Append(new base::StringValue("scope2"));
    base_manifest.Set(keys::kOAuth2Scopes, scopes);
  
    // OAuth2 section should be parsed for an extension.
    {
      base::DictionaryValue ext_manifest;
      // Lack of "app" section representa an extension. So the base manifest
      // itself represents an extension.
      ext_manifest.MergeDictionary(&base_manifest);
      ext_manifest.SetString(keys::kKey, kExtensionKey);
      ext_manifest.SetBoolean(keys::kOAuth2AutoApprove, true);
  
      Manifest manifest(&ext_manifest, "test");
      scoped_refptr<extensions::Extension> extension =
          LoadAndExpectSuccess(manifest);
      EXPECT_TRUE(extension->install_warnings().empty());
      EXPECT_EQ("client1", OAuth2Info::GetOAuth2Info(extension.get()).client_id);
      EXPECT_EQ(2U, OAuth2Info::GetOAuth2Info(extension.get()).scopes.size());
      EXPECT_EQ("scope1", OAuth2Info::GetOAuth2Info(extension.get()).scopes[0]);
      EXPECT_EQ("scope2", OAuth2Info::GetOAuth2Info(extension.get()).scopes[1]);
      EXPECT_TRUE(OAuth2Info::GetOAuth2Info(extension.get()).auto_approve);
    }
  
    // OAuth2 section should be parsed for a packaged app.
    {
      base::DictionaryValue app_manifest;
      app_manifest.SetString(keys::kLaunchLocalPath, "launch.html");
      app_manifest.MergeDictionary(&base_manifest);
  
      Manifest manifest(&app_manifest, "test");
      scoped_refptr<extensions::Extension> extension =
          LoadAndExpectSuccess(manifest);
      EXPECT_TRUE(extension->install_warnings().empty());
      EXPECT_EQ("client1", OAuth2Info::GetOAuth2Info(extension.get()).client_id);
      EXPECT_EQ(2U, OAuth2Info::GetOAuth2Info(extension.get()).scopes.size());
      EXPECT_EQ("scope1", OAuth2Info::GetOAuth2Info(extension.get()).scopes[0]);
      EXPECT_EQ("scope2", OAuth2Info::GetOAuth2Info(extension.get()).scopes[1]);
      EXPECT_FALSE(OAuth2Info::GetOAuth2Info(extension.get()).auto_approve);
    }
  
    // OAuth2 section should NOT be parsed for a hosted app.
    {
      base::DictionaryValue app_manifest;
      app_manifest.SetString(keys::kLaunchWebURL, "http://www.google.com");
      app_manifest.MergeDictionary(&base_manifest);
  
      Manifest manifest(&app_manifest, "test");
      scoped_refptr<extensions::Extension> extension =
          LoadAndExpectSuccess(manifest);
      EXPECT_EQ(1U, extension->install_warnings().size());
      const extensions::InstallWarning& warning =
          extension->install_warnings()[0];
      EXPECT_EQ("'oauth2' is only allowed for extensions, legacy packaged apps "
                    "and packaged apps, and this is a hosted app.",
                warning.message);
      EXPECT_EQ("", OAuth2Info::GetOAuth2Info(extension.get()).client_id);
      EXPECT_TRUE(OAuth2Info::GetOAuth2Info(extension.get()).scopes.empty());
      EXPECT_FALSE(OAuth2Info::GetOAuth2Info(extension.get()).auto_approve);
    }
  }
  
  TEST_F(OAuth2ManifestTest, AutoApproveNotSetExtensionNotOnWhitelist) {
    base::DictionaryValue* ext_manifest =
        CreateManifest(AUTO_APPROVE_NOT_SET, false);
    Manifest manifest(ext_manifest, "test");
    scoped_refptr<extensions::Extension> extension =
        LoadAndExpectSuccess(manifest);
    EXPECT_TRUE(extension->install_warnings().empty());
    EXPECT_FALSE(OAuth2Info::GetOAuth2Info(extension.get()).auto_approve);
  }
  
  TEST_F(OAuth2ManifestTest, AutoApproveFalseExtensionNotOnWhitelist) {
    base::DictionaryValue* ext_manifest =
        CreateManifest(AUTO_APPROVE_FALSE, false);
    Manifest manifest(ext_manifest, "test");
    scoped_refptr<extensions::Extension> extension =
        LoadAndExpectSuccess(manifest);
    EXPECT_EQ(1U, extension->install_warnings().size());
    const extensions::InstallWarning& warning =
        extension->install_warnings()[0];
    EXPECT_EQ(kAutoApproveNotAllowedWarning, warning.message);
    EXPECT_FALSE(OAuth2Info::GetOAuth2Info(extension.get()).auto_approve);
  }
  
  TEST_F(OAuth2ManifestTest, AutoApproveTrueExtensionNotOnWhitelist) {
    base::DictionaryValue* ext_manifest =
        CreateManifest(AUTO_APPROVE_TRUE, false);
    Manifest manifest(ext_manifest, "test");
    scoped_refptr<extensions::Extension> extension =
        LoadAndExpectSuccess(manifest);
    EXPECT_EQ(1U, extension->install_warnings().size());
    const extensions::InstallWarning& warning =
        extension->install_warnings()[0];
    EXPECT_EQ(kAutoApproveNotAllowedWarning, warning.message);
    EXPECT_FALSE(OAuth2Info::GetOAuth2Info(extension.get()).auto_approve);
  }
  
  TEST_F(OAuth2ManifestTest, AutoApproveInvalidExtensionNotOnWhitelist) {
    base::DictionaryValue* ext_manifest =
        CreateManifest(AUTO_APPROVE_INVALID, false);
    Manifest manifest(ext_manifest, "test");
    scoped_refptr<extensions::Extension> extension =
        LoadAndExpectSuccess(manifest);
    EXPECT_EQ(1U, extension->install_warnings().size());
    const extensions::InstallWarning& warning =
        extension->install_warnings()[0];
    EXPECT_EQ(kAutoApproveNotAllowedWarning, warning.message);
    EXPECT_FALSE(OAuth2Info::GetOAuth2Info(extension.get()).auto_approve);
  }
  
  TEST_F(OAuth2ManifestTest, AutoApproveNotSetExtensionOnWhitelist) {
    base::DictionaryValue* ext_manifest =
        CreateManifest(AUTO_APPROVE_NOT_SET, true);
    Manifest manifest(ext_manifest, "test");
    scoped_refptr<extensions::Extension> extension =
        LoadAndExpectSuccess(manifest);
    EXPECT_TRUE(extension->install_warnings().empty());
    EXPECT_FALSE(OAuth2Info::GetOAuth2Info(extension.get()).auto_approve);
  }
  
  TEST_F(OAuth2ManifestTest, AutoApproveFalseExtensionOnWhitelist) {
    base::DictionaryValue* ext_manifest =
        CreateManifest(AUTO_APPROVE_FALSE, true);
    Manifest manifest(ext_manifest, "test");
    scoped_refptr<extensions::Extension> extension =
        LoadAndExpectSuccess(manifest);
    EXPECT_TRUE(extension->install_warnings().empty());
    EXPECT_FALSE(OAuth2Info::GetOAuth2Info(extension.get()).auto_approve);
  }
  
  TEST_F(OAuth2ManifestTest, AutoApproveTrueExtensionOnWhitelist) {
    base::DictionaryValue* ext_manifest =
        CreateManifest(AUTO_APPROVE_TRUE, true);
    Manifest manifest(ext_manifest, "test");
    scoped_refptr<extensions::Extension> extension =
        LoadAndExpectSuccess(manifest);
    EXPECT_TRUE(extension->install_warnings().empty());
    EXPECT_TRUE(OAuth2Info::GetOAuth2Info(extension.get()).auto_approve);
  }
  
  TEST_F(OAuth2ManifestTest, AutoApproveInvalidExtensionOnWhitelist) {
    base::DictionaryValue* ext_manifest =
        CreateManifest(AUTO_APPROVE_INVALID, true);
    Manifest manifest(ext_manifest, "test");
    std::string error;
    scoped_refptr<extensions::Extension> extension =
        LoadExtension(manifest, &error);
    EXPECT_EQ(
        "Invalid value for 'oauth2.auto_approve'. Value must be true or false.",
        error);
  }
  
  }  // namespace extensions
  