Home | History | Annotate | Download | only in webui
      1 // Copyright (c) 2013 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/net_export_ui.h"
      6 
      7 #include <string>
      8 
      9 #include "base/bind.h"
     10 #include "base/memory/scoped_ptr.h"
     11 #include "base/strings/string_util.h"
     12 #include "base/strings/utf_string_conversions.h"
     13 #include "base/values.h"
     14 #include "chrome/browser/browser_process.h"
     15 #include "chrome/browser/net/chrome_net_log.h"
     16 #include "chrome/browser/net/net_log_temp_file.h"
     17 #include "chrome/browser/profiles/profile.h"
     18 #include "chrome/common/url_constants.h"
     19 #include "content/public/browser/browser_thread.h"
     20 #include "content/public/browser/url_data_source.h"
     21 #include "content/public/browser/web_contents.h"
     22 #include "content/public/browser/web_ui.h"
     23 #include "content/public/browser/web_ui_data_source.h"
     24 #include "content/public/browser/web_ui_message_handler.h"
     25 #include "grit/browser_resources.h"
     26 
     27 #if defined(OS_ANDROID)
     28 #include "chrome/browser/android/intent_helper.h"
     29 #endif
     30 
     31 using content::BrowserThread;
     32 using content::WebContents;
     33 using content::WebUIMessageHandler;
     34 
     35 namespace {
     36 
     37 content::WebUIDataSource* CreateNetExportHTMLSource() {
     38   content::WebUIDataSource* source =
     39       content::WebUIDataSource::Create(chrome::kChromeUINetExportHost);
     40 
     41   source->SetJsonPath("strings.js");
     42   source->AddResourcePath("net_export.js", IDR_NET_EXPORT_JS);
     43   source->SetDefaultResource(IDR_NET_EXPORT_HTML);
     44   return source;
     45 }
     46 
     47 // This class receives javascript messages from the renderer.
     48 // Note that the WebUI infrastructure runs on the UI thread, therefore all of
     49 // this class's public methods are expected to run on the UI thread. All static
     50 // functions except SendEmail run on FILE_USER_BLOCKING thread.
     51 class NetExportMessageHandler
     52     : public WebUIMessageHandler,
     53       public base::SupportsWeakPtr<NetExportMessageHandler> {
     54  public:
     55   NetExportMessageHandler();
     56   virtual ~NetExportMessageHandler();
     57 
     58   // WebUIMessageHandler implementation.
     59   virtual void RegisterMessages() OVERRIDE;
     60 
     61   // Messages.
     62   void OnGetExportNetLogInfo(const base::ListValue* list);
     63   void OnStartNetLog(const base::ListValue* list);
     64   void OnStopNetLog(const base::ListValue* list);
     65   void OnSendNetLog(const base::ListValue* list);
     66 
     67  private:
     68   // Calls NetLogTempFile's ProcessCommand with DO_START and DO_STOP commands.
     69   static void ProcessNetLogCommand(
     70       base::WeakPtr<NetExportMessageHandler> net_export_message_handler,
     71       NetLogTempFile* net_log_temp_file,
     72       NetLogTempFile::Command command);
     73 
     74   // Returns the path to the file which has NetLog data.
     75   static base::FilePath GetNetLogFileName(NetLogTempFile* net_log_temp_file);
     76 
     77   // Send state/file information from NetLogTempFile.
     78   static void SendExportNetLogInfo(
     79       base::WeakPtr<NetExportMessageHandler> net_export_message_handler,
     80       NetLogTempFile* net_log_temp_file);
     81 
     82   // Send NetLog data via email. This runs on UI thread.
     83   static void SendEmail(const base::FilePath& file_to_send);
     84 
     85   // Call NetExportView.onExportNetLogInfoChanged JavsScript function in the
     86   // renderer, passing in |arg|. Takes ownership of |arg|.
     87   void OnExportNetLogInfoChanged(base::Value* arg);
     88 
     89   // Cache of g_browser_process->net_log()->net_log_temp_file().
     90   NetLogTempFile* net_log_temp_file_;
     91 
     92   base::WeakPtrFactory<NetExportMessageHandler> weak_ptr_factory_;
     93 
     94   DISALLOW_COPY_AND_ASSIGN(NetExportMessageHandler);
     95 };
     96 
     97 NetExportMessageHandler::NetExportMessageHandler()
     98     : net_log_temp_file_(g_browser_process->net_log()->net_log_temp_file()),
     99       weak_ptr_factory_(this) {
    100 }
    101 
    102 NetExportMessageHandler::~NetExportMessageHandler() {
    103   // Cancel any in-progress requests to collect net_log into temporary file.
    104   BrowserThread::PostTask(
    105       BrowserThread::FILE_USER_BLOCKING,
    106       FROM_HERE,
    107       base::Bind(&NetLogTempFile::ProcessCommand,
    108                  base::Unretained(net_log_temp_file_),
    109                  NetLogTempFile::DO_STOP));
    110 }
    111 
    112 void NetExportMessageHandler::RegisterMessages() {
    113   DCHECK_CURRENTLY_ON(BrowserThread::UI);
    114 
    115   web_ui()->RegisterMessageCallback(
    116       "getExportNetLogInfo",
    117       base::Bind(&NetExportMessageHandler::OnGetExportNetLogInfo,
    118                  base::Unretained(this)));
    119   web_ui()->RegisterMessageCallback(
    120       "startNetLog",
    121       base::Bind(&NetExportMessageHandler::OnStartNetLog,
    122                  base::Unretained(this)));
    123   web_ui()->RegisterMessageCallback(
    124       "stopNetLog",
    125       base::Bind(&NetExportMessageHandler::OnStopNetLog,
    126                  base::Unretained(this)));
    127   web_ui()->RegisterMessageCallback(
    128       "sendNetLog",
    129       base::Bind(&NetExportMessageHandler::OnSendNetLog,
    130                  base::Unretained(this)));
    131 }
    132 
    133 void NetExportMessageHandler::OnGetExportNetLogInfo(
    134     const base::ListValue* list) {
    135   BrowserThread::PostTask(
    136       BrowserThread::FILE_USER_BLOCKING,
    137       FROM_HERE,
    138       base::Bind(&NetExportMessageHandler::SendExportNetLogInfo,
    139                  weak_ptr_factory_.GetWeakPtr(),
    140                  net_log_temp_file_));
    141 }
    142 
    143 void NetExportMessageHandler::OnStartNetLog(const base::ListValue* list) {
    144   bool strip_private_data = false;
    145   if (!list->GetBoolean(0, &strip_private_data)) {
    146     NOTREACHED() << "Failed to convert argument 1";
    147     return;
    148   }
    149   ProcessNetLogCommand(weak_ptr_factory_.GetWeakPtr(),
    150                        net_log_temp_file_,
    151                        (strip_private_data ?
    152                             NetLogTempFile::DO_START_STRIP_PRIVATE_DATA :
    153                             NetLogTempFile::DO_START));
    154 }
    155 
    156 void NetExportMessageHandler::OnStopNetLog(const base::ListValue* list) {
    157   ProcessNetLogCommand(weak_ptr_factory_.GetWeakPtr(),
    158                        net_log_temp_file_,
    159                        NetLogTempFile::DO_STOP);
    160 }
    161 
    162 void NetExportMessageHandler::OnSendNetLog(const base::ListValue* list) {
    163   content::BrowserThread::PostTaskAndReplyWithResult(
    164     content::BrowserThread::FILE_USER_BLOCKING,
    165         FROM_HERE,
    166         base::Bind(&NetExportMessageHandler::GetNetLogFileName,
    167                    base::Unretained(net_log_temp_file_)),
    168         base::Bind(&NetExportMessageHandler::SendEmail));
    169 }
    170 
    171 // static
    172 void NetExportMessageHandler::ProcessNetLogCommand(
    173     base::WeakPtr<NetExportMessageHandler> net_export_message_handler,
    174     NetLogTempFile* net_log_temp_file,
    175     NetLogTempFile::Command command) {
    176   if (!BrowserThread::CurrentlyOn(BrowserThread::FILE_USER_BLOCKING)) {
    177     BrowserThread::PostTask(
    178         BrowserThread::FILE_USER_BLOCKING,
    179         FROM_HERE,
    180         base::Bind(&NetExportMessageHandler::ProcessNetLogCommand,
    181                    net_export_message_handler,
    182                    net_log_temp_file,
    183                    command));
    184     return;
    185   }
    186 
    187   DCHECK_CURRENTLY_ON(BrowserThread::FILE_USER_BLOCKING);
    188   net_log_temp_file->ProcessCommand(command);
    189   SendExportNetLogInfo(net_export_message_handler, net_log_temp_file);
    190 }
    191 
    192 // static
    193 base::FilePath NetExportMessageHandler::GetNetLogFileName(
    194     NetLogTempFile* net_log_temp_file) {
    195   DCHECK_CURRENTLY_ON(BrowserThread::FILE_USER_BLOCKING);
    196   base::FilePath net_export_file_path;
    197   net_log_temp_file->GetFilePath(&net_export_file_path);
    198   return net_export_file_path;
    199 }
    200 
    201 // static
    202 void NetExportMessageHandler::SendExportNetLogInfo(
    203     base::WeakPtr<NetExportMessageHandler> net_export_message_handler,
    204     NetLogTempFile* net_log_temp_file) {
    205   DCHECK_CURRENTLY_ON(BrowserThread::FILE_USER_BLOCKING);
    206   base::Value* value = net_log_temp_file->GetState();
    207   if (!BrowserThread::PostTask(
    208       BrowserThread::UI, FROM_HERE,
    209       base::Bind(&NetExportMessageHandler::OnExportNetLogInfoChanged,
    210                  net_export_message_handler,
    211                  value))) {
    212     // Failed posting the task, avoid leaking.
    213     delete value;
    214   }
    215 }
    216 
    217 // static
    218 void NetExportMessageHandler::SendEmail(const base::FilePath& file_to_send) {
    219   if (file_to_send.empty())
    220     return;
    221   DCHECK_CURRENTLY_ON(BrowserThread::UI);
    222 
    223 #if defined(OS_ANDROID)
    224   std::string email;
    225   std::string subject = "net_internals_log";
    226   std::string title = "Issue number: ";
    227   std::string body =
    228       "Please add some informative text about the network issues.";
    229   base::FilePath::StringType file_to_attach(file_to_send.value());
    230   chrome::android::SendEmail(
    231       base::UTF8ToUTF16(email), base::UTF8ToUTF16(subject),
    232       base::UTF8ToUTF16(body), base::UTF8ToUTF16(title),
    233       base::UTF8ToUTF16(file_to_attach));
    234 #endif
    235 }
    236 
    237 void NetExportMessageHandler::OnExportNetLogInfoChanged(base::Value* arg) {
    238   scoped_ptr<base::Value> value(arg);
    239   DCHECK_CURRENTLY_ON(BrowserThread::UI);
    240   web_ui()->CallJavascriptFunction(
    241       "NetExportView.getInstance().onExportNetLogInfoChanged", *arg);
    242 }
    243 
    244 }  // namespace
    245 
    246 NetExportUI::NetExportUI(content::WebUI* web_ui) : WebUIController(web_ui) {
    247   web_ui->AddMessageHandler(new NetExportMessageHandler());
    248 
    249   // Set up the chrome://net-export/ source.
    250   Profile* profile = Profile::FromWebUI(web_ui);
    251   content::WebUIDataSource::Add(profile, CreateNetExportHTMLSource());
    252 }
    253