| // Copyright 2018 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #ifndef CHROME_APP_SHIM_APP_SHIM_CONTROLLER_H_ |
| #define CHROME_APP_SHIM_APP_SHIM_CONTROLLER_H_ |
| |
| #include <vector> |
| |
| #import <AppKit/AppKit.h> |
| |
| #include "base/files/file_path.h" |
| #include "base/mac/scoped_nsobject.h" |
| #include "chrome/common/mac/app_shim.mojom.h" |
| #include "mojo/public/cpp/bindings/pending_associated_receiver.h" |
| #include "mojo/public/cpp/bindings/pending_receiver.h" |
| #include "mojo/public/cpp/bindings/receiver.h" |
| #include "mojo/public/cpp/bindings/remote.h" |
| #include "mojo/public/cpp/platform/named_platform_channel.h" |
| #include "mojo/public/cpp/system/isolated_connection.h" |
| #include "url/gurl.h" |
| |
| namespace apps { |
| class MachBootstrapAcceptorTest; |
| } |
| |
| @class AppShimDelegate; |
| @class ProfileMenuTarget; |
| @class ApplicationDockMenuTarget; |
| |
| // The AppShimController is responsible for launching and maintaining the |
| // connection with the main Chrome process, and generally controls the lifetime |
| // of the app shim process. |
| class AppShimController : public chrome::mojom::AppShim { |
| public: |
| struct Params { |
| Params(); |
| Params(const Params& other); |
| ~Params(); |
| // The full path of the user data dir. |
| base::FilePath user_data_dir; |
| // The relative path of the profile. |
| base::FilePath profile_dir; |
| std::string app_id; |
| std::u16string app_name; |
| GURL app_url; |
| }; |
| |
| explicit AppShimController(const Params& params); |
| |
| AppShimController(const AppShimController&) = delete; |
| AppShimController& operator=(const AppShimController&) = delete; |
| |
| ~AppShimController() override; |
| |
| chrome::mojom::AppShimHost* host() const { return host_.get(); } |
| |
| // Called by AppShimDelegate in response to receiving the notification |
| // -[NSApplicationDelegate applicationDidFinishLaunching:]. This kicks off |
| // the initialization process (connecting to Chrome, etc). |
| void OnAppFinishedLaunching(); |
| |
| // Called by AppShimDelegate in response a file being opened. If this occurs |
| // before OnDidFinishLaunching, then the argument is the files that triggered |
| // the launch of the app. |
| void OpenFiles(const std::vector<base::FilePath>& files); |
| |
| // Called when a profile is selected from the profiles NSMenu. |
| void ProfileMenuItemSelected(uint32_t index); |
| |
| // Called when a item is selected from the application dock menu. |
| void CommandFromDock(uint32_t index); |
| |
| // Called by AppShimDelegate in response to an URL being opened. If this |
| // occurs before OnDidFinishLaunching, then the argument is the files that |
| // triggered the launch of the app. |
| void OpenUrls(const std::vector<GURL>& urls); |
| |
| NSMenu* GetApplicationDockMenu(); |
| |
| private: |
| friend class TestShimClient; |
| friend class apps::MachBootstrapAcceptorTest; |
| |
| // The state of initialization. |
| enum class InitState { |
| // Waiting for OnAppFinishedLaunching to be called. |
| kWaitingForAppToFinishLaunch, |
| // Waiting for PollForChromeReady to connect to the browser process. |
| kWaitingForChromeReady, |
| // Has sent OnShimConnected to the browser process, waiting for the |
| // response. |
| kHasSentOnShimConnected, |
| // Has received the OnShimConnected response from the browser, initializaton |
| // is now complete. |
| kHasReceivedOnShimConnectedResponse, |
| }; |
| |
| // Init step 1 after OnAppFinishedLaunching. Find a running instance of Chrome |
| // to connect to, or launch Chrome if none is found. |
| void FindOrLaunchChrome(); |
| |
| // Init step 2: Poll for the mach server exposed by Chrome's AppShimListener |
| // to be initialized. Once it has, proceed to SendBootstrapOnShimConnected. |
| // If |time_until_timeout| runs out, quit the app shim. |
| void PollForChromeReady(const base::TimeDelta& time_until_timeout); |
| |
| // Init step 3: Reinterpret |endpoint| as a mojom::AppShimHostBootstrap, and |
| // send the OnShimConnected message. |
| void SendBootstrapOnShimConnected(mojo::PlatformChannelEndpoint endpoint); |
| |
| // Init step 4 (the last): The browser response to OnShimConnected. On |
| // success, this will initialize |shim_receiver_|, through which |this| will |
| // be controlled by the browser. On failure, the app will quit. |
| void OnShimConnectedResponse( |
| chrome::mojom::AppShimLaunchResult result, |
| mojo::PendingReceiver<chrome::mojom::AppShim> app_shim_receiver); |
| |
| // Builds main menu bar items. |
| void SetUpMenu(); |
| void ChannelError(uint32_t custom_reason, const std::string& description); |
| void BootstrapChannelError(uint32_t custom_reason, |
| const std::string& description); |
| |
| // chrome::mojom::AppShim implementation. |
| void CreateRemoteCocoaApplication( |
| mojo::PendingAssociatedReceiver<remote_cocoa::mojom::Application> |
| receiver) override; |
| void CreateCommandDispatcherForWidget(uint64_t widget_id) override; |
| void SetBadgeLabel(const std::string& badge_label) override; |
| void SetUserAttention( |
| chrome::mojom::AppShimAttentionType attention_type) override; |
| void UpdateProfileMenu(std::vector<chrome::mojom::ProfileMenuItemPtr> |
| profile_menu_items) override; |
| void UpdateApplicationDockMenu( |
| std::vector<chrome::mojom::ApplicationDockMenuItemPtr> dock_menu_items) |
| override; |
| |
| // Helper function to set up a connection to the AppShimListener at the given |
| // Mach endpoint name. |
| static mojo::PlatformChannelEndpoint ConnectToBrowser( |
| const mojo::NamedPlatformChannel::ServerName& server_name); |
| |
| // Helper function to search for the Chrome instance holding |
| // chrome::kSingletonLockFilename in the specified |user_data_dir|. |
| static base::scoped_nsobject<NSRunningApplication> |
| FindChromeFromSingletonLock(const base::FilePath& user_data_dir); |
| |
| const Params params_; |
| |
| // Populated by OpenFiles if it was called before OnAppFinishedLaunching |
| // was called. |
| std::vector<base::FilePath> launch_files_; |
| |
| // Populated by OpenUrls if it was called before nAppFinishedLaunching |
| // was called. |
| std::vector<GURL> launch_urls_; |
| |
| // This is the Chrome process that this app is committed to connecting to. |
| // The app will quit if this process is terminated before the mojo connection |
| // is established. |
| // This process is determined by either: |
| // - The pid specified to the app's command line (if it exists). |
| // - The pid specified in the chrome::kSingletonLockFilename file. |
| base::scoped_nsobject<NSRunningApplication> chrome_to_connect_to_; |
| |
| // The Chrome process that was launched by this app in FindOrLaunchChrome. |
| // Note that the app is not compelled to connect to this process (consider the |
| // case where multiple apps launch at the same time, and all launch their own |
| // Chrome -- only one will grab the chrome::kSingletonLockFilename, and all |
| // apps should connect to that). |
| base::scoped_nsobject<NSRunningApplication> chrome_launched_by_app_; |
| |
| mojo::IsolatedConnection bootstrap_mojo_connection_; |
| mojo::Remote<chrome::mojom::AppShimHostBootstrap> host_bootstrap_; |
| |
| mojo::Receiver<chrome::mojom::AppShim> shim_receiver_{this}; |
| mojo::Remote<chrome::mojom::AppShimHost> host_; |
| mojo::PendingReceiver<chrome::mojom::AppShimHost> host_receiver_; |
| |
| base::scoped_nsobject<AppShimDelegate> delegate_; |
| |
| InitState init_state_ = InitState::kWaitingForAppToFinishLaunch; |
| |
| // The target for NSMenuItems in the profile menu. |
| base::scoped_nsobject<ProfileMenuTarget> profile_menu_target_; |
| |
| // The target for NSMenuItems in the application dock menu. |
| base::scoped_nsobject<ApplicationDockMenuTarget> |
| application_dock_menu_target_; |
| |
| // The items in the profile menu. |
| std::vector<chrome::mojom::ProfileMenuItemPtr> profile_menu_items_; |
| |
| // The items in the appliation dock menu. |
| std::vector<chrome::mojom::ApplicationDockMenuItemPtr> dock_menu_items_; |
| |
| NSInteger attention_request_id_ = 0; |
| }; |
| |
| #endif // CHROME_APP_SHIM_APP_SHIM_CONTROLLER_H_ |