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 EXTENSIONS_TEST_EXTENSION_TEST_MESSAGE_LISTENER_H_ 6 #define EXTENSIONS_TEST_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 // BrowserTestBase::TearDownOnMainThread() 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 void ReplyWithError(const std::string& error); 110 111 // Reset the listener to listen again. No settings (such as messages to 112 // listen for) are modified. 113 void Reset(); 114 115 // Getters and setters. 116 was_satisfied()117 bool was_satisfied() const { return satisfied_; } 118 set_failure_message(const std::string & failure_message)119 void set_failure_message(const std::string& failure_message) { 120 failure_message_ = failure_message; 121 } 122 extension_id()123 const std::string& extension_id() const { return extension_id_; } set_extension_id(const std::string & extension_id)124 void set_extension_id(const std::string& extension_id) { 125 extension_id_ = extension_id; 126 } 127 message()128 const std::string& message() const { return message_; } 129 130 private: 131 // Implements the content::NotificationObserver interface. 132 virtual void Observe(int type, 133 const content::NotificationSource& source, 134 const content::NotificationDetails& details) OVERRIDE; 135 136 content::NotificationRegistrar registrar_; 137 138 // The message we're expecting. 139 std::string expected_message_; 140 141 // The last message we received. 142 std::string message_; 143 144 // Whether we've seen expected_message_ yet. 145 bool satisfied_; 146 147 // If we're waiting, then we want to post a quit task when the expected 148 // message arrives. 149 bool waiting_; 150 151 // Whether or not we will wait for any message, regardless of contents. 152 bool wait_for_any_message_; 153 154 // If true, we expect the calling code to manually send a reply. Otherwise, 155 // we send an automatic empty reply to the extension. 156 bool will_reply_; 157 158 // Whether or not we have already replied (we can only reply once). 159 bool replied_; 160 161 // The extension id that we listen for, or empty. 162 std::string extension_id_; 163 164 // The message that signals failure. 165 std::string failure_message_; 166 167 // If we received a message that was the failure message. 168 bool failed_; 169 170 // The function we need to reply to. 171 scoped_refptr<extensions::TestSendMessageFunction> function_; 172 }; 173 174 #endif // EXTENSIONS_TEST_EXTENSION_TEST_MESSAGE_LISTENER_H_ 175