Add ICU message format support
[chromium-blink-merge.git] / chrome / browser / extensions / extension_messages_apitest.cc
blobf62159b374054e378d7e2d23704e4712a96085b9
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 = OpenURLOffTheRecord(
690 profile()->GetOffTheRecordProfile(), chromium_org_url());
691 content::RenderFrameHost* incognito_frame = incognito_browser->
692 tab_strip_model()->GetActiveWebContents()->GetMainFrame();
695 IncognitoConnectability::ScopedAlertTracker alert_tracker(
696 IncognitoConnectability::ScopedAlertTracker::ALWAYS_DENY);
698 // No connection because incognito-enabled hasn't been set for the app, and
699 // the user denied our interactive request.
700 EXPECT_EQ(
701 COULD_NOT_ESTABLISH_CONNECTION_ERROR,
702 CanConnectAndSendMessagesToFrame(incognito_frame, app.get(), NULL));
703 EXPECT_EQ(1, alert_tracker.GetAndResetAlertCount());
705 // Try again. User has already denied so alert not shown.
706 EXPECT_EQ(
707 COULD_NOT_ESTABLISH_CONNECTION_ERROR,
708 CanConnectAndSendMessagesToFrame(incognito_frame, app.get(), NULL));
709 EXPECT_EQ(0, alert_tracker.GetAndResetAlertCount());
712 // It's not possible to allow an app in incognito.
713 ExtensionPrefs::Get(profile())->SetIsIncognitoEnabled(app->id(), true);
714 EXPECT_EQ(COULD_NOT_ESTABLISH_CONNECTION_ERROR,
715 CanConnectAndSendMessagesToFrame(incognito_frame, app.get(), NULL));
718 IN_PROC_BROWSER_TEST_F(ExternallyConnectableMessagingTest,
719 FromIncognitoDenyExtension) {
720 InitializeTestServer();
722 scoped_refptr<const Extension> extension = LoadChromiumConnectableExtension();
724 Browser* incognito_browser = OpenURLOffTheRecord(
725 profile()->GetOffTheRecordProfile(), chromium_org_url());
726 content::RenderFrameHost* incognito_frame =
727 incognito_browser->tab_strip_model()
728 ->GetActiveWebContents()
729 ->GetMainFrame();
732 IncognitoConnectability::ScopedAlertTracker alert_tracker(
733 IncognitoConnectability::ScopedAlertTracker::ALWAYS_DENY);
735 // The alert doesn't show for extensions.
736 EXPECT_EQ(COULD_NOT_ESTABLISH_CONNECTION_ERROR,
737 CanConnectAndSendMessagesToFrame(
738 incognito_frame, extension.get(), NULL));
739 EXPECT_EQ(0, alert_tracker.GetAndResetAlertCount());
742 // Allowing the extension in incognito mode will bypass the deny.
743 ExtensionPrefs::Get(profile())->SetIsIncognitoEnabled(extension->id(), true);
744 EXPECT_EQ(
746 CanConnectAndSendMessagesToFrame(incognito_frame, extension.get(), NULL));
749 // Tests connection from incognito tabs when the extension doesn't have an event
750 // handler for the connection event.
751 IN_PROC_BROWSER_TEST_F(ExternallyConnectableMessagingTest,
752 FromIncognitoNoEventHandlerInApp) {
753 InitializeTestServer();
755 scoped_refptr<const Extension> app = LoadChromiumConnectableApp(false);
756 ASSERT_TRUE(app->is_platform_app());
758 Browser* incognito_browser = OpenURLOffTheRecord(
759 profile()->GetOffTheRecordProfile(), chromium_org_url());
760 content::RenderFrameHost* incognito_frame =
761 incognito_browser->tab_strip_model()
762 ->GetActiveWebContents()
763 ->GetMainFrame();
766 IncognitoConnectability::ScopedAlertTracker alert_tracker(
767 IncognitoConnectability::ScopedAlertTracker::ALWAYS_ALLOW);
769 // No connection because incognito-enabled hasn't been set for the app, and
770 // the app hasn't installed event handlers.
771 EXPECT_EQ(
772 COULD_NOT_ESTABLISH_CONNECTION_ERROR,
773 CanConnectAndSendMessagesToFrame(incognito_frame, app.get(), NULL));
774 // No dialog should have been shown.
775 EXPECT_EQ(0, alert_tracker.GetAndResetAlertCount());
779 // Tests connection from incognito tabs when the user accepts the connection
780 // request. Spanning mode only. Separate tests for apps and extensions.
782 // TODO(kalman): see comment above about split mode.
783 IN_PROC_BROWSER_TEST_F(ExternallyConnectableMessagingTest,
784 FromIncognitoAllowApp) {
785 InitializeTestServer();
787 scoped_refptr<const Extension> app = LoadChromiumConnectableApp();
788 ASSERT_TRUE(app->is_platform_app());
790 Browser* incognito_browser = OpenURLOffTheRecord(
791 profile()->GetOffTheRecordProfile(), chromium_org_url());
792 content::RenderFrameHost* incognito_frame = incognito_browser->
793 tab_strip_model()->GetActiveWebContents()->GetMainFrame();
796 IncognitoConnectability::ScopedAlertTracker alert_tracker(
797 IncognitoConnectability::ScopedAlertTracker::ALWAYS_ALLOW);
799 // Connection allowed even with incognito disabled, because the user
800 // accepted the interactive request.
801 EXPECT_EQ(
802 OK, CanConnectAndSendMessagesToFrame(incognito_frame, app.get(), NULL));
803 EXPECT_EQ(1, alert_tracker.GetAndResetAlertCount());
805 // Try again. User has already allowed.
806 EXPECT_EQ(
807 OK, CanConnectAndSendMessagesToFrame(incognito_frame, app.get(), NULL));
808 EXPECT_EQ(0, alert_tracker.GetAndResetAlertCount());
811 // Apps can't be allowed in incognito mode, but it's moot because it's
812 // already allowed.
813 ExtensionPrefs::Get(profile())->SetIsIncognitoEnabled(app->id(), true);
814 EXPECT_EQ(OK,
815 CanConnectAndSendMessagesToFrame(incognito_frame, app.get(), NULL));
818 // Tests connection from incognito tabs when there are multiple tabs open to the
819 // same origin. The user should only need to accept the connection request once.
820 IN_PROC_BROWSER_TEST_F(ExternallyConnectableMessagingTest,
821 FromIncognitoPromptApp) {
822 InitializeTestServer();
824 scoped_refptr<const Extension> app = LoadChromiumConnectableApp();
825 ASSERT_TRUE(app->is_platform_app());
827 // Open an incognito browser with two tabs displaying "chromium.org".
828 Browser* incognito_browser = OpenURLOffTheRecord(
829 profile()->GetOffTheRecordProfile(), chromium_org_url());
830 content::RenderFrameHost* incognito_frame1 =
831 incognito_browser->tab_strip_model()
832 ->GetActiveWebContents()
833 ->GetMainFrame();
834 InfoBarService* infobar_service1 = InfoBarService::FromWebContents(
835 incognito_browser->tab_strip_model()->GetActiveWebContents());
837 CHECK(OpenURLOffTheRecord(profile()->GetOffTheRecordProfile(),
838 chromium_org_url()) == incognito_browser);
839 content::RenderFrameHost* incognito_frame2 =
840 incognito_browser->tab_strip_model()
841 ->GetActiveWebContents()
842 ->GetMainFrame();
843 InfoBarService* infobar_service2 = InfoBarService::FromWebContents(
844 incognito_browser->tab_strip_model()->GetActiveWebContents());
845 EXPECT_EQ(2, incognito_browser->tab_strip_model()->count());
846 EXPECT_NE(incognito_frame1, incognito_frame2);
848 // Trigger a infobars in both tabs by trying to send messages.
849 std::string script =
850 base::StringPrintf("assertions.trySendMessage('%s')", app->id().c_str());
851 CHECK(content::ExecuteScript(incognito_frame1, script));
852 CHECK(content::ExecuteScript(incognito_frame2, script));
853 EXPECT_EQ(1U, infobar_service1->infobar_count());
854 EXPECT_EQ(1U, infobar_service2->infobar_count());
856 // Navigating away will dismiss the infobar on the active tab only.
857 ui_test_utils::NavigateToURL(incognito_browser, google_com_url());
858 EXPECT_EQ(1U, infobar_service1->infobar_count());
859 EXPECT_EQ(0U, infobar_service2->infobar_count());
861 // Navigate back and accept the infobar this time. Both should be dismissed.
863 IncognitoConnectability::ScopedAlertTracker alert_tracker(
864 IncognitoConnectability::ScopedAlertTracker::ALWAYS_ALLOW);
866 ui_test_utils::NavigateToURL(incognito_browser, chromium_org_url());
867 incognito_frame2 = incognito_browser->tab_strip_model()
868 ->GetActiveWebContents()
869 ->GetMainFrame();
870 EXPECT_NE(incognito_frame1, incognito_frame2);
872 EXPECT_EQ(1U, infobar_service1->infobar_count());
873 EXPECT_EQ(OK, CanConnectAndSendMessagesToFrame(incognito_frame2, app.get(),
874 NULL));
875 EXPECT_EQ(1, alert_tracker.GetAndResetAlertCount());
876 EXPECT_EQ(0U, infobar_service1->infobar_count());
880 IN_PROC_BROWSER_TEST_F(ExternallyConnectableMessagingTest, IllegalArguments) {
881 // Tests that malformed arguments to connect() don't crash.
882 // Regression test for crbug.com/472700.
883 InitializeTestServer();
884 LoadChromiumConnectableExtension();
885 ui_test_utils::NavigateToURL(browser(), chromium_org_url());
886 bool result;
887 CHECK(content::ExecuteScriptAndExtractBool(
888 browser()->tab_strip_model()->GetActiveWebContents(),
889 "assertions.tryIllegalArguments()", &result));
890 EXPECT_TRUE(result);
893 IN_PROC_BROWSER_TEST_F(ExternallyConnectableMessagingTest,
894 FromIncognitoAllowExtension) {
895 InitializeTestServer();
897 scoped_refptr<const Extension> extension = LoadChromiumConnectableExtension();
899 Browser* incognito_browser = OpenURLOffTheRecord(
900 profile()->GetOffTheRecordProfile(), chromium_org_url());
901 content::RenderFrameHost* incognito_frame =
902 incognito_browser->tab_strip_model()
903 ->GetActiveWebContents()
904 ->GetMainFrame();
907 IncognitoConnectability::ScopedAlertTracker alert_tracker(
908 IncognitoConnectability::ScopedAlertTracker::ALWAYS_ALLOW);
910 // No alert is shown.
911 EXPECT_EQ(COULD_NOT_ESTABLISH_CONNECTION_ERROR,
912 CanConnectAndSendMessagesToFrame(
913 incognito_frame, extension.get(), NULL));
914 EXPECT_EQ(0, alert_tracker.GetAndResetAlertCount());
917 // Allowing the extension in incognito mode is what allows connections.
918 ExtensionPrefs::Get(profile())->SetIsIncognitoEnabled(extension->id(), true);
919 EXPECT_EQ(
921 CanConnectAndSendMessagesToFrame(incognito_frame, extension.get(), NULL));
924 // Tests a connection from an iframe within a tab which doesn't have
925 // permission. Iframe should work.
926 IN_PROC_BROWSER_TEST_F(ExternallyConnectableMessagingTest,
927 FromIframeWithPermission) {
928 InitializeTestServer();
930 scoped_refptr<const Extension> extension = LoadChromiumConnectableExtension();
932 ui_test_utils::NavigateToURL(browser(), google_com_url());
933 EXPECT_EQ(NAMESPACE_NOT_DEFINED,
934 CanConnectAndSendMessagesToMainFrame(extension.get()));
935 EXPECT_FALSE(AreAnyNonWebApisDefinedForMainFrame());
937 ASSERT_TRUE(AppendIframe(chromium_org_url()));
939 EXPECT_EQ(OK, CanConnectAndSendMessagesToIFrame(extension.get()));
940 EXPECT_FALSE(AreAnyNonWebApisDefinedForIFrame());
943 // Tests connection from an iframe without permission within a tab that does.
944 // Iframe shouldn't work.
945 IN_PROC_BROWSER_TEST_F(ExternallyConnectableMessagingTest,
946 FromIframeWithoutPermission) {
947 InitializeTestServer();
949 scoped_refptr<const Extension> extension = LoadChromiumConnectableExtension();
951 ui_test_utils::NavigateToURL(browser(), chromium_org_url());
952 EXPECT_EQ(OK, CanConnectAndSendMessagesToMainFrame(extension.get()));
953 EXPECT_FALSE(AreAnyNonWebApisDefinedForMainFrame());
955 ASSERT_TRUE(AppendIframe(google_com_url()));
957 EXPECT_EQ(NAMESPACE_NOT_DEFINED,
958 CanConnectAndSendMessagesToIFrame(extension.get()));
959 EXPECT_FALSE(AreAnyNonWebApisDefinedForIFrame());
962 // Tests externally_connectable between a web page and an extension with a
963 // TLS channel ID created for the origin.
964 class ExternallyConnectableMessagingWithTlsChannelIdTest :
965 public ExternallyConnectableMessagingTest {
966 public:
967 ExternallyConnectableMessagingWithTlsChannelIdTest()
968 : tls_channel_id_created_(false, false) {
971 std::string CreateTlsChannelId() {
972 scoped_refptr<net::URLRequestContextGetter> request_context_getter(
973 profile()->GetRequestContext());
974 scoped_ptr<crypto::ECPrivateKey> channel_id_key;
975 net::ChannelIDService::Request request;
976 content::BrowserThread::PostTask(
977 content::BrowserThread::IO, FROM_HERE,
978 base::Bind(&ExternallyConnectableMessagingWithTlsChannelIdTest::
979 CreateDomainBoundCertOnIOThread,
980 base::Unretained(this), base::Unretained(&channel_id_key),
981 base::Unretained(&request), request_context_getter));
982 tls_channel_id_created_.Wait();
983 // Create the expected value.
984 std::vector<uint8> spki_vector;
985 if (!channel_id_key->ExportPublicKey(&spki_vector))
986 return std::string();
987 base::StringPiece spki(reinterpret_cast<char*>(
988 vector_as_array(&spki_vector)), spki_vector.size());
989 base::DictionaryValue jwk_value;
990 net::JwkSerializer::ConvertSpkiFromDerToJwk(spki, &jwk_value);
991 std::string tls_channel_id_value;
992 base::JSONWriter::Write(jwk_value, &tls_channel_id_value);
993 return tls_channel_id_value;
996 private:
997 void CreateDomainBoundCertOnIOThread(
998 scoped_ptr<crypto::ECPrivateKey>* channel_id_key,
999 net::ChannelIDService::Request* request,
1000 scoped_refptr<net::URLRequestContextGetter> request_context_getter) {
1001 DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
1002 net::ChannelIDService* channel_id_service =
1003 request_context_getter->GetURLRequestContext()->
1004 channel_id_service();
1005 int status = channel_id_service->GetOrCreateChannelID(
1006 chromium_org_url().host(), channel_id_key,
1007 base::Bind(&ExternallyConnectableMessagingWithTlsChannelIdTest::
1008 GotDomainBoundCert,
1009 base::Unretained(this)),
1010 request);
1011 if (status == net::ERR_IO_PENDING)
1012 return;
1013 GotDomainBoundCert(status);
1016 void GotDomainBoundCert(int status) {
1017 ASSERT_TRUE(status == net::OK);
1018 tls_channel_id_created_.Signal();
1021 base::WaitableEvent tls_channel_id_created_;
1024 // Tests a web connectable extension that receives TLS channel id on a site
1025 // that can connect to it, with a TLS channel ID having been generated.
1026 IN_PROC_BROWSER_TEST_F(ExternallyConnectableMessagingWithTlsChannelIdTest,
1027 WebConnectableWithNonEmptyTlsChannelId) {
1028 InitializeTestServer();
1029 std::string expected_tls_channel_id_value = CreateTlsChannelId();
1031 scoped_refptr<const Extension> chromium_connectable =
1032 LoadChromiumConnectableExtensionWithTlsChannelId();
1033 ASSERT_TRUE(chromium_connectable.get());
1035 ui_test_utils::NavigateToURL(browser(), chromium_org_url());
1037 // Since the extension requests the TLS channel ID, it gets it for a site that
1038 // can connect to it, but only if the page also asks to send it.
1039 EXPECT_EQ(std::string(),
1040 GetTlsChannelIdFromPortConnect(chromium_connectable.get(), false));
1041 EXPECT_EQ(std::string(),
1042 GetTlsChannelIdFromSendMessage(chromium_connectable.get(), false));
1044 // If the page does ask to send the TLS channel ID, it's sent and non-empty.
1045 std::string tls_channel_id_from_port_connect =
1046 GetTlsChannelIdFromPortConnect(chromium_connectable.get(), true);
1047 EXPECT_NE(0u, tls_channel_id_from_port_connect.size());
1049 // The same value is received by both connect and sendMessage.
1050 std::string tls_channel_id_from_send_message =
1051 GetTlsChannelIdFromSendMessage(chromium_connectable.get(), true);
1052 EXPECT_EQ(tls_channel_id_from_port_connect, tls_channel_id_from_send_message);
1054 // And since a TLS channel ID exists for the domain, the value received is
1055 // parseable as a JWK. (In particular, it has the same value we created by
1056 // converting the public key to JWK with net::ConvertSpkiFromDerToJwk.)
1057 std::string tls_channel_id(tls_channel_id_from_port_connect);
1058 EXPECT_EQ(expected_tls_channel_id_value, tls_channel_id);
1060 // The TLS channel ID shouldn't change from one connection to the next...
1061 std::string tls_channel_id2 =
1062 GetTlsChannelIdFromPortConnect(chromium_connectable.get(), true);
1063 EXPECT_EQ(tls_channel_id, tls_channel_id2);
1064 tls_channel_id2 =
1065 GetTlsChannelIdFromSendMessage(chromium_connectable.get(), true);
1066 EXPECT_EQ(tls_channel_id, tls_channel_id2);
1068 // nor should it change when navigating away, revisiting the page and
1069 // requesting it again.
1070 ui_test_utils::NavigateToURL(browser(), google_com_url());
1071 ui_test_utils::NavigateToURL(browser(), chromium_org_url());
1072 tls_channel_id2 =
1073 GetTlsChannelIdFromPortConnect(chromium_connectable.get(), true);
1074 EXPECT_EQ(tls_channel_id, tls_channel_id2);
1075 tls_channel_id2 =
1076 GetTlsChannelIdFromSendMessage(chromium_connectable.get(), true);
1077 EXPECT_EQ(tls_channel_id, tls_channel_id2);
1080 // Tests a web connectable extension that receives TLS channel id, but
1081 // immediately closes its background page upon receipt of a message.
1082 // Same flakiness seen in http://crbug.com/297866
1083 IN_PROC_BROWSER_TEST_F(ExternallyConnectableMessagingWithTlsChannelIdTest,
1084 DISABLED_WebConnectableWithNonEmptyTlsChannelIdAndClosedBackgroundPage) {
1085 InitializeTestServer();
1086 std::string expected_tls_channel_id_value = CreateTlsChannelId();
1088 scoped_refptr<const Extension> chromium_connectable =
1089 LoadChromiumConnectableExtensionWithTlsChannelId();
1091 ui_test_utils::NavigateToURL(browser(), chromium_org_url());
1092 // If the page does ask for it, it isn't empty, even if the background page
1093 // closes upon receipt of the connect.
1094 std::string tls_channel_id = GetTlsChannelIdFromPortConnect(
1095 chromium_connectable.get(), true, close_background_message());
1096 EXPECT_EQ(expected_tls_channel_id_value, tls_channel_id);
1097 // A subsequent connect will still succeed, even if the background page was
1098 // previously closed.
1099 tls_channel_id =
1100 GetTlsChannelIdFromPortConnect(chromium_connectable.get(), true);
1101 // And the expected value is still retrieved.
1102 EXPECT_EQ(expected_tls_channel_id_value, tls_channel_id);
1105 IN_PROC_BROWSER_TEST_F(ExtensionApiTest, MessagingUserGesture) {
1106 const char kManifest[] = "{"
1107 " \"name\": \"user_gesture\","
1108 " \"version\": \"1.0\","
1109 " \"background\": {"
1110 " \"scripts\": [\"background.js\"]"
1111 " },"
1112 " \"manifest_version\": 2"
1113 "}";
1115 TestExtensionDir receiver_dir;
1116 receiver_dir.WriteManifest(kManifest);
1117 receiver_dir.WriteFile(FILE_PATH_LITERAL("background.js"),
1118 "chrome.runtime.onMessageExternal.addListener(\n"
1119 " function(msg, sender, reply) {\n"
1120 " reply({result:chrome.test.isProcessingUserGesture()});\n"
1121 " });");
1122 const Extension* receiver = LoadExtension(receiver_dir.unpacked_path());
1123 ASSERT_TRUE(receiver);
1125 TestExtensionDir sender_dir;
1126 sender_dir.WriteManifest(kManifest);
1127 sender_dir.WriteFile(FILE_PATH_LITERAL("background.js"), "");
1128 const Extension* sender = LoadExtension(sender_dir.unpacked_path());
1129 ASSERT_TRUE(sender);
1131 EXPECT_EQ("false",
1132 ExecuteScriptInBackgroundPage(sender->id(),
1133 base::StringPrintf(
1134 "chrome.test.runWithoutUserGesture(function() {\n"
1135 " chrome.runtime.sendMessage('%s', {}, function(response) {\n"
1136 " window.domAutomationController.send('' + response.result);\n"
1137 " });\n"
1138 "});", receiver->id().c_str())));
1140 EXPECT_EQ("true",
1141 ExecuteScriptInBackgroundPage(sender->id(),
1142 base::StringPrintf(
1143 "chrome.test.runWithUserGesture(function() {\n"
1144 " chrome.runtime.sendMessage('%s', {}, function(response) {\n"
1145 " window.domAutomationController.send('' + response.result);\n"
1146 " });\n"
1147 "});", receiver->id().c_str())));
1150 // Tests that a hosted app on a connectable site doesn't interfere with the
1151 // connectability of that site.
1152 IN_PROC_BROWSER_TEST_F(ExternallyConnectableMessagingTest, HostedAppOnWebsite) {
1153 InitializeTestServer();
1155 scoped_refptr<const Extension> app = LoadChromiumHostedApp();
1157 // The presence of the hosted app shouldn't give the ability to send messages.
1158 ui_test_utils::NavigateToURL(browser(), chromium_org_url());
1159 EXPECT_EQ(NAMESPACE_NOT_DEFINED,
1160 CanConnectAndSendMessagesToMainFrame(app.get()));
1161 EXPECT_FALSE(AreAnyNonWebApisDefinedForMainFrame());
1163 // Once a connectable extension is installed, it should.
1164 scoped_refptr<const Extension> extension = LoadChromiumConnectableExtension();
1165 EXPECT_EQ(OK, CanConnectAndSendMessagesToMainFrame(extension.get()));
1166 EXPECT_FALSE(AreAnyNonWebApisDefinedForMainFrame());
1169 // Tests that an invalid extension ID specified in a hosted app does not crash
1170 // the hosted app's renderer.
1172 // This is a regression test for http://crbug.com/326250#c12.
1173 IN_PROC_BROWSER_TEST_F(ExternallyConnectableMessagingTest,
1174 InvalidExtensionIDFromHostedApp) {
1175 InitializeTestServer();
1177 // The presence of the chromium hosted app triggers this bug. The chromium
1178 // connectable extension needs to be installed to set up the runtime bindings.
1179 LoadChromiumHostedApp();
1180 LoadChromiumConnectableExtension();
1182 scoped_refptr<const Extension> invalid =
1183 ExtensionBuilder()
1184 // A bit scary that this works...
1185 .SetID("invalid")
1186 .SetManifest(DictionaryBuilder()
1187 .Set("name", "Fake extension")
1188 .Set("version", "1")
1189 .Set("manifest_version", 2))
1190 .Build();
1192 ui_test_utils::NavigateToURL(browser(), chromium_org_url());
1193 EXPECT_EQ(COULD_NOT_ESTABLISH_CONNECTION_ERROR,
1194 CanConnectAndSendMessagesToMainFrame(invalid.get()));
1197 #endif // !defined(OS_WIN) - http://crbug.com/350517.
1199 } // namespace
1201 }; // namespace extensions