| // Copyright 2014 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/web/webui/web_ui_ios_data_source_impl.h" |
| |
| #include <string> |
| |
| #include "base/bind.h" |
| #include "base/memory/ref_counted_memory.h" |
| #include "base/strings/string_util.h" |
| #include "base/strings/utf_string_conversions.h" |
| #import "ios/web/public/web_client.h" |
| #include "ui/base/webui/jstemplate_builder.h" |
| #include "ui/base/webui/web_ui_util.h" |
| |
| #if !defined(__has_feature) || !__has_feature(objc_arc) |
| #error "This file requires ARC support." |
| #endif |
| |
| namespace web { |
| |
| // static |
| WebUIIOSDataSource* WebUIIOSDataSource::Create(const std::string& source_name) { |
| return new WebUIIOSDataSourceImpl(source_name); |
| } |
| |
| // static |
| void WebUIIOSDataSource::Add(BrowserState* browser_state, |
| WebUIIOSDataSource* source) { |
| URLDataManagerIOS::AddWebUIIOSDataSource(browser_state, source); |
| } |
| |
| // Internal class to hide the fact that WebUIIOSDataSourceImpl implements |
| // URLDataSourceIOS. |
| class WebUIIOSDataSourceImpl::InternalDataSource : public URLDataSourceIOS { |
| public: |
| InternalDataSource(WebUIIOSDataSourceImpl* parent) : parent_(parent) {} |
| |
| ~InternalDataSource() override {} |
| |
| // URLDataSourceIOS implementation. |
| std::string GetSource() const override { return parent_->GetSource(); } |
| std::string GetMimeType(const std::string& path) const override { |
| return parent_->GetMimeType(path); |
| } |
| void StartDataRequest( |
| const std::string& path, |
| const URLDataSourceIOS::GotDataCallback& callback) override { |
| return parent_->StartDataRequest(path, callback); |
| } |
| bool ShouldReplaceExistingSource() const override { |
| return parent_->replace_existing_source_; |
| } |
| bool AllowCaching() const override { return false; } |
| bool ShouldDenyXFrameOptions() const override { |
| return parent_->deny_xframe_options_; |
| } |
| bool IsGzipped(const std::string& path) const override { |
| return parent_->IsGzipped(path); |
| } |
| |
| private: |
| WebUIIOSDataSourceImpl* parent_; |
| }; |
| |
| WebUIIOSDataSourceImpl::WebUIIOSDataSourceImpl(const std::string& source_name) |
| : URLDataSourceIOSImpl(source_name, new InternalDataSource(this)), |
| source_name_(source_name), |
| default_resource_(-1), |
| deny_xframe_options_(true), |
| load_time_data_defaults_added_(false), |
| replace_existing_source_(true) {} |
| |
| WebUIIOSDataSourceImpl::~WebUIIOSDataSourceImpl() {} |
| |
| void WebUIIOSDataSourceImpl::AddString(const std::string& name, |
| const base::string16& value) { |
| localized_strings_.SetString(name, value); |
| replacements_[name] = base::UTF16ToUTF8(value); |
| } |
| |
| void WebUIIOSDataSourceImpl::AddString(const std::string& name, |
| const std::string& value) { |
| localized_strings_.SetString(name, value); |
| replacements_[name] = value; |
| } |
| |
| void WebUIIOSDataSourceImpl::AddLocalizedString(const std::string& name, |
| int ids) { |
| localized_strings_.SetString(name, GetWebClient()->GetLocalizedString(ids)); |
| replacements_[name] = |
| base::UTF16ToUTF8(GetWebClient()->GetLocalizedString(ids)); |
| } |
| |
| void WebUIIOSDataSourceImpl::AddLocalizedStrings( |
| const base::DictionaryValue& localized_strings) { |
| localized_strings_.MergeDictionary(&localized_strings); |
| ui::TemplateReplacementsFromDictionaryValue(localized_strings, |
| &replacements_); |
| } |
| |
| void WebUIIOSDataSourceImpl::AddBoolean(const std::string& name, bool value) { |
| localized_strings_.SetBoolean(name, value); |
| } |
| |
| void WebUIIOSDataSourceImpl::SetJsonPath(const std::string& path) { |
| json_path_ = path; |
| } |
| |
| void WebUIIOSDataSourceImpl::AddResourcePath(const std::string& path, |
| int resource_id) { |
| path_to_idr_map_[path] = resource_id; |
| } |
| |
| void WebUIIOSDataSourceImpl::SetDefaultResource(int resource_id) { |
| default_resource_ = resource_id; |
| } |
| |
| void WebUIIOSDataSourceImpl::DisableDenyXFrameOptions() { |
| deny_xframe_options_ = false; |
| } |
| |
| const ui::TemplateReplacements* WebUIIOSDataSourceImpl::GetReplacements() |
| const { |
| return &replacements_; |
| } |
| |
| std::string WebUIIOSDataSourceImpl::GetSource() const { |
| return source_name_; |
| } |
| |
| std::string WebUIIOSDataSourceImpl::GetMimeType(const std::string& path) const { |
| if (base::EndsWith(path, ".js", base::CompareCase::INSENSITIVE_ASCII)) |
| return "application/javascript"; |
| |
| if (base::EndsWith(path, ".json", base::CompareCase::INSENSITIVE_ASCII)) |
| return "application/json"; |
| |
| if (base::EndsWith(path, ".pdf", base::CompareCase::INSENSITIVE_ASCII)) |
| return "application/pdf"; |
| |
| if (base::EndsWith(path, ".css", base::CompareCase::INSENSITIVE_ASCII)) |
| return "text/css"; |
| |
| if (base::EndsWith(path, ".svg", base::CompareCase::INSENSITIVE_ASCII)) |
| return "image/svg+xml"; |
| |
| return "text/html"; |
| } |
| |
| void WebUIIOSDataSourceImpl::EnsureLoadTimeDataDefaultsAdded() { |
| if (load_time_data_defaults_added_) |
| return; |
| |
| load_time_data_defaults_added_ = true; |
| base::DictionaryValue defaults; |
| webui::SetLoadTimeDataDefaults(web::GetWebClient()->GetApplicationLocale(), |
| &defaults); |
| AddLocalizedStrings(defaults); |
| } |
| |
| void WebUIIOSDataSourceImpl::StartDataRequest( |
| const std::string& path, |
| const URLDataSourceIOS::GotDataCallback& callback) { |
| EnsureLoadTimeDataDefaultsAdded(); |
| |
| if (!json_path_.empty() && path == json_path_) { |
| SendLocalizedStringsAsJSON(callback); |
| return; |
| } |
| |
| int resource_id = PathToIdrOrDefault(path); |
| DCHECK_NE(resource_id, -1); |
| scoped_refptr<base::RefCountedMemory> response( |
| GetWebClient()->GetDataResourceBytes(resource_id)); |
| callback.Run(response); |
| } |
| |
| void WebUIIOSDataSourceImpl::SendLocalizedStringsAsJSON( |
| const URLDataSourceIOS::GotDataCallback& callback) { |
| std::string template_data; |
| webui::AppendJsonJS(&localized_strings_, &template_data); |
| callback.Run(base::RefCountedString::TakeString(&template_data)); |
| } |
| |
| int WebUIIOSDataSourceImpl::PathToIdrOrDefault(const std::string& path) const { |
| auto it = path_to_idr_map_.find(path); |
| return it == path_to_idr_map_.end() ? default_resource_ : it->second; |
| } |
| |
| bool WebUIIOSDataSourceImpl::IsGzipped(const std::string& path) const { |
| if (!json_path_.empty() && path == json_path_) { |
| return false; |
| } |
| |
| return GetWebClient()->IsDataResourceGzipped(PathToIdrOrDefault(path)); |
| } |
| |
| } // namespace web |