1// Copyright (c) 2013 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#ifndef WIN8_VIEWER_METRO_VIEWER_PROCESS_HOST_H_
6#define WIN8_VIEWER_METRO_VIEWER_PROCESS_HOST_H_
7
8#include "base/basictypes.h"
9#include "base/callback.h"
10#include "base/memory/scoped_ptr.h"
11#include "base/strings/string16.h"
12#include "base/threading/non_thread_safe.h"
13#include "ipc/ipc_channel_proxy.h"
14#include "ipc/ipc_listener.h"
15#include "ipc/ipc_sender.h"
16#include "ipc/message_filter.h"
17#include "ui/gfx/native_widget_types.h"
18#include "win8/viewer/metro_viewer_exports.h"
19
20namespace base {
21class SingleThreadTaskRunner;
22class WaitableEvent;
23}
24
25namespace IPC {
26class ChannelProxy;
27class Message;
28}
29
30namespace win8 {
31
32// Abstract base class for various Metro viewer process host implementations.
33class METRO_VIEWER_EXPORT MetroViewerProcessHost : public IPC::Listener,
34                                                   public IPC::Sender,
35                                                   public base::NonThreadSafe {
36 public:
37  typedef base::Callback<void(const base::FilePath&, int, void*)>
38      OpenFileCompletion;
39
40  typedef base::Callback<void(const std::vector<base::FilePath>&, void*)>
41      OpenMultipleFilesCompletion;
42
43  typedef base::Callback<void(const base::FilePath&, int, void*)>
44      SaveFileCompletion;
45
46  typedef base::Callback<void(const base::FilePath&, int, void*)>
47      SelectFolderCompletion;
48
49  typedef base::Callback<void(void*)> FileSelectionCanceled;
50
51  // Initializes a viewer process host to connect to the Metro viewer process
52  // over IPC. The given task runner correspond to a thread on which
53  // IPC::Channel is created and used (e.g. IO thread). Instantly connects to
54  // the viewer process if one is already connected to |ipc_channel_name|; a
55  // viewer can otherwise be launched synchronously via
56  // LaunchViewerAndWaitForConnection().
57  explicit MetroViewerProcessHost(
58      base::SingleThreadTaskRunner* ipc_task_runner);
59  virtual ~MetroViewerProcessHost();
60
61  // Returns the process id of the viewer process if one is connected to this
62  // host, returns base::kNullProcessId otherwise.
63  base::ProcessId GetViewerProcessId();
64
65  // Launches the viewer process associated with the given |app_user_model_id|
66  // and blocks until that viewer process connects or until a timeout is
67  // reached. Returns true if the viewer process connects before the timeout is
68  // reached. NOTE: this assumes that the app referred to by |app_user_model_id|
69  // is registered as the default browser.
70  bool LaunchViewerAndWaitForConnection(
71      const base::string16& app_user_model_id);
72
73  // Handles the activate desktop command for Metro Chrome Ash. The |ash_exit|
74  // parameter indicates whether the Ash process would be shutdown after
75  // activating the desktop.
76  static void HandleActivateDesktop(const base::FilePath& shortcut,
77                                    bool ash_exit);
78
79  // Handles the metro exit command.  Notifies the metro viewer to shutdown
80  // gracefully.
81  static void HandleMetroExit();
82
83  // Handles the open file operation for Metro Chrome Ash. The on_success
84  // callback passed in is invoked when we receive the opened file name from
85  // the metro viewer. The on failure callback is invoked on failure.
86  static void HandleOpenFile(const base::string16& title,
87                             const base::FilePath& default_path,
88                             const base::string16& filter,
89                             const OpenFileCompletion& on_success,
90                             const FileSelectionCanceled& on_failure);
91
92  // Handles the open multiple file operation for Metro Chrome Ash. The
93  // on_success callback passed in is invoked when we receive the opened file
94  // names from the metro viewer. The on failure callback is invoked on failure.
95  static void HandleOpenMultipleFiles(
96      const base::string16& title,
97      const base::FilePath& default_path,
98      const base::string16& filter,
99      const OpenMultipleFilesCompletion& on_success,
100      const FileSelectionCanceled& on_failure);
101
102  // Handles the save file operation for Metro Chrome Ash. The on_success
103  // callback passed in is invoked when we receive the saved file name from
104  // the metro viewer. The on failure callback is invoked on failure.
105  static void HandleSaveFile(const base::string16& title,
106                             const base::FilePath& default_path,
107                             const base::string16& filter,
108                             int filter_index,
109                             const base::string16& default_extension,
110                             const SaveFileCompletion& on_success,
111                             const FileSelectionCanceled& on_failure);
112
113  // Handles the select folder for Metro Chrome Ash. The on_success
114  // callback passed in is invoked when we receive the folder name from the
115  // metro viewer. The on failure callback is invoked on failure.
116  static void HandleSelectFolder(const base::string16& title,
117                                 const SelectFolderCompletion& on_success,
118                                 const FileSelectionCanceled& on_failure);
119
120 protected:
121  // IPC::Sender implementation:
122  virtual bool Send(IPC::Message* msg) OVERRIDE;
123
124  // IPC::Listener implementation:
125  virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE;
126  virtual void OnChannelError() OVERRIDE = 0;
127
128 private:
129  // The following are the implementation for the corresponding static methods
130  // above, see them for descriptions.
131  void HandleOpenFileImpl(const base::string16& title,
132                          const base::FilePath& default_path,
133                          const base::string16& filter,
134                          const OpenFileCompletion& on_success,
135                          const FileSelectionCanceled& on_failure);
136  void HandleOpenMultipleFilesImpl(
137      const base::string16& title,
138      const base::FilePath& default_path,
139      const base::string16& filter,
140      const OpenMultipleFilesCompletion& on_success,
141      const FileSelectionCanceled& on_failure);
142  void HandleSaveFileImpl(const base::string16& title,
143                          const base::FilePath& default_path,
144                          const base::string16& filter,
145                          int filter_index,
146                          const base::string16& default_extension,
147                          const SaveFileCompletion& on_success,
148                          const FileSelectionCanceled& on_failure);
149  void HandleSelectFolderImpl(const base::string16& title,
150                              const SelectFolderCompletion& on_success,
151                              const FileSelectionCanceled& on_failure);
152
153  // Called over IPC by the viewer process to tell this host that it should be
154  // drawing to |target_surface|.
155  virtual void OnSetTargetSurface(gfx::NativeViewId target_surface,
156                                  float device_scale) = 0;
157
158  // Called over IPC by the viewer process to request that the url passed in be
159  // opened.
160  virtual void OnOpenURL(const base::string16& url) = 0;
161
162  // Called over IPC by the viewer process to request that the search string
163  // passed in is passed to the default search provider and a URL navigation be
164  // performed.
165  virtual void OnHandleSearchRequest(const base::string16& search_string) = 0;
166
167  // Called over IPC by the viewer process when the window size has changed.
168  virtual void OnWindowSizeChanged(uint32 width, uint32 height) = 0;
169
170  void NotifyChannelConnected();
171
172  // IPC message handing methods:
173  void OnFileSaveAsDone(bool success,
174                        const base::FilePath& filename,
175                        int filter_index);
176  void OnFileOpenDone(bool success, const base::FilePath& filename);
177  void OnMultiFileOpenDone(bool success,
178                           const std::vector<base::FilePath>& files);
179  void OnSelectFolderDone(bool success, const base::FilePath& folder);
180
181  // Inner message filter used to handle connection event on the IPC channel
182  // proxy's background thread. This prevents consumers of
183  // MetroViewerProcessHost from having to pump messages on their own message
184  // loop.
185  class InternalMessageFilter : public IPC::MessageFilter {
186   public:
187    InternalMessageFilter(MetroViewerProcessHost* owner);
188
189    // IPC::MessageFilter implementation.
190    virtual void OnChannelConnected(int32 peer_pid) OVERRIDE;
191
192   private:
193    MetroViewerProcessHost* owner_;
194    DISALLOW_COPY_AND_ASSIGN(InternalMessageFilter);
195  };
196
197  scoped_ptr<IPC::ChannelProxy> channel_;
198  scoped_ptr<base::WaitableEvent> channel_connected_event_;
199  scoped_refptr<InternalMessageFilter> message_filter_;
200
201  static MetroViewerProcessHost* instance_;
202
203  // Saved callbacks which inform the caller about the result of the open file/
204  // save file/select operations.
205  OpenFileCompletion file_open_completion_callback_;
206  OpenMultipleFilesCompletion multi_file_open_completion_callback_;
207  SaveFileCompletion file_saveas_completion_callback_;
208  SelectFolderCompletion select_folder_completion_callback_;
209  FileSelectionCanceled failure_callback_;
210
211  DISALLOW_COPY_AND_ASSIGN(MetroViewerProcessHost);
212};
213
214}  // namespace win8
215
216#endif  // WIN8_VIEWER_METRO_VIEWER_PROCESS_HOST_H_
217