1// Copyright (c) 2011 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#include "chrome/browser/ui/webui/conflicts_ui.h"
6
7#if defined(OS_WIN)
8
9#include <string>
10
11#include "base/string_number_conversions.h"
12#include "base/utf_string_conversions.h"
13#include "base/values.h"
14#include "chrome/browser/enumerate_modules_model_win.h"
15#include "chrome/browser/metrics/user_metrics.h"
16#include "chrome/browser/profiles/profile.h"
17#include "chrome/browser/ui/webui/chrome_url_data_manager.h"
18#include "chrome/common/jstemplate_builder.h"
19#include "chrome/common/url_constants.h"
20#include "content/browser/tab_contents/tab_contents.h"
21#include "content/common/notification_observer.h"
22#include "content/common/notification_registrar.h"
23#include "content/common/notification_service.h"
24#include "grit/browser_resources.h"
25#include "grit/chromium_strings.h"
26#include "grit/generated_resources.h"
27#include "grit/theme_resources.h"
28#include "ui/base/l10n/l10n_util.h"
29#include "ui/base/resource/resource_bundle.h"
30
31namespace {
32
33////////////////////////////////////////////////////////////////////////////////
34//
35// ConflictsUIHTMLSource
36//
37////////////////////////////////////////////////////////////////////////////////
38
39class ConflictsUIHTMLSource : public ChromeURLDataManager::DataSource {
40 public:
41  ConflictsUIHTMLSource()
42      : DataSource(chrome::kChromeUIConflictsHost, MessageLoop::current()) {}
43
44  // Called when the network layer has requested a resource underneath
45  // the path we registered.
46  virtual void StartDataRequest(const std::string& path,
47                                bool is_incognito,
48                                int request_id);
49
50  virtual std::string GetMimeType(const std::string&) const {
51    return "text/html";
52  }
53
54 private:
55  DISALLOW_COPY_AND_ASSIGN(ConflictsUIHTMLSource);
56};
57
58void ConflictsUIHTMLSource::StartDataRequest(const std::string& path,
59                                             bool is_incognito,
60                                             int request_id) {
61  // Strings used in the JsTemplate file.
62  DictionaryValue localized_strings;
63  localized_strings.SetString("loadingMessage",
64      l10n_util::GetStringUTF16(IDS_CONFLICTS_LOADING_MESSAGE));
65  localized_strings.SetString("modulesLongTitle",
66      l10n_util::GetStringUTF16(IDS_CONFLICTS_CHECK_PAGE_TITLE_LONG));
67  localized_strings.SetString("modulesBlurb",
68      l10n_util::GetStringUTF16(IDS_CONFLICTS_EXPLANATION_TEXT));
69  localized_strings.SetString("moduleSuspectedBad",
70      l10n_util::GetStringUTF16(IDS_CONFLICTS_CHECK_WARNING_SUSPECTED));
71  localized_strings.SetString("moduleConfirmedBad",
72      l10n_util::GetStringUTF16(IDS_CONFLICTS_CHECK_WARNING_CONFIRMED));
73  localized_strings.SetString("helpCenterLink",
74      l10n_util::GetStringUTF16(IDS_CONFLICTS_HELP_CENTER_LINK));
75  localized_strings.SetString("investigatingText",
76      l10n_util::GetStringUTF16(IDS_CONFLICTS_CHECK_INVESTIGATING));
77  localized_strings.SetString("modulesNoneLoaded",
78      l10n_util::GetStringUTF16(IDS_CONFLICTS_NO_MODULES_LOADED));
79  localized_strings.SetString("headerSoftware",
80      l10n_util::GetStringUTF16(IDS_CONFLICTS_HEADER_SOFTWARE));
81  localized_strings.SetString("headerSignedBy",
82      l10n_util::GetStringUTF16(IDS_CONFLICTS_HEADER_SIGNED_BY));
83  localized_strings.SetString("headerLocation",
84      l10n_util::GetStringUTF16(IDS_CONFLICTS_HEADER_LOCATION));
85  localized_strings.SetString("headerVersion",
86      l10n_util::GetStringUTF16(IDS_CONFLICTS_HEADER_VERSION));
87  localized_strings.SetString("headerHelpTip",
88      l10n_util::GetStringUTF16(IDS_CONFLICTS_HEADER_HELP_TIP));
89
90  ChromeURLDataManager::DataSource::SetFontAndTextDirection(&localized_strings);
91
92  static const base::StringPiece flags_html(
93      ResourceBundle::GetSharedInstance().GetRawDataResource(
94          IDR_ABOUT_CONFLICTS_HTML));
95  std::string full_html(flags_html.data(), flags_html.size());
96  jstemplate_builder::AppendJsonHtml(&localized_strings, &full_html);
97  jstemplate_builder::AppendI18nTemplateSourceHtml(&full_html);
98  jstemplate_builder::AppendI18nTemplateProcessHtml(&full_html);
99  jstemplate_builder::AppendJsTemplateSourceHtml(&full_html);
100
101  scoped_refptr<RefCountedBytes> html_bytes(new RefCountedBytes);
102  html_bytes->data.resize(full_html.size());
103  std::copy(full_html.begin(), full_html.end(), html_bytes->data.begin());
104
105  SendResponse(request_id, html_bytes);
106}
107
108////////////////////////////////////////////////////////////////////////////////
109//
110// ConflictsDOMHandler
111//
112////////////////////////////////////////////////////////////////////////////////
113
114// The handler for JavaScript messages for the about:flags page.
115class ConflictsDOMHandler : public WebUIMessageHandler,
116                            public NotificationObserver {
117 public:
118  ConflictsDOMHandler() {}
119  virtual ~ConflictsDOMHandler() {}
120
121  // WebUIMessageHandler implementation.
122  virtual void RegisterMessages();
123
124  // Callback for the "requestModuleList" message.
125  void HandleRequestModuleList(const ListValue* args);
126
127 private:
128  void SendModuleList();
129
130  void Observe(NotificationType type,
131               const NotificationSource& source,
132               const NotificationDetails& details);
133
134  NotificationRegistrar registrar_;
135
136  DISALLOW_COPY_AND_ASSIGN(ConflictsDOMHandler);
137};
138
139void ConflictsDOMHandler::RegisterMessages() {
140  web_ui_->RegisterMessageCallback("requestModuleList",
141      NewCallback(this, &ConflictsDOMHandler::HandleRequestModuleList));
142}
143
144void ConflictsDOMHandler::HandleRequestModuleList(const ListValue* args) {
145  // This request is handled asynchronously. See Observe for when we reply back.
146  registrar_.Add(this, NotificationType::MODULE_LIST_ENUMERATED,
147                 NotificationService::AllSources());
148  EnumerateModulesModel::GetInstance()->ScanNow();
149}
150
151void ConflictsDOMHandler::SendModuleList() {
152  EnumerateModulesModel* loaded_modules = EnumerateModulesModel::GetInstance();
153  ListValue* list = loaded_modules->GetModuleList();
154  DictionaryValue results;
155  results.Set("moduleList", list);
156
157  // Add the section title and the total count for bad modules found.
158  int confirmed_bad = loaded_modules->confirmed_bad_modules_detected();
159  int suspected_bad = loaded_modules->suspected_bad_modules_detected();
160  string16 table_title;
161  if (!confirmed_bad && !suspected_bad) {
162    table_title += l10n_util::GetStringFUTF16(
163        IDS_CONFLICTS_CHECK_PAGE_TABLE_TITLE_SUFFIX_ONE,
164            base::IntToString16(list->GetSize()));
165  } else {
166    table_title += l10n_util::GetStringFUTF16(
167        IDS_CONFLICTS_CHECK_PAGE_TABLE_TITLE_SUFFIX_TWO,
168            base::IntToString16(list->GetSize()),
169            base::IntToString16(confirmed_bad),
170            base::IntToString16(suspected_bad));
171  }
172  results.SetString("modulesTableTitle", table_title);
173
174  web_ui_->CallJavascriptFunction("returnModuleList", results);
175}
176
177void ConflictsDOMHandler::Observe(NotificationType type,
178                                  const NotificationSource& source,
179                                  const NotificationDetails& details) {
180  switch (type.value) {
181    case NotificationType::MODULE_LIST_ENUMERATED:
182      SendModuleList();
183      registrar_.RemoveAll();
184      break;
185    default:
186      NOTREACHED();
187      break;
188  }
189}
190
191}  // namespace
192
193///////////////////////////////////////////////////////////////////////////////
194//
195// ConflictsUI
196//
197///////////////////////////////////////////////////////////////////////////////
198
199ConflictsUI::ConflictsUI(TabContents* contents) : WebUI(contents) {
200  UserMetrics::RecordAction(
201      UserMetricsAction("ViewAboutConflicts"), contents->profile());
202
203  AddMessageHandler((new ConflictsDOMHandler())->Attach(this));
204
205  ConflictsUIHTMLSource* html_source = new ConflictsUIHTMLSource();
206
207  // Set up the about:conflicts source.
208  contents->profile()->GetChromeURLDataManager()->AddDataSource(html_source);
209}
210
211// static
212RefCountedMemory* ConflictsUI::GetFaviconResourceBytes() {
213  return ResourceBundle::GetSharedInstance().
214      LoadDataResourceBytes(IDR_CONFLICT_FAVICON);
215}
216
217#endif
218