From b795155cfcf7583c9bc1d9527e07a5d3ee5742b3 Mon Sep 17 00:00:00 2001 From: eranm Date: Wed, 3 Jun 2015 01:38:13 -0700 Subject: Refactoring: Moving the SafeJsonParser to its own component. So it can be used by other components, particularly parsing Certificate Transparency's Signed Tree Heads fetched from third-parties. BUG= Review URL: https://codereview.chromium.org/1140053003 Cr-Commit-Position: refs/heads/master@{#332573} --- chrome/app/generated_resources.grd | 3 - chrome/browser/BUILD.gn | 1 + chrome/browser/DEPS | 1 + chrome/browser/extensions/DEPS | 5 ++ .../management/chrome_management_api_delegate.cc | 23 ++--- chrome/browser/extensions/webstore_data_fetcher.cc | 13 ++- .../browser/extensions/webstore_install_helper.cc | 4 +- .../browser/extensions/webstore_install_helper.h | 4 +- chrome/browser/safe_json_parser.cc | 87 ------------------- chrome/browser/safe_json_parser.h | 62 -------------- chrome/browser/safe_json_parser_browsertest.cc | 4 +- .../supervised_user/supervised_user_site_list.cc | 12 +-- .../search/common/json_response_fetcher.cc | 16 ++-- .../web_resource/chrome_web_resource_service.cc | 7 +- chrome/chrome_browser.gypi | 3 +- chrome/chrome_utility.gypi | 3 + chrome/common/chrome_utility_messages.h | 17 ---- chrome/utility/BUILD.gn | 1 + chrome/utility/DEPS | 1 + chrome/utility/chrome_content_utility_client.cc | 20 +---- chrome/utility/chrome_content_utility_client.h | 1 - chrome/utility/safe_json_parser_handler.cc | 18 ++++ chrome/utility/safe_json_parser_handler.h | 34 ++++++++ components/BUILD.gn | 1 + components/components.gyp | 1 + components/components_strings.grd | 3 + components/safe_json_parser.gypi | 49 +++++++++++ components/safe_json_parser/BUILD.gn | 36 ++++++++ components/safe_json_parser/DEPS | 8 ++ components/safe_json_parser/safe_json_parser.cc | 97 ++++++++++++++++++++++ components/safe_json_parser/safe_json_parser.h | 66 +++++++++++++++ .../safe_json_parser_message_filter.cc | 55 ++++++++++++ .../safe_json_parser_message_filter.h | 38 +++++++++ .../safe_json_parser/safe_json_parser_messages.cc | 33 ++++++++ .../safe_json_parser/safe_json_parser_messages.h | 37 +++++++++ ipc/ipc_message_start.h | 1 + 36 files changed, 536 insertions(+), 229 deletions(-) delete mode 100644 chrome/browser/safe_json_parser.cc delete mode 100644 chrome/browser/safe_json_parser.h create mode 100644 chrome/utility/safe_json_parser_handler.cc create mode 100644 chrome/utility/safe_json_parser_handler.h create mode 100644 components/safe_json_parser.gypi create mode 100644 components/safe_json_parser/BUILD.gn create mode 100644 components/safe_json_parser/DEPS create mode 100644 components/safe_json_parser/safe_json_parser.cc create mode 100644 components/safe_json_parser/safe_json_parser.h create mode 100644 components/safe_json_parser/safe_json_parser_message_filter.cc create mode 100644 components/safe_json_parser/safe_json_parser_message_filter.h create mode 100644 components/safe_json_parser/safe_json_parser_messages.cc create mode 100644 components/safe_json_parser/safe_json_parser_messages.h diff --git a/chrome/app/generated_resources.grd b/chrome/app/generated_resources.grd index 824248c..95c2e61 100644 --- a/chrome/app/generated_resources.grd +++ b/chrome/app/generated_resources.grd @@ -3798,9 +3798,6 @@ Even if you have downloaded files from this website before, the website might ha Image Decoder - - JSON Parser - V8 Proxy Resolver diff --git a/chrome/browser/BUILD.gn b/chrome/browser/BUILD.gn index f3e16ec..30127a3 100644 --- a/chrome/browser/BUILD.gn +++ b/chrome/browser/BUILD.gn @@ -258,6 +258,7 @@ source_set("browser") { "//components/password_manager/content/browser", "//components/plugins/common", "//components/precache/content", + "//components/safe_json_parser", "//components/sessions", "//components/storage_monitor", "//components/translate/content/browser", diff --git a/chrome/browser/DEPS b/chrome/browser/DEPS index cd2bc8b..4f7ac97 100644 --- a/chrome/browser/DEPS +++ b/chrome/browser/DEPS @@ -72,6 +72,7 @@ include_rules = [ "+components/query_parser", "+components/rappor", "+components/renderer_context_menu", + "+components/safe_json_parser", "+components/search", "+components/search_engines", "+components/search_provider_logos", diff --git a/chrome/browser/extensions/DEPS b/chrome/browser/extensions/DEPS index 2f74ae8..fec4f0f 100644 --- a/chrome/browser/extensions/DEPS +++ b/chrome/browser/extensions/DEPS @@ -9,7 +9,12 @@ include_rules = [ "+components/crx_file", "+components/user_manager", "+extensions/strings/grit/extensions_strings.h", + "+grit", # For generated headers # For access to testing command line switches. "+ppapi/shared_impl", + + # For safe_json_parser + "+components/safe_json_parser", + "+ui/base", ] diff --git a/chrome/browser/extensions/api/management/chrome_management_api_delegate.cc b/chrome/browser/extensions/api/management/chrome_management_api_delegate.cc index 546e27a..22dcd5e 100644 --- a/chrome/browser/extensions/api/management/chrome_management_api_delegate.cc +++ b/chrome/browser/extensions/api/management/chrome_management_api_delegate.cc @@ -12,7 +12,6 @@ #include "chrome/browser/extensions/launch_util.h" #include "chrome/browser/favicon/favicon_service_factory.h" #include "chrome/browser/profiles/profile.h" -#include "chrome/browser/safe_json_parser.h" #include "chrome/browser/ui/browser_dialogs.h" #include "chrome/browser/ui/browser_finder.h" #include "chrome/browser/ui/browser_window.h" @@ -24,6 +23,7 @@ #include "chrome/common/extensions/manifest_handlers/app_launch_info.h" #include "chrome/common/web_application_info.h" #include "components/favicon/core/favicon_service.h" +#include "components/safe_json_parser/safe_json_parser.h" #include "content/public/browser/browser_context.h" #include "content/public/browser/utility_process_host.h" #include "content/public/browser/utility_process_host_client.h" @@ -184,16 +184,17 @@ void ChromeManagementAPIDelegate:: GetPermissionWarningsByManifestFunctionDelegate( extensions::ManagementGetPermissionWarningsByManifestFunction* function, const std::string& manifest_str) const { - scoped_refptr parser(new SafeJsonParser( - manifest_str, - base::Bind( - &extensions::ManagementGetPermissionWarningsByManifestFunction:: - OnParseSuccess, - function), - base::Bind( - &extensions::ManagementGetPermissionWarningsByManifestFunction:: - OnParseFailure, - function))); + scoped_refptr parser( + new safe_json_parser::SafeJsonParser( + manifest_str, + base::Bind( + &extensions::ManagementGetPermissionWarningsByManifestFunction:: + OnParseSuccess, + function), + base::Bind( + &extensions::ManagementGetPermissionWarningsByManifestFunction:: + OnParseFailure, + function))); parser->Start(); } diff --git a/chrome/browser/extensions/webstore_data_fetcher.cc b/chrome/browser/extensions/webstore_data_fetcher.cc index 0805cae..8c07cec 100644 --- a/chrome/browser/extensions/webstore_data_fetcher.cc +++ b/chrome/browser/extensions/webstore_data_fetcher.cc @@ -7,7 +7,7 @@ #include "base/bind.h" #include "base/values.h" #include "chrome/browser/extensions/webstore_data_fetcher_delegate.h" -#include "chrome/browser/safe_json_parser.h" +#include "components/safe_json_parser/safe_json_parser.h" #include "extensions/common/extension_urls.h" #include "net/base/load_flags.h" #include "net/url_request/url_fetcher.h" @@ -82,12 +82,11 @@ void WebstoreDataFetcher::OnURLFetchComplete(const net::URLFetcher* source) { std::string webstore_json_data; fetcher->GetResponseAsString(&webstore_json_data); - scoped_refptr parser = - new SafeJsonParser(webstore_json_data, - base::Bind(&WebstoreDataFetcher::OnJsonParseSuccess, - AsWeakPtr()), - base::Bind(&WebstoreDataFetcher::OnJsonParseFailure, - AsWeakPtr())); + scoped_refptr parser = + new safe_json_parser::SafeJsonParser( + webstore_json_data, + base::Bind(&WebstoreDataFetcher::OnJsonParseSuccess, AsWeakPtr()), + base::Bind(&WebstoreDataFetcher::OnJsonParseFailure, AsWeakPtr())); // The parser will call us back via one of the callbacks. parser->Start(); } diff --git a/chrome/browser/extensions/webstore_install_helper.cc b/chrome/browser/extensions/webstore_install_helper.cc index 3f708f6..b487bf6 100644 --- a/chrome/browser/extensions/webstore_install_helper.cc +++ b/chrome/browser/extensions/webstore_install_helper.cc @@ -7,7 +7,7 @@ #include "base/bind.h" #include "base/values.h" #include "chrome/browser/bitmap_fetcher/bitmap_fetcher.h" -#include "chrome/browser/safe_json_parser.h" +#include "components/safe_json_parser/safe_json_parser.h" #include "content/public/browser/browser_thread.h" #include "net/base/load_flags.h" #include "net/url_request/url_request.h" @@ -49,7 +49,7 @@ void WebstoreInstallHelper::Start() { // Use base::Unretained so that base::Bind won't AddRef() on us. Otherwise, // we'll have two callbacks holding references to us, only one of which will // ever be called. - json_parser_ = new SafeJsonParser( + json_parser_ = new safe_json_parser::SafeJsonParser( manifest_, base::Bind(&WebstoreInstallHelper::OnJSONParseSucceeded, base::Unretained(this)), diff --git a/chrome/browser/extensions/webstore_install_helper.h b/chrome/browser/extensions/webstore_install_helper.h index 0a24af1..7cdb865 100644 --- a/chrome/browser/extensions/webstore_install_helper.h +++ b/chrome/browser/extensions/webstore_install_helper.h @@ -26,7 +26,9 @@ namespace net { class URLRequestContextGetter; } +namespace safe_json_parser { class SafeJsonParser; +} namespace extensions { @@ -94,7 +96,7 @@ class WebstoreInstallHelper : public base::RefCounted, // The manifest to parse. std::string manifest_; - scoped_refptr json_parser_; + scoped_refptr json_parser_; // If |icon_url_| is non-empty, it needs to be fetched and decoded into an // SkBitmap. diff --git a/chrome/browser/safe_json_parser.cc b/chrome/browser/safe_json_parser.cc deleted file mode 100644 index 232fdd4..0000000 --- a/chrome/browser/safe_json_parser.cc +++ /dev/null @@ -1,87 +0,0 @@ -// Copyright 2013 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 "chrome/browser/safe_json_parser.h" - -#include "chrome/common/chrome_utility_messages.h" -#include "chrome/grit/generated_resources.h" -#include "content/public/browser/browser_thread.h" -#include "content/public/browser/utility_process_host.h" -#include "ui/base/l10n/l10n_util.h" - -using content::BrowserThread; -using content::UtilityProcessHost; - -SafeJsonParser::SafeJsonParser(const std::string& unsafe_json, - const SuccessCallback& success_callback, - const ErrorCallback& error_callback) - : unsafe_json_(unsafe_json), - success_callback_(success_callback), - error_callback_(error_callback) {} - -void SafeJsonParser::Start() { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); - BrowserThread::PostTask( - BrowserThread::IO, - FROM_HERE, - base::Bind(&SafeJsonParser::StartWorkOnIOThread, this)); -} - -SafeJsonParser::~SafeJsonParser() {} - -void SafeJsonParser::StartWorkOnIOThread() { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); - UtilityProcessHost* host = - UtilityProcessHost::Create(this, base::MessageLoopProxy::current().get()); - host->SetName(l10n_util::GetStringUTF16( - IDS_UTILITY_PROCESS_JSON_PARSER_NAME)); - host->Send(new ChromeUtilityMsg_ParseJSON(unsafe_json_)); -} - -void SafeJsonParser::OnJSONParseSucceeded(const base::ListValue& wrapper) { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); - const base::Value* value = NULL; - CHECK(wrapper.Get(0, &value)); - - parsed_json_.reset(value->DeepCopy()); - ReportResults(); -} - -void SafeJsonParser::OnJSONParseFailed(const std::string& error_message) { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); - error_ = error_message; - ReportResults(); -} - -void SafeJsonParser::ReportResults() { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); - - BrowserThread::PostTask( - BrowserThread::UI, - FROM_HERE, - base::Bind(&SafeJsonParser::ReportResultOnUIThread, this)); -} - -void SafeJsonParser::ReportResultOnUIThread() { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); - if (error_.empty() && parsed_json_) { - if (!success_callback_.is_null()) - success_callback_.Run(parsed_json_.Pass()); - } else { - if (!error_callback_.is_null()) - error_callback_.Run(error_); - } -} - -bool SafeJsonParser::OnMessageReceived(const IPC::Message& message) { - bool handled = true; - IPC_BEGIN_MESSAGE_MAP(SafeJsonParser, message) - IPC_MESSAGE_HANDLER(ChromeUtilityHostMsg_ParseJSON_Succeeded, - OnJSONParseSucceeded) - IPC_MESSAGE_HANDLER(ChromeUtilityHostMsg_ParseJSON_Failed, - OnJSONParseFailed) - IPC_MESSAGE_UNHANDLED(handled = false) - IPC_END_MESSAGE_MAP() - return handled; -} diff --git a/chrome/browser/safe_json_parser.h b/chrome/browser/safe_json_parser.h deleted file mode 100644 index 67ca547..0000000 --- a/chrome/browser/safe_json_parser.h +++ /dev/null @@ -1,62 +0,0 @@ -// Copyright 2013 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. - -#ifndef CHROME_BROWSER_SAFE_JSON_PARSER_H_ -#define CHROME_BROWSER_SAFE_JSON_PARSER_H_ - -#include - -#include "base/basictypes.h" -#include "base/callback.h" -#include "base/memory/scoped_ptr.h" -#include "content/public/browser/utility_process_host_client.h" - -namespace base { -class ListValue; -class Value; -} - -namespace IPC { -class Message; -} - -// SafeJsonParser parses a given JSON safely via a utility process. The object -// is ref-counted and kept alive after Start() is called until one of the two -// callbacks is called. -class SafeJsonParser : public content::UtilityProcessHostClient { - public: - typedef base::Callback)> SuccessCallback; - typedef base::Callback ErrorCallback; - - SafeJsonParser(const std::string& unsafe_json, - const SuccessCallback& success_callback, - const ErrorCallback& error_callback); - - void Start(); - - private: - ~SafeJsonParser() override; - - void StartWorkOnIOThread(); - - void OnJSONParseSucceeded(const base::ListValue& wrapper); - void OnJSONParseFailed(const std::string& error_message); - - void ReportResults(); - void ReportResultOnUIThread(); - - // Implementing pieces of the UtilityProcessHostClient interface. - bool OnMessageReceived(const IPC::Message& message) override; - - const std::string unsafe_json_; - SuccessCallback success_callback_; - ErrorCallback error_callback_; - - scoped_ptr parsed_json_; - std::string error_; - - DISALLOW_COPY_AND_ASSIGN(SafeJsonParser); -}; - -#endif // CHROME_BROWSER_SAFE_JSON_PARSER_H_ diff --git a/chrome/browser/safe_json_parser_browsertest.cc b/chrome/browser/safe_json_parser_browsertest.cc index b6c45377..97957f0 100644 --- a/chrome/browser/safe_json_parser_browsertest.cc +++ b/chrome/browser/safe_json_parser_browsertest.cc @@ -7,13 +7,15 @@ #include "base/json/json_writer.h" #include "base/memory/scoped_ptr.h" #include "base/values.h" -#include "chrome/browser/safe_json_parser.h" #include "chrome/test/base/in_process_browser_test.h" +#include "components/safe_json_parser/safe_json_parser.h" #include "content/public/test/test_browser_thread_bundle.h" #include "content/public/test/test_utils.h" namespace { +using safe_json_parser::SafeJsonParser; + std::string MaybeToJson(const base::Value* value) { if (!value) return "(null)"; diff --git a/chrome/browser/supervised_user/supervised_user_site_list.cc b/chrome/browser/supervised_user/supervised_user_site_list.cc index 2c1b89a..52fc3d8 100644 --- a/chrome/browser/supervised_user/supervised_user_site_list.cc +++ b/chrome/browser/supervised_user/supervised_user_site_list.cc @@ -10,7 +10,7 @@ #include "base/metrics/histogram_macros.h" #include "base/task_runner_util.h" #include "base/values.h" -#include "chrome/browser/safe_json_parser.h" +#include "components/safe_json_parser/safe_json_parser.h" #include "content/public/browser/browser_thread.h" #include "url/gurl.h" @@ -156,11 +156,11 @@ void SupervisedUserSiteList::ParseJson( } // TODO(bauerb): Use batch mode to load multiple whitelists? - scoped_refptr parser(new SafeJsonParser( - json, - base::Bind(&SupervisedUserSiteList::OnJsonParseSucceeded, path, - base::TimeTicks::Now(), callback), - base::Bind(&HandleError, path))); + scoped_refptr parser( + new safe_json_parser::SafeJsonParser( + json, base::Bind(&SupervisedUserSiteList::OnJsonParseSucceeded, path, + base::TimeTicks::Now(), callback), + base::Bind(&HandleError, path))); parser->Start(); } diff --git a/chrome/browser/ui/app_list/search/common/json_response_fetcher.cc b/chrome/browser/ui/app_list/search/common/json_response_fetcher.cc index d4a9c3af..cfda62b 100644 --- a/chrome/browser/ui/app_list/search/common/json_response_fetcher.cc +++ b/chrome/browser/ui/app_list/search/common/json_response_fetcher.cc @@ -6,7 +6,7 @@ #include "base/bind.h" #include "base/values.h" -#include "chrome/browser/safe_json_parser.h" +#include "components/safe_json_parser/safe_json_parser.h" #include "net/base/load_flags.h" #include "net/url_request/url_fetcher.h" #include "net/url_request/url_request_status.h" @@ -72,14 +72,12 @@ void JSONResponseFetcher::OnURLFetchComplete( std::string json_data; fetcher->GetResponseAsString(&json_data); - scoped_refptr parser = - new SafeJsonParser(json_data, - base::Bind( - &JSONResponseFetcher::OnJsonParseSuccess, - weak_factory_.GetWeakPtr()), - base::Bind( - &JSONResponseFetcher::OnJsonParseError, - weak_factory_.GetWeakPtr())); + scoped_refptr parser = + new safe_json_parser::SafeJsonParser( + json_data, base::Bind(&JSONResponseFetcher::OnJsonParseSuccess, + weak_factory_.GetWeakPtr()), + base::Bind(&JSONResponseFetcher::OnJsonParseError, + weak_factory_.GetWeakPtr())); // The parser will call us back via one of the callbacks. parser->Start(); } diff --git a/chrome/browser/web_resource/chrome_web_resource_service.cc b/chrome/browser/web_resource/chrome_web_resource_service.cc index a7069384..47e37bd 100644 --- a/chrome/browser/web_resource/chrome_web_resource_service.cc +++ b/chrome/browser/web_resource/chrome_web_resource_service.cc @@ -8,8 +8,8 @@ #include "base/memory/ref_counted.h" #include "chrome/browser/browser_process.h" -#include "chrome/browser/safe_json_parser.h" #include "chrome/common/chrome_switches.h" +#include "components/safe_json_parser/safe_json_parser.h" #include "url/gurl.h" ChromeWebResourceService::ChromeWebResourceService( @@ -39,7 +39,8 @@ void ChromeWebResourceService::ParseJSON( const SuccessCallback& success_callback, const ErrorCallback& error_callback) { // SafeJsonParser releases itself on completion. - scoped_refptr json_parser( - new SafeJsonParser(data, success_callback, error_callback)); + scoped_refptr json_parser( + new safe_json_parser::SafeJsonParser(data, success_callback, + error_callback)); json_parser->Start(); } diff --git a/chrome/chrome_browser.gypi b/chrome/chrome_browser.gypi index a533516..a790155 100644 --- a/chrome/chrome_browser.gypi +++ b/chrome/chrome_browser.gypi @@ -690,8 +690,6 @@ 'browser/safe_browsing/srt_field_trial_win.h', 'browser/safe_browsing/srt_global_error_win.cc', 'browser/safe_browsing/srt_global_error_win.h', - 'browser/safe_json_parser.cc', - 'browser/safe_json_parser.h', 'browser/search/contextual_search_policy_handler_android.cc', 'browser/search/contextual_search_policy_handler_android.h', 'browser/search/contextual_search_promo_source_android.cc', @@ -3201,6 +3199,7 @@ '../components/components.gyp:plugins_common', '../components/components.gyp:power', '../components/components.gyp:precache_content', + '../components/components.gyp:safe_json_parser', '../components/components.gyp:sessions_content', '../components/components.gyp:storage_monitor', '../components/components.gyp:translate_content_browser', diff --git a/chrome/chrome_utility.gypi b/chrome/chrome_utility.gypi index 11b74fe..6b1db2f 100644 --- a/chrome/chrome_utility.gypi +++ b/chrome/chrome_utility.gypi @@ -19,6 +19,8 @@ 'utility/local_discovery/service_discovery_message_handler.h', 'utility/printing_handler.cc', 'utility/printing_handler.h', + 'utility/safe_json_parser_handler.cc', + 'utility/safe_json_parser_handler.h', 'utility/shell_handler_win.cc', 'utility/shell_handler_win.h', 'utility/utility_message_handler.h', @@ -101,6 +103,7 @@ 'dependencies': [ '../base/base.gyp:base', '../components/components_strings.gyp:components_strings', + '../components/components.gyp:safe_json_parser_message_filter', '../components/components.gyp:search_engines', '../components/components.gyp:url_fixer', '../content/content.gyp:content_common', diff --git a/chrome/common/chrome_utility_messages.h b/chrome/common/chrome_utility_messages.h index 76e7a1c..aa519cb 100644 --- a/chrome/common/chrome_utility_messages.h +++ b/chrome/common/chrome_utility_messages.h @@ -125,10 +125,6 @@ IPC_STRUCT_END() // Utility process messages: // These are messages from the browser to the utility process. -// Tell the utility process to parse a JSON string into a Value object. -IPC_MESSAGE_CONTROL1(ChromeUtilityMsg_ParseJSON, - std::string /* JSON to parse */) - // Tell the utility process to decode the given image data. IPC_MESSAGE_CONTROL3(ChromeUtilityMsg_DecodeImage, std::vector /* encoded image contents */, @@ -219,19 +215,6 @@ IPC_MESSAGE_CONTROL0(ChromeUtilityMsg_DetectSeccompSupport) // Utility process host messages: // These are messages from the utility process to the browser. -// Reply when the utility process successfully parsed a JSON string. -// -// WARNING: The result can be of any Value subclass type, but we can't easily -// pass indeterminate value types by const object reference with our IPC macros, -// so we put the result Value into a ListValue. Handlers should examine the -// first (and only) element of the ListValue for the actual result. -IPC_MESSAGE_CONTROL1(ChromeUtilityHostMsg_ParseJSON_Succeeded, - base::ListValue) - -// Reply when the utility process failed in parsing a JSON string. -IPC_MESSAGE_CONTROL1(ChromeUtilityHostMsg_ParseJSON_Failed, - std::string /* error message, if any*/) - // Reply when the utility process has failed while unpacking and parsing a // web resource. |error_message| is a user-readable explanation of what // went wrong. diff --git a/chrome/utility/BUILD.gn b/chrome/utility/BUILD.gn index ed55bb0..fbe9073 100644 --- a/chrome/utility/BUILD.gn +++ b/chrome/utility/BUILD.gn @@ -17,6 +17,7 @@ static_library("utility") { public_deps = [] deps = [ "//base", + "//components/safe_json_parser:safe_json_parser_message_filter", "//components/search_engines", "//components/strings", "//components/url_fixer", diff --git a/chrome/utility/DEPS b/chrome/utility/DEPS index 134c052..fb25cd1 100644 --- a/chrome/utility/DEPS +++ b/chrome/utility/DEPS @@ -3,6 +3,7 @@ include_rules = [ "+content/public/child", "+content/public/utility", "+components/wifi", + "+components/safe_json_parser", "+courgette", "+extensions/common", "+sandbox/linux/seccomp-bpf/sandbox_bpf.h", diff --git a/chrome/utility/chrome_content_utility_client.cc b/chrome/utility/chrome_content_utility_client.cc index 6b92765..700e6a0 100644 --- a/chrome/utility/chrome_content_utility_client.cc +++ b/chrome/utility/chrome_content_utility_client.cc @@ -6,13 +6,13 @@ #include "base/command_line.h" #include "base/files/file_path.h" -#include "base/json/json_reader.h" #include "base/memory/ref_counted.h" #include "base/time/time.h" #include "chrome/common/chrome_utility_messages.h" #include "chrome/common/safe_browsing/zip_analyzer.h" #include "chrome/common/safe_browsing/zip_analyzer_results.h" #include "chrome/utility/chrome_content_utility_ipc_whitelist.h" +#include "chrome/utility/safe_json_parser_handler.h" #include "chrome/utility/utility_message_handler.h" #include "content/public/child/image_decoder_utils.h" #include "content/public/common/content_switches.h" @@ -154,6 +154,8 @@ ChromeContentUtilityClient::ChromeContentUtilityClient() handlers_.push_back(new ShellHandler()); handlers_.push_back(new FontCacheHandler()); #endif + + handlers_.push_back(new SafeJsonParserHandler()); } ChromeContentUtilityClient::~ChromeContentUtilityClient() { @@ -186,7 +188,6 @@ bool ChromeContentUtilityClient::OnMessageReceived( IPC_MESSAGE_HANDLER(ChromeUtilityMsg_RobustJPEGDecodeImage, OnRobustJPEGDecodeImage) #endif // defined(OS_CHROMEOS) - IPC_MESSAGE_HANDLER(ChromeUtilityMsg_ParseJSON, OnParseJSON) IPC_MESSAGE_HANDLER(ChromeUtilityMsg_PatchFileBsdiff, OnPatchFileBsdiff) IPC_MESSAGE_HANDLER(ChromeUtilityMsg_PatchFileCourgette, @@ -369,21 +370,6 @@ void ChromeContentUtilityClient::OnRobustJPEGDecodeImage( } #endif // defined(OS_CHROMEOS) -void ChromeContentUtilityClient::OnParseJSON(const std::string& json) { - int error_code; - std::string error; - scoped_ptr value = base::JSONReader::ReadAndReturnError( - json, base::JSON_PARSE_RFC, &error_code, &error); - if (value) { - base::ListValue wrapper; - wrapper.Append(value.Pass()); - Send(new ChromeUtilityHostMsg_ParseJSON_Succeeded(wrapper)); - } else { - Send(new ChromeUtilityHostMsg_ParseJSON_Failed(error)); - } - ReleaseProcessIfNeeded(); -} - void ChromeContentUtilityClient::OnPatchFileBsdiff( const base::FilePath& input_file, const base::FilePath& patch_file, diff --git a/chrome/utility/chrome_content_utility_client.h b/chrome/utility/chrome_content_utility_client.h index c71ae10..b442d14 100644 --- a/chrome/utility/chrome_content_utility_client.h +++ b/chrome/utility/chrome_content_utility_client.h @@ -62,7 +62,6 @@ class ChromeContentUtilityClient : public content::ContentUtilityClient { void OnDetectSeccompSupport(); #endif - void OnParseJSON(const std::string& json); void OnPatchFileBsdiff(const base::FilePath& input_file, const base::FilePath& patch_file, const base::FilePath& output_file); diff --git a/chrome/utility/safe_json_parser_handler.cc b/chrome/utility/safe_json_parser_handler.cc new file mode 100644 index 0000000..e60cba3 --- /dev/null +++ b/chrome/utility/safe_json_parser_handler.cc @@ -0,0 +1,18 @@ +// 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 "chrome/utility/safe_json_parser_handler.h" + +#include "components/safe_json_parser/safe_json_parser_message_filter.h" + +SafeJsonParserHandler::SafeJsonParserHandler() + : handler_(new safe_json_parser::SafeJsonParserMessageFilter) { +} + +SafeJsonParserHandler::~SafeJsonParserHandler() { +} + +bool SafeJsonParserHandler::OnMessageReceived(const IPC::Message& message) { + return handler_->OnMessageReceived(message); +} diff --git a/chrome/utility/safe_json_parser_handler.h b/chrome/utility/safe_json_parser_handler.h new file mode 100644 index 0000000..d6809b6 --- /dev/null +++ b/chrome/utility/safe_json_parser_handler.h @@ -0,0 +1,34 @@ +// 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. + +#ifndef CHROME_UTILITY_SAFE_JSON_PARSER_HANDLER_H_ +#define CHROME_UTILITY_SAFE_JSON_PARSER_HANDLER_H_ + +#include "base/macros.h" +#include "base/memory/scoped_ptr.h" +#include "chrome/utility/utility_message_handler.h" + +namespace safe_json_parser { +class SafeJsonParserMessageFilter; +} // namespace safe_json_parser + +// Dispatches IPCs for out of process JSON parsing. This is an adapter class +// that delegates to safe_json_parser::SafeJsonParserMessageFilter, since the +// SafeJsonParserMessageFilter in //components/safe_json_parser can't directly +// depend on //chrome/utility. +class SafeJsonParserHandler : public UtilityMessageHandler { + public: + SafeJsonParserHandler(); + ~SafeJsonParserHandler() override; + + // UtilityMessageHandler + bool OnMessageReceived(const IPC::Message& message) override; + + private: + scoped_ptr handler_; + + DISALLOW_COPY_AND_ASSIGN(SafeJsonParserHandler); +}; + +#endif // CHROME_UTILITY_SAFE_JSON_PARSER_HANDLER_H_ diff --git a/components/BUILD.gn b/components/BUILD.gn index e8affcd..7dfac1c 100644 --- a/components/BUILD.gn +++ b/components/BUILD.gn @@ -240,6 +240,7 @@ group("all_components") { "//components/guest_view/browser", "//components/guest_view/common", "//components/guest_view/renderer", + "//components/safe_json_parser", "//components/scheduler", ] } diff --git a/components/components.gyp b/components/components.gyp index ff61c3f..4fef48a 100644 --- a/components/components.gyp +++ b/components/components.gyp @@ -95,6 +95,7 @@ 'devtools_http_handler.gypi', 'navigation_interception.gypi', 'power.gypi', + 'safe_json_parser.gypi', 'visitedlink.gypi', 'web_cache.gypi', 'web_contents_delegate_android.gypi', diff --git a/components/components_strings.grd b/components/components_strings.grd index 7f6c472..697cfe9 100644 --- a/components/components_strings.grd +++ b/components/components_strings.grd @@ -186,6 +186,9 @@ Learn more + + JSON Parser + diff --git a/components/safe_json_parser.gypi b/components/safe_json_parser.gypi new file mode 100644 index 0000000..04fb288 --- /dev/null +++ b/components/safe_json_parser.gypi @@ -0,0 +1,49 @@ +# 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. + +{ + 'targets': [ + { + # GN version: //components/safe_json_parser + 'target_name': 'safe_json_parser', + #'type': '<(component)', + 'type': 'static_library', + 'dependencies': [ + 'safe_json_parser_message_filter', + '../base/base.gyp:base', + '../components/components_strings.gyp:components_strings', + '../content/content.gyp:content_browser', + '../ui/base/ui_base.gyp:ui_base', + ], + 'include_dirs': [ + '..', + ], + 'defines': [ + 'SAFE_JSON_PARSER_IMPLEMENTATION', + ], + 'sources': [ + 'safe_json_parser/safe_json_parser.h', + 'safe_json_parser/safe_json_parser.cc', + ], + }, + { + 'target_name': 'safe_json_parser_message_filter', + 'type': 'static_library', + 'dependencies': [ + '../base/base.gyp:base', + '../content/content.gyp:content_browser', + '../ipc/ipc.gyp:ipc', + ], + 'include_dirs': [ + '..', + ], + 'sources': [ + 'safe_json_parser/safe_json_parser_messages.cc', + 'safe_json_parser/safe_json_parser_messages.h', + 'safe_json_parser/safe_json_parser_message_filter.cc', + 'safe_json_parser/safe_json_parser_message_filter.h', + ], + }, + ], +} diff --git a/components/safe_json_parser/BUILD.gn b/components/safe_json_parser/BUILD.gn new file mode 100644 index 0000000..95be97b --- /dev/null +++ b/components/safe_json_parser/BUILD.gn @@ -0,0 +1,36 @@ +# 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. + +# GYP version: components/safe_json_parser.gypi:safe_json_parser +static_library("safe_json_parser") { + sources = [ + "safe_json_parser.cc", + "safe_json_parser.h", + ] + + defines = [ "SAFE_JSON_PARSER_IMPLEMENTATION" ] + + deps = [ + ":safe_json_parser_message_filter", + "//base", + "//components/strings", + "//content/public/browser", + "//ui/base", + ] +} + +static_library("safe_json_parser_message_filter") { + sources = [ + "safe_json_parser_message_filter.cc", + "safe_json_parser_message_filter.h", + "safe_json_parser_messages.cc", + "safe_json_parser_messages.h", + ] + + deps = [ + "//base", + "//content/public/browser", + "//ipc", + ] +} diff --git a/components/safe_json_parser/DEPS b/components/safe_json_parser/DEPS new file mode 100644 index 0000000..4e771fc --- /dev/null +++ b/components/safe_json_parser/DEPS @@ -0,0 +1,8 @@ +include_rules = [ + "+base", + "+content/public", + "+grit", # For generated headers + "+grit/components_strings.h", # For generated headers + "+ipc", + "+ui/base", +] diff --git a/components/safe_json_parser/safe_json_parser.cc b/components/safe_json_parser/safe_json_parser.cc new file mode 100644 index 0000000..0ad94c5 --- /dev/null +++ b/components/safe_json_parser/safe_json_parser.cc @@ -0,0 +1,97 @@ +// Copyright 2013 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 "components/safe_json_parser/safe_json_parser.h" + +#include + +#include "base/strings/utf_string_conversions.h" +#include "base/tuple.h" +#include "base/values.h" +#include "components/safe_json_parser/safe_json_parser_messages.h" +#include "content/public/browser/browser_thread.h" +#include "content/public/browser/utility_process_host.h" +#include "grit/components_strings.h" +#include "ipc/ipc_message_macros.h" +#include "ui/base/l10n/l10n_util.h" + +using content::BrowserThread; +using content::UtilityProcessHost; + +namespace safe_json_parser { + +SafeJsonParser::SafeJsonParser(const std::string& unsafe_json, + const SuccessCallback& success_callback, + const ErrorCallback& error_callback) + : unsafe_json_(unsafe_json), + success_callback_(success_callback), + error_callback_(error_callback) { +} + +void SafeJsonParser::Start() { + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + BrowserThread::PostTask( + BrowserThread::IO, FROM_HERE, + base::Bind(&SafeJsonParser::StartWorkOnIOThread, this)); +} + +SafeJsonParser::~SafeJsonParser() { +} + +void SafeJsonParser::StartWorkOnIOThread() { + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); + UtilityProcessHost* host = + UtilityProcessHost::Create(this, base::MessageLoopProxy::current().get()); + host->SetName( + l10n_util::GetStringUTF16(IDS_UTILITY_PROCESS_JSON_PARSER_NAME)); + host->Send(new SafeJsonParserMsg_ParseJSON(unsafe_json_)); +} + +void SafeJsonParser::OnJSONParseSucceeded(const base::ListValue& wrapper) { + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); + const base::Value* value = NULL; + CHECK(wrapper.Get(0, &value)); + + parsed_json_.reset(value->DeepCopy()); + ReportResults(); +} + +void SafeJsonParser::OnJSONParseFailed(const std::string& error_message) { + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); + error_ = error_message; + ReportResults(); +} + +void SafeJsonParser::ReportResults() { + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); + + BrowserThread::PostTask( + BrowserThread::UI, FROM_HERE, + base::Bind(&SafeJsonParser::ReportResultOnUIThread, this)); +} + +void SafeJsonParser::ReportResultOnUIThread() { + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + if (error_.empty() && parsed_json_) { + if (!success_callback_.is_null()) + success_callback_.Run(parsed_json_.Pass()); + } else { + if (!error_callback_.is_null()) + error_callback_.Run(error_); + } +} + +bool SafeJsonParser::OnMessageReceived(const IPC::Message& message) { + bool handled = true; + IPC_BEGIN_MESSAGE_MAP(SafeJsonParser, message) + IPC_MESSAGE_HANDLER(SafeJsonParserHostMsg_ParseJSON_Succeeded, + OnJSONParseSucceeded) + IPC_MESSAGE_HANDLER(SafeJsonParserHostMsg_ParseJSON_Failed, + OnJSONParseFailed) + IPC_MESSAGE_UNHANDLED(handled = false) + IPC_END_MESSAGE_MAP() + return handled; +} + +} // namespace safe_json_parser diff --git a/components/safe_json_parser/safe_json_parser.h b/components/safe_json_parser/safe_json_parser.h new file mode 100644 index 0000000..2ff1d9d --- /dev/null +++ b/components/safe_json_parser/safe_json_parser.h @@ -0,0 +1,66 @@ +// Copyright 2013 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. + +#ifndef COMPONENTS_SAFE_JSON_PARSER_SAFE_JSON_PARSER_H_ +#define COMPONENTS_SAFE_JSON_PARSER_SAFE_JSON_PARSER_H_ + +#include + +#include "base/basictypes.h" +#include "base/callback.h" +#include "base/memory/scoped_ptr.h" +#include "content/public/browser/utility_process_host_client.h" + +namespace base { +class ListValue; +class Value; +} + +namespace IPC { +class Message; +} + +namespace safe_json_parser { + +// SafeJsonParser parses a given JSON safely via a utility process. The object +// is ref-counted and kept alive after Start() is called until one of the two +// callbacks is called. +class SafeJsonParser : public content::UtilityProcessHostClient { + public: + typedef base::Callback)> SuccessCallback; + typedef base::Callback ErrorCallback; + + SafeJsonParser(const std::string& unsafe_json, + const SuccessCallback& success_callback, + const ErrorCallback& error_callback); + + void Start(); + + private: + ~SafeJsonParser() override; + + void StartWorkOnIOThread(); + + void OnJSONParseSucceeded(const base::ListValue& wrapper); + void OnJSONParseFailed(const std::string& error_message); + + void ReportResults(); + void ReportResultOnUIThread(); + + // Implementing pieces of the UtilityProcessHostClient interface. + bool OnMessageReceived(const IPC::Message& message) override; + + const std::string unsafe_json_; + SuccessCallback success_callback_; + ErrorCallback error_callback_; + + scoped_ptr parsed_json_; + std::string error_; + + DISALLOW_COPY_AND_ASSIGN(SafeJsonParser); +}; + +} // namespace safe_json_parser + +#endif // COMPONENTS_SAFE_JSON_PARSER_SAFE_JSON_PARSER_H_ diff --git a/components/safe_json_parser/safe_json_parser_message_filter.cc b/components/safe_json_parser/safe_json_parser_message_filter.cc new file mode 100644 index 0000000..f5cf05e --- /dev/null +++ b/components/safe_json_parser/safe_json_parser_message_filter.cc @@ -0,0 +1,55 @@ +// 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 "components/safe_json_parser/safe_json_parser_message_filter.h" + +#include "base/json/json_reader.h" +#include "base/values.h" +#include "components/safe_json_parser/safe_json_parser_messages.h" +#include "content/public/utility/utility_thread.h" +#include "ipc/ipc_message.h" + +namespace { + +bool Send(IPC::Message* message) { + return content::UtilityThread::Get()->Send(message); +} + +} // namespace + +namespace safe_json_parser { + +SafeJsonParserMessageFilter::SafeJsonParserMessageFilter() { +} +SafeJsonParserMessageFilter::~SafeJsonParserMessageFilter() { +} + +bool SafeJsonParserMessageFilter::OnMessageReceived( + const IPC::Message& message) { + bool handled = true; + IPC_BEGIN_MESSAGE_MAP(SafeJsonParserMessageFilter, message) + IPC_MESSAGE_HANDLER(SafeJsonParserMsg_ParseJSON, OnParseJSON) + IPC_MESSAGE_UNHANDLED(handled = false) + IPC_END_MESSAGE_MAP() + + return handled; +} + +void SafeJsonParserMessageFilter::OnParseJSON(const std::string& json) { + int error_code; + std::string error; + scoped_ptr value = base::JSONReader::ReadAndReturnError( + json, base::JSON_PARSE_RFC, &error_code, &error); + if (value) { + base::ListValue wrapper; + wrapper.Append(value.Pass()); + Send(new SafeJsonParserHostMsg_ParseJSON_Succeeded(wrapper)); + } else { + Send(new SafeJsonParserHostMsg_ParseJSON_Failed(error)); + } + + content::UtilityThread::Get()->ReleaseProcessIfNeeded(); +} + +} // namespace safe_json_parser diff --git a/components/safe_json_parser/safe_json_parser_message_filter.h b/components/safe_json_parser/safe_json_parser_message_filter.h new file mode 100644 index 0000000..f0b061d --- /dev/null +++ b/components/safe_json_parser/safe_json_parser_message_filter.h @@ -0,0 +1,38 @@ +// 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. + +#ifndef COMPONENTS_SAFE_JSON_PARSER_SAFE_JSON_PARSER_MESSAGE_FILTER_H_ +#define COMPONENTS_SAFE_JSON_PARSER_SAFE_JSON_PARSER_MESSAGE_FILTER_H_ + +#include + +#include "base/macros.h" + +namespace IPC { +class Message; +} // namespace IPC + +namespace safe_json_parser { + +// A Handler for the ParseJSON IPC message that does the actual JSON parsing +// in the sandboxed process. Modelled after IPC::MessageFilter but does not +// directly implement it as it will be used by an adapter class under +// //chrome/utility. +class SafeJsonParserMessageFilter { + public: + SafeJsonParserMessageFilter(); + ~SafeJsonParserMessageFilter(); + // Returns true if it receives a message it could handle (currently + // only SafeJsonParserMsg_ParseJSON), false otherwise. + bool OnMessageReceived(const IPC::Message& message); + + private: + void OnParseJSON(const std::string& json); + + DISALLOW_COPY_AND_ASSIGN(SafeJsonParserMessageFilter); +}; + +} // namespace safe_json_parser + +#endif // COMPONENTS_SAFE_JSON_PARSER_SAFE_JSON_PARSER_MESSAGE_FILTER_H_ diff --git a/components/safe_json_parser/safe_json_parser_messages.cc b/components/safe_json_parser/safe_json_parser_messages.cc new file mode 100644 index 0000000..2e2c5cf --- /dev/null +++ b/components/safe_json_parser/safe_json_parser_messages.cc @@ -0,0 +1,33 @@ +// 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. + +// Get basic type definitions. +#define IPC_MESSAGE_IMPL +#include "components/safe_json_parser/safe_json_parser_messages.h" + +// Generate constructors. +#include "ipc/struct_constructor_macros.h" +#include "components/safe_json_parser/safe_json_parser_messages.h" + +// Generate destructors. +#include "ipc/struct_destructor_macros.h" +#include "components/safe_json_parser/safe_json_parser_messages.h" + +// Generate param traits write methods. +#include "ipc/param_traits_write_macros.h" +namespace IPC { +#include "components/safe_json_parser/safe_json_parser_messages.h" +} // namespace IPC + +// Generate param traits read methods. +#include "ipc/param_traits_read_macros.h" +namespace IPC { +#include "components/safe_json_parser/safe_json_parser_messages.h" +} // namespace IPC + +// Generate param traits log methods. +#include "ipc/param_traits_log_macros.h" +namespace IPC { +#include "components/safe_json_parser/safe_json_parser_messages.h" +} // namespace IPC diff --git a/components/safe_json_parser/safe_json_parser_messages.h b/components/safe_json_parser/safe_json_parser_messages.h new file mode 100644 index 0000000..ad92795 --- /dev/null +++ b/components/safe_json_parser/safe_json_parser_messages.h @@ -0,0 +1,37 @@ +// 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. + +// Message definition file, included multiple times, hence no include guard. + +#include +#include + +#include "base/strings/string16.h" +#include "content/public/common/common_param_traits.h" +#include "content/public/common/common_param_traits_macros.h" +#include "ipc/ipc_message_macros.h" +#include "ipc/ipc_message_utils.h" + +#define IPC_MESSAGE_START SafeJsonParserMsgStart + +//------------------------------------------------------------------------------ +// Process messages: +// This is a message from the browser to the utility process telling it to parse +// a JSON string into a Value object. +IPC_MESSAGE_CONTROL1(SafeJsonParserMsg_ParseJSON, + std::string /* JSON to parse */) + +//------------------------------------------------------------------------------ +// Host messages: Reply when the utility process successfully parsed a JSON +// string. +// +// WARNING: The result can be of any Value subclass type, but we can't easily +// pass indeterminate value types by const object reference with our IPC macros, +// so we put the result Value into a ListValue. Handlers should examine the +// first (and only) element of the ListValue for the actual result. +IPC_MESSAGE_CONTROL1(SafeJsonParserHostMsg_ParseJSON_Succeeded, base::ListValue) + +// Reply when the utility process failed in parsing a JSON string. +IPC_MESSAGE_CONTROL1(SafeJsonParserHostMsg_ParseJSON_Failed, + std::string /* error message, if any*/) diff --git a/ipc/ipc_message_start.h b/ipc/ipc_message_start.h index d4966bc..9543a66 100644 --- a/ipc/ipc_message_start.h +++ b/ipc/ipc_message_start.h @@ -124,6 +124,7 @@ enum IPCMessageStart { DataReductionProxyStart, ContentSettingsMsgStart, ChromeAppBannerMsgStart, + SafeJsonParserMsgStart, LastIPCMsgStart // Must come last. }; -- cgit v1.1