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

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: 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 namespace {
67
68 enum PolicyPermission {
69 DISALLOW, // The host is not allowed.
70 ALLOW_SYSTEM_ONLY, // Allowed only when installed on system level.
71 ALLOW_ALL, // Allowed when installed on system or user level.
72 };
73
74 PolicyPermission IsNativeMessagingHostAllowed(
75 const PrefService* pref_service,
76 const std::string& native_host_name) {
77 PolicyPermission allow_result = ALLOW_ALL;
78 if (pref_service->IsManagedPreference(
79 pref_names::kNativeMessagingUserLevelHosts)) {
80 if (!pref_service->GetBoolean(pref_names::kNativeMessagingUserLevelHosts))
81 allow_result = ALLOW_SYSTEM_ONLY;
82 }
83
84 // All native messaging hosts are allowed if there is no blacklist.
85 if (!pref_service->IsManagedPreference(pref_names::kNativeMessagingBlacklist))
86 return allow_result;
87 const base::ListValue* blacklist =
88 pref_service->GetList(pref_names::kNativeMessagingBlacklist);
89 if (!blacklist)
90 return allow_result;
91
92 // Check if the name or the wildcard is in the blacklist.
93 base::StringValue name_value(native_host_name);
94 base::StringValue wildcard_value("*");
95 if (blacklist->Find(name_value) == blacklist->end() &&
96 blacklist->Find(wildcard_value) == blacklist->end()) {
97 return allow_result;
98 }
99
100 // The native messaging host is blacklisted. Check the whitelist.
101 if (pref_service->IsManagedPreference(
102 pref_names::kNativeMessagingWhitelist)) {
103 const base::ListValue* whitelist =
104 pref_service->GetList(pref_names::kNativeMessagingWhitelist);
105 if (whitelist && whitelist->Find(name_value) != whitelist->end())
106 return allow_result;
107 }
108
109 return DISALLOW;
110 }
111
112 } // namespace
113
64 const char kReceivingEndDoesntExistError[] = 114 const char kReceivingEndDoesntExistError[] =
65 "Could not establish connection. Receiving end does not exist."; 115 "Could not establish connection. Receiving end does not exist.";
66 #if defined(OS_WIN) || defined(OS_MACOSX) || defined(OS_LINUX) 116 #if defined(OS_WIN) || defined(OS_MACOSX) || defined(OS_LINUX)
67 const char kMissingPermissionError[] = 117 const char kMissingPermissionError[] =
68 "Access to native messaging requires nativeMessaging permission."; 118 "Access to native messaging requires nativeMessaging permission.";
69 const char kProhibitedByPoliciesError[] = 119 const char kProhibitedByPoliciesError[] =
70 "Access to the native messaging host was disabled by the system " 120 "Access to the native messaging host was disabled by the system "
71 "administrator."; 121 "administrator.";
72 #endif 122 #endif
73 123
(...skipping 290 matching lines...) Expand 10 before | Expand all | Expand 10 after
364 } 414 }
365 415
366 if (!has_permission) { 416 if (!has_permission) {
367 DispatchOnDisconnect(source, receiver_port_id, kMissingPermissionError); 417 DispatchOnDisconnect(source, receiver_port_id, kMissingPermissionError);
368 return; 418 return;
369 } 419 }
370 420
371 PrefService* pref_service = profile->GetPrefs(); 421 PrefService* pref_service = profile->GetPrefs();
372 422
373 // Verify that the host is not blocked by policies. 423 // Verify that the host is not blocked by policies.
374 NativeMessageProcessHost::PolicyPermission policy_permission = 424 PolicyPermission policy_permission =
375 NativeMessageProcessHost::IsHostAllowed(pref_service, native_app_name); 425 IsNativeMessagingHostAllowed(pref_service, native_app_name);
376 if (policy_permission == NativeMessageProcessHost::DISALLOW) { 426 if (policy_permission == DISALLOW) {
377 DispatchOnDisconnect(source, receiver_port_id, kProhibitedByPoliciesError); 427 DispatchOnDisconnect(source, receiver_port_id, kProhibitedByPoliciesError);
378 return; 428 return;
379 } 429 }
380 430
381 scoped_ptr<MessageChannel> channel(new MessageChannel()); 431 scoped_ptr<MessageChannel> channel(new MessageChannel());
382 channel->opener.reset(new ExtensionMessagePort(source, MSG_ROUTING_CONTROL, 432 channel->opener.reset(new ExtensionMessagePort(source, MSG_ROUTING_CONTROL,
383 source_extension_id)); 433 source_extension_id));
384 434
385 // Get handle of the native view and pass it to the native messaging host. 435 // Get handle of the native view and pass it to the native messaging host.
386 gfx::NativeView native_view = 436 gfx::NativeView native_view =
387 content::RenderWidgetHost::FromID(source_process_id, source_routing_id)-> 437 content::RenderWidgetHost::FromID(source_process_id, source_routing_id)->
388 GetView()->GetNativeView(); 438 GetView()->GetNativeView();
389 439
390 scoped_ptr<NativeMessageProcessHost> native_process = 440 scoped_ptr<NativeMessageHost> native_host = NativeMessageHost::Create(
391 NativeMessageProcessHost::Create( 441 native_view,
392 native_view, 442 source_extension_id,
393 base::WeakPtr<NativeMessageProcessHost::Client>( 443 native_app_name,
394 weak_factory_.GetWeakPtr()), 444 policy_permission == ALLOW_ALL);
395 source_extension_id, native_app_name, receiver_port_id,
396 policy_permission == NativeMessageProcessHost::ALLOW_ALL);
397 445
398 // Abandon the channel. 446 // Abandon the channel.
399 if (!native_process.get()) { 447 if (!native_host.get()) {
400 LOG(ERROR) << "Failed to create native process."; 448 LOG(ERROR) << "Failed to create native process.";
401 DispatchOnDisconnect( 449 DispatchOnDisconnect(
402 source, receiver_port_id, kReceivingEndDoesntExistError); 450 source, receiver_port_id, kReceivingEndDoesntExistError);
403 return; 451 return;
404 } 452 }
405 channel->receiver.reset(new NativeMessagePort(native_process.release())); 453 channel->receiver.reset(new NativeMessagePort(
454 weak_factory_.GetWeakPtr(), receiver_port_id, native_host.Pass()));
406 455
407 // Keep the opener alive until the channel is closed. 456 // Keep the opener alive until the channel is closed.
408 channel->opener->IncrementLazyKeepaliveCount(); 457 channel->opener->IncrementLazyKeepaliveCount();
409 458
410 AddChannel(channel.release(), receiver_port_id); 459 AddChannel(channel.release(), receiver_port_id);
411 #else // !(defined(OS_WIN) || defined(OS_MACOSX) || defined(OS_LINUX)) 460 #else // !(defined(OS_WIN) || defined(OS_MACOSX) || defined(OS_LINUX))
412 const char kNativeMessagingNotSupportedError[] = 461 const char kNativeMessagingNotSupportedError[] =
413 "Native Messaging is not supported on this platform."; 462 "Native Messaging is not supported on this platform.";
414 DispatchOnDisconnect( 463 DispatchOnDisconnect(
415 source, receiver_port_id, kNativeMessagingNotSupportedError); 464 source, receiver_port_id, kNativeMessagingNotSupportedError);
(...skipping 139 matching lines...) Expand 10 before | Expand all | Expand 10 after
555 if (iter == channels_.end()) { 604 if (iter == channels_.end()) {
556 // If this channel is pending, queue up the PostMessage to run once 605 // If this channel is pending, queue up the PostMessage to run once
557 // the channel opens. 606 // the channel opens.
558 EnqueuePendingMessage(source_port_id, channel_id, message); 607 EnqueuePendingMessage(source_port_id, channel_id, message);
559 return; 608 return;
560 } 609 }
561 610
562 DispatchMessage(source_port_id, iter->second, message); 611 DispatchMessage(source_port_id, iter->second, message);
563 } 612 }
564 613
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, 614 void MessageService::Observe(int type,
571 const content::NotificationSource& source, 615 const content::NotificationSource& source,
572 const content::NotificationDetails& details) { 616 const content::NotificationDetails& details) {
573 switch (type) { 617 switch (type) {
574 case content::NOTIFICATION_RENDERER_PROCESS_TERMINATED: 618 case content::NOTIFICATION_RENDERER_PROCESS_TERMINATED:
575 case content::NOTIFICATION_RENDERER_PROCESS_CLOSED: { 619 case content::NOTIFICATION_RENDERER_PROCESS_CLOSED: {
576 content::RenderProcessHost* renderer = 620 content::RenderProcessHost* renderer =
577 content::Source<content::RenderProcessHost>(source).ptr(); 621 content::Source<content::RenderProcessHost>(source).ptr();
578 OnProcessClosed(renderer); 622 OnProcessClosed(renderer);
579 break; 623 break;
(...skipping 175 matching lines...) Expand 10 before | Expand all | Expand 10 after
755 } 799 }
756 800
757 void MessageService::DispatchOnDisconnect(content::RenderProcessHost* source, 801 void MessageService::DispatchOnDisconnect(content::RenderProcessHost* source,
758 int port_id, 802 int port_id,
759 const std::string& error_message) { 803 const std::string& error_message) {
760 ExtensionMessagePort port(source, MSG_ROUTING_CONTROL, ""); 804 ExtensionMessagePort port(source, MSG_ROUTING_CONTROL, "");
761 port.DispatchOnDisconnect(GET_OPPOSITE_PORT_ID(port_id), error_message); 805 port.DispatchOnDisconnect(GET_OPPOSITE_PORT_ID(port_id), error_message);
762 } 806 }
763 807
764 } // namespace extensions 808 } // namespace extensions
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698