blob: c6c3966253b7c8e4f8b33afb069282ba3792b6c6 [file] [log] [blame]
// Copyright 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "ios/chrome/browser/ui/webui/net_export/net_export_ui.h"
#include <memory>
#include <string>
#include "base/bind.h"
#include "base/location.h"
#include "base/macros.h"
#include "base/memory/ptr_util.h"
#include "base/scoped_observer.h"
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
#include "base/values.h"
#include "components/grit/components_resources.h"
#include "components/net_log/chrome_net_log.h"
#include "components/net_log/net_export_file_writer.h"
#include "components/net_log/net_export_ui_constants.h"
#include "ios/chrome/browser/application_context.h"
#include "ios/chrome/browser/browser_state/chrome_browser_state.h"
#include "ios/chrome/browser/chrome_url_constants.h"
#include "ios/chrome/browser/ui/show_mail_composer_util.h"
#include "ios/chrome/common/channel_info.h"
#include "ios/chrome/grit/ios_strings.h"
#include "ios/web/public/web_thread.h"
#include "ios/web/public/web_ui_ios_data_source.h"
#include "ios/web/public/webui/web_ui_ios.h"
#include "ios/web/public/webui/web_ui_ios_message_handler.h"
#include "net/log/net_log_capture_mode.h"
#include "net/url_request/url_request_context_getter.h"
namespace {
web::WebUIIOSDataSource* CreateNetExportHTMLSource() {
web::WebUIIOSDataSource* source =
web::WebUIIOSDataSource::Create(kChromeUINetExportHost);
source->SetJsonPath("strings.js");
source->AddResourcePath(net_log::kNetExportUIJS, IDR_NET_LOG_NET_EXPORT_JS);
source->SetDefaultResource(IDR_NET_LOG_NET_EXPORT_HTML);
return source;
}
// This class receives javascript messages from the renderer.
// Note that the WebUI infrastructure runs on the UI thread, therefore all of
// this class's public methods are expected to run on the UI thread. All static
// functions except SendEmail run on FILE_USER_BLOCKING thread.
class NetExportMessageHandler
: public web::WebUIIOSMessageHandler,
public base::SupportsWeakPtr<NetExportMessageHandler>,
public net_log::NetExportFileWriter::StateObserver {
public:
NetExportMessageHandler();
~NetExportMessageHandler() override;
// WebUIMessageHandler implementation.
void RegisterMessages() override;
// Messages.
void OnEnableNotifyUIWithState(const base::ListValue* list);
void OnStartNetLog(const base::ListValue* list);
void OnStopNetLog(const base::ListValue* list);
void OnSendNetLog(const base::ListValue* list);
// net_log::NetExportFileWriter::StateObserver implementation.
void OnNewState(const base::DictionaryValue& state) override;
private:
// Send NetLog data via email.
static void SendEmail(const base::FilePath& file_to_send);
void NotifyUIWithState(
std::unique_ptr<base::DictionaryValue> file_writer_state);
// Cache of GetApplicationContex()->GetNetLog()->net_export_file_writer().
// This is owned by ChromeNetLog which is owned by BrowserProcessImpl.
net_log::NetExportFileWriter* file_writer_;
ScopedObserver<net_log::NetExportFileWriter,
net_log::NetExportFileWriter::StateObserver>
state_observer_manager_;
base::WeakPtrFactory<NetExportMessageHandler> weak_ptr_factory_;
DISALLOW_COPY_AND_ASSIGN(NetExportMessageHandler);
};
NetExportMessageHandler::NetExportMessageHandler()
: file_writer_(
GetApplicationContext()->GetNetLog()->net_export_file_writer()),
state_observer_manager_(this),
weak_ptr_factory_(this) {
file_writer_->Initialize(
web::WebThread::GetTaskRunnerForThread(web::WebThread::IO));
}
NetExportMessageHandler::~NetExportMessageHandler() {
file_writer_->StopNetLog(nullptr, nullptr);
}
void NetExportMessageHandler::RegisterMessages() {
DCHECK_CURRENTLY_ON(web::WebThread::UI);
web_ui()->RegisterMessageCallback(
net_log::kEnableNotifyUIWithStateHandler,
base::Bind(&NetExportMessageHandler::OnEnableNotifyUIWithState,
base::Unretained(this)));
web_ui()->RegisterMessageCallback(
net_log::kStartNetLogHandler,
base::Bind(&NetExportMessageHandler::OnStartNetLog,
base::Unretained(this)));
web_ui()->RegisterMessageCallback(
net_log::kStopNetLogHandler,
base::Bind(&NetExportMessageHandler::OnStopNetLog,
base::Unretained(this)));
web_ui()->RegisterMessageCallback(
net_log::kSendNetLogHandler,
base::Bind(&NetExportMessageHandler::OnSendNetLog,
base::Unretained(this)));
}
void NetExportMessageHandler::OnEnableNotifyUIWithState(
const base::ListValue* list) {
DCHECK_CURRENTLY_ON(web::WebThread::UI);
if (!state_observer_manager_.IsObservingSources()) {
state_observer_manager_.Add(file_writer_);
}
NotifyUIWithState(file_writer_->GetState());
}
void NetExportMessageHandler::OnStartNetLog(const base::ListValue* list) {
DCHECK_CURRENTLY_ON(web::WebThread::UI);
const base::Value::ListStorage& params = list->GetList();
// Determine the capture mode.
net::NetLogCaptureMode capture_mode = net::NetLogCaptureMode::Default();
if (params.size() > 0 && params[0].is_string()) {
capture_mode = net_log::NetExportFileWriter::CaptureModeFromString(
params[0].GetString());
}
// Determine the max file size.
size_t max_log_file_size = net_log::NetExportFileWriter::kNoLimit;
if (params.size() > 1 && params[1].is_int() && params[1].GetInt() > 0) {
max_log_file_size = params[1].GetInt();
}
file_writer_->StartNetLog(
base::FilePath(), capture_mode, max_log_file_size,
base::CommandLine::ForCurrentProcess()->GetCommandLineString(),
GetChannelString(),
{GetApplicationContext()->GetSystemURLRequestContext()});
}
void NetExportMessageHandler::OnStopNetLog(const base::ListValue* list) {
DCHECK_CURRENTLY_ON(web::WebThread::UI);
file_writer_->StopNetLog(
nullptr, GetApplicationContext()->GetSystemURLRequestContext());
}
void NetExportMessageHandler::OnSendNetLog(const base::ListValue* list) {
DCHECK_CURRENTLY_ON(web::WebThread::UI);
file_writer_->GetFilePathToCompletedLog(
base::Bind(&NetExportMessageHandler::SendEmail));
}
void NetExportMessageHandler::OnNewState(const base::DictionaryValue& state) {
NotifyUIWithState(state.CreateDeepCopy());
}
// static
void NetExportMessageHandler::SendEmail(const base::FilePath& file_to_send) {
if (file_to_send.empty())
return;
DCHECK_CURRENTLY_ON(web::WebThread::UI);
std::string email;
std::string subject = "net_internals_log";
std::string title = "Issue number: ";
std::string body =
"Please add some informative text about the network issues.";
ShowMailComposer(base::UTF8ToUTF16(email), base::UTF8ToUTF16(subject),
base::UTF8ToUTF16(body), base::UTF8ToUTF16(title),
file_to_send,
IDS_IOS_NET_EXPORT_NO_EMAIL_ACCOUNTS_ALERT_TITLE,
IDS_IOS_NET_EXPORT_NO_EMAIL_ACCOUNTS_ALERT_MESSAGE);
}
void NetExportMessageHandler::NotifyUIWithState(
std::unique_ptr<base::DictionaryValue> file_writer_state) {
DCHECK_CURRENTLY_ON(web::WebThread::UI);
DCHECK(web_ui());
web_ui()->CallJavascriptFunction(net_log::kOnExportNetLogInfoChanged,
*file_writer_state);
}
} // namespace
NetExportUI::NetExportUI(web::WebUIIOS* web_ui)
: web::WebUIIOSController(web_ui) {
web_ui->AddMessageHandler(base::MakeUnique<NetExportMessageHandler>());
web::WebUIIOSDataSource::Add(ios::ChromeBrowserState::FromWebUIIOS(web_ui),
CreateNetExportHTMLSource());
}