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 #ifndef CHROME_BROWSER_EXTENSIONS_EXTENSION_TEST_MESSAGE_LISTENER_H_ 6 #define CHROME_BROWSER_EXTENSIONS_EXTENSION_TEST_MESSAGE_LISTENER_H_ 7 8 #include <string> 9 10 #include "base/compiler_specific.h" 11 #include "base/memory/ref_counted.h" 12 #include "content/public/browser/notification_observer.h" 13 #include "content/public/browser/notification_registrar.h" 14 15 namespace extensions { 16 class TestSendMessageFunction; 17 } 18 19 // This class helps us wait for incoming messages sent from javascript via 20 // chrome.test.sendMessage(). A sample usage would be: 21 // 22 // ExtensionTestMessageListener listener("foo", false); // won't reply 23 // ... do some work 24 // ASSERT_TRUE(listener.WaitUntilSatisfied()); 25 // 26 // It is also possible to have the extension wait for our reply. This is 27 // useful for coordinating multiple pages/processes and having them wait on 28 // each other. Example: 29 // 30 // ExtensionTestMessageListener listener1("foo1", true); // will reply 31 // ExtensionTestMessageListener listener2("foo2", true); // will reply 32 // ASSERT_TRUE(listener1.WaitUntilSatisfied()); 33 // ASSERT_TRUE(listener2.WaitUntilSatisfied()); 34 // ... do some work 35 // listener1.Reply("foo2 is ready"); 36 // listener2.Reply("foo1 is ready"); 37 // 38 // Further, we can use this to listen for a success and failure message: 39 // 40 // ExtensionTestMessageListener listener("success", will_reply); 41 // listener.set_failure_message("failure"); 42 // ASSERT_TRUE(listener.WaitUntilSatisfied()); 43 // if (listener.message() == "success") { 44 // HandleSuccess(); 45 // } else { 46 // ASSERT_EQ("failure", listener.message()); 47 // HandleFailure(); 48 // } 49 // 50 // Or, use it to listen to any arbitrary message: 51 // 52 // ExtensionTestMessageListener listener(will_reply); 53 // ASSERT_TRUE(listener.WaitUntilSatisfied()); 54 // if (listener.message() == "foo") 55 // HandleFoo(); 56 // else if (listener.message() == "bar") 57 // HandleBar(); 58 // else if (listener.message() == "baz") 59 // HandleBaz(); 60 // else 61 // NOTREACHED(); 62 // 63 // You can also use the class to listen for messages from a specified extension: 64 // 65 // ExtensionTestMessageListener listener(will_reply); 66 // listener.set_extension_id(extension->id()); 67 // ASSERT_TRUE(listener.WaitUntilSatisfied()); 68 // ... do some work. 69 // 70 // Finally, you can reset the listener to reuse it. 71 // 72 // ExtensionTestMessageListener listener(true); // will reply 73 // ASSERT_TRUE(listener.WaitUntilSatisfied()); 74 // while (listener.message() != "end") { 75 // Handle(listener.message()); 76 // listener.Reply("bar"); 77 // listener.Reset(); 78 // ASSERT_TRUE(listener.WaitUntilSatisfied()); 79 // } 80 // 81 // Note that when using it in browser tests, you need to make sure it gets 82 // destructed *before* the browser gets torn down. Two common patterns are to 83 // either make it a local variable inside your test body, or if it's a member 84 // variable of a ExtensionBrowserTest subclass, override the 85 // InProcessBrowserTest::CleanUpOnMainThread() method and clean it up there. 86 class ExtensionTestMessageListener : public content::NotificationObserver { 87 public: 88 // We immediately start listening for |expected_message|. 89 ExtensionTestMessageListener(const std::string& expected_message, 90 bool will_reply); 91 // Construct a message listener which will listen for any message. 92 explicit ExtensionTestMessageListener(bool will_reply); 93 94 virtual ~ExtensionTestMessageListener(); 95 96 // This returns true immediately if we've already gotten the expected 97 // message, or waits until it arrives. 98 // Returns false if the wait is interrupted and we still haven't gotten the 99 // message, or if the message was equal to |failure_message_|. 100 bool WaitUntilSatisfied(); 101 102 // Send the given message as a reply. It is only valid to call this after 103 // WaitUntilSatisfied has returned true, and if will_reply is true. 104 void Reply(const std::string& message); 105 106 // Convenience method that formats int as a string and sends it. 107 void Reply(int message); 108 109 // Reset the listener to listen again. No settings (such as messages to 110 // listen for) are modified. 111 void Reset(); 112 113 // Getters and setters. 114 was_satisfied()115 bool was_satisfied() const { return satisfied_; } 116 set_failure_message(const std::string & failure_message)117 void set_failure_message(const std::string& failure_message) { 118 failure_message_ = failure_message; 119 } 120 extension_id()121 const std::string& extension_id() const { return extension_id_; } set_extension_id(const std::string & extension_id)122 void set_extension_id(const std::string& extension_id) { 123 extension_id_ = extension_id; 124 } 125 message()126 const std::string& message() const { return message_; } 127 128 private: 129 // Implements the content::NotificationObserver interface. 130 virtual void Observe(int type, 131 const content::NotificationSource& source, 132 const content::NotificationDetails& details) OVERRIDE; 133 134 content::NotificationRegistrar registrar_; 135 136 // The message we're expecting. 137 std::string expected_message_; 138 139 // The last message we received. 140 std::string message_; 141 142 // Whether we've seen expected_message_ yet. 143 bool satisfied_; 144 145 // If we're waiting, then we want to post a quit task when the expected 146 // message arrives. 147 bool waiting_; 148 149 // Whether or not we will wait for any message, regardless of contents. 150 bool wait_for_any_message_; 151 152 // If true, we expect the calling code to manually send a reply. Otherwise, 153 // we send an automatic empty reply to the extension. 154 bool will_reply_; 155 156 // Whether or not we have already replied (we can only reply once). 157 bool replied_; 158 159 // The extension id that we listen for, or empty. 160 std::string extension_id_; 161 162 // The message that signals failure. 163 std::string failure_message_; 164 165 // If we received a message that was the failure message. 166 bool failed_; 167 168 // The function we need to reply to. 169 scoped_refptr<extensions::TestSendMessageFunction> function_; 170 }; 171 172 #endif // CHROME_BROWSER_EXTENSIONS_EXTENSION_TEST_MESSAGE_LISTENER_H_ 173