1 // Copyright 2014 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/ui/views/apps/app_info_dialog/app_info_permissions_panel.h" 6 7 #include "apps/saved_files_service.h" 8 #include "base/callback.h" 9 #include "base/memory/scoped_ptr.h" 10 #include "base/strings/utf_string_conversions.h" 11 #include "chrome/browser/extensions/extension_service.h" 12 #include "chrome/browser/extensions/test_extension_system.h" 13 #include "chrome/test/base/testing_profile.h" 14 #include "content/public/test/test_browser_thread_bundle.h" 15 #include "extensions/common/extension_builder.h" 16 #include "extensions/common/manifest.h" 17 #include "extensions/common/permissions/permission_set.h" 18 #include "extensions/common/permissions/permissions_data.h" 19 #include "grit/generated_resources.h" 20 #include "testing/gmock/include/gmock/gmock-matchers.h" 21 #include "testing/gtest/include/gtest/gtest.h" 22 #include "ui/base/l10n/l10n_util.h" 23 24 namespace { 25 26 const char kTestExtensionId[] = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"; 27 28 } // namespace 29 30 using base::FilePath; 31 using testing::Contains; 32 using testing::Eq; 33 34 class AppInfoPermissionsPanelTest : public testing::Test { 35 protected: 36 AppInfoPermissionsPanelTest() {} 37 38 scoped_ptr<base::DictionaryValue> ValidAppManifest() { 39 return extensions::DictionaryBuilder() 40 .Set("name", "Test App Name") 41 .Set("version", "2.0") 42 .Set("manifest_version", 2) 43 .Set("app", 44 extensions::DictionaryBuilder().Set( 45 "background", 46 extensions::DictionaryBuilder().Set( 47 "scripts", 48 extensions::ListBuilder().Append("background.js")))) 49 .Build(); 50 } 51 52 TestingProfile profile_; 53 54 // We need the UI thread in order to construct UI elements in the view. 55 content::TestBrowserThreadBundle thread_bundle_; 56 }; 57 58 // Tests that an app with no permissions is treated correctly. 59 TEST_F(AppInfoPermissionsPanelTest, NoPermissionsObtainedCorrectly) { 60 scoped_refptr<const extensions::Extension> app = 61 extensions::ExtensionBuilder() 62 .SetManifest(ValidAppManifest()) 63 .SetID(kTestExtensionId) 64 .Build(); 65 AppInfoPermissionsPanel panel(&profile_, app); 66 67 EXPECT_TRUE(panel.GetActivePermissionMessages().empty()); 68 EXPECT_TRUE(panel.GetRetainedFilePaths().empty()); 69 } 70 71 // Tests that an app's required permissions are detected and converted to 72 // messages correctly. 73 TEST_F(AppInfoPermissionsPanelTest, RequiredPermissionsObtainedCorrectly) { 74 scoped_refptr<const extensions::Extension> app = 75 extensions::ExtensionBuilder() 76 .SetManifest(ValidAppManifest()) 77 .MergeManifest(extensions::DictionaryBuilder().Set( 78 "permissions", 79 extensions::ListBuilder() 80 .Append("desktopCapture") // A valid permission with a 81 // message 82 .Append("bad_perm") // An invalid permission 83 .Append("notifications") // An valid permission with 84 // no message 85 .Append("serial"))) // Another valid permission with 86 // a message 87 .SetID(kTestExtensionId) 88 .Build(); 89 AppInfoPermissionsPanel panel(&profile_, app); 90 91 const std::vector<base::string16> permission_messages = 92 panel.GetActivePermissionMessages(); 93 ASSERT_EQ(2U, permission_messages.size()); 94 EXPECT_EQ( 95 l10n_util::GetStringUTF8(IDS_EXTENSION_PROMPT_WARNING_DESKTOP_CAPTURE), 96 base::UTF16ToUTF8(permission_messages[0])); 97 EXPECT_EQ(l10n_util::GetStringUTF8(IDS_EXTENSION_PROMPT_WARNING_SERIAL), 98 base::UTF16ToUTF8(permission_messages[1])); 99 } 100 101 // Tests that an app's optional permissions are detected and converted to 102 // messages correctly. 103 TEST_F(AppInfoPermissionsPanelTest, OptionalPermissionsObtainedCorrectly) { 104 scoped_refptr<const extensions::Extension> app = 105 extensions::ExtensionBuilder() 106 .SetManifest(ValidAppManifest()) 107 .MergeManifest(extensions::DictionaryBuilder().Set( 108 "optional_permissions", 109 extensions::ListBuilder() 110 .Append("clipboardRead") // A valid permission with a 111 // message 112 .Append("bad_perm") // An invalid permission 113 .Append("idle") // A valid permission with 114 // no message 115 .Append("serial"))) // Another valid permission with 116 // a message 117 .SetID(kTestExtensionId) 118 .Build(); 119 AppInfoPermissionsPanel panel(&profile_, app); 120 121 // Optional permissions don't appear until they are 'activated' at runtime. 122 // TODO(sashab): Activate the optional permissions and ensure they are 123 // successfully added to the dialog. 124 EXPECT_TRUE(panel.GetActivePermissionMessages().empty()); 125 EXPECT_TRUE(panel.GetRetainedFilePaths().empty()); 126 } 127 128 // Tests that an app's retained files are detected and converted to paths 129 // correctly. 130 TEST_F(AppInfoPermissionsPanelTest, RetainedFilePermissionsObtainedCorrectly) { 131 scoped_refptr<const extensions::Extension> app = 132 extensions::ExtensionBuilder() 133 .SetManifest(ValidAppManifest()) 134 .MergeManifest(extensions::DictionaryBuilder().Set( 135 "permissions", 136 extensions::ListBuilder().Append( 137 extensions::DictionaryBuilder().Set( 138 "fileSystem", 139 extensions::ListBuilder().Append("retainEntries"))))) 140 .SetID(kTestExtensionId) 141 .Build(); 142 AppInfoPermissionsPanel panel(&profile_, app); 143 apps::SavedFilesService* files_service = 144 apps::SavedFilesService::Get(&profile_); 145 files_service->RegisterFileEntry( 146 app->id(), "file_id_1", FilePath(FILE_PATH_LITERAL("file_1.ext")), false); 147 files_service->RegisterFileEntry( 148 app->id(), "file_id_2", FilePath(FILE_PATH_LITERAL("file_2.ext")), false); 149 files_service->RegisterFileEntry( 150 app->id(), "file_id_3", FilePath(FILE_PATH_LITERAL("file_3.ext")), false); 151 152 const std::vector<base::string16> permission_messages = 153 panel.GetActivePermissionMessages(); 154 ASSERT_TRUE(permission_messages.empty()); 155 156 // Since we have no guarantees on the order of retained files, make sure the 157 // list is the expected length and all required entries are present. 158 const std::vector<base::string16> retained_file_paths = 159 panel.GetRetainedFilePaths(); 160 ASSERT_EQ(3U, retained_file_paths.size()); 161 EXPECT_THAT(retained_file_paths, 162 Contains(Eq(base::UTF8ToUTF16("file_1.ext")))); 163 EXPECT_THAT(retained_file_paths, 164 Contains(Eq(base::UTF8ToUTF16("file_2.ext")))); 165 EXPECT_THAT(retained_file_paths, 166 Contains(Eq(base::UTF8ToUTF16("file_3.ext")))); 167 } 168