extension_frame_host_browsertest.cc 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199
  1. // Copyright 2021 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. #include "extensions/browser/extension_frame_host.h"
  5. #include <string>
  6. #include "base/memory/ref_counted.h"
  7. #include "content/public/browser/web_contents_user_data.h"
  8. #include "extensions/browser/browsertest_util.h"
  9. #include "extensions/browser/extension_host.h"
  10. #include "extensions/browser/process_manager.h"
  11. #include "extensions/common/constants.h"
  12. #include "extensions/common/extension.h"
  13. #include "extensions/shell/browser/shell_extension_host_delegate.h"
  14. #include "extensions/shell/browser/shell_extension_web_contents_observer.h"
  15. #include "extensions/shell/browser/shell_extensions_browser_client.h"
  16. #include "extensions/shell/test/shell_apitest.h"
  17. #include "extensions/test/result_catcher.h"
  18. #include "testing/gtest/include/gtest/gtest-spi.h"
  19. #include "testing/gtest/include/gtest/gtest.h"
  20. namespace extensions {
  21. namespace {
  22. class TestExtensionFrameHost : public ExtensionFrameHost {
  23. public:
  24. explicit TestExtensionFrameHost(content::WebContents* web_contents)
  25. : ExtensionFrameHost(web_contents) {}
  26. TestExtensionFrameHost(const TestExtensionFrameHost&) = delete;
  27. TestExtensionFrameHost& operator=(const TestExtensionFrameHost&) = delete;
  28. ~TestExtensionFrameHost() override = default;
  29. void SetInvalidRequest(const std::string& name) { invalid_request_ = name; }
  30. private:
  31. // mojom::LocalFrameHost:
  32. void Request(mojom::RequestParamsPtr params,
  33. RequestCallback callback) override {
  34. // If the name of |params| is set to an invalid request, it sets it to
  35. // an empty string so that the request causes an error.
  36. if (invalid_request_ == params->name)
  37. params->name = std::string();
  38. ExtensionFrameHost::Request(std::move(params), std::move(callback));
  39. }
  40. std::string invalid_request_;
  41. };
  42. class TestShellExtensionWebContentsObserver
  43. : public ExtensionWebContentsObserver,
  44. public content::WebContentsUserData<
  45. TestShellExtensionWebContentsObserver> {
  46. public:
  47. TestShellExtensionWebContentsObserver(
  48. const TestShellExtensionWebContentsObserver&) = delete;
  49. TestShellExtensionWebContentsObserver& operator=(
  50. const TestShellExtensionWebContentsObserver&) = delete;
  51. ~TestShellExtensionWebContentsObserver() override = default;
  52. // Creates and initializes an instance of this class for the given
  53. // |web_contents|, if it doesn't already exist.
  54. static void CreateForWebContents(content::WebContents* web_contents) {
  55. content::WebContentsUserData<TestShellExtensionWebContentsObserver>::
  56. CreateForWebContents(web_contents);
  57. // Initialize this instance if necessary.
  58. FromWebContents(web_contents)->Initialize();
  59. }
  60. // Overrides to create TestExtensionFrameHost.
  61. std::unique_ptr<ExtensionFrameHost> CreateExtensionFrameHost(
  62. content::WebContents* web_contents) override {
  63. return std::make_unique<TestExtensionFrameHost>(web_contents);
  64. }
  65. private:
  66. friend class content::WebContentsUserData<
  67. TestShellExtensionWebContentsObserver>;
  68. explicit TestShellExtensionWebContentsObserver(
  69. content::WebContents* web_contents)
  70. : ExtensionWebContentsObserver(web_contents),
  71. content::WebContentsUserData<TestShellExtensionWebContentsObserver>(
  72. *web_contents) {}
  73. WEB_CONTENTS_USER_DATA_KEY_DECL();
  74. };
  75. WEB_CONTENTS_USER_DATA_KEY_IMPL(TestShellExtensionWebContentsObserver);
  76. class TestShellExtensionHostDelegate : public ShellExtensionHostDelegate {
  77. public:
  78. TestShellExtensionHostDelegate() = default;
  79. TestShellExtensionHostDelegate(const TestShellExtensionHostDelegate&) =
  80. delete;
  81. TestShellExtensionHostDelegate& operator=(
  82. const TestShellExtensionHostDelegate&) = delete;
  83. ~TestShellExtensionHostDelegate() override = default;
  84. // Overrides to create TestShellExtensionWebContentsObserver.
  85. void OnExtensionHostCreated(content::WebContents* web_contents) override {
  86. TestShellExtensionWebContentsObserver::CreateForWebContents(web_contents);
  87. }
  88. };
  89. class ExtensionFrameHostTestExtensionsBrowserClient
  90. : public ShellExtensionsBrowserClient {
  91. public:
  92. ExtensionFrameHostTestExtensionsBrowserClient() = default;
  93. ExtensionFrameHostTestExtensionsBrowserClient(
  94. const ExtensionFrameHostTestExtensionsBrowserClient&) = delete;
  95. ExtensionFrameHostTestExtensionsBrowserClient& operator=(
  96. const ExtensionFrameHostTestExtensionsBrowserClient&) = delete;
  97. ~ExtensionFrameHostTestExtensionsBrowserClient() override = default;
  98. // Overrides to create TestShellExtensionHostDelegate.
  99. std::unique_ptr<ExtensionHostDelegate> CreateExtensionHostDelegate()
  100. override {
  101. return std::make_unique<TestShellExtensionHostDelegate>();
  102. }
  103. // Overrides to return TestShellExtensionWebContentsObserver.
  104. ExtensionWebContentsObserver* GetExtensionWebContentsObserver(
  105. content::WebContents* web_contents) override {
  106. return TestShellExtensionWebContentsObserver::FromWebContents(web_contents);
  107. }
  108. };
  109. } // namespace
  110. class ExtensionFrameHostBrowserTest : public ShellApiTest {
  111. public:
  112. ExtensionFrameHostBrowserTest() = default;
  113. ExtensionFrameHostBrowserTest(const ExtensionFrameHostBrowserTest&) = delete;
  114. ExtensionFrameHostBrowserTest& operator=(
  115. const ExtensionFrameHostBrowserTest&) = delete;
  116. ~ExtensionFrameHostBrowserTest() override = default;
  117. void SetUpOnMainThread() override {
  118. ShellApiTest::SetUpOnMainThread();
  119. extensions_browser_client_ =
  120. std::make_unique<ExtensionFrameHostTestExtensionsBrowserClient>();
  121. ExtensionsBrowserClient::Set(extensions_browser_client_.get());
  122. extension_ = LoadExtension("extension");
  123. ASSERT_TRUE(extension_.get());
  124. ResultCatcher catcher;
  125. ASSERT_TRUE(catcher.GetNextResult());
  126. }
  127. protected:
  128. const Extension* extension() const { return extension_.get(); }
  129. void SetInvalidNameOnRequest(const std::string& method_name) {
  130. ExtensionHost* host =
  131. ProcessManager::Get(browser_context())
  132. ->GetBackgroundHostForExtension(extension()->id());
  133. ASSERT_TRUE(host);
  134. ASSERT_TRUE(host->host_contents());
  135. ExtensionWebContentsObserver* observer =
  136. extensions_browser_client_->GetExtensionWebContentsObserver(
  137. host->host_contents());
  138. static_cast<TestExtensionFrameHost*>(
  139. observer->extension_frame_host_for_testing())
  140. ->SetInvalidRequest(method_name);
  141. }
  142. private:
  143. scoped_refptr<const Extension> extension_;
  144. std::unique_ptr<ExtensionFrameHostTestExtensionsBrowserClient>
  145. extensions_browser_client_;
  146. };
  147. // Test that when ExtensionFrameHost dispatches an invalid request it gets
  148. // an error associated with it. This is a regression test for
  149. // https://crbug.com/1196377.
  150. IN_PROC_BROWSER_TEST_F(ExtensionFrameHostBrowserTest, InValidNameRequest) {
  151. // Set 'test.getConfig' is invalid request.
  152. SetInvalidNameOnRequest("test.getConfig");
  153. // Run a script asynchronously that passes the test.
  154. ResultCatcher catcher;
  155. ASSERT_TRUE(browsertest_util::ExecuteScriptInBackgroundPageNoWait(
  156. browser_context(), extension()->id(), R"(
  157. chrome.test.getConfig(() => {
  158. const expectedError = 'Access to extension API denied.';
  159. if (chrome.runtime.lastError &&
  160. expectedError == chrome.runtime.lastError.message) {
  161. chrome.test.notifyPass();
  162. } else {
  163. chrome.test.notifyFail('TestFailed');
  164. }
  165. });)"));
  166. ASSERT_TRUE(catcher.GetNextResult());
  167. }
  168. } // namespace extensions