Chromium Code Reviews| Index: chrome/browser/ssl/chrome_security_state_model_client_browser_tests.cc |
| diff --git a/chrome/browser/ssl/chrome_security_state_model_client_browser_tests.cc b/chrome/browser/ssl/chrome_security_state_model_client_browser_tests.cc |
| index 64a9b83d86c975ebceb35bf440b583b751500291..0e0a2ffe3284fd2a994e26464ab981c18355bda4 100644 |
| --- a/chrome/browser/ssl/chrome_security_state_model_client_browser_tests.cc |
| +++ b/chrome/browser/ssl/chrome_security_state_model_client_browser_tests.cc |
| @@ -1122,6 +1122,194 @@ IN_PROC_BROWSER_TEST_F(ChromeSecurityStateModelClientTestWithPasswordCcSwitch, |
| content::SSLStatus::DISPLAYED_PASSWORD_FIELD_ON_HTTP); |
| } |
| +// A WebContentsDelegate that keeps track of messages that have been |
| +// added to the console. Messages can be retrieved or cleared with |
| +// console_messages() and ClearConsoleMessages(). The user of this class |
| +// can set a callback to run when the next console message notification |
| +// arrives. |
| +class ConsoleWebContentsDelegate : public content::WebContentsDelegate { |
| + public: |
| + ConsoleWebContentsDelegate() : content::WebContentsDelegate() {} |
| + ~ConsoleWebContentsDelegate() override {} |
| + |
| + const std::vector<base::string16>& console_messages() const { |
| + return console_messages_; |
| + } |
| + |
| + void set_console_message_callback(const base::Closure& callback) { |
| + console_message_callback_ = callback; |
| + } |
| + |
| + void ClearConsoleMessages() { console_messages_.clear(); } |
| + |
| + // content::WebContentsDelegate |
| + bool AddMessageToConsole(content::WebContents* source, |
| + int32_t level, |
| + const base::string16& message, |
| + int32_t line_no, |
| + const base::string16& source_id) override { |
| + console_messages_.push_back(message); |
| + if (!console_message_callback_.is_null()) { |
| + console_message_callback_.Run(); |
| + console_message_callback_.Reset(); |
| + } |
| + return true; |
| + } |
| + |
| + private: |
| + std::vector<base::string16> console_messages_; |
| + base::Closure console_message_callback_; |
| + |
| + DISALLOW_COPY_AND_ASSIGN(ConsoleWebContentsDelegate); |
| +}; |
| + |
| +// Checks that |delegate| has observed exactly one console message for |
| +// HTTP_SHOW_WARNING. This does not check for the exact string (for fear |
| +// of being too brittle) but rather just a keyword ("not secure"). |
| +void CheckForOneHttpWarningConsoleMessage( |
| + const ConsoleWebContentsDelegate& delegate) { |
| + const std::vector<base::string16>& messages = delegate.console_messages(); |
| + ASSERT_EQ(1u, messages.size()); |
| + EXPECT_NE(base::string16::npos, |
| + messages[0].find(base::ASCIIToUTF16("not secure"))); |
| +} |
| + |
| +// Tests that console messages are printed upon a call to |
| +// GetSecurityInfo() on an HTTP_SHOW_WARNING page, exactly once per |
| +// main-frame navigation. |
| +IN_PROC_BROWSER_TEST_F(ChromeSecurityStateModelClientTestWithPasswordCcSwitch, |
| + ConsoleMessage) { |
| + ConsoleWebContentsDelegate delegate; |
| + content::WebContents* contents = |
| + browser()->tab_strip_model()->GetActiveWebContents(); |
| + ASSERT_TRUE(contents); |
| + contents->SetDelegate(&delegate); |
| + |
| + // Navigate to an HTTP page. Use a non-local hostname so that is it |
| + // not considered secure. |
| + GURL http_url = |
| + GetURLWithNonLocalHostname(embedded_test_server(), "/title1.html"); |
| + ui_test_utils::NavigateToURL(browser(), http_url); |
| + content::NavigationEntry* entry = contents->GetController().GetVisibleEntry(); |
| + ASSERT_TRUE(entry); |
| + EXPECT_EQ(http_url, entry->GetURL()); |
| + EXPECT_TRUE(delegate.console_messages().empty()); |
| + |
| + // Trigger the HTTP_SHOW_WARNING state. |
| + base::RunLoop first_message; |
| + contents->OnPasswordInputShownOnHttp(); |
| + ChromeSecurityStateModelClient* client = |
| + ChromeSecurityStateModelClient::FromWebContents(contents); |
| + ASSERT_TRUE(client); |
| + security_state::SecurityStateModel::SecurityInfo security_info; |
| + |
| + // After calling GetSecurityInfo(), wait for a console message. |
| + delegate.set_console_message_callback(first_message.QuitClosure()); |
| + client->GetSecurityInfo(&security_info); |
| + first_message.Run(); |
| + EXPECT_EQ(security_state::SecurityStateModel::HTTP_SHOW_WARNING, |
| + security_info.security_level); |
| + |
| + // Check that the expected console message is present. |
| + ASSERT_NO_FATAL_FAILURE(CheckForOneHttpWarningConsoleMessage(delegate)); |
| + delegate.ClearConsoleMessages(); |
| + |
| + // Two subsequent calls to GetSecurityInfo() -- one on the same |
| + // navigation and one on another navigation -- should only result in |
| + // one additional console message. |
|
estark
2016/10/12 22:57:09
Note: these tests only sort of make sense. We real
|
| + client->GetSecurityInfo(&security_info); |
| + GURL second_http_url = |
| + GetURLWithNonLocalHostname(embedded_test_server(), "/title2.html"); |
| + ui_test_utils::NavigateToURL(browser(), second_http_url); |
| + entry = contents->GetController().GetVisibleEntry(); |
| + ASSERT_TRUE(entry); |
| + EXPECT_EQ(second_http_url, entry->GetURL()); |
| + client->GetSecurityInfo(&security_info); |
| + EXPECT_EQ(security_state::SecurityStateModel::NONE, |
| + security_info.security_level); |
| + contents->OnPasswordInputShownOnHttp(); |
| + base::RunLoop second_message; |
| + delegate.set_console_message_callback(second_message.QuitClosure()); |
| + client->GetSecurityInfo(&security_info); |
| + second_message.Run(); |
| + ASSERT_NO_FATAL_FAILURE(CheckForOneHttpWarningConsoleMessage(delegate)); |
| +} |
| + |
| +// Tests that new HTTP_SHOW_WARNING console messages are not printed for |
| +// subframe navigations. |
| +IN_PROC_BROWSER_TEST_F(ChromeSecurityStateModelClientTestWithPasswordCcSwitch, |
| + ConsoleMessageNotPrintedForFrameNavigation) { |
| + ConsoleWebContentsDelegate delegate; |
| + content::WebContents* contents = |
| + browser()->tab_strip_model()->GetActiveWebContents(); |
| + ASSERT_TRUE(contents); |
| + contents->SetDelegate(&delegate); |
| + |
| + // Navigate to an HTTP page. Use a non-local hostname so that is it |
| + // not considered secure. |
| + GURL http_url = GetURLWithNonLocalHostname(embedded_test_server(), |
| + "/ssl/page_with_frame.html"); |
| + ui_test_utils::NavigateToURL(browser(), http_url); |
| + content::NavigationEntry* entry = contents->GetController().GetVisibleEntry(); |
| + ASSERT_TRUE(entry); |
| + EXPECT_EQ(http_url, entry->GetURL()); |
| + EXPECT_TRUE(delegate.console_messages().empty()); |
| + |
| + // Trigger the HTTP_SHOW_WARNING state. |
| + base::RunLoop first_message; |
| + contents->OnPasswordInputShownOnHttp(); |
| + ChromeSecurityStateModelClient* client = |
| + ChromeSecurityStateModelClient::FromWebContents(contents); |
| + ASSERT_TRUE(client); |
| + security_state::SecurityStateModel::SecurityInfo security_info; |
| + |
| + // After calling GetSecurityInfo(), wait for a console message. |
| + delegate.set_console_message_callback(first_message.QuitClosure()); |
| + client->GetSecurityInfo(&security_info); |
| + first_message.Run(); |
| + EXPECT_EQ(security_state::SecurityStateModel::HTTP_SHOW_WARNING, |
| + security_info.security_level); |
| + |
| + // Check that the expected console message is present. |
| + ASSERT_NO_FATAL_FAILURE(CheckForOneHttpWarningConsoleMessage(delegate)); |
| + delegate.ClearConsoleMessages(); |
| + |
| + // Navigate the subframe and call GetSecurityInfo(). While the |
| + // security level is still HTTP_SHOW_WARNING, an additional console |
| + // message should not be logged because there was already a console |
| + // message logged for the current main-frame navigation. |
| + content::WindowedNotificationObserver subframe_observer( |
| + content::NOTIFICATION_LOAD_STOP, |
| + content::Source<content::NavigationController>( |
| + &contents->GetController())); |
| + EXPECT_TRUE(content::ExecuteScript( |
| + contents, "document.getElementById('navFrame').src = '/title2.html';")); |
| + subframe_observer.Wait(); |
| + client->GetSecurityInfo(&security_info); |
| + EXPECT_EQ(security_state::SecurityStateModel::HTTP_SHOW_WARNING, |
| + security_info.security_level); |
| + |
| + // Do a main frame navigation and then call GetSecurityInfo() |
| + // again. From the above subframe navigation and this main-frame |
| + // navigation, exactly one console message is expected. |
| + GURL second_http_url = |
| + GetURLWithNonLocalHostname(embedded_test_server(), "/title2.html"); |
| + ui_test_utils::NavigateToURL(browser(), second_http_url); |
| + entry = contents->GetController().GetVisibleEntry(); |
| + ASSERT_TRUE(entry); |
| + EXPECT_EQ(second_http_url, entry->GetURL()); |
| + client->GetSecurityInfo(&security_info); |
| + EXPECT_EQ(security_state::SecurityStateModel::NONE, |
| + security_info.security_level); |
| + |
| + contents->OnPasswordInputShownOnHttp(); |
| + base::RunLoop second_message; |
| + delegate.set_console_message_callback(second_message.QuitClosure()); |
| + client->GetSecurityInfo(&security_info); |
| + second_message.Run(); |
| + ASSERT_NO_FATAL_FAILURE(CheckForOneHttpWarningConsoleMessage(delegate)); |
| +} |
| + |
| // Tests that the SecurityStateModel for a WebContents is up to date |
| // when the WebContents is inserted into a Browser's TabStripModel. |
| IN_PROC_BROWSER_TEST_F(ChromeSecurityStateModelClientTest, AddedTab) { |