15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/files/file_path.h"
6868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/path_service.h"
7868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/string_number_conversions.h"
8868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/stringprintf.h"
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/values.h"
107dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "chrome/browser/chrome_notification_types.h"
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/extensions/event_router.h"
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/extensions/extension_apitest.h"
13a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)#include "chrome/browser/extensions/extension_prefs.h"
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/extensions/extension_system.h"
157dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "chrome/browser/extensions/test_extension_dir.h"
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/profiles/profile.h"
17868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "chrome/browser/ui/browser.h"
18868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "chrome/browser/ui/tabs/tab_strip_model.h"
19868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "chrome/common/chrome_paths.h"
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/common/chrome_switches.h"
21868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "chrome/test/base/ui_test_utils.h"
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/notification_registrar.h"
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/notification_service.h"
24868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "content/public/test/browser_test_utils.h"
25868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "net/dns/mock_host_resolver.h"
26868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "net/test/embedded_test_server/embedded_test_server.h"
277dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "url/gurl.h"
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
297dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochnamespace extensions {
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace {
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class MessageSender : public content::NotificationObserver {
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MessageSender() {
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_HOST_DID_STOP_LOADING,
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   content::NotificationService::AllSources());
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
40eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  static scoped_ptr<base::ListValue> BuildEventArguments(
41eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      const bool last_message,
42eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      const std::string& data) {
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DictionaryValue* event = new DictionaryValue();
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    event->SetBoolean("lastMessage", last_message);
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    event->SetString("data", data);
46eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    scoped_ptr<base::ListValue> arguments(new base::ListValue());
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    arguments->Append(event);
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return arguments.Pass();
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
517dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  static scoped_ptr<Event> BuildEvent(scoped_ptr<base::ListValue> event_args,
527dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch                                      Profile* profile,
537dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch                                      GURL event_url) {
547dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    scoped_ptr<Event> event(new Event("test.onMessage", event_args.Pass()));
552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    event->restrict_to_profile = profile;
562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    event->event_url = event_url;
572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return event.Pass();
582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void Observe(int type,
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                       const content::NotificationSource& source,
622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                       const content::NotificationDetails& details) OVERRIDE {
637dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    EventRouter* event_router = ExtensionSystem::Get(
647dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch        content::Source<Profile>(source).ptr())->event_router();
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Sends four messages to the extension. All but the third message sent
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // from the origin http://b.com/ are supposed to arrive.
682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    event_router->BroadcastEvent(BuildEvent(
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        BuildEventArguments(false, "no restriction"),
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        content::Source<Profile>(source).ptr(),
712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        GURL()));
722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    event_router->BroadcastEvent(BuildEvent(
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        BuildEventArguments(false, "http://a.com/"),
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        content::Source<Profile>(source).ptr(),
752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        GURL("http://a.com/")));
762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    event_router->BroadcastEvent(BuildEvent(
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        BuildEventArguments(false, "http://b.com/"),
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        content::Source<Profile>(source).ptr(),
792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        GURL("http://b.com/")));
802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    event_router->BroadcastEvent(BuildEvent(
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        BuildEventArguments(true, "last message"),
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        content::Source<Profile>(source).ptr(),
832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        GURL()));
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  content::NotificationRegistrar registrar_;
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Tests that message passing between extensions and content scripts works.
902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)IN_PROC_BROWSER_TEST_F(ExtensionApiTest, Messaging) {
91eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  ASSERT_TRUE(StartEmbeddedTestServer());
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_TRUE(RunExtensionTest("messaging/connect")) << message_;
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Tests that message passing from one extension to another works.
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)IN_PROC_BROWSER_TEST_F(ExtensionApiTest, MessagingExternal) {
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_TRUE(LoadExtension(
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      test_data_dir_.AppendASCII("..").AppendASCII("good")
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    .AppendASCII("Extensions")
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    .AppendASCII("bjafgdebaacbbbecmhlhpofkepfkgcpa")
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    .AppendASCII("1.0")));
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_TRUE(RunExtensionTest("messaging/connect_external")) << message_;
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Tests that messages with event_urls are only passed to extensions with
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// appropriate permissions.
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)IN_PROC_BROWSER_TEST_F(ExtensionApiTest, MessagingEventURL) {
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MessageSender sender;
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_TRUE(RunExtensionTest("messaging/event_url")) << message_;
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Tests connecting from a panel to its extension.
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class PanelMessagingTest : public ExtensionApiTest {
1152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE {
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ExtensionApiTest::SetUpCommandLine(command_line);
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    command_line->AppendSwitch(switches::kEnablePanels);
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)IN_PROC_BROWSER_TEST_F(PanelMessagingTest, MessagingPanel) {
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_TRUE(RunExtensionTest("messaging/connect_panel")) << message_;
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
124868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
125868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)// Tests externally_connectable between a web page and an extension.
126868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)//
127868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)// TODO(kalman): Test between extensions. This is already tested in this file,
128868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)// but not with externally_connectable set in the manifest.
129868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)//
130868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)// TODO(kalman): Test with host permissions.
131868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)class ExternallyConnectableMessagingTest : public ExtensionApiTest {
132868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) protected:
133868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // Result codes from the test. These must match up with |results| in
1347dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  // c/t/d/extensions/api_test/externally_connectable/assertions.json.
135868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  enum Result {
136868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    OK = 0,
137868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    NAMESPACE_NOT_DEFINED = 1,
138868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    FUNCTION_NOT_DEFINED = 2,
139868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    COULD_NOT_ESTABLISH_CONNECTION_ERROR = 3,
140868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    OTHER_ERROR = 4,
141868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    INCORRECT_RESPONSE_SENDER = 5,
142868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    INCORRECT_RESPONSE_MESSAGE = 6,
143868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  };
144868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
145868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  Result CanConnectAndSendMessages(const std::string& extension_id) {
146a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    return CanConnectAndSendMessages(browser(), extension_id);
147a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  }
148a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
149a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  Result CanConnectAndSendMessages(Browser* browser,
150a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                                   const std::string& extension_id) {
151868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    int result;
152868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    CHECK(content::ExecuteScriptAndExtractInt(
153a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)        browser->tab_strip_model()->GetActiveWebContents(),
154868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        "assertions.canConnectAndSendMessages('" + extension_id + "')",
155868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        &result));
156868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return static_cast<Result>(result);
157868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
158868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
159868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  testing::AssertionResult AreAnyNonWebApisDefined() {
160868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    // All runtime API methods are non-web except for sendRequest and connect.
1617d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    const char* non_messaging_apis[] = {
162868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        "getBackgroundPage",
163868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        "getManifest",
164868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        "getURL",
165868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        "reload",
166868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        "requestUpdateCheck",
167868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        "connectNative",
168868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        "sendNativeMessage",
169868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        "onStartup",
170868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        "onInstalled",
171868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        "onSuspend",
172868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        "onSuspendCanceled",
173868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        "onUpdateAvailable",
174868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        "onBrowserUpdateAvailable",
175868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        "onConnect",
176868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        "onConnectExternal",
177868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        "onMessage",
178868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        "onMessageExternal",
179eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        "onRestartRequired",
180868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        "id",
181868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    };
1827d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
1837d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    // Turn the array into a JS array, which effectively gets eval()ed.
1847d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    std::string as_js_array;
1857d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    for (size_t i = 0; i < arraysize(non_messaging_apis); ++i) {
1867d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      as_js_array += as_js_array.empty() ? "[" : ",";
1877d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      as_js_array += base::StringPrintf("'%s'", non_messaging_apis[i]);
1887d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    }
1897d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    as_js_array += "]";
1907d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
1917d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    bool any_defined;
1927d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    CHECK(content::ExecuteScriptAndExtractBool(
1937d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)        browser()->tab_strip_model()->GetActiveWebContents(),
1947d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)        "assertions.areAnyRuntimePropertiesDefined(" + as_js_array + ")",
1957d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)        &any_defined));
1967d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    return any_defined ?
1977d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)        testing::AssertionSuccess() : testing::AssertionFailure();
198868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
199868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
200868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  GURL GetURLForPath(const std::string& host, const std::string& path) {
201868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    std::string port = base::IntToString(embedded_test_server()->port());
202868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    GURL::Replacements replacements;
203868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    replacements.SetHostStr(host);
204868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    replacements.SetPortStr(port);
205868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return embedded_test_server()->GetURL(path).ReplaceComponents(replacements);
206868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
207868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
2087d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  GURL chromium_org_url() {
2097dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    return GetURLForPath("www.chromium.org", "/chromium.org.html");
210868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
211868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
2127d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  GURL google_com_url() {
2137dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    return GetURLForPath("www.google.com", "/google.com.html");
2147d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  }
2157d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
2167dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  const Extension* LoadChromiumConnectableExtension() {
217a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    return LoadExtensionIntoDir(&web_connectable_dir_, base::StringPrintf(
2187dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch        "{"
2197dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch        "  \"name\": \"chromium_connectable\","
2207dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch        "  %s,"
2217dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch        "  \"externally_connectable\": {"
2227dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch        "    \"matches\": [\"*://*.chromium.org:*/*\"]"
2237dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch        "  }"
2247dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch        "}",
2257dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch        common_manifest()));
2267dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  }
2277dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
2287dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  scoped_refptr<const Extension> LoadNotConnectableExtension() {
229a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    return LoadExtensionIntoDir(&not_connectable_dir_, base::StringPrintf(
2307dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch        "{"
2317dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch        "  \"name\": \"not_connectable\","
2327dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch        "  %s"
2337dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch        "}",
2347dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch        common_manifest()));
2357d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  }
2367d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
2377d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  void InitializeTestServer() {
2387d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    base::FilePath test_data;
2397dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    EXPECT_TRUE(PathService::Get(chrome::DIR_TEST_DATA, &test_data));
2407dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    embedded_test_server()->ServeFilesFromDirectory(test_data.AppendASCII(
2417dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch        "extensions/api_test/messaging/externally_connectable/sites"));
2427d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
2437d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    host_resolver()->AddRule("*", embedded_test_server()->base_url().host());
2447d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  }
2457d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
2467d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) private:
247a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  const Extension* LoadExtensionIntoDir(TestExtensionDir* dir,
248a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                                        const std::string& manifest) {
249a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    dir->WriteManifest(manifest);
250a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    dir->WriteFile(FILE_PATH_LITERAL("background.js"),
2517dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch        "chrome.runtime.onMessageExternal.addListener(\n"
2527dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch        "    function(message, sender, reply) {\n"
2537dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch        "  reply({ message: message, sender: sender });\n"
2547dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch        "});\n"
2557dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch        "chrome.runtime.onConnectExternal.addListener(function(port) {\n"
2567dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch        "  port.onMessage.addListener(function(message) {\n"
2577dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch        "    port.postMessage({ message: message, sender: port.sender });\n"
2587dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch        "  });\n"
2597dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch        "});\n");
260a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    return LoadExtension(dir->unpacked_path());
261868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
2627dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
2637dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  const char* common_manifest() {
2647dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    return "\"version\": \"1.0\","
2657dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch           "\"background\": {"
2667dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch           "    \"scripts\": [\"background.js\"],"
2677dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch           "    \"persistent\": false"
2687dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch           "},"
2697dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch           "\"manifest_version\": 2";
2707dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  }
2717dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
2727dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  TestExtensionDir web_connectable_dir_;
2737dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  TestExtensionDir not_connectable_dir_;
274868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)};
275868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
2767d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)IN_PROC_BROWSER_TEST_F(ExternallyConnectableMessagingTest, NotInstalled) {
2777d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  InitializeTestServer();
2787d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
2797d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  const char kFakeId[] = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
2807d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
2817d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  ui_test_utils::NavigateToURL(browser(), chromium_org_url());
2827d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  EXPECT_EQ(NAMESPACE_NOT_DEFINED, CanConnectAndSendMessages(kFakeId));
283868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  EXPECT_FALSE(AreAnyNonWebApisDefined());
284868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
2857d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  ui_test_utils::NavigateToURL(browser(), google_com_url());
2867d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  EXPECT_EQ(NAMESPACE_NOT_DEFINED, CanConnectAndSendMessages(kFakeId));
287868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  EXPECT_FALSE(AreAnyNonWebApisDefined());
2887d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)}
2897d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
2907d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)// Tests two extensions on the same sites: one web connectable, one not.
2917d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)IN_PROC_BROWSER_TEST_F(ExternallyConnectableMessagingTest,
2927d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)                       WebConnectableAndNotConnectable) {
2937d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  InitializeTestServer();
294868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
295868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // Install the web connectable extension. chromium.org can connect to it,
296868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // google.com can't.
2977dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  const Extension* chromium_connectable = LoadChromiumConnectableExtension();
2987dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  ASSERT_TRUE(chromium_connectable);
299868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
3007d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  ui_test_utils::NavigateToURL(browser(), chromium_org_url());
3017dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  EXPECT_EQ(OK, CanConnectAndSendMessages(chromium_connectable->id()));
302868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  EXPECT_FALSE(AreAnyNonWebApisDefined());
303868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
3047d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  ui_test_utils::NavigateToURL(browser(), google_com_url());
3057d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  EXPECT_EQ(NAMESPACE_NOT_DEFINED,
3067dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch            CanConnectAndSendMessages(chromium_connectable->id()));
307868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  EXPECT_FALSE(AreAnyNonWebApisDefined());
308868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
309868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // Install the non-connectable extension. Nothing can connect to it.
3107dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  const Extension* not_connectable = LoadNotConnectableExtension();
3117dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  ASSERT_TRUE(not_connectable);
312868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
3137d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  ui_test_utils::NavigateToURL(browser(), chromium_org_url());
3147dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  // Namespace will be defined here because |chromium_connectable| can connect
3157dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  // to it - so this will be the "cannot establish connection" error.
316868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  EXPECT_EQ(COULD_NOT_ESTABLISH_CONNECTION_ERROR,
317868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)            CanConnectAndSendMessages(not_connectable->id()));
318868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  EXPECT_FALSE(AreAnyNonWebApisDefined());
319868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
3207d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  ui_test_utils::NavigateToURL(browser(), google_com_url());
3217d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  EXPECT_EQ(NAMESPACE_NOT_DEFINED,
322868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)            CanConnectAndSendMessages(not_connectable->id()));
323868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  EXPECT_FALSE(AreAnyNonWebApisDefined());
324868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
3257d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
3267d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)// Tests that enabling and disabling an extension makes the runtime bindings
3277d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)// appear and disappear.
3287d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)//
3297d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)// TODO(kalman): Test with multiple extensions that can be accessed by the same
3307d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)// host.
3317d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)IN_PROC_BROWSER_TEST_F(ExternallyConnectableMessagingTest,
3327d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)                       EnablingAndDisabling) {
3337d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  InitializeTestServer();
3347d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
3357dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  const Extension* chromium_connectable = LoadChromiumConnectableExtension();
3367dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  ASSERT_TRUE(chromium_connectable);
3377dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  const Extension* not_connectable = LoadNotConnectableExtension();
3387dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  ASSERT_TRUE(not_connectable);
3397d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
3407d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  ui_test_utils::NavigateToURL(browser(), chromium_org_url());
3417dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  EXPECT_EQ(OK, CanConnectAndSendMessages(chromium_connectable->id()));
3427d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  EXPECT_EQ(COULD_NOT_ESTABLISH_CONNECTION_ERROR,
3437d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)            CanConnectAndSendMessages(not_connectable->id()));
3447d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
3457dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  DisableExtension(chromium_connectable->id());
3464311e82a78ceafbe0585f51d4c8a86df9f21aa0dBen Murdoch  EXPECT_EQ(COULD_NOT_ESTABLISH_CONNECTION_ERROR,
3477dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch            CanConnectAndSendMessages(chromium_connectable->id()));
3487d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
3497dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  EnableExtension(chromium_connectable->id());
3507dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  EXPECT_EQ(OK, CanConnectAndSendMessages(chromium_connectable->id()));
3517d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  EXPECT_EQ(COULD_NOT_ESTABLISH_CONNECTION_ERROR,
3527d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)            CanConnectAndSendMessages(not_connectable->id()));
3537d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)}
3547dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
355a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)// Tests connection from incognito tabs. Spanning mode only.
356a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)//
357a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)// TODO(kalman): ensure that we exercise split vs spanning incognito logic
358a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)// somewhere. This is a test that should be shared with the content script logic
359a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)// so it's not really our specific concern for web connectable.
360a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)IN_PROC_BROWSER_TEST_F(ExternallyConnectableMessagingTest, FromIncognito) {
361a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  InitializeTestServer();
362a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
363a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  const Extension* chromium_connectable = LoadChromiumConnectableExtension();
364a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  ASSERT_TRUE(chromium_connectable);
365a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
366a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  Browser* incognito_browser = ui_test_utils::OpenURLOffTheRecord(
367a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      profile()->GetOffTheRecordProfile(),
368a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      chromium_org_url());
369a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
370a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  // No connection because incognito enabled hasn't been set.
371a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  const std::string& id = chromium_connectable->id();
372a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  EXPECT_EQ(COULD_NOT_ESTABLISH_CONNECTION_ERROR,
373a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)            CanConnectAndSendMessages(incognito_browser, id));
374a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
375a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  // Then yes.
376a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  ExtensionPrefs::Get(profile())->SetIsIncognitoEnabled(id, true);
377a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  EXPECT_EQ(OK, CanConnectAndSendMessages(incognito_browser, id));
378a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)}
379a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
3807dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch}  // namespace
3817dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch}  // namespace extensions
382