OLD | NEW |
1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 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/usb/web_usb_permission_provider.h" | 5 #include "chrome/browser/usb/web_usb_permission_provider.h" |
6 | 6 |
7 #include <stddef.h> | 7 #include <stddef.h> |
8 #include <utility> | 8 #include <utility> |
9 | 9 |
10 #include "base/command_line.h" | |
11 #include "base/stl_util.h" | 10 #include "base/stl_util.h" |
12 #include "chrome/browser/profiles/profile.h" | 11 #include "chrome/browser/profiles/profile.h" |
13 #include "chrome/browser/usb/usb_blocklist.h" | 12 #include "chrome/browser/usb/usb_blocklist.h" |
14 #include "chrome/browser/usb/usb_chooser_context.h" | 13 #include "chrome/browser/usb/usb_chooser_context.h" |
15 #include "chrome/browser/usb/usb_chooser_context_factory.h" | 14 #include "chrome/browser/usb/usb_chooser_context_factory.h" |
16 #include "chrome/browser/usb/usb_tab_helper.h" | 15 #include "chrome/browser/usb/usb_tab_helper.h" |
17 #include "chrome/common/chrome_switches.h" | |
18 #include "content/public/browser/browser_thread.h" | 16 #include "content/public/browser/browser_thread.h" |
19 #include "content/public/browser/render_frame_host.h" | 17 #include "content/public/browser/render_frame_host.h" |
20 #include "content/public/browser/web_contents.h" | 18 #include "content/public/browser/web_contents.h" |
21 #include "device/usb/usb_device.h" | 19 #include "device/usb/usb_device.h" |
22 #include "device/usb/webusb_descriptors.h" | 20 #include "device/usb/webusb_descriptors.h" |
23 | 21 |
| 22 using content::RenderFrameHost; |
24 using content::WebContents; | 23 using content::WebContents; |
25 | 24 |
26 namespace { | 25 namespace { |
27 | 26 |
28 bool FindOriginInDescriptorSet(const device::WebUsbAllowedOrigins* set, | 27 bool FindOriginInDescriptorSet(const device::WebUsbAllowedOrigins* set, |
29 const GURL& origin, | 28 const GURL& origin, |
30 const uint8_t* configuration_value, | 29 const uint8_t* configuration_value, |
31 const uint8_t* first_interface) { | 30 const uint8_t* first_interface) { |
32 if (base::CommandLine::ForCurrentProcess()->HasSwitch( | |
33 switches::kDisableWebUsbSecurity)) | |
34 return true; | |
35 | |
36 if (!set) | 31 if (!set) |
37 return false; | 32 return false; |
38 if (base::ContainsValue(set->origins, origin)) | 33 if (base::ContainsValue(set->origins, origin)) |
39 return true; | 34 return true; |
40 for (const auto& configuration : set->configurations) { | 35 for (const auto& configuration : set->configurations) { |
41 if (configuration_value && | 36 if (configuration_value && |
42 *configuration_value != configuration.configuration_value) | 37 *configuration_value != configuration.configuration_value) |
43 continue; | 38 continue; |
44 if (base::ContainsValue(configuration.origins, origin)) | 39 if (base::ContainsValue(configuration.origins, origin)) |
45 return true; | 40 return true; |
46 for (const auto& function : configuration.functions) { | 41 for (const auto& function : configuration.functions) { |
47 if (first_interface && *first_interface != function.first_interface) | 42 if (first_interface && *first_interface != function.first_interface) |
48 continue; | 43 continue; |
49 if (base::ContainsValue(function.origins, origin)) | 44 if (base::ContainsValue(function.origins, origin)) |
50 return true; | 45 return true; |
51 } | 46 } |
52 } | 47 } |
53 return false; | 48 return false; |
54 } | 49 } |
55 | 50 |
56 } // namespace | 51 } // namespace |
57 | 52 |
58 // static | 53 // static |
59 bool WebUSBPermissionProvider::HasDevicePermission( | 54 bool WebUSBPermissionProvider::HasDevicePermission( |
60 content::RenderFrameHost* render_frame_host, | 55 RenderFrameHost* render_frame_host, |
61 scoped_refptr<const device::UsbDevice> device) { | 56 scoped_refptr<const device::UsbDevice> device) { |
62 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); | 57 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); |
63 | 58 |
64 if (UsbBlocklist::Get().IsExcluded(device)) | 59 if (UsbBlocklist::Get().IsExcluded(device)) |
65 return false; | 60 return false; |
66 | 61 |
67 WebContents* web_contents = | 62 WebContents* web_contents = |
68 WebContents::FromRenderFrameHost(render_frame_host); | 63 WebContents::FromRenderFrameHost(render_frame_host); |
69 GURL embedding_origin = | 64 RenderFrameHost* main_frame = web_contents->GetMainFrame(); |
70 web_contents->GetMainFrame()->GetLastCommittedURL().GetOrigin(); | 65 GURL embedding_origin = main_frame->GetLastCommittedURL().GetOrigin(); |
71 GURL requesting_origin = render_frame_host->GetLastCommittedURL().GetOrigin(); | 66 GURL requesting_origin = render_frame_host->GetLastCommittedURL().GetOrigin(); |
72 Profile* profile = | 67 Profile* profile = |
73 Profile::FromBrowserContext(web_contents->GetBrowserContext()); | 68 Profile::FromBrowserContext(web_contents->GetBrowserContext()); |
74 UsbChooserContext* chooser_context = | 69 UsbChooserContext* chooser_context = |
75 UsbChooserContextFactory::GetForProfile(profile); | 70 UsbChooserContextFactory::GetForProfile(profile); |
76 | 71 |
77 if (!chooser_context->HasDevicePermission(requesting_origin, embedding_origin, | 72 if (!chooser_context->HasDevicePermission(requesting_origin, embedding_origin, |
78 device)) { | 73 device)) { |
79 return false; | 74 return false; |
80 } | 75 } |
81 | 76 |
82 // On Android it is not possible to read the WebUSB descriptors until Chrome | 77 // On Android it is not possible to read the WebUSB descriptors until Chrome |
83 // has been granted permission to open it. Instead we grant provisional access | 78 // has been granted permission to open it. Instead we grant provisional access |
84 // to the device and perform the allowed origins check when the client tries | 79 // to the device and perform the allowed origins check when the client tries |
85 // to open it. | 80 // to open it. |
86 if (!device->permission_granted()) | 81 if (!device->permission_granted()) |
87 return true; | 82 return true; |
88 | 83 |
89 return FindOriginInDescriptorSet(device->webusb_allowed_origins(), | 84 // Embedded frames must have their origin in the list provided by the device. |
90 requesting_origin, nullptr, nullptr); | 85 if (render_frame_host != main_frame) { |
| 86 return FindOriginInDescriptorSet(device->webusb_allowed_origins(), |
| 87 requesting_origin, nullptr, nullptr); |
| 88 } |
| 89 |
| 90 return true; |
91 } | 91 } |
92 | 92 |
93 WebUSBPermissionProvider::WebUSBPermissionProvider( | 93 WebUSBPermissionProvider::WebUSBPermissionProvider( |
94 content::RenderFrameHost* render_frame_host) | 94 RenderFrameHost* render_frame_host) |
95 : render_frame_host_(render_frame_host), weak_factory_(this) { | 95 : render_frame_host_(render_frame_host), weak_factory_(this) { |
96 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); | 96 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); |
97 DCHECK(render_frame_host_); | 97 DCHECK(render_frame_host_); |
98 } | 98 } |
99 | 99 |
100 WebUSBPermissionProvider::~WebUSBPermissionProvider() {} | 100 WebUSBPermissionProvider::~WebUSBPermissionProvider() {} |
101 | 101 |
102 base::WeakPtr<device::usb::PermissionProvider> | 102 base::WeakPtr<device::usb::PermissionProvider> |
103 WebUSBPermissionProvider::GetWeakPtr() { | 103 WebUSBPermissionProvider::GetWeakPtr() { |
104 return weak_factory_.GetWeakPtr(); | 104 return weak_factory_.GetWeakPtr(); |
105 } | 105 } |
106 | 106 |
107 bool WebUSBPermissionProvider::HasDevicePermission( | 107 bool WebUSBPermissionProvider::HasDevicePermission( |
108 scoped_refptr<const device::UsbDevice> device) const { | 108 scoped_refptr<const device::UsbDevice> device) const { |
109 return HasDevicePermission(render_frame_host_, device); | 109 return HasDevicePermission(render_frame_host_, device); |
110 } | 110 } |
111 | 111 |
112 bool WebUSBPermissionProvider::HasConfigurationPermission( | 112 bool WebUSBPermissionProvider::HasConfigurationPermission( |
113 uint8_t requested_configuration_value, | 113 uint8_t requested_configuration_value, |
114 scoped_refptr<const device::UsbDevice> device) const { | 114 scoped_refptr<const device::UsbDevice> device) const { |
115 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); | 115 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); |
116 return FindOriginInDescriptorSet( | 116 |
117 device->webusb_allowed_origins(), | 117 // Embedded frames may only access configurations if their origin in the list |
118 render_frame_host_->GetLastCommittedURL().GetOrigin(), | 118 // provided by the device. |
119 &requested_configuration_value, nullptr); | 119 RenderFrameHost* main_frame = |
| 120 WebContents::FromRenderFrameHost(render_frame_host_)->GetMainFrame(); |
| 121 if (render_frame_host_ != main_frame) { |
| 122 return FindOriginInDescriptorSet( |
| 123 device->webusb_allowed_origins(), |
| 124 render_frame_host_->GetLastCommittedURL().GetOrigin(), |
| 125 &requested_configuration_value, nullptr); |
| 126 } |
| 127 |
| 128 return true; |
120 } | 129 } |
121 | 130 |
122 bool WebUSBPermissionProvider::HasFunctionPermission( | 131 bool WebUSBPermissionProvider::HasFunctionPermission( |
123 uint8_t requested_function, | 132 uint8_t requested_function, |
124 uint8_t configuration_value, | 133 uint8_t configuration_value, |
125 scoped_refptr<const device::UsbDevice> device) const { | 134 scoped_refptr<const device::UsbDevice> device) const { |
126 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); | 135 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); |
127 return FindOriginInDescriptorSet( | 136 |
128 device->webusb_allowed_origins(), | 137 // Embedded frames may only access configurations if their origin in the list |
129 render_frame_host_->GetLastCommittedURL().GetOrigin(), | 138 // provided by the device. |
130 &configuration_value, &requested_function); | 139 RenderFrameHost* main_frame = |
| 140 WebContents::FromRenderFrameHost(render_frame_host_)->GetMainFrame(); |
| 141 if (render_frame_host_ != main_frame) { |
| 142 return FindOriginInDescriptorSet( |
| 143 device->webusb_allowed_origins(), |
| 144 render_frame_host_->GetLastCommittedURL().GetOrigin(), |
| 145 &configuration_value, &requested_function); |
| 146 } |
| 147 |
| 148 return true; |
131 } | 149 } |
132 | 150 |
133 void WebUSBPermissionProvider::IncrementConnectionCount() { | 151 void WebUSBPermissionProvider::IncrementConnectionCount() { |
134 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); | 152 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); |
135 WebContents* web_contents = | 153 WebContents* web_contents = |
136 WebContents::FromRenderFrameHost(render_frame_host_); | 154 WebContents::FromRenderFrameHost(render_frame_host_); |
137 UsbTabHelper* tab_helper = UsbTabHelper::FromWebContents(web_contents); | 155 UsbTabHelper* tab_helper = UsbTabHelper::FromWebContents(web_contents); |
138 tab_helper->IncrementConnectionCount(render_frame_host_); | 156 tab_helper->IncrementConnectionCount(render_frame_host_); |
139 } | 157 } |
140 | 158 |
141 void WebUSBPermissionProvider::DecrementConnectionCount() { | 159 void WebUSBPermissionProvider::DecrementConnectionCount() { |
142 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); | 160 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); |
143 WebContents* web_contents = | 161 WebContents* web_contents = |
144 WebContents::FromRenderFrameHost(render_frame_host_); | 162 WebContents::FromRenderFrameHost(render_frame_host_); |
145 UsbTabHelper* tab_helper = UsbTabHelper::FromWebContents(web_contents); | 163 UsbTabHelper* tab_helper = UsbTabHelper::FromWebContents(web_contents); |
146 tab_helper->DecrementConnectionCount(render_frame_host_); | 164 tab_helper->DecrementConnectionCount(render_frame_host_); |
147 } | 165 } |
OLD | NEW |