Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(445)

Side by Side Diff: components/safe_json/safe_json_parser_impl.cc

Issue 2049303002: Add the UtilityProcessMojoClient class and convert SafeJsonParser (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 4 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2013 The Chromium Authors. All rights reserved. 1 // Copyright 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "components/safe_json/safe_json_parser_impl.h" 5 #include "components/safe_json/safe_json_parser_impl.h"
6 6
7 #include <utility> 7 #include "base/callback.h"
8
9 #include "base/sequenced_task_runner.h" 8 #include "base/sequenced_task_runner.h"
10 #include "base/strings/utf_string_conversions.h"
11 #include "base/threading/sequenced_task_runner_handle.h" 9 #include "base/threading/sequenced_task_runner_handle.h"
12 #include "base/threading/thread_task_runner_handle.h"
13 #include "base/tuple.h"
14 #include "base/values.h" 10 #include "base/values.h"
15 #include "content/public/browser/browser_thread.h" 11 #include "content/public/browser/browser_thread.h"
16 #include "content/public/browser/utility_process_host.h"
17 #include "content/public/common/service_registry.h"
18 #include "grit/components_strings.h" 12 #include "grit/components_strings.h"
19 #include "ui/base/l10n/l10n_util.h" 13 #include "ui/base/l10n/l10n_util.h"
20 14
21 using content::BrowserThread;
22 using content::UtilityProcessHost;
23
24 namespace safe_json { 15 namespace safe_json {
25 16
26 SafeJsonParserImpl::SafeJsonParserImpl(const std::string& unsafe_json, 17 SafeJsonParserImpl::SafeJsonParserImpl(const std::string& unsafe_json,
27 const SuccessCallback& success_callback, 18 const SuccessCallback& success_callback,
28 const ErrorCallback& error_callback) 19 const ErrorCallback& error_callback)
29 : unsafe_json_(unsafe_json), 20 : unsafe_json_(unsafe_json),
30 success_callback_(success_callback), 21 success_callback_(success_callback),
31 error_callback_(error_callback) { 22 error_callback_(error_callback) {
32 io_thread_checker_.DetachFromThread(); 23 io_thread_checker_.DetachFromThread();
33 } 24 }
34 25
35 SafeJsonParserImpl::~SafeJsonParserImpl() { 26 SafeJsonParserImpl::~SafeJsonParserImpl() = default;
36 }
37
38 void SafeJsonParserImpl::StartWorkOnIOThread() {
39 DCHECK_CURRENTLY_ON(BrowserThread::IO);
40 DCHECK(io_thread_checker_.CalledOnValidThread());
41 // TODO(amistry): This UtilityProcessHost dance is likely to be done multiple
42 // times as more tasks are migrated to Mojo. Create some sort of helper class
43 // to eliminate the code duplication.
44 utility_process_host_ = UtilityProcessHost::Create(
45 this, base::ThreadTaskRunnerHandle::Get().get())->AsWeakPtr();
46 utility_process_host_->SetName(
47 l10n_util::GetStringUTF16(IDS_UTILITY_PROCESS_JSON_PARSER_NAME));
48 if (!utility_process_host_->Start()) {
49 ReportResults();
50 return;
51 }
52
53 content::ServiceRegistry* service_registry =
54 utility_process_host_->GetServiceRegistry();
55 service_registry->ConnectToRemoteService(mojo::GetProxy(&service_));
56 service_.set_connection_error_handler(
57 base::Bind(&SafeJsonParserImpl::ReportResults, this));
58
59 service_->Parse(unsafe_json_,
60 base::Bind(&SafeJsonParserImpl::OnParseDone, this));
61 }
62
63 void SafeJsonParserImpl::ReportResults() {
64 // There should be a DCHECK_CURRENTLY_ON(BrowserThread::IO) here. However, if
65 // the parser process is still alive on shutdown, this might run on the IO
66 // thread while the IO thread message loop is shutting down. This happens
67 // after the IO thread has unregistered from the BrowserThread list, causing
68 // the DCHECK to fail.
69 DCHECK(io_thread_checker_.CalledOnValidThread());
70 io_thread_checker_.DetachFromThread();
71
72 // Maintain a reference to |this| since either |utility_process_host_| or
73 // |service_| may have the last reference and destroying those might delete
74 // |this|.
75 scoped_refptr<SafeJsonParserImpl> ref(this);
76 // Shut down the utility process if it's still running.
77 delete utility_process_host_.get();
78 service_.reset();
79
80 caller_task_runner_->PostTask(
81 FROM_HERE,
82 base::Bind(&SafeJsonParserImpl::ReportResultsOnOriginThread, this));
83 }
84
85 void SafeJsonParserImpl::ReportResultsOnOriginThread() {
86 DCHECK(caller_task_runner_->RunsTasksOnCurrentThread());
87 if (error_.empty() && parsed_json_) {
88 if (!success_callback_.is_null())
89 success_callback_.Run(std::move(parsed_json_));
90 } else {
91 if (!error_callback_.is_null())
92 error_callback_.Run(error_);
93 }
94 }
95
96 bool SafeJsonParserImpl::OnMessageReceived(const IPC::Message& message) {
97 return false;
98 }
99
100 void SafeJsonParserImpl::OnParseDone(const base::ListValue& wrapper,
101 mojo::String error) {
102 DCHECK(io_thread_checker_.CalledOnValidThread());
103 if (!wrapper.empty()) {
104 const base::Value* value = NULL;
105 CHECK(wrapper.Get(0, &value));
106 parsed_json_.reset(value->DeepCopy());
107 } else {
108 error_ = error.get();
109 }
110 ReportResults();
111 }
112 27
113 void SafeJsonParserImpl::Start() { 28 void SafeJsonParserImpl::Start() {
114 caller_task_runner_ = base::SequencedTaskRunnerHandle::Get(); 29 caller_task_runner_ = base::SequencedTaskRunnerHandle::Get();
115 30
116 BrowserThread::PostTask( 31 content::BrowserThread::PostTask(
117 BrowserThread::IO, FROM_HERE, 32 content::BrowserThread::IO, FROM_HERE,
118 base::Bind(&SafeJsonParserImpl::StartWorkOnIOThread, this)); 33 base::Bind(&SafeJsonParserImpl::StartOnIoThread, this));
34 }
35
36 void SafeJsonParserImpl::StartOnIoThread() {
37 DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
38 DCHECK(io_thread_checker_.CalledOnValidThread());
grt (UTC plus 2) 2016/06/09 14:48:58 what's the advantage of doing these two things? wh
Patrick Monette 2016/06/10 18:13:23 There's a comment explaining this with the declara
grt (UTC plus 2) 2016/06/10 19:03:06 Ah, I missed that. The problem is that CURRENTLY_O
Patrick Monette 2016/06/10 21:29:46 Maybe amistry@ can answer that? :)
Anand Mistry (off Chromium) 2016/06/14 00:32:29 Um... yes... this is a problem with the rest of Ch
39 mojo_json_parser_.reset(
40 new content::UtilityProcessMojoClient<mojom::SafeJsonParser>(
41 l10n_util::GetStringUTF16(IDS_UTILITY_PROCESS_JSON_PARSER_NAME)));
42
43 mojo_json_parser_->set_error_handler(
44 base::Bind(&SafeJsonParserImpl::OnConnectionError, this));
45 mojo_json_parser_->Start();
46
47 mojo_json_parser_->service()->Parse(
48 unsafe_json_, base::Bind(&SafeJsonParserImpl::OnParseDone, this));
grt (UTC plus 2) 2016/06/09 14:48:58 does this class support calling |Start| multiple t
Patrick Monette 2016/06/10 18:13:23 Done.
49 }
50
51 void SafeJsonParserImpl::OnConnectionError() {
52 DCHECK(io_thread_checker_.CalledOnValidThread());
53 io_thread_checker_.DetachFromThread();
Anand Mistry (off Chromium) 2016/06/14 00:32:29 I know this was already there, but the DetachFromT
Patrick Monette 2016/06/14 21:23:32 Removed.
54
55 caller_task_runner_->PostTask(
56 FROM_HERE, base::Bind(&SafeJsonParserImpl::ReportResults, this, nullptr,
57 "Json error"));
58
59 // Shut down the utility process. Doing this last to make sure the last
60 // reference to this is not released before binding with ReportResults().
61 mojo_json_parser_.reset();
62 }
63
64 void SafeJsonParserImpl::OnParseDone(const base::ListValue& wrapper,
65 const mojo::String& error) {
66 DCHECK(io_thread_checker_.CalledOnValidThread());
67 io_thread_checker_.DetachFromThread();
68
69 // Shut down the utility process.
70 mojo_json_parser_.reset();
71
72 std::unique_ptr<base::Value> parsed_json;
73 std::string error_message;
74 if (!wrapper.empty()) {
75 const base::Value* value = NULL;
76 CHECK(wrapper.Get(0, &value));
77 parsed_json.reset(value->DeepCopy());
78 } else {
79 error_message = error.get();
80 }
81
82 // Call ReportResults() on caller's thread.
83 caller_task_runner_->PostTask(
84 FROM_HERE, base::Bind(&SafeJsonParserImpl::ReportResults, this,
85 base::Passed(&parsed_json), error_message));
86 }
87
88 void SafeJsonParserImpl::ReportResults(std::unique_ptr<base::Value> parsed_json,
grt (UTC plus 2) 2016/06/09 14:48:58 apologies if this is a silly question; i haven't l
Patrick Monette 2016/06/10 18:13:23 It was an artifact of when this class was refcount
89 const std::string& error) {
90 DCHECK(caller_task_runner_->RunsTasksOnCurrentThread());
91 if (error.empty() && parsed_json) {
92 if (!success_callback_.is_null())
93 success_callback_.Run(std::move(parsed_json));
94 } else {
95 if (!error_callback_.is_null())
96 error_callback_.Run(error);
97 }
119 } 98 }
120 99
121 } // namespace safe_json 100 } // namespace safe_json
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698