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
3// found in the LICENSE file.
4
5#ifndef COMPONENTS_NACL_RENDERER_NEXE_LOAD_MANAGER_H_
6#define COMPONENTS_NACL_RENDERER_NEXE_LOAD_MANAGER_H_
7
8#include <map>
9#include <string>
10
11#include "base/files/file.h"
12#include "base/macros.h"
13#include "base/memory/scoped_ptr.h"
14#include "base/memory/shared_memory.h"
15#include "base/memory/weak_ptr.h"
16#include "base/time/time.h"
17#include "ppapi/c/private/ppb_nacl_private.h"
18#include "url/gurl.h"
19
20namespace content {
21class PepperPluginInstance;
22}
23
24namespace nacl {
25
26class ManifestServiceChannel;
27class TrustedPluginChannel;
28
29// NexeLoadManager provides methods for reporting the progress of loading a
30// nexe.
31class NexeLoadManager {
32 public:
33  ~NexeLoadManager();
34
35  static void Create(PP_Instance instance);
36  // Non-owning pointer.
37  static NexeLoadManager* Get(PP_Instance instance);
38  static void Delete(PP_Instance instance);
39
40  void NexeFileDidOpen(int32_t pp_error,
41                       const base::File& file,
42                       int32_t http_status,
43                       int64_t nexe_bytes_read,
44                       const std::string& url,
45                       base::TimeDelta time_since_open);
46  void ReportLoadSuccess(const std::string& url,
47                         uint64_t loaded_bytes,
48                         uint64_t total_bytes);
49  void ReportLoadError(PP_NaClError error,
50                       const std::string& error_message);
51
52  // console_message is a part of the error that is logged to
53  // the JavaScript console but is not reported to JavaScript via
54  // the lastError property.  This is used to report internal errors which
55  // may easily change in new versions of the browser and we don't want apps
56  // to come to depend on the details of these errors.
57  void ReportLoadError(PP_NaClError error,
58                       const std::string& error_message,
59                       const std::string& console_message);
60  void ReportLoadAbort();
61  void NexeDidCrash();
62
63  // TODO(dmichael): Everything below this comment should eventually be made
64  // private, when ppb_nacl_private_impl.cc is no longer using them directly.
65  // The intent is for this class to only expose functions for reporting a
66  // load state transition (e.g., ReportLoadError, ReportProgress,
67  // ReportLoadAbort, etc.)
68  void set_trusted_plugin_channel(scoped_ptr<TrustedPluginChannel> channel);
69  void set_manifest_service_channel(
70      scoped_ptr<ManifestServiceChannel> channel);
71
72  PP_NaClReadyState nacl_ready_state();
73  void set_nacl_ready_state(PP_NaClReadyState ready_state);
74
75  void SetReadOnlyProperty(PP_Var key, PP_Var value);
76  void SetLastError(const std::string& error);
77  void LogToConsole(const std::string& message);
78
79  bool is_installed() const { return is_installed_; }
80
81  int32_t exit_status() const { return exit_status_; }
82  void set_exit_status(int32_t exit_status);
83
84  void InitializePlugin(uint32_t argc, const char* argn[], const char* argv[]);
85
86  void ReportStartupOverhead() const;
87
88  int64_t nexe_size() const { return nexe_size_; }
89
90  bool RequestNaClManifest(const std::string& url);
91  void ProcessNaClManifest(const std::string& program_url);
92
93  // URL resolution support.
94  // plugin_base_url is the URL used for resolving relative URLs used in
95  // src="...".
96  const GURL& plugin_base_url() const { return plugin_base_url_; }
97
98  // manifest_base_url is the URL used for resolving relative URLs mentioned
99  // in manifest files.  If the manifest is a data URI, this is an empty string
100  const GURL& manifest_base_url() const { return manifest_base_url_; }
101
102  // Returns the manifest URL passed as an argument for this plugin instance.
103  std::string GetManifestURLArgument() const;
104
105  // Returns true if the MIME type for this plugin matches the type for PNaCl,
106  // false otherwise.
107  bool IsPNaCl() const;
108
109  // Returns true if dev interfaces are enabled for this plugin.
110  bool DevInterfacesEnabled() const;
111
112  // Returns the time that the work for PNaCl translation began.
113  base::Time pnacl_start_time() const { return pnacl_start_time_; }
114  void set_pnacl_start_time(base::Time time) {
115    pnacl_start_time_ = time;
116  }
117
118  const std::string& program_url() const { return program_url_; }
119
120  void set_crash_info_shmem_handle(base::SharedMemoryHandle h) {
121    crash_info_shmem_handle_ = h;
122  }
123
124 private:
125  DISALLOW_COPY_AND_ASSIGN(NexeLoadManager);
126
127  explicit NexeLoadManager(PP_Instance instance);
128
129  void ReportDeadNexe();
130
131  // Copies a crash log to the console, one line at a time.
132  void CopyCrashLogToJsConsole(const std::string& crash_log);
133
134  PP_Instance pp_instance_;
135  PP_NaClReadyState nacl_ready_state_;
136  bool nexe_error_reported_;
137
138  std::string program_url_;
139
140  // A flag indicating if the NaCl executable is being loaded from an installed
141  // application.  This flag is used to bucket UMA statistics more precisely to
142  // help determine whether nexe loading problems are caused by networking
143  // issues.  (Installed applications will be loaded from disk.)
144  // Unfortunately, the definition of what it means to be part of an installed
145  // application is a little murky - for example an installed application can
146  // register a mime handler that loads NaCl executables into an arbitrary web
147  // page.  As such, the flag actually means "our best guess, based on the URLs
148  // for NaCl resources that we have seen so far".
149  bool is_installed_;
150
151  // Time of a successful nexe load.
152  base::Time ready_time_;
153
154  // Time of plugin initialization.
155  base::Time init_time_;
156
157  // Time of the start of loading a NaCl module.
158  base::Time load_start_;
159
160  // The exit status of the plugin process.
161  // This will have a value in the range (0x00-0xff) if the exit status is set,
162  // or -1 if set_exit_status() has never been called.
163  int32_t exit_status_;
164
165  // Size of the downloaded nexe, in bytes.
166  int64_t nexe_size_;
167
168  // Non-owning.
169  content::PepperPluginInstance* plugin_instance_;
170
171  // The URL for the document corresponding to this plugin instance.
172  GURL plugin_base_url_;
173
174  GURL manifest_base_url_;
175
176  // Arguments passed to this plugin instance from the DOM.
177  std::map<std::string, std::string> args_;
178
179  // We store mime_type_ outside of args_ explicitly because we change it to be
180  // lowercase.
181  std::string mime_type_;
182
183  base::Time pnacl_start_time_;
184
185  base::SharedMemoryHandle crash_info_shmem_handle_;
186
187  scoped_ptr<TrustedPluginChannel> trusted_plugin_channel_;
188  scoped_ptr<ManifestServiceChannel> manifest_service_channel_;
189  base::WeakPtrFactory<NexeLoadManager> weak_factory_;
190};
191
192}  // namespace nacl
193
194#endif  // COMPONENTS_NACL_RENDERER_NEXE_LOAD_MANAGER_H_
195