summaryrefslogtreecommitdiffstats
path: root/chrome/browser/extensions/extension_uitest.cc
diff options
context:
space:
mode:
Diffstat (limited to 'chrome/browser/extensions/extension_uitest.cc')
-rw-r--r--chrome/browser/extensions/extension_uitest.cc169
1 files changed, 169 insertions, 0 deletions
diff --git a/chrome/browser/extensions/extension_uitest.cc b/chrome/browser/extensions/extension_uitest.cc
index 102bbac..9180966 100644
--- a/chrome/browser/extensions/extension_uitest.cc
+++ b/chrome/browser/extensions/extension_uitest.cc
@@ -20,6 +20,8 @@ static const char kTestDirectorySimpleApiCall[] =
"extensions/uitest/simple_api_call";
static const char kTestDirectoryRoundtripApiCall[] =
"extensions/uitest/roundtrip_api_call";
+static const char kTestDirectoryBrowserEvent[] =
+ "extensions/uitest/event_sink";
// Base class to test extensions almost end-to-end by including browser
// startup, manifest parsing, and the actual process model in the
@@ -279,4 +281,171 @@ TEST_F(RoundtripApiCallExtensionTest, RunTest) {
}
#endif // defined(OS_WIN)
+// This proxy is specific to BrowserEventExtensionTest.
+class BrowserEventAutomationProxy : public MultiMessageAutomationProxy {
+ public:
+ explicit BrowserEventAutomationProxy(int execution_timeout)
+ : MultiMessageAutomationProxy(execution_timeout),
+ tab_(NULL) {
+ }
+
+ // Must set before initiating test.
+ TabProxy* tab_;
+
+ // Counts the number of times we got a given event.
+ std::map<std::string, int> event_count_;
+
+ // Array containing the names of the events to fire to the extension.
+ static const char* event_names_[];
+
+ protected:
+ // Process a message received from the test extension.
+ virtual void HandleMessageFromChrome();
+
+ // Fire an event of the given name to the test extension.
+ void FireEvent(const char* event_name);
+};
+
+const char* BrowserEventAutomationProxy::event_names_[] = {
+ // Window events.
+ "window-created",
+ "window-removed",
+ "window-focus-changed",
+
+ // Tab events.
+ "tab-created",
+ "tab-updated",
+ "tab-moved",
+ "tab-selection-changed",
+ "tab-attached",
+ "tab-detached",
+ "tab-removed",
+
+ // Page action events.
+ "page-action-executed",
+
+ // Bookmark events.
+ "bookmark-added",
+ "bookmark-removed",
+ "bookmark-changed",
+ "bookmark-moved",
+ "bookmark-children-reordered",
+};
+
+void BrowserEventAutomationProxy::HandleMessageFromChrome() {
+ namespace keys = extension_automation_constants;
+ ASSERT_TRUE(tab_ != NULL);
+
+ std::string message(message());
+ std::string origin(origin());
+ std::string target(target());
+
+ ASSERT_TRUE(message.length() > 0);
+ ASSERT_STREQ(keys::kAutomationOrigin, origin.c_str());
+
+ if (target == keys::kAutomationRequestTarget) {
+ // This should be a request for the current window. We don't need to
+ // respond, as this is used only as an indication that the extension
+ // page is now loaded.
+ scoped_ptr<Value> message_value(JSONReader::Read(message, false));
+ ASSERT_TRUE(message_value->IsType(Value::TYPE_DICTIONARY));
+ DictionaryValue* message_dict =
+ reinterpret_cast<DictionaryValue*>(message_value.get());
+
+ std::string name;
+ message_dict->GetString(keys::kAutomationNameKey, &name);
+ ASSERT_STREQ(name.c_str(), "GetCurrentWindow");
+
+ // Send an OpenChannelToExtension message to chrome. Note: the JSON
+ // reader expects quoted property keys.
+ tab_->HandleMessageFromExternalHost(
+ "{\"rqid\":0, \"extid\": \"88884444789ABCDEF0123456789ABCDEF0123456\","
+ " \"connid\": 1}",
+ keys::kAutomationOrigin,
+ keys::kAutomationPortRequestTarget);
+ } else if (target == keys::kAutomationPortResponseTarget) {
+ // This is a response to the open channel request. This means we know
+ // that the port is ready to send us messages. Fire all the events now.
+ for (int i = 0; i < arraysize(event_names_); ++i) {
+ FireEvent(event_names_[i]);
+ }
+ } else if (target == keys::kAutomationPortRequestTarget) {
+ // This is the test extension calling us back. Make sure its telling
+ // us that it received an event. We do this by checking to see if the
+ // message is a simple string of one of the event names that is fired.
+ //
+ // There is a special message "ACK" which means that the extension
+ // received the port connection. This is not an event response and
+ // should happen before all events.
+ scoped_ptr<Value> message_value(JSONReader::Read(message, false));
+ ASSERT_TRUE(message_value->IsType(Value::TYPE_DICTIONARY));
+ DictionaryValue* message_dict =
+ reinterpret_cast<DictionaryValue*>(message_value.get());
+
+ std::string event_name;
+ message_dict->GetString(L"data", &event_name);
+ if (event_name == "\"ACK\"") {
+ ASSERT_EQ(0, event_count_.size());
+ } else {
+ ++event_count_[event_name];
+ }
+ }
+}
+
+void BrowserEventAutomationProxy::FireEvent(const char* event_name) {
+ namespace keys = extension_automation_constants;
+
+ // Build the event message to send to the extension. The only important
+ // part is the name, as the payload is not used by the test extension.
+ std::string message;
+ message += "[\"";
+ message += event_name;
+ message += "\", \"[]\"]";
+
+ tab_->HandleMessageFromExternalHost(
+ message,
+ keys::kAutomationOrigin,
+ keys::kAutomationBrowserEventRequestTarget);
+}
+
+class BrowserEventExtensionTest
+ : public ExtensionUITest<
+ CustomAutomationProxyTest<BrowserEventAutomationProxy>> {
+ public:
+ BrowserEventExtensionTest()
+ : ExtensionUITest<
+ CustomAutomationProxyTest<
+ BrowserEventAutomationProxy> >(kTestDirectoryBrowserEvent) {
+ }
+
+ void DoAdditionalPreNavigateSetup(TabProxy* tab) {
+ BrowserEventAutomationProxy* proxy =
+ static_cast<BrowserEventAutomationProxy*>(automation());
+ proxy->tab_ = tab;
+ }
+
+ private:
+
+ DISALLOW_COPY_AND_ASSIGN(BrowserEventExtensionTest);
+};
+
+// TODO(port) Should become portable once
+// ExternalTabMessageLoop is ported.
+#if defined(OS_WIN)
+TEST_F(BrowserEventExtensionTest, RunTest) {
+ TestWithURL(GURL(
+ "chrome-extension://88884444789ABCDEF0123456789ABCDEF0123456/test.html"));
+ BrowserEventAutomationProxy* proxy =
+ static_cast<BrowserEventAutomationProxy*>(automation());
+
+ EXPECT_EQ(arraysize(BrowserEventAutomationProxy::event_names_),
+ proxy->event_count_.size());
+ for (std::map<std::string, int>::iterator i = proxy->event_count_.begin();
+ i != proxy->event_count_.end(); ++i) {
+ const std::pair<std::string, int>& value = *i;
+ ASSERT_EQ(1, value.second);
+ }
+}
+#endif // defined(OS_WIN)
+
} // namespace