Home | History | Annotate | Download | only in browser
      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 #ifndef CONTENT_BROWSER_PLUGIN_LOADER_POSIX_H_
      6 #define CONTENT_BROWSER_PLUGIN_LOADER_POSIX_H_
      7 
      8 #include <deque>
      9 #include <vector>
     10 
     11 #include "base/basictypes.h"
     12 #include "base/compiler_specific.h"
     13 #include "base/memory/ref_counted.h"
     14 #include "base/time/time.h"
     15 #include "content/browser/plugin_service_impl.h"
     16 #include "content/public/browser/utility_process_host_client.h"
     17 #include "content/public/common/webplugininfo.h"
     18 #include "ipc/ipc_sender.h"
     19 
     20 namespace base {
     21 class MessageLoopProxy;
     22 }
     23 
     24 namespace content {
     25 class UtilityProcessHost;
     26 
     27 // This class is responsible for managing the out-of-process plugin loading on
     28 // POSIX systems. It primarily lives on the IO thread, but has a brief stay on
     29 // the FILE thread to iterate over plugin directories when it is first
     30 // constructed.
     31 //
     32 // The following is the algorithm used to load plugins:
     33 // 1. This asks the PluginList for the list of all potential plugins to attempt
     34 //    to load. This is referred to as the canonical list.
     35 // 2. The child process this hosts is forked and the canonical list is sent to
     36 //    it.
     37 // 3. The child process iterates over the canonical list, attempting to load
     38 //    each plugin in the order specified by the list. It sends an IPC message
     39 //    to the browser after each load, indicating success or failure. The two
     40 //    processes synchronize the position in the vector that will be used to
     41 //    attempt to load the next plugin.
     42 // 4. If the child dies during this process, the host forks another child and
     43 //    resumes loading at the position past the plugin that it just attempted to
     44 //    load, bypassing the problematic plugin.
     45 // 5. This algorithm continues until the canonical list has been walked to the
     46 //    end, after which the list of loaded plugins is set on the PluginList and
     47 //    the completion callback is run.
     48 class CONTENT_EXPORT PluginLoaderPosix
     49     : public NON_EXPORTED_BASE(UtilityProcessHostClient),
     50       public IPC::Sender {
     51  public:
     52   PluginLoaderPosix();
     53 
     54   // Must be called from the IO thread.
     55   void LoadPlugins(
     56       scoped_refptr<base::MessageLoopProxy> target_loop,
     57       const PluginService::GetPluginsCallback& callback);
     58 
     59   // UtilityProcessHostClient:
     60   virtual void OnProcessCrashed(int exit_code) OVERRIDE;
     61   virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE;
     62 
     63   // IPC::Sender:
     64   virtual bool Send(IPC::Message* msg) OVERRIDE;
     65 
     66  private:
     67   struct PendingCallback {
     68     PendingCallback(scoped_refptr<base::MessageLoopProxy> target_loop,
     69                     const PluginService::GetPluginsCallback& callback);
     70     ~PendingCallback();
     71 
     72     scoped_refptr<base::MessageLoopProxy> target_loop;
     73     PluginService::GetPluginsCallback callback;
     74   };
     75 
     76   virtual ~PluginLoaderPosix();
     77 
     78   // Called on the FILE thread to get the list of plugin paths to probe.
     79   void GetPluginsToLoad();
     80 
     81   // Must be called on the IO thread.
     82   virtual void LoadPluginsInternal();
     83 
     84   // Message handlers.
     85   void OnPluginLoaded(uint32 index, const WebPluginInfo& plugin);
     86   void OnPluginLoadFailed(uint32 index, const base::FilePath& plugin_path);
     87 
     88   // Checks if the plugin path is an internal plugin, and, if it is, adds it to
     89   // |loaded_plugins_|.
     90   bool MaybeAddInternalPlugin(const base::FilePath& plugin_path);
     91 
     92   // Runs all the registered callbacks on each's target loop if the condition
     93   // for ending the load process is done (i.e. the |next_load_index_| is outside
     94   // the range of the |canonical_list_|).
     95   bool MaybeRunPendingCallbacks();
     96 
     97   // The process host for which this is a client.
     98   base::WeakPtr<UtilityProcessHost> process_host_;
     99 
    100   // A list of paths to plugins which will be loaded by the utility process, in
    101   // the order specified by this vector.
    102   std::vector<base::FilePath> canonical_list_;
    103 
    104   // The index in |canonical_list_| of the plugin that the child process will
    105   // attempt to load next.
    106   size_t next_load_index_;
    107 
    108   // Internal plugins that have been registered at the time of loading.
    109   std::vector<WebPluginInfo> internal_plugins_;
    110 
    111   // A vector of plugins that have been loaded successfully.
    112   std::vector<WebPluginInfo> loaded_plugins_;
    113 
    114   // The callback and message loop on which the callback will be run when the
    115   // plugin loading process has been completed.
    116   std::deque<PendingCallback> callbacks_;
    117 
    118   // The time at which plugin loading started.
    119   base::TimeTicks load_start_time_;
    120 
    121   friend class MockPluginLoaderPosix;
    122   DISALLOW_COPY_AND_ASSIGN(PluginLoaderPosix);
    123 };
    124 
    125 }  // namespace content
    126 
    127 #endif  // CONTENT_BROWSER_PLUGIN_LOADER_POSIX_H_
    128