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"
14ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch#include "base/json/json_file_value_serializer.h"
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/memory/weak_ptr.h"
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/path_service.h"
17868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/string16.h"
182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/strings/string_number_conversions.h"
19868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/utf_string_conversions.h"
20f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "base/threading/sequenced_worker_pool.h"
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/values.h"
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/plugins/plugin_prefs.h"
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/profiles/profile.h"
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/common/chrome_paths.h"
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/common/chrome_switches.h"
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/common/chrome_version_info.h"
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/common/url_constants.h"
283240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch#include "content/public/browser/browser_thread.h"
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/plugin_service.h"
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/user_metrics.h"
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/web_ui.h"
322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "content/public/browser/web_ui_data_source.h"
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/web_ui_message_handler.h"
34ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch#include "content/public/common/webplugininfo.h"
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "grit/browser_resources.h"
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "grit/chromium_strings.h"
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "grit/generated_resources.h"
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "grit/theme_resources.h"
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/base/l10n/l10n_util.h"
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/base/resource/resource_bundle.h"
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_WIN)
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/win/windows_version.h"
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)using base::ASCIIToUTF16;
475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)using base::UserMetricsAction;
4890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)using content::BrowserThread;
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using content::PluginService;
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using content::WebUIMessageHandler;
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace {
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)content::WebUIDataSource* CreateNaClUIHTMLSource() {
552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  content::WebUIDataSource* source =
562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      content::WebUIDataSource::Create(chrome::kChromeUINaClHost);
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  source->SetUseJsonJSFormatV2();
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  source->AddLocalizedString("loadingMessage", IDS_NACL_LOADING_MESSAGE);
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  source->AddLocalizedString("naclLongTitle", IDS_NACL_TITLE_MESSAGE);
612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  source->SetJsonPath("strings.js");
622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  source->AddResourcePath("about_nacl.css", IDR_ABOUT_NACL_CSS);
632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  source->AddResourcePath("about_nacl.js", IDR_ABOUT_NACL_JS);
642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  source->SetDefaultResource(IDR_ABOUT_NACL_HTML);
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return source;
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)////////////////////////////////////////////////////////////////////////////////
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
7090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// NaClDomHandler
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)////////////////////////////////////////////////////////////////////////////////
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// The handler for JavaScript messages for the about:flags page.
7590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)class NaClDomHandler : public WebUIMessageHandler {
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
7790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  NaClDomHandler();
7890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  virtual ~NaClDomHandler();
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // WebUIMessageHandler implementation.
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void RegisterMessages() OVERRIDE;
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
83ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch private:
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Callback for the "requestNaClInfo" message.
855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  void HandleRequestNaClInfo(const base::ListValue* args);
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Callback for the NaCl plugin information.
88ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  void OnGotPlugins(const std::vector<content::WebPluginInfo>& plugins);
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // A helper callback that receives the result of checking if PNaCl path
91ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  // exists and checking the PNaCl |version|. |is_valid| is true if the PNaCl
92ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  // path that was returned by PathService is valid, and false otherwise.
93f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  void DidCheckPathAndVersion(const std::string* version, bool is_valid);
9490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Called when enough information is gathered to return data back to the page.
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void MaybeRespondToPage();
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Helper for MaybeRespondToPage -- called after enough information
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // is gathered.
1005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  void PopulatePageInformation(base::DictionaryValue* naclInfo);
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
102d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  // Returns whether the specified plugin is enabled.
103d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  bool isPluginEnabled(size_t plugin_index);
104d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch
105d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  // Adds information regarding the operating system and chrome version to list.
1065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  void AddOperatingSystemInfo(base::ListValue* list);
107d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch
108d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  // Adds the list of plugins for NaCl to list.
1095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  void AddPluginList(base::ListValue* list);
110d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch
111ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  // Adds the information relevant to PNaCl (e.g., enablement, paths, version)
112ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  // to the list.
1135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  void AddPnaclInfo(base::ListValue* list);
114d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch
115d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  // Adds the information relevant to NaCl to list.
1165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  void AddNaClInfo(base::ListValue* list);
117d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Whether the page has requested data.
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool page_has_requested_data_;
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Whether the plugin information is ready.
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool has_plugin_info_;
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // Whether PNaCl path was validated. PathService can return a path
12590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // that does not exists, so it needs to be validated.
12690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  bool pnacl_path_validated_;
12790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  bool pnacl_path_exists_;
128ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  std::string pnacl_version_string_;
12990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
1304e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  // Factory for the creating refs in callbacks.
1314e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  base::WeakPtrFactory<NaClDomHandler> weak_ptr_factory_;
1324e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
13390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(NaClDomHandler);
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)NaClDomHandler::NaClDomHandler()
1374e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    : page_has_requested_data_(false),
13890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      has_plugin_info_(false),
13990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      pnacl_path_validated_(false),
1404e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      pnacl_path_exists_(false),
1414e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      weak_ptr_factory_(this) {
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PluginService::GetInstance()->GetPlugins(base::Bind(
14390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      &NaClDomHandler::OnGotPlugins, weak_ptr_factory_.GetWeakPtr()));
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)NaClDomHandler::~NaClDomHandler() {
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)void NaClDomHandler::RegisterMessages() {
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  web_ui()->RegisterMessageCallback(
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "requestNaClInfo",
15290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      base::Bind(&NaClDomHandler::HandleRequestNaClInfo,
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 base::Unretained(this)));
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Helper functions for collecting a list of key-value pairs that will
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// be displayed.
1585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void AddPair(base::ListValue* list,
159a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)             const base::string16& key,
160a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)             const base::string16& value) {
1615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  base::DictionaryValue* results = new base::DictionaryValue();
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  results->SetString("key", key);
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  results->SetString("value", value);
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  list->Append(results);
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Generate an empty data-pair which acts as a line break.
1685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void AddLineBreak(base::ListValue* list) {
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AddPair(list, ASCIIToUTF16(""), ASCIIToUTF16(""));
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
172d3868032626d59662ff73b372b5d584c1d144c53Ben Murdochbool NaClDomHandler::isPluginEnabled(size_t plugin_index) {
173d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  std::vector<content::WebPluginInfo> info_array;
174d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  PluginService::GetInstance()->GetPluginInfoArray(
175d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch      GURL(), "application/x-nacl", false, &info_array, NULL);
176d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  PluginPrefs* plugin_prefs =
177d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch      PluginPrefs::GetForProfile(Profile::FromWebUI(web_ui())).get();
178d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  return (!info_array.empty() &&
179d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch          plugin_prefs->IsPluginEnabled(info_array[plugin_index]));
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void NaClDomHandler::AddOperatingSystemInfo(base::ListValue* list) {
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Obtain the Chrome version info.
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  chrome::VersionInfo version_info;
185d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  AddPair(list,
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          l10n_util::GetStringUTF16(IDS_PRODUCT_NAME),
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          ASCIIToUTF16(version_info.Version() + " (" +
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                       chrome::VersionInfo::GetVersionStringModifier() + ")"));
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // OS version information.
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // TODO(jvoung): refactor this to share the extra windows labeling
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // with about:flash, or something.
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string os_label = version_info.OSType();
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_WIN)
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::win::OSInfo* os = base::win::OSInfo::GetInstance();
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  switch (os->version()) {
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case base::win::VERSION_XP: os_label += " XP"; break;
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case base::win::VERSION_SERVER_2003:
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      os_label += " Server 2003 or XP Pro 64 bit";
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case base::win::VERSION_VISTA: os_label += " Vista or Server 2008"; break;
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case base::win::VERSION_WIN7: os_label += " 7 or Server 2008 R2"; break;
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case base::win::VERSION_WIN8: os_label += " 8 or Server 2012"; break;
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    default:  os_label += " UNKNOWN"; break;
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  os_label += " SP" + base::IntToString(os->service_pack().major);
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (os->service_pack().minor > 0)
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    os_label += "." + base::IntToString(os->service_pack().minor);
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (os->architecture() == base::win::OSInfo::X64_ARCHITECTURE)
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    os_label += " 64 bit";
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
212d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  AddPair(list,
2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          l10n_util::GetStringUTF16(IDS_ABOUT_VERSION_OS),
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          ASCIIToUTF16(os_label));
215d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  AddLineBreak(list);
216d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch}
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void NaClDomHandler::AddPluginList(base::ListValue* list) {
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Obtain the version of the NaCl plugin.
220ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  std::vector<content::WebPluginInfo> info_array;
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PluginService::GetInstance()->GetPluginInfoArray(
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      GURL(), "application/x-nacl", false, &info_array, NULL);
223a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  base::string16 nacl_version;
224a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  base::string16 nacl_key = ASCIIToUTF16("NaCl plugin");
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (info_array.empty()) {
226d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch    AddPair(list, nacl_key, ASCIIToUTF16("Disabled"));
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Only the 0th plugin is used.
2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    nacl_version = info_array[0].version + ASCIIToUTF16(" ") +
2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        info_array[0].path.LossyDisplayName();
231d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch    if (!isPluginEnabled(0)) {
2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      nacl_version += ASCIIToUTF16(" (Disabled in profile prefs)");
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
235d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch    AddPair(list, nacl_key, nacl_version);
2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Mark the rest as not used.
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (size_t i = 1; i < info_array.size(); ++i) {
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      nacl_version = info_array[i].version + ASCIIToUTF16(" ") +
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          info_array[i].path.LossyDisplayName();
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      nacl_version += ASCIIToUTF16(" (not used)");
242d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch      if (!isPluginEnabled(i)) {
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        nacl_version += ASCIIToUTF16(" (Disabled in profile prefs)");
244d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch      }
245d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch      AddPair(list, nacl_key, nacl_version);
2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
248d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  AddLineBreak(list);
249d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch}
2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void NaClDomHandler::AddPnaclInfo(base::ListValue* list) {
252d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  // Display whether PNaCl is enabled.
253a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  base::string16 pnacl_enabled_string = ASCIIToUTF16("Enabled");
254d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  if (!isPluginEnabled(0)) {
255d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch    pnacl_enabled_string = ASCIIToUTF16("Disabled in profile prefs");
2563551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  } else if (CommandLine::ForCurrentProcess()->HasSwitch(
2573551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                 switches::kDisablePnacl)) {
2583551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    pnacl_enabled_string = ASCIIToUTF16("Disabled by flag '--disable-pnacl'");
259d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  }
260d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  AddPair(list,
261d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch          ASCIIToUTF16("Portable Native Client (PNaCl)"),
262d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch          pnacl_enabled_string);
2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Obtain the version of the PNaCl translator.
2652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::FilePath pnacl_path;
2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool got_path = PathService::Get(chrome::DIR_PNACL_COMPONENT, &pnacl_path);
26790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if (!got_path || pnacl_path.empty() || !pnacl_path_exists_) {
268d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch    AddPair(list,
2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            ASCIIToUTF16("PNaCl translator"),
2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            ASCIIToUTF16("Not installed"));
2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
272d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch    AddPair(list,
2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            ASCIIToUTF16("PNaCl translator path"),
2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            pnacl_path.LossyDisplayName());
275d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch    AddPair(list,
2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            ASCIIToUTF16("PNaCl translator version"),
277ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch            ASCIIToUTF16(pnacl_version_string_));
2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
279d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  AddLineBreak(list);
280d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch}
281d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch
2825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void NaClDomHandler::AddNaClInfo(base::ListValue* list) {
283a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  base::string16 nacl_enabled_string = ASCIIToUTF16("Disabled");
284d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  if (isPluginEnabled(0) &&
285d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch      CommandLine::ForCurrentProcess()->HasSwitch(switches::kEnableNaCl)) {
286d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch    nacl_enabled_string = ASCIIToUTF16("Enabled by flag '--enable-nacl'");
287d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  }
288d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  AddPair(list,
289d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch          ASCIIToUTF16("Native Client (non-portable, outside web store)"),
290d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch          nacl_enabled_string);
291d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  AddLineBreak(list);
292d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch}
293d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch
2945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void NaClDomHandler::HandleRequestNaClInfo(const base::ListValue* args) {
295d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  page_has_requested_data_ = true;
296ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  // Force re-validation of PNaCl's path in the next call to
297d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  // MaybeRespondToPage(), in case PNaCl went from not-installed
298d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  // to installed since the request.
299d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  pnacl_path_validated_ = false;
300d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  MaybeRespondToPage();
301d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch}
302d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch
303d3868032626d59662ff73b372b5d584c1d144c53Ben Murdochvoid NaClDomHandler::OnGotPlugins(
304d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch    const std::vector<content::WebPluginInfo>& plugins) {
305d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  has_plugin_info_ = true;
306d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  MaybeRespondToPage();
307d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch}
3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void NaClDomHandler::PopulatePageInformation(base::DictionaryValue* naclInfo) {
310d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  DCHECK(pnacl_path_validated_);
311d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  // Store Key-Value pairs of about-information.
3125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  scoped_ptr<base::ListValue> list(new base::ListValue());
313d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  // Display the operating system and chrome version information.
314d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  AddOperatingSystemInfo(list.get());
315d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  // Display the list of plugins serving NaCl.
316d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  AddPluginList(list.get());
317d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  // Display information relevant to PNaCl.
318d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  AddPnaclInfo(list.get());
319d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  // Display information relevant to NaCl (non-portable.
320d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch  AddNaClInfo(list.get());
3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // naclInfo will take ownership of list, and clean it up on destruction.
3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  naclInfo->Set("naclInfo", list.release());
3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
325f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)void NaClDomHandler::DidCheckPathAndVersion(const std::string* version,
326f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                                            bool is_valid) {
32790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  pnacl_path_validated_ = true;
328f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  pnacl_path_exists_ = is_valid;
329ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  pnacl_version_string_ = *version;
33090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  MaybeRespondToPage();
33190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
33290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
333ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdochvoid CheckVersion(const base::FilePath& pnacl_path, std::string* version) {
334ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  base::FilePath pnacl_json_path =
335f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      pnacl_path.AppendASCII("pnacl_public_pnacl_json");
336ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  JSONFileValueSerializer serializer(pnacl_json_path);
337ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  std::string error;
338ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  scoped_ptr<base::Value> root(serializer.Deserialize(NULL, &error));
339ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  if (!root || !root->IsType(base::Value::TYPE_DICTIONARY))
340ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    return;
341ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
342ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  // Now try to get the field. This may leave version empty if the
343ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  // the "get" fails (no key, or wrong type).
344f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  static_cast<base::DictionaryValue*>(root.get())->GetStringASCII(
345f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      "pnacl-version", version);
346ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch}
347ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
348f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)bool CheckPathAndVersion(std::string* version) {
3493240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  base::FilePath pnacl_path;
3503240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  bool got_path = PathService::Get(chrome::DIR_PNACL_COMPONENT, &pnacl_path);
351f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  if (got_path && !pnacl_path.empty() && base::PathExists(pnacl_path)) {
352ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    CheckVersion(pnacl_path, version);
353f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    return true;
354f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  }
355f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  return false;
3563240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch}
3573240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch
35890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)void NaClDomHandler::MaybeRespondToPage() {
3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Don't reply until everything is ready.  The page will show a 'loading'
3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // message until then.
3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!page_has_requested_data_ || !has_plugin_info_)
3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
36490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if (!pnacl_path_validated_) {
365ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    std::string* version_string = new std::string;
366f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    base::PostTaskAndReplyWithResult(
367f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        BrowserThread::GetBlockingPool(),
3683240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch        FROM_HERE,
369f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        base::Bind(&CheckPathAndVersion, version_string),
370ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch        base::Bind(&NaClDomHandler::DidCheckPathAndVersion,
3713240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch                   weak_ptr_factory_.GetWeakPtr(),
372ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch                   base::Owned(version_string)));
37390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    return;
37490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  }
37590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
3765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  base::DictionaryValue naclInfo;
3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PopulatePageInformation(&naclInfo);
3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  web_ui()->CallJavascriptFunction("nacl.returnNaClInfo", naclInfo);
3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace
3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)///////////////////////////////////////////////////////////////////////////////
3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// NaClUI
3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)///////////////////////////////////////////////////////////////////////////////
3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)NaClUI::NaClUI(content::WebUI* web_ui) : WebUIController(web_ui) {
3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  content::RecordAction(UserMetricsAction("ViewAboutNaCl"));
3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
39290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  web_ui->AddMessageHandler(new NaClDomHandler());
3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Set up the about:nacl source.
3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Profile* profile = Profile::FromWebUI(web_ui);
3962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  content::WebUIDataSource::Add(profile, CreateNaClUIHTMLSource());
3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
398