| OLD | NEW |
| (Empty) |
| 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. | |
| 4 | |
| 5 #include "chrome/browser/extensions/api/serial/serial_port_enumerator.h" | |
| 6 | |
| 7 #include "base/file_util.h" | |
| 8 #include "base/files/file_enumerator.h" | |
| 9 #include "base/files/file_path.h" | |
| 10 #include "base/strings/string_util.h" | |
| 11 #include "content/public/browser/browser_thread.h" | |
| 12 | |
| 13 using content::BrowserThread; | |
| 14 | |
| 15 namespace extensions { | |
| 16 | |
| 17 // static | |
| 18 SerialPortEnumerator::StringSet SerialPortEnumerator::GenerateValidPatterns() { | |
| 19 // TODO(miket): the set of patterns should be larger. See the rxtx project. | |
| 20 // | |
| 21 // TODO(miket): The list of patterns tested at runtime should also be | |
| 22 // OS-dependent. | |
| 23 const char* VALID_PATTERNS[] = { | |
| 24 "/dev/*Bluetooth*", | |
| 25 "/dev/*Modem*", | |
| 26 "/dev/*bluetooth*", | |
| 27 "/dev/*modem*", | |
| 28 "/dev/*serial*", | |
| 29 "/dev/ttyACM*", | |
| 30 "/dev/ttyS*", | |
| 31 "/dev/ttyUSB*", | |
| 32 "/dev/tty.SLAB_*", | |
| 33 "/dev/cu.SLAB_*", | |
| 34 }; | |
| 35 | |
| 36 StringSet valid_patterns; | |
| 37 for (size_t i = 0; i < arraysize(VALID_PATTERNS); ++i) | |
| 38 valid_patterns.insert(VALID_PATTERNS[i]); | |
| 39 | |
| 40 return valid_patterns; | |
| 41 } | |
| 42 | |
| 43 // static | |
| 44 // | |
| 45 // TODO(miket): Investigate udev. Search for equivalent solutions on OSX. | |
| 46 // Continue to examine rxtx code. | |
| 47 // | |
| 48 // On a fairly ordinary Linux machine, ls -l /dev | wc -l returned about 200 | |
| 49 // items. So we're doing about N(VALID_PATTERNS) * 200 = 1,600 MatchPattern | |
| 50 // calls to find maybe a dozen serial ports in a small number of milliseconds | |
| 51 // (a single trial of SerialPortEnumeratorTest.ValidPortNames took 6ms to run). | |
| 52 // It's not cheap, but then again, we don't expect users of this API to be | |
| 53 // enumerating too often (at worst on every click of a UI element that displays | |
| 54 // the generated list). | |
| 55 // | |
| 56 // An upside-down approach would instead take each pattern and turn it into a | |
| 57 // string generator (something like /dev/ttyS[0-9]{0,3}) and then expanding | |
| 58 // that into a series of possible paths, perhaps early-outing if we knew that | |
| 59 // port patterns were contiguous (e.g., /dev/ttyS1 can't exist if /dev/ttyS0 | |
| 60 // doesn't exist). | |
| 61 // | |
| 62 // Caching seems undesirable. Many devices can be dynamically added to and | |
| 63 // removed from the system, so we really do want to regenerate the set each | |
| 64 // time. | |
| 65 // | |
| 66 // TODO(miket): this might be refactorable into serial_connection.cc, if | |
| 67 // Windows serial-port enumeration also entails looking through a directory. | |
| 68 SerialPortEnumerator::StringSet | |
| 69 SerialPortEnumerator::GenerateValidSerialPortNames() { | |
| 70 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); | |
| 71 const base::FilePath kDevRoot("/dev"); | |
| 72 const int kFilesAndSymLinks = | |
| 73 base::FileEnumerator::FILES | | |
| 74 base::FileEnumerator::SHOW_SYM_LINKS; | |
| 75 | |
| 76 StringSet valid_patterns = GenerateValidPatterns(); | |
| 77 StringSet name_set; | |
| 78 base::FileEnumerator enumerator(kDevRoot, false, kFilesAndSymLinks); | |
| 79 do { | |
| 80 const base::FilePath next_device_path(enumerator.Next()); | |
| 81 const std::string next_device = next_device_path.value(); | |
| 82 if (next_device.empty()) | |
| 83 break; | |
| 84 | |
| 85 StringSet::const_iterator i = valid_patterns.begin(); | |
| 86 for (; i != valid_patterns.end(); ++i) { | |
| 87 if (MatchPattern(next_device, *i)) { | |
| 88 name_set.insert(next_device); | |
| 89 break; | |
| 90 } | |
| 91 } | |
| 92 } while (true); | |
| 93 | |
| 94 return name_set; | |
| 95 } | |
| 96 | |
| 97 } // namespace extensions | |
| OLD | NEW |