| OLD | NEW |
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 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 // On Linux, when the user tries to launch a second copy of chrome, we check | 5 // On Linux, when the user tries to launch a second copy of chrome, we check |
| 6 // for a socket in the user's profile directory. If the socket file is open we | 6 // for a socket in the user's profile directory. If the socket file is open we |
| 7 // send a message to the first chrome browser process with the current | 7 // send a message to the first chrome browser process with the current |
| 8 // directory and second process command line flags. The second process then | 8 // directory and second process command line flags. The second process then |
| 9 // exits. | 9 // exits. |
| 10 // | 10 // |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 55 #include <stddef.h> | 55 #include <stddef.h> |
| 56 | 56 |
| 57 #include "base/base_paths.h" | 57 #include "base/base_paths.h" |
| 58 #include "base/bind.h" | 58 #include "base/bind.h" |
| 59 #include "base/command_line.h" | 59 #include "base/command_line.h" |
| 60 #include "base/files/file_path.h" | 60 #include "base/files/file_path.h" |
| 61 #include "base/files/file_util.h" | 61 #include "base/files/file_util.h" |
| 62 #include "base/location.h" | 62 #include "base/location.h" |
| 63 #include "base/logging.h" | 63 #include "base/logging.h" |
| 64 #include "base/macros.h" | 64 #include "base/macros.h" |
| 65 #include "base/memory/ref_counted.h" |
| 65 #include "base/message_loop/message_loop.h" | 66 #include "base/message_loop/message_loop.h" |
| 66 #include "base/path_service.h" | 67 #include "base/path_service.h" |
| 67 #include "base/posix/eintr_wrapper.h" | 68 #include "base/posix/eintr_wrapper.h" |
| 68 #include "base/posix/safe_strerror.h" | 69 #include "base/posix/safe_strerror.h" |
| 69 #include "base/rand_util.h" | 70 #include "base/rand_util.h" |
| 70 #include "base/sequenced_task_runner_helpers.h" | 71 #include "base/sequenced_task_runner_helpers.h" |
| 71 #include "base/single_thread_task_runner.h" | 72 #include "base/single_thread_task_runner.h" |
| 73 #include "base/single_thread_task_runner.h" |
| 72 #include "base/stl_util.h" | 74 #include "base/stl_util.h" |
| 73 #include "base/strings/string_number_conversions.h" | 75 #include "base/strings/string_number_conversions.h" |
| 74 #include "base/strings/string_split.h" | 76 #include "base/strings/string_split.h" |
| 75 #include "base/strings/string_util.h" | 77 #include "base/strings/string_util.h" |
| 76 #include "base/strings/stringprintf.h" | 78 #include "base/strings/stringprintf.h" |
| 77 #include "base/strings/sys_string_conversions.h" | 79 #include "base/strings/sys_string_conversions.h" |
| 78 #include "base/strings/utf_string_conversions.h" | 80 #include "base/strings/utf_string_conversions.h" |
| 79 #include "base/threading/platform_thread.h" | 81 #include "base/threading/platform_thread.h" |
| 82 #include "base/threading/thread_task_runner_handle.h" |
| 80 #include "base/time/time.h" | 83 #include "base/time/time.h" |
| 81 #include "base/timer/timer.h" | 84 #include "base/timer/timer.h" |
| 82 #include "build/build_config.h" | 85 #include "build/build_config.h" |
| 83 #include "chrome/common/chrome_constants.h" | 86 #include "chrome/common/chrome_constants.h" |
| 84 #include "chrome/grit/chromium_strings.h" | 87 #include "chrome/grit/chromium_strings.h" |
| 85 #include "chrome/grit/generated_resources.h" | 88 #include "chrome/grit/generated_resources.h" |
| 86 #include "content/public/browser/browser_thread.h" | 89 #include "content/public/browser/browser_thread.h" |
| 87 #include "net/base/network_interfaces.h" | 90 #include "net/base/network_interfaces.h" |
| 88 #include "ui/base/l10n/l10n_util.h" | 91 #include "ui/base/l10n/l10n_util.h" |
| 89 | 92 |
| (...skipping 367 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 457 class ProcessSingleton::LinuxWatcher | 460 class ProcessSingleton::LinuxWatcher |
| 458 : public base::MessageLoopForIO::Watcher, | 461 : public base::MessageLoopForIO::Watcher, |
| 459 public base::MessageLoop::DestructionObserver, | 462 public base::MessageLoop::DestructionObserver, |
| 460 public base::RefCountedThreadSafe<ProcessSingleton::LinuxWatcher, | 463 public base::RefCountedThreadSafe<ProcessSingleton::LinuxWatcher, |
| 461 BrowserThread::DeleteOnIOThread> { | 464 BrowserThread::DeleteOnIOThread> { |
| 462 public: | 465 public: |
| 463 // A helper class to read message from an established socket. | 466 // A helper class to read message from an established socket. |
| 464 class SocketReader : public base::MessageLoopForIO::Watcher { | 467 class SocketReader : public base::MessageLoopForIO::Watcher { |
| 465 public: | 468 public: |
| 466 SocketReader(ProcessSingleton::LinuxWatcher* parent, | 469 SocketReader(ProcessSingleton::LinuxWatcher* parent, |
| 467 base::MessageLoop* ui_message_loop, | 470 scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner, |
| 468 int fd) | 471 int fd) |
| 469 : parent_(parent), | 472 : parent_(parent), |
| 470 ui_message_loop_(ui_message_loop), | 473 ui_task_runner_(ui_task_runner), |
| 471 fd_(fd), | 474 fd_(fd), |
| 472 bytes_read_(0) { | 475 bytes_read_(0) { |
| 473 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 476 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| 474 // Wait for reads. | 477 // Wait for reads. |
| 475 base::MessageLoopForIO::current()->WatchFileDescriptor( | 478 base::MessageLoopForIO::current()->WatchFileDescriptor( |
| 476 fd, true, base::MessageLoopForIO::WATCH_READ, &fd_reader_, this); | 479 fd, true, base::MessageLoopForIO::WATCH_READ, &fd_reader_, this); |
| 477 // If we haven't completed in a reasonable amount of time, give up. | 480 // If we haven't completed in a reasonable amount of time, give up. |
| 478 timer_.Start(FROM_HERE, base::TimeDelta::FromSeconds(kTimeoutInSeconds), | 481 timer_.Start(FROM_HERE, base::TimeDelta::FromSeconds(kTimeoutInSeconds), |
| 479 this, &SocketReader::CleanupAndDeleteSelf); | 482 this, &SocketReader::CleanupAndDeleteSelf); |
| 480 } | 483 } |
| (...skipping 17 matching lines...) Expand all Loading... |
| 498 | 501 |
| 499 parent_->RemoveSocketReader(this); | 502 parent_->RemoveSocketReader(this); |
| 500 // We're deleted beyond this point. | 503 // We're deleted beyond this point. |
| 501 } | 504 } |
| 502 | 505 |
| 503 base::MessageLoopForIO::FileDescriptorWatcher fd_reader_; | 506 base::MessageLoopForIO::FileDescriptorWatcher fd_reader_; |
| 504 | 507 |
| 505 // The ProcessSingleton::LinuxWatcher that owns us. | 508 // The ProcessSingleton::LinuxWatcher that owns us. |
| 506 ProcessSingleton::LinuxWatcher* const parent_; | 509 ProcessSingleton::LinuxWatcher* const parent_; |
| 507 | 510 |
| 508 // A reference to the UI message loop. | 511 // A reference to the UI task runner. |
| 509 base::MessageLoop* const ui_message_loop_; | 512 scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner_; |
| 510 | 513 |
| 511 // The file descriptor we're reading. | 514 // The file descriptor we're reading. |
| 512 const int fd_; | 515 const int fd_; |
| 513 | 516 |
| 514 // Store the message in this buffer. | 517 // Store the message in this buffer. |
| 515 char buf_[kMaxMessageLength]; | 518 char buf_[kMaxMessageLength]; |
| 516 | 519 |
| 517 // Tracks the number of bytes we've read in case we're getting partial | 520 // Tracks the number of bytes we've read in case we're getting partial |
| 518 // reads. | 521 // reads. |
| 519 size_t bytes_read_; | 522 size_t bytes_read_; |
| 520 | 523 |
| 521 base::OneShotTimer timer_; | 524 base::OneShotTimer timer_; |
| 522 | 525 |
| 523 DISALLOW_COPY_AND_ASSIGN(SocketReader); | 526 DISALLOW_COPY_AND_ASSIGN(SocketReader); |
| 524 }; | 527 }; |
| 525 | 528 |
| 526 // We expect to only be constructed on the UI thread. | 529 // We expect to only be constructed on the UI thread. |
| 527 explicit LinuxWatcher(ProcessSingleton* parent) | 530 explicit LinuxWatcher(ProcessSingleton* parent) |
| 528 : ui_message_loop_(base::MessageLoop::current()), | 531 : ui_task_runner_(base::ThreadTaskRunnerHandle::Get()), parent_(parent) {} |
| 529 parent_(parent) { | |
| 530 } | |
| 531 | 532 |
| 532 // Start listening for connections on the socket. This method should be | 533 // Start listening for connections on the socket. This method should be |
| 533 // called from the IO thread. | 534 // called from the IO thread. |
| 534 void StartListening(int socket); | 535 void StartListening(int socket); |
| 535 | 536 |
| 536 // This method determines if we should use the same process and if we should, | 537 // This method determines if we should use the same process and if we should, |
| 537 // opens a new browser tab. This runs on the UI thread. | 538 // opens a new browser tab. This runs on the UI thread. |
| 538 // |reader| is for sending back ACK message. | 539 // |reader| is for sending back ACK message. |
| 539 void HandleMessage(const std::string& current_dir, | 540 void HandleMessage(const std::string& current_dir, |
| 540 const std::vector<std::string>& argv, | 541 const std::vector<std::string>& argv, |
| (...skipping 23 matching lines...) Expand all Loading... |
| 564 ml->RemoveDestructionObserver(this); | 565 ml->RemoveDestructionObserver(this); |
| 565 } | 566 } |
| 566 | 567 |
| 567 // Removes and deletes the SocketReader. | 568 // Removes and deletes the SocketReader. |
| 568 void RemoveSocketReader(SocketReader* reader); | 569 void RemoveSocketReader(SocketReader* reader); |
| 569 | 570 |
| 570 base::MessageLoopForIO::FileDescriptorWatcher fd_watcher_; | 571 base::MessageLoopForIO::FileDescriptorWatcher fd_watcher_; |
| 571 | 572 |
| 572 // A reference to the UI message loop (i.e., the message loop we were | 573 // A reference to the UI message loop (i.e., the message loop we were |
| 573 // constructed on). | 574 // constructed on). |
| 574 base::MessageLoop* ui_message_loop_; | 575 scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner_; |
| 575 | 576 |
| 576 // The ProcessSingleton that owns us. | 577 // The ProcessSingleton that owns us. |
| 577 ProcessSingleton* const parent_; | 578 ProcessSingleton* const parent_; |
| 578 | 579 |
| 579 std::set<SocketReader*> readers_; | 580 std::set<SocketReader*> readers_; |
| 580 | 581 |
| 581 DISALLOW_COPY_AND_ASSIGN(LinuxWatcher); | 582 DISALLOW_COPY_AND_ASSIGN(LinuxWatcher); |
| 582 }; | 583 }; |
| 583 | 584 |
| 584 void ProcessSingleton::LinuxWatcher::OnFileCanReadWithoutBlocking(int fd) { | 585 void ProcessSingleton::LinuxWatcher::OnFileCanReadWithoutBlocking(int fd) { |
| 585 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 586 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| 586 // Accepting incoming client. | 587 // Accepting incoming client. |
| 587 sockaddr_un from; | 588 sockaddr_un from; |
| 588 socklen_t from_len = sizeof(from); | 589 socklen_t from_len = sizeof(from); |
| 589 int connection_socket = HANDLE_EINTR(accept( | 590 int connection_socket = HANDLE_EINTR(accept( |
| 590 fd, reinterpret_cast<sockaddr*>(&from), &from_len)); | 591 fd, reinterpret_cast<sockaddr*>(&from), &from_len)); |
| 591 if (-1 == connection_socket) { | 592 if (-1 == connection_socket) { |
| 592 PLOG(ERROR) << "accept() failed"; | 593 PLOG(ERROR) << "accept() failed"; |
| 593 return; | 594 return; |
| 594 } | 595 } |
| 595 DCHECK(base::SetNonBlocking(connection_socket)) | 596 DCHECK(base::SetNonBlocking(connection_socket)) |
| 596 << "Failed to make non-blocking socket."; | 597 << "Failed to make non-blocking socket."; |
| 597 SocketReader* reader = new SocketReader(this, | 598 SocketReader* reader = |
| 598 ui_message_loop_, | 599 new SocketReader(this, ui_task_runner_, connection_socket); |
| 599 connection_socket); | |
| 600 readers_.insert(reader); | 600 readers_.insert(reader); |
| 601 } | 601 } |
| 602 | 602 |
| 603 void ProcessSingleton::LinuxWatcher::StartListening(int socket) { | 603 void ProcessSingleton::LinuxWatcher::StartListening(int socket) { |
| 604 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 604 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| 605 // Watch for client connections on this socket. | 605 // Watch for client connections on this socket. |
| 606 base::MessageLoopForIO* ml = base::MessageLoopForIO::current(); | 606 base::MessageLoopForIO* ml = base::MessageLoopForIO::current(); |
| 607 ml->AddDestructionObserver(this); | 607 ml->AddDestructionObserver(this); |
| 608 ml->WatchFileDescriptor(socket, true, base::MessageLoopForIO::WATCH_READ, | 608 ml->WatchFileDescriptor(socket, true, base::MessageLoopForIO::WATCH_READ, |
| 609 &fd_watcher_, this); | 609 &fd_watcher_, this); |
| 610 } | 610 } |
| 611 | 611 |
| 612 void ProcessSingleton::LinuxWatcher::HandleMessage( | 612 void ProcessSingleton::LinuxWatcher::HandleMessage( |
| 613 const std::string& current_dir, const std::vector<std::string>& argv, | 613 const std::string& current_dir, const std::vector<std::string>& argv, |
| 614 SocketReader* reader) { | 614 SocketReader* reader) { |
| 615 DCHECK(ui_message_loop_ == base::MessageLoop::current()); | 615 DCHECK(ui_task_runner_->BelongsToCurrentThread()); |
| 616 DCHECK(reader); | 616 DCHECK(reader); |
| 617 | 617 |
| 618 if (parent_->notification_callback_.Run(base::CommandLine(argv), | 618 if (parent_->notification_callback_.Run(base::CommandLine(argv), |
| 619 base::FilePath(current_dir))) { | 619 base::FilePath(current_dir))) { |
| 620 // Send back "ACK" message to prevent the client process from starting up. | 620 // Send back "ACK" message to prevent the client process from starting up. |
| 621 reader->FinishWithACK(kACKToken, arraysize(kACKToken) - 1); | 621 reader->FinishWithACK(kACKToken, arraysize(kACKToken) - 1); |
| 622 } else { | 622 } else { |
| 623 LOG(WARNING) << "Not handling interprocess notification as browser" | 623 LOG(WARNING) << "Not handling interprocess notification as browser" |
| 624 " is shutting down"; | 624 " is shutting down"; |
| 625 // Send back "SHUTDOWN" message, so that the client process can start up | 625 // Send back "SHUTDOWN" message, so that the client process can start up |
| (...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 689 // terminated unexpectly. | 689 // terminated unexpectly. |
| 690 timer_.Stop(); | 690 timer_.Stop(); |
| 691 | 691 |
| 692 std::string current_dir = tokens[1]; | 692 std::string current_dir = tokens[1]; |
| 693 // Remove the first two tokens. The remaining tokens should be the command | 693 // Remove the first two tokens. The remaining tokens should be the command |
| 694 // line argv array. | 694 // line argv array. |
| 695 tokens.erase(tokens.begin()); | 695 tokens.erase(tokens.begin()); |
| 696 tokens.erase(tokens.begin()); | 696 tokens.erase(tokens.begin()); |
| 697 | 697 |
| 698 // Return to the UI thread to handle opening a new browser tab. | 698 // Return to the UI thread to handle opening a new browser tab. |
| 699 ui_message_loop_->task_runner()->PostTask( | 699 ui_task_runner_->PostTask( |
| 700 FROM_HERE, base::Bind(&ProcessSingleton::LinuxWatcher::HandleMessage, | 700 FROM_HERE, base::Bind(&ProcessSingleton::LinuxWatcher::HandleMessage, |
| 701 parent_, current_dir, tokens, this)); | 701 parent_, current_dir, tokens, this)); |
| 702 fd_reader_.StopWatchingFileDescriptor(); | 702 fd_reader_.StopWatchingFileDescriptor(); |
| 703 | 703 |
| 704 // LinuxWatcher::HandleMessage() is in charge of destroying this SocketReader | 704 // LinuxWatcher::HandleMessage() is in charge of destroying this SocketReader |
| 705 // object by invoking SocketReader::FinishWithACK(). | 705 // object by invoking SocketReader::FinishWithACK(). |
| 706 } | 706 } |
| 707 | 707 |
| 708 void ProcessSingleton::LinuxWatcher::SocketReader::FinishWithACK( | 708 void ProcessSingleton::LinuxWatcher::SocketReader::FinishWithACK( |
| 709 const char *message, size_t length) { | 709 const char *message, size_t length) { |
| (...skipping 345 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1055 } | 1055 } |
| 1056 | 1056 |
| 1057 void ProcessSingleton::KillProcess(int pid) { | 1057 void ProcessSingleton::KillProcess(int pid) { |
| 1058 // TODO(james.su@gmail.com): Is SIGKILL ok? | 1058 // TODO(james.su@gmail.com): Is SIGKILL ok? |
| 1059 int rv = kill(static_cast<base::ProcessHandle>(pid), SIGKILL); | 1059 int rv = kill(static_cast<base::ProcessHandle>(pid), SIGKILL); |
| 1060 // ESRCH = No Such Process (can happen if the other process is already in | 1060 // ESRCH = No Such Process (can happen if the other process is already in |
| 1061 // progress of shutting down and finishes before we try to kill it). | 1061 // progress of shutting down and finishes before we try to kill it). |
| 1062 DCHECK(rv == 0 || errno == ESRCH) << "Error killing process: " | 1062 DCHECK(rv == 0 || errno == ESRCH) << "Error killing process: " |
| 1063 << base::safe_strerror(errno); | 1063 << base::safe_strerror(errno); |
| 1064 } | 1064 } |
| OLD | NEW |