Index: chrome/browser/ui/webui/settings/md_settings_ui.cc |
diff --git a/chrome/browser/ui/webui/settings/md_settings_ui.cc b/chrome/browser/ui/webui/settings/md_settings_ui.cc |
index 6e30deb2b5c5ed387ff911bb5cb9a4026e44fe40..4e0581289d4b152d1c67cf5b5bf55e5d368feb6d 100644 |
--- a/chrome/browser/ui/webui/settings/md_settings_ui.cc |
+++ b/chrome/browser/ui/webui/settings/md_settings_ui.cc |
@@ -6,9 +6,14 @@ |
#include <stddef.h> |
-#include <string> |
+#include <vector> |
+#include "base/bind.h" |
#include "base/metrics/histogram_macros.h" |
+#include "base/strings/string_piece.h" |
+#include "base/strings/string_split.h" |
+#include "base/strings/string_util.h" |
+#include "base/strings/stringprintf.h" |
#include "chrome/browser/profiles/profile.h" |
#include "chrome/browser/ui/webui/settings/about_handler.h" |
#include "chrome/browser/ui/webui/settings/appearance_handler.h" |
@@ -32,9 +37,13 @@ |
#include "chrome/common/url_constants.h" |
#include "content/public/browser/web_contents.h" |
#include "content/public/browser/web_ui.h" |
-#include "content/public/browser/web_ui_data_source.h" |
+ |
+// TODO(dbeam): make content/public interface for this. |
+#include "content/browser/webui/shared_resources_data_source.h" |
+ |
#include "grit/settings_resources.h" |
#include "grit/settings_resources_map.h" |
+#include "ui/base/resource/resource_bundle.h" |
#if defined(OS_CHROMEOS) |
#include "ash/common/system/chromeos/palette/palette_utils.h" |
@@ -58,11 +67,15 @@ |
#include "chrome/browser/ui/webui/settings/native_certificates_handler.h" |
#endif // defined(USE_NSS_CERTS) |
+#include "third_party/re2/src/re2/re2.h" |
+ |
namespace settings { |
MdSettingsUI::MdSettingsUI(content::WebUI* web_ui, const GURL& url) |
: content::WebUIController(web_ui), |
- WebContentsObserver(web_ui->GetWebContents()) { |
+ WebContentsObserver(web_ui->GetWebContents()), |
+ html_source_(nullptr) { |
+ // weak_ptr_factory_(this) { |
Profile* profile = Profile::FromWebUI(web_ui); |
AddSettingsPageUIHandler(new AppearanceHandler(web_ui)); |
@@ -108,40 +121,154 @@ MdSettingsUI::MdSettingsUI(content::WebUI* web_ui, const GURL& url) |
CHECK(url.GetOrigin() == GURL(chrome::kChromeUISettingsURL).GetOrigin() || |
url.GetOrigin() == GURL(chrome::kChromeUIMdSettingsURL).GetOrigin()); |
- content::WebUIDataSource* html_source = |
- content::WebUIDataSource::Create(url.host()); |
+ html_source_ = content::WebUIDataSource::Create(url.host()); |
+ html_source_->SetRequestFilter( |
+ base::Bind(&MdSettingsUI::RequestFilter, base::Unretained(this))); |
#if defined(OS_CHROMEOS) |
chromeos::settings::EasyUnlockSettingsHandler* easy_unlock_handler = |
- chromeos::settings::EasyUnlockSettingsHandler::Create(html_source, |
+ chromeos::settings::EasyUnlockSettingsHandler::Create(html_source_, |
profile); |
if (easy_unlock_handler) |
AddSettingsPageUIHandler(easy_unlock_handler); |
- html_source->AddBoolean("noteAllowed", ash::IsPaletteEnabled()); |
- html_source->AddBoolean("quickUnlockEnabled", |
- chromeos::IsQuickUnlockEnabled()); |
+ html_source_->AddBoolean("noteAllowed", ash::IsPaletteEnabled()); |
+ html_source_->AddBoolean("quickUnlockEnabled", |
+ chromeos::IsQuickUnlockEnabled()); |
#endif |
- AddSettingsPageUIHandler(AboutHandler::Create(html_source, profile)); |
- AddSettingsPageUIHandler(ResetSettingsHandler::Create(html_source, profile)); |
+ AddSettingsPageUIHandler(AboutHandler::Create(html_source_, profile)); |
+ AddSettingsPageUIHandler(ResetSettingsHandler::Create(html_source_, profile)); |
// Add all settings resources. |
for (size_t i = 0; i < kSettingsResourcesSize; ++i) { |
- html_source->AddResourcePath(kSettingsResources[i].name, |
- kSettingsResources[i].value); |
+ html_source_->AddResourcePath(kSettingsResources[i].name, |
+ kSettingsResources[i].value); |
} |
- AddLocalizedStrings(html_source, profile); |
- html_source->SetDefaultResource(IDR_SETTINGS_SETTINGS_HTML); |
+ AddLocalizedStrings(html_source_, profile); |
+ html_source_->SetDefaultResource(IDR_SETTINGS_SETTINGS_HTML); |
+ |
+ base::TimeTicks then = base::TimeTicks::Now(); |
+ |
+ std::vector<GURL> urls; |
+ GatherPreloadUrls(GURL("chrome://md-settings/settings.html"), &urls); |
+ |
+ for (const GURL& url : urls) { |
+ const std::string spec = url.spec(); |
+ |
+ std::string rel; |
+ std::string as; |
+ if (base::EndsWith(spec, ".js", base::CompareCase::INSENSITIVE_ASCII)) { |
+ rel = "preload"; |
+ as = " as=\"script\""; |
+ } else if (base::EndsWith(spec, ".css", |
+ base::CompareCase::INSENSITIVE_ASCII)) { |
+ rel = "preload"; |
+ as = " as=\"style\""; |
+ } else if (base::EndsWith(spec, ".html", |
+ base::CompareCase::INSENSITIVE_ASCII)) { |
+ continue; |
+ rel = "import"; |
+ // as="document" doesn't work yet. |
+ } |
+ |
+ preloads_.append(base::StringPrintf( |
+ "<link rel=\"%s\" href=\"%s\"%s>\n", |
+ rel.c_str(), spec.c_str(), as.c_str())); |
+ } |
+ |
+ LOG(ERROR) << "time gathering: " << (base::TimeTicks::Now() - then).InMilliseconds(); |
content::WebUIDataSource::Add(web_ui->GetWebContents()->GetBrowserContext(), |
- html_source); |
+ html_source_); |
} |
MdSettingsUI::~MdSettingsUI() { |
} |
+bool MdSettingsUI::RequestFilter( |
+ const std::string& path, |
+ const content::WebUIDataSource::GotDataCallback& callback) { |
+ if (!path.empty()) |
+ return false; |
+ |
+ base::StringPiece settings_html = |
+ ui::ResourceBundle::GetSharedInstance().GetRawDataResource( |
+ IDR_SETTINGS_SETTINGS_HTML); |
+ |
+ std::string preloads_placeholder("<!-- preloads -->"); |
+ size_t preloads_start = settings_html.find(preloads_placeholder); |
+ |
+ std::string response; |
+ settings_html.substr(0, preloads_start).AppendToString(&response); |
+ response.append(preloads_); |
+ settings_html.substr(preloads_start + preloads_placeholder.size()) |
+ .AppendToString(&response); |
+ |
+ callback.Run(base::RefCountedString::TakeString(&response)); |
+ return true; |
+} |
+ |
+void MdSettingsUI::GatherPreloadUrls(const GURL& url, std::vector<GURL>* urls) { |
+ CHECK(url.SchemeIs(content::kChromeUIScheme) && |
+ (url.host() == content::kChromeUIResourcesHost || |
+ url.host() == chrome::kChromeUISettingsHost || |
+ url.host() == chrome::kChromeUIMdSettingsHost)); |
+ |
+ std::string path = url.path(); |
+ CHECK(!path.empty()); |
+ |
+ if (path[0] == '/') |
+ path.erase(0, 1); |
+ |
+ int idr = -1; |
+ |
+ if (url.host() == content::kChromeUIResourcesHost) { |
+ const auto& map = content::SharedResourcesDataSource::GetResourcesMap(); |
+ auto it = map.find(path); |
+ if (it != map.end()) |
+ idr = it->second; |
+ } else { |
+ const auto& map = html_source_->path_to_idr_map(); |
+ auto it = map.find(path); |
+ if (it != map.end()) |
+ idr = it->second; |
+ } |
+ |
+ if (idr == -1) { |
+ LOG(ERROR) << "@@ unknown url: " << url << ", path: " << path << " @@"; |
+ return; |
+ } |
+ |
+ std::string resource = ui::ResourceBundle::GetSharedInstance() |
+ .GetRawDataResource(idr).as_string(); |
+ |
+ re2::StringPiece re2_resource(resource); |
+ |
+ re2::RE2 regex( |
+ "<link[^>]+?rel=\"import\"[^>]+?href=\"([^\"]+)\"|" |
+ "<link[^>]+?rel=\"stylesheet\"[^>]+?href=\"([^\"]+)\"|" |
+ "<script[^>]+?src=\"([^\"]+)"); |
+ |
+ re2::StringPiece html, css, js; |
+ |
+ while (re2::RE2::FindAndConsume(&re2_resource, regex, &html, &css, &js)) { |
+ CHECK_EQ(html.empty() + css.empty() + js.empty(), 2); |
+ |
+ std::string new_path = html.as_string() + css.as_string() + js.as_string(); |
+ CHECK(!new_path.empty()); |
+ |
+ GURL new_url = url.Resolve(new_path); |
+ |
+ if (std::find(urls->begin(), urls->end(), new_url) != urls->end()) |
+ continue; |
+ |
+ urls->push_back(new_url); |
+ GatherPreloadUrls(new_url, urls); |
+ } |
+} |
+ |
void MdSettingsUI::AddSettingsPageUIHandler(SettingsPageUIHandler* handler) { |
DCHECK(handler); |
handlers_.insert(handler); |