Extensions cleanup: Merge IsSyncableApp+Extension, ShouldSyncApp+Extension
[chromium-blink-merge.git] / chrome / browser / extensions / extension_messages_apitest.cc
blob4ee239573b2b78b6400d2336c964cb8597588741
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.
5 #include "base/base64.h"
6 #include "base/files/file_path.h"
7 #include "base/json/json_reader.h"
8 #include "base/json/json_writer.h"
9 #include "base/path_service.h"
10 #include "base/strings/string_number_conversions.h"
11 #include "base/strings/string_piece.h"
12 #include "base/strings/stringprintf.h"
13 #include "base/strings/utf_string_conversions.h"
14 #include "base/synchronization/waitable_event.h"
15 #include "base/values.h"
16 #include "chrome/browser/chrome_notification_types.h"
17 #include "chrome/browser/extensions/api/messaging/incognito_connectability.h"
18 #include "chrome/browser/extensions/extension_apitest.h"
19 #include "chrome/browser/extensions/test_extension_dir.h"
20 #include "chrome/browser/infobars/infobar_service.h"
21 #include "chrome/browser/profiles/profile.h"
22 #include "chrome/browser/ui/browser.h"
23 #include "chrome/browser/ui/tabs/tab_strip_model.h"
24 #include "chrome/common/chrome_paths.h"
25 #include "chrome/common/chrome_switches.h"
26 #include "chrome/test/base/ui_test_utils.h"
27 #include "content/public/browser/notification_registrar.h"
28 #include "content/public/browser/notification_service.h"
29 #include "content/public/test/browser_test_utils.h"
30 #include "extensions/browser/event_router.h"
31 #include "extensions/browser/extension_prefs.h"
32 #include "extensions/browser/extension_system.h"
33 #include "extensions/common/api/runtime.h"
34 #include "extensions/common/extension_builder.h"
35 #include "extensions/common/value_builder.h"
36 #include "net/cert/asn1_util.h"
37 #include "net/cert/jwk_serializer.h"
38 #include "net/dns/mock_host_resolver.h"
39 #include "net/ssl/channel_id_service.h"
40 #include "net/test/embedded_test_server/embedded_test_server.h"
41 #include "net/url_request/url_request_context.h"
42 #include "net/url_request/url_request_context_getter.h"
43 #include "url/gurl.h"
45 namespace extensions {
46 namespace {
48 class MessageSender : public content::NotificationObserver {
49 public:
50 MessageSender() {
51 registrar_.Add(this,
52 extensions::NOTIFICATION_EXTENSION_HOST_DID_STOP_FIRST_LOAD,
53 content::NotificationService::AllSources());
56 private:
57 static scoped_ptr<base::ListValue> BuildEventArguments(
58 const bool last_message,
59 const std::string& data) {
60 base::DictionaryValue* event = new base::DictionaryValue();
61 event->SetBoolean("lastMessage", last_message);
62 event->SetString("data", data);
63 scoped_ptr<base::ListValue> arguments(new base::ListValue());
64 arguments->Append(event);
65 return arguments.Pass();
68 static scoped_ptr<Event> BuildEvent(scoped_ptr<base::ListValue> event_args,
69 Profile* profile,
70 GURL event_url) {
71 scoped_ptr<Event> event(new Event(events::TEST_ON_MESSAGE, "test.onMessage",
72 event_args.Pass()));
73 event->restrict_to_browser_context = profile;
74 event->event_url = event_url;
75 return event.Pass();
78 void Observe(int type,
79 const content::NotificationSource& source,
80 const content::NotificationDetails& details) override {
81 DCHECK_EQ(extensions::NOTIFICATION_EXTENSION_HOST_DID_STOP_FIRST_LOAD,
82 type);
83 EventRouter* event_router =
84 EventRouter::Get(content::Source<Profile>(source).ptr());
86 // Sends four messages to the extension. All but the third message sent
87 // from the origin http://b.com/ are supposed to arrive.
88 event_router->BroadcastEvent(BuildEvent(
89 BuildEventArguments(false, "no restriction"),
90 content::Source<Profile>(source).ptr(),
91 GURL()));
92 event_router->BroadcastEvent(BuildEvent(
93 BuildEventArguments(false, "http://a.com/"),
94 content::Source<Profile>(source).ptr(),
95 GURL("http://a.com/")));
96 event_router->BroadcastEvent(BuildEvent(
97 BuildEventArguments(false, "http://b.com/"),
98 content::Source<Profile>(source).ptr(),
99 GURL("http://b.com/")));
100 event_router->BroadcastEvent(BuildEvent(
101 BuildEventArguments(true, "last message"),
102 content::Source<Profile>(source).ptr(),
103 GURL()));
106 content::NotificationRegistrar registrar_;
109 // Tests that message passing between extensions and content scripts works.
110 IN_PROC_BROWSER_TEST_F(ExtensionApiTest, Messaging) {
111 ASSERT_TRUE(StartEmbeddedTestServer());
112 ASSERT_TRUE(RunExtensionTest("messaging/connect")) << message_;
115 // Tests that message passing from one extension to another works.
116 IN_PROC_BROWSER_TEST_F(ExtensionApiTest, MessagingExternal) {
117 ASSERT_TRUE(LoadExtension(
118 test_data_dir_.AppendASCII("..").AppendASCII("good")
119 .AppendASCII("Extensions")
120 .AppendASCII("bjafgdebaacbbbecmhlhpofkepfkgcpa")
121 .AppendASCII("1.0")));
123 ASSERT_TRUE(RunExtensionTest("messaging/connect_external")) << message_;
126 // Tests that messages with event_urls are only passed to extensions with
127 // appropriate permissions.
128 IN_PROC_BROWSER_TEST_F(ExtensionApiTest, MessagingEventURL) {
129 MessageSender sender;
130 ASSERT_TRUE(RunExtensionTest("messaging/event_url")) << message_;
133 // Tests connecting from a panel to its extension.
134 class PanelMessagingTest : public ExtensionApiTest {
135 void SetUpCommandLine(base::CommandLine* command_line) override {
136 ExtensionApiTest::SetUpCommandLine(command_line);
137 command_line->AppendSwitch(switches::kEnablePanels);
141 IN_PROC_BROWSER_TEST_F(PanelMessagingTest, MessagingPanel) {
142 ASSERT_TRUE(RunExtensionTest("messaging/connect_panel")) << message_;
145 // XXX(kalman): All web messaging tests disabled on windows due to extreme
146 // flakiness. See http://crbug.com/350517.
147 #if !defined(OS_WIN)
149 // Tests externally_connectable between a web page and an extension.
151 // TODO(kalman): Test between extensions. This is already tested in this file,
152 // but not with externally_connectable set in the manifest.
154 // TODO(kalman): Test with host permissions.
155 class ExternallyConnectableMessagingTest : public ExtensionApiTest {
156 protected:
157 // Result codes from the test. These must match up with |results| in
158 // c/t/d/extensions/api_test/externally_connectable/assertions.json.
159 enum Result {
160 OK = 0,
161 NAMESPACE_NOT_DEFINED = 1,
162 FUNCTION_NOT_DEFINED = 2,
163 COULD_NOT_ESTABLISH_CONNECTION_ERROR = 3,
164 OTHER_ERROR = 4,
165 INCORRECT_RESPONSE_SENDER = 5,
166 INCORRECT_RESPONSE_MESSAGE = 6,
169 bool AppendIframe(const GURL& src) {
170 bool result;
171 CHECK(content::ExecuteScriptAndExtractBool(
172 browser()->tab_strip_model()->GetActiveWebContents(),
173 "actions.appendIframe('" + src.spec() + "');", &result));
174 return result;
177 Result CanConnectAndSendMessagesToMainFrame(const Extension* extension,
178 const char* message = NULL) {
179 return CanConnectAndSendMessagesToFrame(
180 browser()->tab_strip_model()->GetActiveWebContents()->GetMainFrame(),
181 extension,
182 message);
185 Result CanConnectAndSendMessagesToIFrame(const Extension* extension,
186 const char* message = NULL) {
187 content::RenderFrameHost* frame = content::FrameMatchingPredicate(
188 browser()->tab_strip_model()->GetActiveWebContents(),
189 base::Bind(&content::FrameIsChildOfMainFrame));
190 return CanConnectAndSendMessagesToFrame(frame, extension, message);
193 Result CanConnectAndSendMessagesToFrame(content::RenderFrameHost* frame,
194 const Extension* extension,
195 const char* message) {
196 int result;
197 std::string command = base::StringPrintf(
198 "assertions.canConnectAndSendMessages('%s', %s, %s)",
199 extension->id().c_str(),
200 extension->is_platform_app() ? "true" : "false",
201 message ? base::StringPrintf("'%s'", message).c_str() : "undefined");
202 CHECK(content::ExecuteScriptAndExtractInt(frame, command, &result));
203 return static_cast<Result>(result);
206 testing::AssertionResult AreAnyNonWebApisDefinedForMainFrame() {
207 return AreAnyNonWebApisDefinedForFrame(
208 browser()->tab_strip_model()->GetActiveWebContents()->GetMainFrame());
211 testing::AssertionResult AreAnyNonWebApisDefinedForIFrame() {
212 content::RenderFrameHost* frame = content::FrameMatchingPredicate(
213 browser()->tab_strip_model()->GetActiveWebContents(),
214 base::Bind(&content::FrameIsChildOfMainFrame));
215 return AreAnyNonWebApisDefinedForFrame(frame);
218 testing::AssertionResult AreAnyNonWebApisDefinedForFrame(
219 content::RenderFrameHost* frame) {
220 // All runtime API methods are non-web except for sendRequest and connect.
221 const char* const non_messaging_apis[] = {
222 "getBackgroundPage",
223 "getManifest",
224 "getURL",
225 "reload",
226 "requestUpdateCheck",
227 "restart",
228 "connectNative",
229 "sendNativeMessage",
230 "onStartup",
231 "onInstalled",
232 "onSuspend",
233 "onSuspendCanceled",
234 "onUpdateAvailable",
235 "onBrowserUpdateAvailable",
236 "onConnect",
237 "onConnectExternal",
238 "onMessage",
239 "onMessageExternal",
240 "onRestartRequired",
241 // Note: no "id" here because this test method is used for hosted apps,
242 // which do have access to runtime.id.
245 // Turn the array into a JS array, which effectively gets eval()ed.
246 std::string as_js_array;
247 for (size_t i = 0; i < arraysize(non_messaging_apis); ++i) {
248 as_js_array += as_js_array.empty() ? "[" : ",";
249 as_js_array += base::StringPrintf("'%s'", non_messaging_apis[i]);
251 as_js_array += "]";
253 bool any_defined;
254 CHECK(content::ExecuteScriptAndExtractBool(
255 frame,
256 "assertions.areAnyRuntimePropertiesDefined(" + as_js_array + ")",
257 &any_defined));
258 return any_defined ?
259 testing::AssertionSuccess() : testing::AssertionFailure();
262 std::string GetTlsChannelIdFromPortConnect(const Extension* extension,
263 bool include_tls_channel_id,
264 const char* message = NULL) {
265 return GetTlsChannelIdFromAssertion("getTlsChannelIdFromPortConnect",
266 extension,
267 include_tls_channel_id,
268 message);
271 std::string GetTlsChannelIdFromSendMessage(const Extension* extension,
272 bool include_tls_channel_id,
273 const char* message = NULL) {
274 return GetTlsChannelIdFromAssertion("getTlsChannelIdFromSendMessage",
275 extension,
276 include_tls_channel_id,
277 message);
280 GURL GetURLForPath(const std::string& host, const std::string& path) {
281 std::string port = base::IntToString(embedded_test_server()->port());
282 GURL::Replacements replacements;
283 replacements.SetHostStr(host);
284 replacements.SetPortStr(port);
285 return embedded_test_server()->GetURL(path).ReplaceComponents(replacements);
288 GURL chromium_org_url() {
289 return GetURLForPath("www.chromium.org", "/chromium.org.html");
292 GURL google_com_url() {
293 return GetURLForPath("www.google.com", "/google.com.html");
296 scoped_refptr<const Extension> LoadChromiumConnectableExtension() {
297 scoped_refptr<const Extension> extension =
298 LoadExtensionIntoDir(&web_connectable_dir_,
299 base::StringPrintf(
301 " \"name\": \"chromium_connectable\","
302 " %s,"
303 " \"externally_connectable\": {"
304 " \"matches\": [\"*://*.chromium.org:*/*\"]"
305 " }"
306 "}",
307 common_manifest()));
308 CHECK(extension.get());
309 return extension;
312 scoped_refptr<const Extension> LoadChromiumConnectableApp(
313 bool with_event_handlers = true) {
314 scoped_refptr<const Extension> extension =
315 LoadExtensionIntoDir(&web_connectable_dir_,
317 " \"app\": {"
318 " \"background\": {"
319 " \"scripts\": [\"background.js\"]"
320 " }"
321 " },"
322 " \"externally_connectable\": {"
323 " \"matches\": [\"*://*.chromium.org:*/*\"]"
324 " },"
325 " \"manifest_version\": 2,"
326 " \"name\": \"app_connectable\","
327 " \"version\": \"1.0\""
328 "}",
329 with_event_handlers);
330 CHECK(extension.get());
331 return extension;
334 scoped_refptr<const Extension> LoadNotConnectableExtension() {
335 scoped_refptr<const Extension> extension =
336 LoadExtensionIntoDir(&not_connectable_dir_,
337 base::StringPrintf(
339 " \"name\": \"not_connectable\","
340 " %s"
341 "}",
342 common_manifest()));
343 CHECK(extension.get());
344 return extension;
347 scoped_refptr<const Extension>
348 LoadChromiumConnectableExtensionWithTlsChannelId() {
349 return LoadExtensionIntoDir(&tls_channel_id_connectable_dir_,
350 connectable_with_tls_channel_id_manifest());
353 scoped_refptr<const Extension> LoadChromiumHostedApp() {
354 scoped_refptr<const Extension> hosted_app =
355 LoadExtensionIntoDir(&hosted_app_dir_,
356 base::StringPrintf(
358 " \"name\": \"chromium_hosted_app\","
359 " \"version\": \"1.0\","
360 " \"manifest_version\": 2,"
361 " \"app\": {"
362 " \"urls\": [\"%s\"],"
363 " \"launch\": {"
364 " \"web_url\": \"%s\""
365 " }\n"
366 " }\n"
367 "}",
368 chromium_org_url().spec().c_str(),
369 chromium_org_url().spec().c_str()));
370 CHECK(hosted_app.get());
371 return hosted_app;
374 void InitializeTestServer() {
375 base::FilePath test_data;
376 EXPECT_TRUE(PathService::Get(chrome::DIR_TEST_DATA, &test_data));
377 embedded_test_server()->ServeFilesFromDirectory(test_data.AppendASCII(
378 "extensions/api_test/messaging/externally_connectable/sites"));
379 ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
380 host_resolver()->AddRule("*", embedded_test_server()->base_url().host());
383 const char* close_background_message() {
384 return "closeBackgroundPage";
387 private:
388 scoped_refptr<const Extension> LoadExtensionIntoDir(
389 TestExtensionDir* dir,
390 const std::string& manifest,
391 bool with_event_handlers = true) {
392 dir->WriteManifest(manifest);
393 if (with_event_handlers) {
394 dir->WriteFile(
395 FILE_PATH_LITERAL("background.js"),
396 base::StringPrintf(
397 "function maybeClose(message) {\n"
398 " if (message.indexOf('%s') >= 0)\n"
399 " window.setTimeout(function() { window.close() }, 0);\n"
400 "}\n"
401 "chrome.runtime.onMessageExternal.addListener(\n"
402 " function(message, sender, reply) {\n"
403 " reply({ message: message, sender: sender });\n"
404 " maybeClose(message);\n"
405 "});\n"
406 "chrome.runtime.onConnectExternal.addListener(function(port) {\n"
407 " port.onMessage.addListener(function(message) {\n"
408 " port.postMessage({ message: message, sender: port.sender "
409 "});\n"
410 " maybeClose(message);\n"
411 " });\n"
412 "});\n",
413 close_background_message()));
414 } else {
415 dir->WriteFile(FILE_PATH_LITERAL("background.js"), "");
417 return LoadExtension(dir->unpacked_path());
420 const char* common_manifest() {
421 return "\"version\": \"1.0\","
422 "\"background\": {"
423 " \"scripts\": [\"background.js\"],"
424 " \"persistent\": false"
425 "},"
426 "\"manifest_version\": 2";
429 std::string connectable_with_tls_channel_id_manifest() {
430 return base::StringPrintf(
432 " \"name\": \"chromium_connectable_with_tls_channel_id\","
433 " %s,"
434 " \"externally_connectable\": {"
435 " \"matches\": [\"*://*.chromium.org:*/*\"],"
436 " \"accepts_tls_channel_id\": true"
437 " }"
438 "}",
439 common_manifest());
442 std::string GetTlsChannelIdFromAssertion(const char* method,
443 const Extension* extension,
444 bool include_tls_channel_id,
445 const char* message) {
446 std::string result;
447 std::string args = "'" + extension->id() + "', ";
448 args += include_tls_channel_id ? "true" : "false";
449 if (message)
450 args += std::string(", '") + message + "'";
451 CHECK(content::ExecuteScriptAndExtractString(
452 browser()->tab_strip_model()->GetActiveWebContents(),
453 base::StringPrintf("assertions.%s(%s)", method, args.c_str()),
454 &result));
455 return result;
458 TestExtensionDir web_connectable_dir_;
459 TestExtensionDir not_connectable_dir_;
460 TestExtensionDir tls_channel_id_connectable_dir_;
461 TestExtensionDir hosted_app_dir_;
464 IN_PROC_BROWSER_TEST_F(ExternallyConnectableMessagingTest, NotInstalled) {
465 InitializeTestServer();
467 scoped_refptr<const Extension> extension =
468 ExtensionBuilder()
469 .SetID("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa")
470 .SetManifest(DictionaryBuilder()
471 .Set("name", "Fake extension")
472 .Set("version", "1")
473 .Set("manifest_version", 2))
474 .Build();
476 ui_test_utils::NavigateToURL(browser(), chromium_org_url());
477 EXPECT_EQ(NAMESPACE_NOT_DEFINED,
478 CanConnectAndSendMessagesToMainFrame(extension.get()));
479 EXPECT_FALSE(AreAnyNonWebApisDefinedForMainFrame());
481 ui_test_utils::NavigateToURL(browser(), google_com_url());
482 EXPECT_EQ(NAMESPACE_NOT_DEFINED,
483 CanConnectAndSendMessagesToMainFrame(extension.get()));
484 EXPECT_FALSE(AreAnyNonWebApisDefinedForMainFrame());
487 // Tests two extensions on the same sites: one web connectable, one not.
488 IN_PROC_BROWSER_TEST_F(ExternallyConnectableMessagingTest,
489 WebConnectableAndNotConnectable) {
490 InitializeTestServer();
492 // Install the web connectable extension. chromium.org can connect to it,
493 // google.com can't.
494 scoped_refptr<const Extension> chromium_connectable =
495 LoadChromiumConnectableExtension();
497 ui_test_utils::NavigateToURL(browser(), chromium_org_url());
498 EXPECT_EQ(OK,
499 CanConnectAndSendMessagesToMainFrame(chromium_connectable.get()));
500 EXPECT_FALSE(AreAnyNonWebApisDefinedForMainFrame());
502 ui_test_utils::NavigateToURL(browser(), google_com_url());
503 EXPECT_EQ(NAMESPACE_NOT_DEFINED,
504 CanConnectAndSendMessagesToMainFrame(chromium_connectable.get()));
505 EXPECT_FALSE(AreAnyNonWebApisDefinedForMainFrame());
507 // Install the non-connectable extension. Nothing can connect to it.
508 scoped_refptr<const Extension> not_connectable =
509 LoadNotConnectableExtension();
511 ui_test_utils::NavigateToURL(browser(), chromium_org_url());
512 // Namespace will be defined here because |chromium_connectable| can connect
513 // to it - so this will be the "cannot establish connection" error.
514 EXPECT_EQ(COULD_NOT_ESTABLISH_CONNECTION_ERROR,
515 CanConnectAndSendMessagesToMainFrame(not_connectable.get()));
516 EXPECT_FALSE(AreAnyNonWebApisDefinedForMainFrame());
518 ui_test_utils::NavigateToURL(browser(), google_com_url());
519 EXPECT_EQ(NAMESPACE_NOT_DEFINED,
520 CanConnectAndSendMessagesToMainFrame(not_connectable.get()));
521 EXPECT_FALSE(AreAnyNonWebApisDefinedForMainFrame());
524 // See http://crbug.com/297866
525 IN_PROC_BROWSER_TEST_F(ExternallyConnectableMessagingTest,
526 DISABLED_BackgroundPageClosesOnMessageReceipt) {
527 InitializeTestServer();
529 // Install the web connectable extension.
530 scoped_refptr<const Extension> chromium_connectable =
531 LoadChromiumConnectableExtension();
533 ui_test_utils::NavigateToURL(browser(), chromium_org_url());
534 // If the background page closes after receipt of the message, it will still
535 // reply to this message...
536 EXPECT_EQ(OK,
537 CanConnectAndSendMessagesToMainFrame(chromium_connectable.get(),
538 close_background_message()));
539 // and be re-opened by receipt of a subsequent message.
540 EXPECT_EQ(OK,
541 CanConnectAndSendMessagesToMainFrame(chromium_connectable.get()));
544 // Tests a web connectable extension that doesn't receive TLS channel id.
545 IN_PROC_BROWSER_TEST_F(ExternallyConnectableMessagingTest,
546 WebConnectableWithoutTlsChannelId) {
547 InitializeTestServer();
549 // Install the web connectable extension. chromium.org can connect to it,
550 // google.com can't.
551 scoped_refptr<const Extension> chromium_connectable =
552 LoadChromiumConnectableExtension();
553 ASSERT_TRUE(chromium_connectable.get());
555 ui_test_utils::NavigateToURL(browser(), chromium_org_url());
556 // The web connectable extension doesn't request the TLS channel ID, so it
557 // doesn't get it, whether or not the page asks for it.
558 EXPECT_EQ(std::string(),
559 GetTlsChannelIdFromPortConnect(chromium_connectable.get(), false));
560 EXPECT_EQ(std::string(),
561 GetTlsChannelIdFromSendMessage(chromium_connectable.get(), true));
562 EXPECT_EQ(std::string(),
563 GetTlsChannelIdFromPortConnect(chromium_connectable.get(), false));
564 EXPECT_EQ(std::string(),
565 GetTlsChannelIdFromSendMessage(chromium_connectable.get(), true));
568 // Tests a web connectable extension that receives TLS channel id with a site
569 // that can't connect to it.
570 IN_PROC_BROWSER_TEST_F(ExternallyConnectableMessagingTest,
571 WebConnectableWithTlsChannelIdWithNonMatchingSite) {
572 InitializeTestServer();
574 scoped_refptr<const Extension> chromium_connectable =
575 LoadChromiumConnectableExtensionWithTlsChannelId();
576 ASSERT_TRUE(chromium_connectable.get());
578 ui_test_utils::NavigateToURL(browser(), google_com_url());
579 // The extension requests the TLS channel ID, but it doesn't get it for a
580 // site that can't connect to it, regardless of whether the page asks for it.
581 EXPECT_EQ(base::IntToString(NAMESPACE_NOT_DEFINED),
582 GetTlsChannelIdFromPortConnect(chromium_connectable.get(), false));
583 EXPECT_EQ(base::IntToString(NAMESPACE_NOT_DEFINED),
584 GetTlsChannelIdFromSendMessage(chromium_connectable.get(), true));
585 EXPECT_EQ(base::IntToString(NAMESPACE_NOT_DEFINED),
586 GetTlsChannelIdFromPortConnect(chromium_connectable.get(), false));
587 EXPECT_EQ(base::IntToString(NAMESPACE_NOT_DEFINED),
588 GetTlsChannelIdFromSendMessage(chromium_connectable.get(), true));
591 // Tests a web connectable extension that receives TLS channel id on a site
592 // that can connect to it, but with no TLS channel ID having been generated.
593 IN_PROC_BROWSER_TEST_F(ExternallyConnectableMessagingTest,
594 WebConnectableWithTlsChannelIdWithEmptyTlsChannelId) {
595 InitializeTestServer();
597 scoped_refptr<const Extension> chromium_connectable =
598 LoadChromiumConnectableExtensionWithTlsChannelId();
599 ASSERT_TRUE(chromium_connectable.get());
601 ui_test_utils::NavigateToURL(browser(), chromium_org_url());
603 // Since the extension requests the TLS channel ID, it gets it for a site that
604 // can connect to it, but only if the page also asks to include it.
605 EXPECT_EQ(std::string(),
606 GetTlsChannelIdFromPortConnect(chromium_connectable.get(), false));
607 EXPECT_EQ(std::string(),
608 GetTlsChannelIdFromSendMessage(chromium_connectable.get(), false));
609 // If the page does ask for it, it isn't empty.
610 std::string tls_channel_id =
611 GetTlsChannelIdFromPortConnect(chromium_connectable.get(), true);
612 // Because the TLS channel ID has never been generated for this domain,
613 // no TLS channel ID is reported.
614 EXPECT_EQ(std::string(), tls_channel_id);
617 // Flaky on Linux and Windows. http://crbug.com/315264
618 // Tests a web connectable extension that receives TLS channel id, but
619 // immediately closes its background page upon receipt of a message.
620 IN_PROC_BROWSER_TEST_F(ExternallyConnectableMessagingTest,
621 DISABLED_WebConnectableWithEmptyTlsChannelIdAndClosedBackgroundPage) {
622 InitializeTestServer();
624 scoped_refptr<const Extension> chromium_connectable =
625 LoadChromiumConnectableExtensionWithTlsChannelId();
627 ui_test_utils::NavigateToURL(browser(), chromium_org_url());
628 // If the page does ask for it, it isn't empty, even if the background page
629 // closes upon receipt of the connect.
630 std::string tls_channel_id = GetTlsChannelIdFromPortConnect(
631 chromium_connectable.get(), true, close_background_message());
632 // Because the TLS channel ID has never been generated for this domain,
633 // no TLS channel ID is reported.
634 EXPECT_EQ(std::string(), tls_channel_id);
635 // A subsequent connect will still succeed, even if the background page was
636 // previously closed.
637 tls_channel_id =
638 GetTlsChannelIdFromPortConnect(chromium_connectable.get(), true);
639 // And the empty value is still retrieved.
640 EXPECT_EQ(std::string(), tls_channel_id);
643 // Tests that enabling and disabling an extension makes the runtime bindings
644 // appear and disappear.
646 // TODO(kalman): Test with multiple extensions that can be accessed by the same
647 // host.
648 IN_PROC_BROWSER_TEST_F(ExternallyConnectableMessagingTest,
649 EnablingAndDisabling) {
650 InitializeTestServer();
652 scoped_refptr<const Extension> chromium_connectable =
653 LoadChromiumConnectableExtension();
654 scoped_refptr<const Extension> not_connectable =
655 LoadNotConnectableExtension();
657 ui_test_utils::NavigateToURL(browser(), chromium_org_url());
658 EXPECT_EQ(OK,
659 CanConnectAndSendMessagesToMainFrame(chromium_connectable.get()));
660 EXPECT_EQ(COULD_NOT_ESTABLISH_CONNECTION_ERROR,
661 CanConnectAndSendMessagesToMainFrame(not_connectable.get()));
663 DisableExtension(chromium_connectable->id());
664 EXPECT_EQ(COULD_NOT_ESTABLISH_CONNECTION_ERROR,
665 CanConnectAndSendMessagesToMainFrame(chromium_connectable.get()));
667 EnableExtension(chromium_connectable->id());
668 EXPECT_EQ(OK,
669 CanConnectAndSendMessagesToMainFrame(chromium_connectable.get()));
670 EXPECT_EQ(COULD_NOT_ESTABLISH_CONNECTION_ERROR,
671 CanConnectAndSendMessagesToMainFrame(not_connectable.get()));
674 // Tests connection from incognito tabs when the user denies the connection
675 // request. Spanning mode only. A separate test for apps and extensions.
677 // TODO(kalman): ensure that we exercise split vs spanning incognito logic
678 // somewhere. This is a test that should be shared with the content script logic
679 // so it's not really our specific concern for web connectable.
681 // TODO(kalman): test messages from incognito extensions too.
682 IN_PROC_BROWSER_TEST_F(ExternallyConnectableMessagingTest,
683 FromIncognitoDenyApp) {
684 InitializeTestServer();
686 scoped_refptr<const Extension> app = LoadChromiumConnectableApp();
687 ASSERT_TRUE(app->is_platform_app());
689 Browser* incognito_browser = ui_test_utils::OpenURLOffTheRecord(
690 profile()->GetOffTheRecordProfile(),
691 chromium_org_url());
692 content::RenderFrameHost* incognito_frame = incognito_browser->
693 tab_strip_model()->GetActiveWebContents()->GetMainFrame();
696 IncognitoConnectability::ScopedAlertTracker alert_tracker(
697 IncognitoConnectability::ScopedAlertTracker::ALWAYS_DENY);
699 // No connection because incognito-enabled hasn't been set for the app, and
700 // the user denied our interactive request.
701 EXPECT_EQ(
702 COULD_NOT_ESTABLISH_CONNECTION_ERROR,
703 CanConnectAndSendMessagesToFrame(incognito_frame, app.get(), NULL));
704 EXPECT_EQ(1, alert_tracker.GetAndResetAlertCount());
706 // Try again. User has already denied so alert not shown.
707 EXPECT_EQ(
708 COULD_NOT_ESTABLISH_CONNECTION_ERROR,
709 CanConnectAndSendMessagesToFrame(incognito_frame, app.get(), NULL));
710 EXPECT_EQ(0, alert_tracker.GetAndResetAlertCount());
713 // It's not possible to allow an app in incognito.
714 ExtensionPrefs::Get(profile())->SetIsIncognitoEnabled(app->id(), true);
715 EXPECT_EQ(COULD_NOT_ESTABLISH_CONNECTION_ERROR,
716 CanConnectAndSendMessagesToFrame(incognito_frame, app.get(), NULL));
719 IN_PROC_BROWSER_TEST_F(ExternallyConnectableMessagingTest,
720 FromIncognitoDenyExtension) {
721 InitializeTestServer();
723 scoped_refptr<const Extension> extension = LoadChromiumConnectableExtension();
725 Browser* incognito_browser = ui_test_utils::OpenURLOffTheRecord(
726 profile()->GetOffTheRecordProfile(), chromium_org_url());
727 content::RenderFrameHost* incognito_frame =
728 incognito_browser->tab_strip_model()
729 ->GetActiveWebContents()
730 ->GetMainFrame();
733 IncognitoConnectability::ScopedAlertTracker alert_tracker(
734 IncognitoConnectability::ScopedAlertTracker::ALWAYS_DENY);
736 // The alert doesn't show for extensions.
737 EXPECT_EQ(COULD_NOT_ESTABLISH_CONNECTION_ERROR,
738 CanConnectAndSendMessagesToFrame(
739 incognito_frame, extension.get(), NULL));
740 EXPECT_EQ(0, alert_tracker.GetAndResetAlertCount());
743 // Allowing the extension in incognito mode will bypass the deny.
744 ExtensionPrefs::Get(profile())->SetIsIncognitoEnabled(extension->id(), true);
745 EXPECT_EQ(
747 CanConnectAndSendMessagesToFrame(incognito_frame, extension.get(), NULL));
750 // Tests connection from incognito tabs when the extension doesn't have an event
751 // handler for the connection event.
752 IN_PROC_BROWSER_TEST_F(ExternallyConnectableMessagingTest,
753 FromIncognitoNoEventHandlerInApp) {
754 InitializeTestServer();
756 scoped_refptr<const Extension> app = LoadChromiumConnectableApp(false);
757 ASSERT_TRUE(app->is_platform_app());
759 Browser* incognito_browser = ui_test_utils::OpenURLOffTheRecord(
760 profile()->GetOffTheRecordProfile(), chromium_org_url());
761 content::RenderFrameHost* incognito_frame =
762 incognito_browser->tab_strip_model()
763 ->GetActiveWebContents()
764 ->GetMainFrame();
767 IncognitoConnectability::ScopedAlertTracker alert_tracker(
768 IncognitoConnectability::ScopedAlertTracker::ALWAYS_ALLOW);
770 // No connection because incognito-enabled hasn't been set for the app, and
771 // the app hasn't installed event handlers.
772 EXPECT_EQ(
773 COULD_NOT_ESTABLISH_CONNECTION_ERROR,
774 CanConnectAndSendMessagesToFrame(incognito_frame, app.get(), NULL));
775 // No dialog should have been shown.
776 EXPECT_EQ(0, alert_tracker.GetAndResetAlertCount());
780 // Tests connection from incognito tabs when the user accepts the connection
781 // request. Spanning mode only. Separate tests for apps and extensions.
783 // TODO(kalman): see comment above about split mode.
784 IN_PROC_BROWSER_TEST_F(ExternallyConnectableMessagingTest,
785 FromIncognitoAllowApp) {
786 InitializeTestServer();
788 scoped_refptr<const Extension> app = LoadChromiumConnectableApp();
789 ASSERT_TRUE(app->is_platform_app());
791 Browser* incognito_browser = ui_test_utils::OpenURLOffTheRecord(
792 profile()->GetOffTheRecordProfile(),
793 chromium_org_url());
794 content::RenderFrameHost* incognito_frame = incognito_browser->
795 tab_strip_model()->GetActiveWebContents()->GetMainFrame();
798 IncognitoConnectability::ScopedAlertTracker alert_tracker(
799 IncognitoConnectability::ScopedAlertTracker::ALWAYS_ALLOW);
801 // Connection allowed even with incognito disabled, because the user
802 // accepted the interactive request.
803 EXPECT_EQ(
804 OK, CanConnectAndSendMessagesToFrame(incognito_frame, app.get(), NULL));
805 EXPECT_EQ(1, alert_tracker.GetAndResetAlertCount());
807 // Try again. User has already allowed.
808 EXPECT_EQ(
809 OK, CanConnectAndSendMessagesToFrame(incognito_frame, app.get(), NULL));
810 EXPECT_EQ(0, alert_tracker.GetAndResetAlertCount());
813 // Apps can't be allowed in incognito mode, but it's moot because it's
814 // already allowed.
815 ExtensionPrefs::Get(profile())->SetIsIncognitoEnabled(app->id(), true);
816 EXPECT_EQ(OK,
817 CanConnectAndSendMessagesToFrame(incognito_frame, app.get(), NULL));
820 // Tests connection from incognito tabs when there are multiple tabs open to the
821 // same origin. The user should only need to accept the connection request once.
822 IN_PROC_BROWSER_TEST_F(ExternallyConnectableMessagingTest,
823 FromIncognitoPromptApp) {
824 InitializeTestServer();
826 scoped_refptr<const Extension> app = LoadChromiumConnectableApp();
827 ASSERT_TRUE(app->is_platform_app());
829 // Open an incognito browser with two tabs displaying "chromium.org".
830 Browser* incognito_browser = ui_test_utils::OpenURLOffTheRecord(
831 profile()->GetOffTheRecordProfile(), chromium_org_url());
832 content::RenderFrameHost* incognito_frame1 =
833 incognito_browser->tab_strip_model()
834 ->GetActiveWebContents()
835 ->GetMainFrame();
836 InfoBarService* infobar_service1 = InfoBarService::FromWebContents(
837 incognito_browser->tab_strip_model()->GetActiveWebContents());
839 CHECK(ui_test_utils::OpenURLOffTheRecord(profile()->GetOffTheRecordProfile(),
840 chromium_org_url()) ==
841 incognito_browser);
842 content::RenderFrameHost* incognito_frame2 =
843 incognito_browser->tab_strip_model()
844 ->GetActiveWebContents()
845 ->GetMainFrame();
846 InfoBarService* infobar_service2 = InfoBarService::FromWebContents(
847 incognito_browser->tab_strip_model()->GetActiveWebContents());
848 EXPECT_EQ(2, incognito_browser->tab_strip_model()->count());
849 EXPECT_NE(incognito_frame1, incognito_frame2);
851 // Trigger a infobars in both tabs by trying to send messages.
852 std::string script =
853 base::StringPrintf("assertions.trySendMessage('%s')", app->id().c_str());
854 CHECK(content::ExecuteScript(incognito_frame1, script));
855 CHECK(content::ExecuteScript(incognito_frame2, script));
856 EXPECT_EQ(1U, infobar_service1->infobar_count());
857 EXPECT_EQ(1U, infobar_service2->infobar_count());
859 // Navigating away will dismiss the infobar on the active tab only.
860 ui_test_utils::NavigateToURL(incognito_browser, google_com_url());
861 EXPECT_EQ(1U, infobar_service1->infobar_count());
862 EXPECT_EQ(0U, infobar_service2->infobar_count());
864 // Navigate back and accept the infobar this time. Both should be dismissed.
866 IncognitoConnectability::ScopedAlertTracker alert_tracker(
867 IncognitoConnectability::ScopedAlertTracker::ALWAYS_ALLOW);
869 ui_test_utils::NavigateToURL(incognito_browser, chromium_org_url());
870 incognito_frame2 = incognito_browser->tab_strip_model()
871 ->GetActiveWebContents()
872 ->GetMainFrame();
873 EXPECT_NE(incognito_frame1, incognito_frame2);
875 EXPECT_EQ(1U, infobar_service1->infobar_count());
876 EXPECT_EQ(OK, CanConnectAndSendMessagesToFrame(incognito_frame2, app.get(),
877 NULL));
878 EXPECT_EQ(1, alert_tracker.GetAndResetAlertCount());
879 EXPECT_EQ(0U, infobar_service1->infobar_count());
883 IN_PROC_BROWSER_TEST_F(ExternallyConnectableMessagingTest, IllegalArguments) {
884 // Tests that malformed arguments to connect() don't crash.
885 // Regression test for crbug.com/472700.
886 InitializeTestServer();
887 LoadChromiumConnectableExtension();
888 ui_test_utils::NavigateToURL(browser(), chromium_org_url());
889 bool result;
890 CHECK(content::ExecuteScriptAndExtractBool(
891 browser()->tab_strip_model()->GetActiveWebContents(),
892 "assertions.tryIllegalArguments()", &result));
893 EXPECT_TRUE(result);
896 IN_PROC_BROWSER_TEST_F(ExternallyConnectableMessagingTest,
897 FromIncognitoAllowExtension) {
898 InitializeTestServer();
900 scoped_refptr<const Extension> extension = LoadChromiumConnectableExtension();
902 Browser* incognito_browser = ui_test_utils::OpenURLOffTheRecord(
903 profile()->GetOffTheRecordProfile(), chromium_org_url());
904 content::RenderFrameHost* incognito_frame =
905 incognito_browser->tab_strip_model()
906 ->GetActiveWebContents()
907 ->GetMainFrame();
910 IncognitoConnectability::ScopedAlertTracker alert_tracker(
911 IncognitoConnectability::ScopedAlertTracker::ALWAYS_ALLOW);
913 // No alert is shown.
914 EXPECT_EQ(COULD_NOT_ESTABLISH_CONNECTION_ERROR,
915 CanConnectAndSendMessagesToFrame(
916 incognito_frame, extension.get(), NULL));
917 EXPECT_EQ(0, alert_tracker.GetAndResetAlertCount());
920 // Allowing the extension in incognito mode is what allows connections.
921 ExtensionPrefs::Get(profile())->SetIsIncognitoEnabled(extension->id(), true);
922 EXPECT_EQ(
924 CanConnectAndSendMessagesToFrame(incognito_frame, extension.get(), NULL));
927 // Tests a connection from an iframe within a tab which doesn't have
928 // permission. Iframe should work.
929 IN_PROC_BROWSER_TEST_F(ExternallyConnectableMessagingTest,
930 FromIframeWithPermission) {
931 InitializeTestServer();
933 scoped_refptr<const Extension> extension = LoadChromiumConnectableExtension();
935 ui_test_utils::NavigateToURL(browser(), google_com_url());
936 EXPECT_EQ(NAMESPACE_NOT_DEFINED,
937 CanConnectAndSendMessagesToMainFrame(extension.get()));
938 EXPECT_FALSE(AreAnyNonWebApisDefinedForMainFrame());
940 ASSERT_TRUE(AppendIframe(chromium_org_url()));
942 EXPECT_EQ(OK, CanConnectAndSendMessagesToIFrame(extension.get()));
943 EXPECT_FALSE(AreAnyNonWebApisDefinedForIFrame());
946 // Tests connection from an iframe without permission within a tab that does.
947 // Iframe shouldn't work.
948 IN_PROC_BROWSER_TEST_F(ExternallyConnectableMessagingTest,
949 FromIframeWithoutPermission) {
950 InitializeTestServer();
952 scoped_refptr<const Extension> extension = LoadChromiumConnectableExtension();
954 ui_test_utils::NavigateToURL(browser(), chromium_org_url());
955 EXPECT_EQ(OK, CanConnectAndSendMessagesToMainFrame(extension.get()));
956 EXPECT_FALSE(AreAnyNonWebApisDefinedForMainFrame());
958 ASSERT_TRUE(AppendIframe(google_com_url()));
960 EXPECT_EQ(NAMESPACE_NOT_DEFINED,
961 CanConnectAndSendMessagesToIFrame(extension.get()));
962 EXPECT_FALSE(AreAnyNonWebApisDefinedForIFrame());
965 // Tests externally_connectable between a web page and an extension with a
966 // TLS channel ID created for the origin.
967 class ExternallyConnectableMessagingWithTlsChannelIdTest :
968 public ExternallyConnectableMessagingTest {
969 public:
970 ExternallyConnectableMessagingWithTlsChannelIdTest()
971 : tls_channel_id_created_(false, false) {
974 std::string CreateTlsChannelId() {
975 scoped_refptr<net::URLRequestContextGetter> request_context_getter(
976 profile()->GetRequestContext());
977 scoped_ptr<crypto::ECPrivateKey> channel_id_key;
978 net::ChannelIDService::Request request;
979 content::BrowserThread::PostTask(
980 content::BrowserThread::IO, FROM_HERE,
981 base::Bind(&ExternallyConnectableMessagingWithTlsChannelIdTest::
982 CreateDomainBoundCertOnIOThread,
983 base::Unretained(this), base::Unretained(&channel_id_key),
984 base::Unretained(&request), request_context_getter));
985 tls_channel_id_created_.Wait();
986 // Create the expected value.
987 std::vector<uint8> spki_vector;
988 if (!channel_id_key->ExportPublicKey(&spki_vector))
989 return std::string();
990 base::StringPiece spki(reinterpret_cast<char*>(
991 vector_as_array(&spki_vector)), spki_vector.size());
992 base::DictionaryValue jwk_value;
993 net::JwkSerializer::ConvertSpkiFromDerToJwk(spki, &jwk_value);
994 std::string tls_channel_id_value;
995 base::JSONWriter::Write(jwk_value, &tls_channel_id_value);
996 return tls_channel_id_value;
999 private:
1000 void CreateDomainBoundCertOnIOThread(
1001 scoped_ptr<crypto::ECPrivateKey>* channel_id_key,
1002 net::ChannelIDService::Request* request,
1003 scoped_refptr<net::URLRequestContextGetter> request_context_getter) {
1004 DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
1005 net::ChannelIDService* channel_id_service =
1006 request_context_getter->GetURLRequestContext()->
1007 channel_id_service();
1008 int status = channel_id_service->GetOrCreateChannelID(
1009 chromium_org_url().host(), channel_id_key,
1010 base::Bind(&ExternallyConnectableMessagingWithTlsChannelIdTest::
1011 GotDomainBoundCert,
1012 base::Unretained(this)),
1013 request);
1014 if (status == net::ERR_IO_PENDING)
1015 return;
1016 GotDomainBoundCert(status);
1019 void GotDomainBoundCert(int status) {
1020 ASSERT_TRUE(status == net::OK);
1021 tls_channel_id_created_.Signal();
1024 base::WaitableEvent tls_channel_id_created_;
1027 // Tests a web connectable extension that receives TLS channel id on a site
1028 // that can connect to it, with a TLS channel ID having been generated.
1029 IN_PROC_BROWSER_TEST_F(ExternallyConnectableMessagingWithTlsChannelIdTest,
1030 WebConnectableWithNonEmptyTlsChannelId) {
1031 InitializeTestServer();
1032 std::string expected_tls_channel_id_value = CreateTlsChannelId();
1034 scoped_refptr<const Extension> chromium_connectable =
1035 LoadChromiumConnectableExtensionWithTlsChannelId();
1036 ASSERT_TRUE(chromium_connectable.get());
1038 ui_test_utils::NavigateToURL(browser(), chromium_org_url());
1040 // Since the extension requests the TLS channel ID, it gets it for a site that
1041 // can connect to it, but only if the page also asks to send it.
1042 EXPECT_EQ(std::string(),
1043 GetTlsChannelIdFromPortConnect(chromium_connectable.get(), false));
1044 EXPECT_EQ(std::string(),
1045 GetTlsChannelIdFromSendMessage(chromium_connectable.get(), false));
1047 // If the page does ask to send the TLS channel ID, it's sent and non-empty.
1048 std::string tls_channel_id_from_port_connect =
1049 GetTlsChannelIdFromPortConnect(chromium_connectable.get(), true);
1050 EXPECT_NE(0u, tls_channel_id_from_port_connect.size());
1052 // The same value is received by both connect and sendMessage.
1053 std::string tls_channel_id_from_send_message =
1054 GetTlsChannelIdFromSendMessage(chromium_connectable.get(), true);
1055 EXPECT_EQ(tls_channel_id_from_port_connect, tls_channel_id_from_send_message);
1057 // And since a TLS channel ID exists for the domain, the value received is
1058 // parseable as a JWK. (In particular, it has the same value we created by
1059 // converting the public key to JWK with net::ConvertSpkiFromDerToJwk.)
1060 std::string tls_channel_id(tls_channel_id_from_port_connect);
1061 EXPECT_EQ(expected_tls_channel_id_value, tls_channel_id);
1063 // The TLS channel ID shouldn't change from one connection to the next...
1064 std::string tls_channel_id2 =
1065 GetTlsChannelIdFromPortConnect(chromium_connectable.get(), true);
1066 EXPECT_EQ(tls_channel_id, tls_channel_id2);
1067 tls_channel_id2 =
1068 GetTlsChannelIdFromSendMessage(chromium_connectable.get(), true);
1069 EXPECT_EQ(tls_channel_id, tls_channel_id2);
1071 // nor should it change when navigating away, revisiting the page and
1072 // requesting it again.
1073 ui_test_utils::NavigateToURL(browser(), google_com_url());
1074 ui_test_utils::NavigateToURL(browser(), chromium_org_url());
1075 tls_channel_id2 =
1076 GetTlsChannelIdFromPortConnect(chromium_connectable.get(), true);
1077 EXPECT_EQ(tls_channel_id, tls_channel_id2);
1078 tls_channel_id2 =
1079 GetTlsChannelIdFromSendMessage(chromium_connectable.get(), true);
1080 EXPECT_EQ(tls_channel_id, tls_channel_id2);
1083 // Tests a web connectable extension that receives TLS channel id, but
1084 // immediately closes its background page upon receipt of a message.
1085 // Same flakiness seen in http://crbug.com/297866
1086 IN_PROC_BROWSER_TEST_F(ExternallyConnectableMessagingWithTlsChannelIdTest,
1087 DISABLED_WebConnectableWithNonEmptyTlsChannelIdAndClosedBackgroundPage) {
1088 InitializeTestServer();
1089 std::string expected_tls_channel_id_value = CreateTlsChannelId();
1091 scoped_refptr<const Extension> chromium_connectable =
1092 LoadChromiumConnectableExtensionWithTlsChannelId();
1094 ui_test_utils::NavigateToURL(browser(), chromium_org_url());
1095 // If the page does ask for it, it isn't empty, even if the background page
1096 // closes upon receipt of the connect.
1097 std::string tls_channel_id = GetTlsChannelIdFromPortConnect(
1098 chromium_connectable.get(), true, close_background_message());
1099 EXPECT_EQ(expected_tls_channel_id_value, tls_channel_id);
1100 // A subsequent connect will still succeed, even if the background page was
1101 // previously closed.
1102 tls_channel_id =
1103 GetTlsChannelIdFromPortConnect(chromium_connectable.get(), true);
1104 // And the expected value is still retrieved.
1105 EXPECT_EQ(expected_tls_channel_id_value, tls_channel_id);
1108 IN_PROC_BROWSER_TEST_F(ExtensionApiTest, MessagingUserGesture) {
1109 const char kManifest[] = "{"
1110 " \"name\": \"user_gesture\","
1111 " \"version\": \"1.0\","
1112 " \"background\": {"
1113 " \"scripts\": [\"background.js\"]"
1114 " },"
1115 " \"manifest_version\": 2"
1116 "}";
1118 TestExtensionDir receiver_dir;
1119 receiver_dir.WriteManifest(kManifest);
1120 receiver_dir.WriteFile(FILE_PATH_LITERAL("background.js"),
1121 "chrome.runtime.onMessageExternal.addListener(\n"
1122 " function(msg, sender, reply) {\n"
1123 " reply({result:chrome.test.isProcessingUserGesture()});\n"
1124 " });");
1125 const Extension* receiver = LoadExtension(receiver_dir.unpacked_path());
1126 ASSERT_TRUE(receiver);
1128 TestExtensionDir sender_dir;
1129 sender_dir.WriteManifest(kManifest);
1130 sender_dir.WriteFile(FILE_PATH_LITERAL("background.js"), "");
1131 const Extension* sender = LoadExtension(sender_dir.unpacked_path());
1132 ASSERT_TRUE(sender);
1134 EXPECT_EQ("false",
1135 ExecuteScriptInBackgroundPage(sender->id(),
1136 base::StringPrintf(
1137 "chrome.test.runWithoutUserGesture(function() {\n"
1138 " chrome.runtime.sendMessage('%s', {}, function(response) {\n"
1139 " window.domAutomationController.send('' + response.result);\n"
1140 " });\n"
1141 "});", receiver->id().c_str())));
1143 EXPECT_EQ("true",
1144 ExecuteScriptInBackgroundPage(sender->id(),
1145 base::StringPrintf(
1146 "chrome.test.runWithUserGesture(function() {\n"
1147 " chrome.runtime.sendMessage('%s', {}, function(response) {\n"
1148 " window.domAutomationController.send('' + response.result);\n"
1149 " });\n"
1150 "});", receiver->id().c_str())));
1153 // Tests that a hosted app on a connectable site doesn't interfere with the
1154 // connectability of that site.
1155 IN_PROC_BROWSER_TEST_F(ExternallyConnectableMessagingTest, HostedAppOnWebsite) {
1156 InitializeTestServer();
1158 scoped_refptr<const Extension> app = LoadChromiumHostedApp();
1160 // The presence of the hosted app shouldn't give the ability to send messages.
1161 ui_test_utils::NavigateToURL(browser(), chromium_org_url());
1162 EXPECT_EQ(NAMESPACE_NOT_DEFINED,
1163 CanConnectAndSendMessagesToMainFrame(app.get()));
1164 EXPECT_FALSE(AreAnyNonWebApisDefinedForMainFrame());
1166 // Once a connectable extension is installed, it should.
1167 scoped_refptr<const Extension> extension = LoadChromiumConnectableExtension();
1168 EXPECT_EQ(OK, CanConnectAndSendMessagesToMainFrame(extension.get()));
1169 EXPECT_FALSE(AreAnyNonWebApisDefinedForMainFrame());
1172 // Tests that an invalid extension ID specified in a hosted app does not crash
1173 // the hosted app's renderer.
1175 // This is a regression test for http://crbug.com/326250#c12.
1176 IN_PROC_BROWSER_TEST_F(ExternallyConnectableMessagingTest,
1177 InvalidExtensionIDFromHostedApp) {
1178 InitializeTestServer();
1180 // The presence of the chromium hosted app triggers this bug. The chromium
1181 // connectable extension needs to be installed to set up the runtime bindings.
1182 LoadChromiumHostedApp();
1183 LoadChromiumConnectableExtension();
1185 scoped_refptr<const Extension> invalid =
1186 ExtensionBuilder()
1187 // A bit scary that this works...
1188 .SetID("invalid")
1189 .SetManifest(DictionaryBuilder()
1190 .Set("name", "Fake extension")
1191 .Set("version", "1")
1192 .Set("manifest_version", 2))
1193 .Build();
1195 ui_test_utils::NavigateToURL(browser(), chromium_org_url());
1196 EXPECT_EQ(COULD_NOT_ESTABLISH_CONNECTION_ERROR,
1197 CanConnectAndSendMessagesToMainFrame(invalid.get()));
1200 #endif // !defined(OS_WIN) - http://crbug.com/350517.
1202 } // namespace
1204 }; // namespace extensions