Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(43)

Side by Side Diff: chrome/browser/extensions/api/messaging/message_service.cc

Issue 591463003: Remote Assistance on Chrome OS Part III - NativeMessageHost (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@native_messaging
Patch Set: Fix NativeMessagingBasic test on Release builds Created 6 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "chrome/browser/extensions/api/messaging/message_service.h" 5 #include "chrome/browser/extensions/api/messaging/message_service.h"
6 6
7 #include "base/atomic_sequence_num.h" 7 #include "base/atomic_sequence_num.h"
8 #include "base/bind.h" 8 #include "base/bind.h"
9 #include "base/callback.h" 9 #include "base/callback.h"
10 #include "base/json/json_writer.h" 10 #include "base/json/json_writer.h"
11 #include "base/lazy_instance.h" 11 #include "base/lazy_instance.h"
12 #include "base/metrics/histogram.h" 12 #include "base/metrics/histogram.h"
13 #include "base/prefs/pref_service.h"
13 #include "base/stl_util.h" 14 #include "base/stl_util.h"
14 #include "base/values.h" 15 #include "base/values.h"
15 #include "chrome/browser/chrome_notification_types.h" 16 #include "chrome/browser/chrome_notification_types.h"
16 #include "chrome/browser/extensions/api/messaging/extension_message_port.h" 17 #include "chrome/browser/extensions/api/messaging/extension_message_port.h"
17 #include "chrome/browser/extensions/api/messaging/incognito_connectability.h" 18 #include "chrome/browser/extensions/api/messaging/incognito_connectability.h"
18 #include "chrome/browser/extensions/api/messaging/native_message_port.h" 19 #include "chrome/browser/extensions/api/messaging/native_message_port.h"
19 #include "chrome/browser/extensions/api/tabs/tabs_constants.h" 20 #include "chrome/browser/extensions/api/tabs/tabs_constants.h"
20 #include "chrome/browser/extensions/extension_service.h" 21 #include "chrome/browser/extensions/extension_service.h"
21 #include "chrome/browser/extensions/extension_tab_util.h" 22 #include "chrome/browser/extensions/extension_tab_util.h"
22 #include "chrome/browser/extensions/extension_util.h" 23 #include "chrome/browser/extensions/extension_util.h"
23 #include "chrome/browser/profiles/profile.h" 24 #include "chrome/browser/profiles/profile.h"
24 #include "chrome/browser/tab_contents/tab_util.h" 25 #include "chrome/browser/tab_contents/tab_util.h"
25 #include "content/public/browser/notification_service.h" 26 #include "content/public/browser/notification_service.h"
26 #include "content/public/browser/render_process_host.h" 27 #include "content/public/browser/render_process_host.h"
27 #include "content/public/browser/render_view_host.h" 28 #include "content/public/browser/render_view_host.h"
28 #include "content/public/browser/render_widget_host.h" 29 #include "content/public/browser/render_widget_host.h"
29 #include "content/public/browser/render_widget_host_view.h" 30 #include "content/public/browser/render_widget_host_view.h"
30 #include "content/public/browser/site_instance.h" 31 #include "content/public/browser/site_instance.h"
31 #include "content/public/browser/web_contents.h" 32 #include "content/public/browser/web_contents.h"
32 #include "extensions/browser/extension_host.h" 33 #include "extensions/browser/extension_host.h"
33 #include "extensions/browser/extension_system.h" 34 #include "extensions/browser/extension_system.h"
34 #include "extensions/browser/extensions_browser_client.h" 35 #include "extensions/browser/extensions_browser_client.h"
35 #include "extensions/browser/lazy_background_task_queue.h" 36 #include "extensions/browser/lazy_background_task_queue.h"
37 #include "extensions/browser/pref_names.h"
36 #include "extensions/browser/process_manager.h" 38 #include "extensions/browser/process_manager.h"
37 #include "extensions/common/extension.h" 39 #include "extensions/common/extension.h"
38 #include "extensions/common/manifest_constants.h" 40 #include "extensions/common/manifest_constants.h"
39 #include "extensions/common/manifest_handlers/background_info.h" 41 #include "extensions/common/manifest_handlers/background_info.h"
40 #include "extensions/common/manifest_handlers/externally_connectable.h" 42 #include "extensions/common/manifest_handlers/externally_connectable.h"
41 #include "extensions/common/manifest_handlers/incognito_info.h" 43 #include "extensions/common/manifest_handlers/incognito_info.h"
42 #include "extensions/common/permissions/permissions_data.h" 44 #include "extensions/common/permissions/permissions_data.h"
43 #include "net/base/completion_callback.h" 45 #include "net/base/completion_callback.h"
44 #include "url/gurl.h" 46 #include "url/gurl.h"
45 47
46 using content::BrowserContext; 48 using content::BrowserContext;
47 using content::SiteInstance; 49 using content::SiteInstance;
48 using content::WebContents; 50 using content::WebContents;
49 51
50 // Since we have 2 ports for every channel, we just index channels by half the 52 // Since we have 2 ports for every channel, we just index channels by half the
51 // port ID. 53 // port ID.
52 #define GET_CHANNEL_ID(port_id) ((port_id) / 2) 54 #define GET_CHANNEL_ID(port_id) ((port_id) / 2)
53 #define GET_CHANNEL_OPENER_ID(channel_id) ((channel_id) * 2) 55 #define GET_CHANNEL_OPENER_ID(channel_id) ((channel_id) * 2)
54 #define GET_CHANNEL_RECEIVERS_ID(channel_id) ((channel_id) * 2 + 1) 56 #define GET_CHANNEL_RECEIVERS_ID(channel_id) ((channel_id) * 2 + 1)
55 57
56 // Port1 is always even, port2 is always odd. 58 // Port1 is always even, port2 is always odd.
57 #define IS_OPENER_PORT_ID(port_id) (((port_id) & 1) == 0) 59 #define IS_OPENER_PORT_ID(port_id) (((port_id) & 1) == 0)
58 60
59 // Change even to odd and vice versa, to get the other side of a given channel. 61 // Change even to odd and vice versa, to get the other side of a given channel.
60 #define GET_OPPOSITE_PORT_ID(source_port_id) ((source_port_id) ^ 1) 62 #define GET_OPPOSITE_PORT_ID(source_port_id) ((source_port_id) ^ 1)
61 63
62 namespace extensions { 64 namespace extensions {
63 65
66 MessageService::PolicyPermission MessageService::IsNativeMessagingHostAllowed(
67 const PrefService* pref_service,
68 const std::string& native_host_name) {
69 PolicyPermission allow_result = ALLOW_ALL;
70 if (pref_service->IsManagedPreference(
71 pref_names::kNativeMessagingUserLevelHosts)) {
72 if (!pref_service->GetBoolean(pref_names::kNativeMessagingUserLevelHosts))
73 allow_result = ALLOW_SYSTEM_ONLY;
74 }
75
76 // All native messaging hosts are allowed if there is no blacklist.
77 if (!pref_service->IsManagedPreference(pref_names::kNativeMessagingBlacklist))
78 return allow_result;
79 const base::ListValue* blacklist =
80 pref_service->GetList(pref_names::kNativeMessagingBlacklist);
81 if (!blacklist)
82 return allow_result;
83
84 // Check if the name or the wildcard is in the blacklist.
85 base::StringValue name_value(native_host_name);
86 base::StringValue wildcard_value("*");
87 if (blacklist->Find(name_value) == blacklist->end() &&
88 blacklist->Find(wildcard_value) == blacklist->end()) {
89 return allow_result;
90 }
91
92 // The native messaging host is blacklisted. Check the whitelist.
93 if (pref_service->IsManagedPreference(
94 pref_names::kNativeMessagingWhitelist)) {
95 const base::ListValue* whitelist =
96 pref_service->GetList(pref_names::kNativeMessagingWhitelist);
97 if (whitelist && whitelist->Find(name_value) != whitelist->end())
98 return allow_result;
99 }
100
101 return DISALLOW;
102 }
103
64 const char kReceivingEndDoesntExistError[] = 104 const char kReceivingEndDoesntExistError[] =
65 "Could not establish connection. Receiving end does not exist."; 105 "Could not establish connection. Receiving end does not exist.";
66 #if defined(OS_WIN) || defined(OS_MACOSX) || defined(OS_LINUX) 106 #if defined(OS_WIN) || defined(OS_MACOSX) || defined(OS_LINUX)
67 const char kMissingPermissionError[] = 107 const char kMissingPermissionError[] =
68 "Access to native messaging requires nativeMessaging permission."; 108 "Access to native messaging requires nativeMessaging permission.";
69 const char kProhibitedByPoliciesError[] = 109 const char kProhibitedByPoliciesError[] =
70 "Access to the native messaging host was disabled by the system " 110 "Access to the native messaging host was disabled by the system "
71 "administrator."; 111 "administrator.";
72 #endif 112 #endif
73 113
(...skipping 290 matching lines...) Expand 10 before | Expand all | Expand 10 after
364 } 404 }
365 405
366 if (!has_permission) { 406 if (!has_permission) {
367 DispatchOnDisconnect(source, receiver_port_id, kMissingPermissionError); 407 DispatchOnDisconnect(source, receiver_port_id, kMissingPermissionError);
368 return; 408 return;
369 } 409 }
370 410
371 PrefService* pref_service = profile->GetPrefs(); 411 PrefService* pref_service = profile->GetPrefs();
372 412
373 // Verify that the host is not blocked by policies. 413 // Verify that the host is not blocked by policies.
374 NativeMessageProcessHost::PolicyPermission policy_permission = 414 PolicyPermission policy_permission =
375 NativeMessageProcessHost::IsHostAllowed(pref_service, native_app_name); 415 IsNativeMessagingHostAllowed(pref_service, native_app_name);
376 if (policy_permission == NativeMessageProcessHost::DISALLOW) { 416 if (policy_permission == DISALLOW) {
377 DispatchOnDisconnect(source, receiver_port_id, kProhibitedByPoliciesError); 417 DispatchOnDisconnect(source, receiver_port_id, kProhibitedByPoliciesError);
378 return; 418 return;
379 } 419 }
380 420
381 scoped_ptr<MessageChannel> channel(new MessageChannel()); 421 scoped_ptr<MessageChannel> channel(new MessageChannel());
382 channel->opener.reset(new ExtensionMessagePort(source, MSG_ROUTING_CONTROL, 422 channel->opener.reset(new ExtensionMessagePort(source, MSG_ROUTING_CONTROL,
383 source_extension_id)); 423 source_extension_id));
384 424
385 // Get handle of the native view and pass it to the native messaging host. 425 // Get handle of the native view and pass it to the native messaging host.
386 gfx::NativeView native_view = 426 gfx::NativeView native_view =
387 content::RenderWidgetHost::FromID(source_process_id, source_routing_id)-> 427 content::RenderWidgetHost::FromID(source_process_id, source_routing_id)->
388 GetView()->GetNativeView(); 428 GetView()->GetNativeView();
389 429
390 scoped_ptr<NativeMessageProcessHost> native_process = 430 std::string error = kReceivingEndDoesntExistError;
391 NativeMessageProcessHost::Create( 431 scoped_ptr<NativeMessageHost> native_host = NativeMessageHost::Create(
392 native_view, 432 native_view,
393 base::WeakPtr<NativeMessageProcessHost::Client>( 433 source_extension_id,
394 weak_factory_.GetWeakPtr()), 434 native_app_name,
395 source_extension_id, native_app_name, receiver_port_id, 435 policy_permission == ALLOW_ALL,
396 policy_permission == NativeMessageProcessHost::ALLOW_ALL); 436 &error);
397 437
398 // Abandon the channel. 438 // Abandon the channel.
399 if (!native_process.get()) { 439 if (!native_host.get()) {
400 LOG(ERROR) << "Failed to create native process."; 440 LOG(ERROR) << "Failed to create native process.";
401 DispatchOnDisconnect( 441 DispatchOnDisconnect(
402 source, receiver_port_id, kReceivingEndDoesntExistError); 442 source, receiver_port_id, error);
403 return; 443 return;
404 } 444 }
405 channel->receiver.reset(new NativeMessagePort(native_process.release())); 445 channel->receiver.reset(new NativeMessagePort(
446 weak_factory_.GetWeakPtr(), receiver_port_id, native_host.Pass()));
406 447
407 // Keep the opener alive until the channel is closed. 448 // Keep the opener alive until the channel is closed.
408 channel->opener->IncrementLazyKeepaliveCount(); 449 channel->opener->IncrementLazyKeepaliveCount();
409 450
410 AddChannel(channel.release(), receiver_port_id); 451 AddChannel(channel.release(), receiver_port_id);
411 #else // !(defined(OS_WIN) || defined(OS_MACOSX) || defined(OS_LINUX)) 452 #else // !(defined(OS_WIN) || defined(OS_MACOSX) || defined(OS_LINUX))
412 const char kNativeMessagingNotSupportedError[] = 453 const char kNativeMessagingNotSupportedError[] =
413 "Native Messaging is not supported on this platform."; 454 "Native Messaging is not supported on this platform.";
414 DispatchOnDisconnect( 455 DispatchOnDisconnect(
415 source, receiver_port_id, kNativeMessagingNotSupportedError); 456 source, receiver_port_id, kNativeMessagingNotSupportedError);
(...skipping 139 matching lines...) Expand 10 before | Expand all | Expand 10 after
555 if (iter == channels_.end()) { 596 if (iter == channels_.end()) {
556 // If this channel is pending, queue up the PostMessage to run once 597 // If this channel is pending, queue up the PostMessage to run once
557 // the channel opens. 598 // the channel opens.
558 EnqueuePendingMessage(source_port_id, channel_id, message); 599 EnqueuePendingMessage(source_port_id, channel_id, message);
559 return; 600 return;
560 } 601 }
561 602
562 DispatchMessage(source_port_id, iter->second, message); 603 DispatchMessage(source_port_id, iter->second, message);
563 } 604 }
564 605
565 void MessageService::PostMessageFromNativeProcess(int port_id,
566 const std::string& message) {
567 PostMessage(port_id, Message(message, false /* user_gesture */));
568 }
569
570 void MessageService::Observe(int type, 606 void MessageService::Observe(int type,
571 const content::NotificationSource& source, 607 const content::NotificationSource& source,
572 const content::NotificationDetails& details) { 608 const content::NotificationDetails& details) {
573 switch (type) { 609 switch (type) {
574 case content::NOTIFICATION_RENDERER_PROCESS_TERMINATED: 610 case content::NOTIFICATION_RENDERER_PROCESS_TERMINATED:
575 case content::NOTIFICATION_RENDERER_PROCESS_CLOSED: { 611 case content::NOTIFICATION_RENDERER_PROCESS_CLOSED: {
576 content::RenderProcessHost* renderer = 612 content::RenderProcessHost* renderer =
577 content::Source<content::RenderProcessHost>(source).ptr(); 613 content::Source<content::RenderProcessHost>(source).ptr();
578 OnProcessClosed(renderer); 614 OnProcessClosed(renderer);
579 break; 615 break;
(...skipping 175 matching lines...) Expand 10 before | Expand all | Expand 10 after
755 } 791 }
756 792
757 void MessageService::DispatchOnDisconnect(content::RenderProcessHost* source, 793 void MessageService::DispatchOnDisconnect(content::RenderProcessHost* source,
758 int port_id, 794 int port_id,
759 const std::string& error_message) { 795 const std::string& error_message) {
760 ExtensionMessagePort port(source, MSG_ROUTING_CONTROL, ""); 796 ExtensionMessagePort port(source, MSG_ROUTING_CONTROL, "");
761 port.DispatchOnDisconnect(GET_OPPOSITE_PORT_ID(port_id), error_message); 797 port.DispatchOnDisconnect(GET_OPPOSITE_PORT_ID(port_id), error_message);
762 } 798 }
763 799
764 } // namespace extensions 800 } // namespace extensions
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698