nacl_ui.cc revision ca12bfac764ba476d6cd062bf1dde12cc64c3f40
15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/ui/webui/nacl_ui.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <string>
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <vector>
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/bind.h"
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/bind_helpers.h"
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/command_line.h"
132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/file_util.h"
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/memory/weak_ptr.h"
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/path_service.h"
16868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/string16.h"
172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/strings/string_number_conversions.h"
18868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/utf_string_conversions.h"
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/values.h"
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/plugins/plugin_prefs.h"
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/profiles/profile.h"
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/common/chrome_paths.h"
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/common/chrome_switches.h"
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/common/chrome_version_info.h"
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/common/url_constants.h"
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/plugin_service.h"
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/user_metrics.h"
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/web_ui.h"
292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "content/public/browser/web_ui_data_source.h"
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/web_ui_message_handler.h"
31ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch#include "content/public/common/webplugininfo.h"
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "grit/browser_resources.h"
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "grit/chromium_strings.h"
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "grit/generated_resources.h"
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "grit/theme_resources.h"
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/base/l10n/l10n_util.h"
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/base/resource/resource_bundle.h"
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_WIN)
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/win/windows_version.h"
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)using content::BrowserThread;
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using content::PluginService;
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using content::UserMetricsAction;
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using content::WebUIMessageHandler;
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace {
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)content::WebUIDataSource* CreateNaClUIHTMLSource() {
512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  content::WebUIDataSource* source =
522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      content::WebUIDataSource::Create(chrome::kChromeUINaClHost);
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  source->SetUseJsonJSFormatV2();
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  source->AddLocalizedString("loadingMessage", IDS_NACL_LOADING_MESSAGE);
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  source->AddLocalizedString("naclLongTitle", IDS_NACL_TITLE_MESSAGE);
572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  source->SetJsonPath("strings.js");
582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  source->AddResourcePath("about_nacl.css", IDR_ABOUT_NACL_CSS);
592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  source->AddResourcePath("about_nacl.js", IDR_ABOUT_NACL_JS);
602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  source->SetDefaultResource(IDR_ABOUT_NACL_HTML);
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return source;
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)////////////////////////////////////////////////////////////////////////////////
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
6690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// NaClDomHandler
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)////////////////////////////////////////////////////////////////////////////////
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)class NaClDomHandler;
7190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
7290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// This class performs a check that the PNaCl path which was returned by
7390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// PathService is valid. One class instance is created per NaClDomHandler
7490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// and it is destroyed after the check is completed.
7590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)class NaClDomHandlerProxy
7690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    : public base::RefCountedThreadSafe<NaClDomHandlerProxy> {
7790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) public:
7890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  explicit NaClDomHandlerProxy(NaClDomHandler* handler);
7990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
8090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // A helper to check if PNaCl path exists.
8190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  void ValidatePnaclPath();
8290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
8390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  void set_handler(NaClDomHandler* handler) { handler_ = handler; }
8490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
8590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) private:
8690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  friend class base::RefCountedThreadSafe<NaClDomHandlerProxy>;
8790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  virtual ~NaClDomHandlerProxy() {}
8890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
8990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // A helper callback that receives the result of checking if PNaCl path
9090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // exists.
9190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  void ValidatePnaclPathCallback(bool is_valid);
9290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
9390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // The handler that requested checking PNaCl file path.
9490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  NaClDomHandler* handler_;  // weak
9590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
9690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(NaClDomHandlerProxy);
9790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)};
9890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// The handler for JavaScript messages for the about:flags page.
10090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)class NaClDomHandler : public WebUIMessageHandler {
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
10290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  NaClDomHandler();
10390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  virtual ~NaClDomHandler();
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // WebUIMessageHandler implementation.
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void RegisterMessages() OVERRIDE;
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Callback for the "requestNaClInfo" message.
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void HandleRequestNaClInfo(const ListValue* args);
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Callback for the NaCl plugin information.
112ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  void OnGotPlugins(const std::vector<content::WebPluginInfo>& plugins);
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // A helper callback that receives the result of checking if PNaCl path
11590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // exists. |is_valid| is true if the PNaCl path that was returned by
11690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // PathService is valid, and false otherwise.
11790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  void DidValidatePnaclPath(bool is_valid);
11890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Called when enough information is gathered to return data back to the page.
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void MaybeRespondToPage();
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Helper for MaybeRespondToPage -- called after enough information
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // is gathered.
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void PopulatePageInformation(DictionaryValue* naclInfo);
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Factory for the creating refs in callbacks.
12890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  base::WeakPtrFactory<NaClDomHandler> weak_ptr_factory_;
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Whether the page has requested data.
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool page_has_requested_data_;
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Whether the plugin information is ready.
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool has_plugin_info_;
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // Whether PNaCl path was validated. PathService can return a path
13790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // that does not exists, so it needs to be validated.
13890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  bool pnacl_path_validated_;
13990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  bool pnacl_path_exists_;
14090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
14190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // A proxy for handling cross threads messages.
14290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  scoped_refptr<NaClDomHandlerProxy> proxy_;
14390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
14490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(NaClDomHandler);
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)NaClDomHandlerProxy::NaClDomHandlerProxy(NaClDomHandler* handler)
14890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    : handler_(handler) {
14990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
15090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
15190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)void NaClDomHandlerProxy::ValidatePnaclPath() {
15290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if (!BrowserThread::CurrentlyOn(BrowserThread::FILE)) {
15390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    BrowserThread::PostTask(
15490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        BrowserThread::FILE, FROM_HERE,
15590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        base::Bind(&NaClDomHandlerProxy::ValidatePnaclPath, this));
15690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    return;
15790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  }
15890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
15990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  base::FilePath pnacl_path;
16090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  bool got_path = PathService::Get(chrome::DIR_PNACL_COMPONENT, &pnacl_path);
16190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // The PathService may return an empty string if PNaCl is not yet installed.
16290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // However, do not trust that the path returned by the PathService exists.
16390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // Check for existence here.
16490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  ValidatePnaclPathCallback(
1657dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    got_path && !pnacl_path.empty() && base::PathExists(pnacl_path));
16690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
16790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
16890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)void NaClDomHandlerProxy::ValidatePnaclPathCallback(bool is_valid) {
16990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) {
17090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    BrowserThread::PostTask(
17190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        BrowserThread::UI, FROM_HERE,
17290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        base::Bind(&NaClDomHandlerProxy::ValidatePnaclPathCallback,
17390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        this, is_valid));
17490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    return;
17590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  }
17690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
17790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // Check that handler_ is still valid, it could be set to NULL if navigation
17890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // happened while checking that the PNaCl file exists.
17990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if (handler_)
18090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    handler_->DidValidatePnaclPath(is_valid);
18190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
18290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
18390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)NaClDomHandler::NaClDomHandler()
184c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    : weak_ptr_factory_(this),
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      page_has_requested_data_(false),
18690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      has_plugin_info_(false),
18790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      pnacl_path_validated_(false),
18890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      pnacl_path_exists_(false),
18990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      proxy_(new NaClDomHandlerProxy(this)) {
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PluginService::GetInstance()->GetPlugins(base::Bind(
19190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      &NaClDomHandler::OnGotPlugins, weak_ptr_factory_.GetWeakPtr()));
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
19490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)NaClDomHandler::~NaClDomHandler() {
195868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (proxy_.get())
19690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    proxy_->set_handler(NULL);
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
19990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)void NaClDomHandler::RegisterMessages() {
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  web_ui()->RegisterMessageCallback(
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "requestNaClInfo",
20290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      base::Bind(&NaClDomHandler::HandleRequestNaClInfo,
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 base::Unretained(this)));
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Helper functions for collecting a list of key-value pairs that will
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// be displayed.
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void AddPair(ListValue* list, const string16& key, const string16& value) {
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DictionaryValue* results = new DictionaryValue();
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  results->SetString("key", key);
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  results->SetString("value", value);
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  list->Append(results);
2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Generate an empty data-pair which acts as a line break.
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void AddLineBreak(ListValue* list) {
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AddPair(list, ASCIIToUTF16(""), ASCIIToUTF16(""));
2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Check whether a commandline switch is turned on or off.
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ListFlagStatus(ListValue* list, const std::string& flag_label,
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    const std::string& flag_name) {
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (CommandLine::ForCurrentProcess()->HasSwitch(flag_name))
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    AddPair(list, ASCIIToUTF16(flag_label), ASCIIToUTF16("On"));
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  else
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    AddPair(list, ASCIIToUTF16(flag_label), ASCIIToUTF16("Off"));
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
22990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)void NaClDomHandler::HandleRequestNaClInfo(const ListValue* args) {
2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  page_has_requested_data_ = true;
2317dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  // Force re-validation of pnacl's path in the next call to
2327dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  // MaybeRespondToPage(), in case PNaCl went from not-installed
2337dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  // to installed since the request.
2347dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  pnacl_path_validated_ = false;
2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MaybeRespondToPage();
2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
23890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)void NaClDomHandler::OnGotPlugins(
239ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    const std::vector<content::WebPluginInfo>& plugins) {
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  has_plugin_info_ = true;
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MaybeRespondToPage();
2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
24490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)void NaClDomHandler::PopulatePageInformation(DictionaryValue* naclInfo) {
24590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  DCHECK(pnacl_path_validated_);
2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Store Key-Value pairs of about-information.
2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<ListValue> list(new ListValue());
2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Obtain the Chrome version info.
2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  chrome::VersionInfo version_info;
2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AddPair(list.get(),
2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          l10n_util::GetStringUTF16(IDS_PRODUCT_NAME),
2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          ASCIIToUTF16(version_info.Version() + " (" +
2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                       chrome::VersionInfo::GetVersionStringModifier() + ")"));
2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // OS version information.
2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // TODO(jvoung): refactor this to share the extra windows labeling
2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // with about:flash, or something.
2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string os_label = version_info.OSType();
2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_WIN)
2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::win::OSInfo* os = base::win::OSInfo::GetInstance();
2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  switch (os->version()) {
2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case base::win::VERSION_XP: os_label += " XP"; break;
2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case base::win::VERSION_SERVER_2003:
2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      os_label += " Server 2003 or XP Pro 64 bit";
2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case base::win::VERSION_VISTA: os_label += " Vista or Server 2008"; break;
2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case base::win::VERSION_WIN7: os_label += " 7 or Server 2008 R2"; break;
2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case base::win::VERSION_WIN8: os_label += " 8 or Server 2012"; break;
2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    default:  os_label += " UNKNOWN"; break;
2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  os_label += " SP" + base::IntToString(os->service_pack().major);
2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (os->service_pack().minor > 0)
2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    os_label += "." + base::IntToString(os->service_pack().minor);
2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (os->architecture() == base::win::OSInfo::X64_ARCHITECTURE)
2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    os_label += " 64 bit";
2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AddPair(list.get(),
2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          l10n_util::GetStringUTF16(IDS_ABOUT_VERSION_OS),
2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          ASCIIToUTF16(os_label));
2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AddLineBreak(list.get());
2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Obtain the version of the NaCl plugin.
285ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  std::vector<content::WebPluginInfo> info_array;
2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PluginService::GetInstance()->GetPluginInfoArray(
2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      GURL(), "application/x-nacl", false, &info_array, NULL);
2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  string16 nacl_version;
2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  string16 nacl_key = ASCIIToUTF16("NaCl plugin");
2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (info_array.empty()) {
2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    AddPair(list.get(), nacl_key, ASCIIToUTF16("Disabled"));
2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PluginPrefs* plugin_prefs =
2947d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)        PluginPrefs::GetForProfile(Profile::FromWebUI(web_ui())).get();
2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Only the 0th plugin is used.
2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    nacl_version = info_array[0].version + ASCIIToUTF16(" ") +
2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        info_array[0].path.LossyDisplayName();
2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!plugin_prefs->IsPluginEnabled(info_array[0])) {
3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      nacl_version += ASCIIToUTF16(" (Disabled in profile prefs)");
3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      AddPair(list.get(), nacl_key, nacl_version);
3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    AddPair(list.get(), nacl_key, nacl_version);
3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Mark the rest as not used.
3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (size_t i = 1; i < info_array.size(); ++i) {
3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      nacl_version = info_array[i].version + ASCIIToUTF16(" ") +
3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          info_array[i].path.LossyDisplayName();
3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      nacl_version += ASCIIToUTF16(" (not used)");
3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (!plugin_prefs->IsPluginEnabled(info_array[i]))
3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        nacl_version += ASCIIToUTF16(" (Disabled in profile prefs)");
3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      AddPair(list.get(), nacl_key, nacl_version);
3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Check that commandline flags are enabled.
3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ListFlagStatus(list.get(), "Flag '--enable-nacl'", switches::kEnableNaCl);
3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AddLineBreak(list.get());
3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Obtain the version of the PNaCl translator.
3232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::FilePath pnacl_path;
3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool got_path = PathService::Get(chrome::DIR_PNACL_COMPONENT, &pnacl_path);
32590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if (!got_path || pnacl_path.empty() || !pnacl_path_exists_) {
3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    AddPair(list.get(),
3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            ASCIIToUTF16("PNaCl translator"),
3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            ASCIIToUTF16("Not installed"));
3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    AddPair(list.get(),
3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            ASCIIToUTF16("PNaCl translator path"),
3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            pnacl_path.LossyDisplayName());
3337d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    // Version string is part of the directory name:
3347d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    // pnacl/<version>/_platform_specific/<arch>/[files]
3357d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    // Keep in sync with pnacl_component_installer.cc.
3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    AddPair(list.get(),
3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            ASCIIToUTF16("PNaCl translator version"),
3387d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)            pnacl_path.DirName().DirName().BaseName().LossyDisplayName());
3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ListFlagStatus(list.get(), "Flag '--enable-pnacl'", switches::kEnablePnacl);
3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // naclInfo will take ownership of list, and clean it up on destruction.
3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  naclInfo->Set("naclInfo", list.release());
3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
34690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)void NaClDomHandler::DidValidatePnaclPath(bool is_valid) {
34790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  pnacl_path_validated_ = true;
34890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  pnacl_path_exists_ = is_valid;
34990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  MaybeRespondToPage();
35090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
35190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
35290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)void NaClDomHandler::MaybeRespondToPage() {
3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Don't reply until everything is ready.  The page will show a 'loading'
3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // message until then.
3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!page_has_requested_data_ || !has_plugin_info_)
3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
35890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if (!pnacl_path_validated_) {
359868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    DCHECK(proxy_.get());
36090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    proxy_->ValidatePnaclPath();
36190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    return;
36290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  }
36390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DictionaryValue naclInfo;
3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PopulatePageInformation(&naclInfo);
3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  web_ui()->CallJavascriptFunction("nacl.returnNaClInfo", naclInfo);
3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace
3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)///////////////////////////////////////////////////////////////////////////////
3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// NaClUI
3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)///////////////////////////////////////////////////////////////////////////////
3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)NaClUI::NaClUI(content::WebUI* web_ui) : WebUIController(web_ui) {
3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  content::RecordAction(UserMetricsAction("ViewAboutNaCl"));
3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
38090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  web_ui->AddMessageHandler(new NaClDomHandler());
3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Set up the about:nacl source.
3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Profile* profile = Profile::FromWebUI(web_ui);
3842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  content::WebUIDataSource::Add(profile, CreateNaClUIHTMLSource());
3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
386