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
3// found in the LICENSE file.
4
5#include "chrome/browser/safe_json_parser.h"
6
7#include "chrome/common/extensions/chrome_utility_extensions_messages.h"
8#include "content/public/browser/browser_thread.h"
9#include "content/public/browser/utility_process_host.h"
10
11using content::BrowserThread;
12using content::UtilityProcessHost;
13
14SafeJsonParser::SafeJsonParser(const std::string& unsafe_json,
15                               const SuccessCallback& success_callback,
16                               const ErrorCallback& error_callback)
17    : unsafe_json_(unsafe_json),
18      success_callback_(success_callback),
19      error_callback_(error_callback) {}
20
21void SafeJsonParser::Start() {
22  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
23  BrowserThread::PostTask(
24      BrowserThread::IO,
25      FROM_HERE,
26      base::Bind(&SafeJsonParser::StartWorkOnIOThread, this));
27}
28
29SafeJsonParser::~SafeJsonParser() {}
30
31void SafeJsonParser::StartWorkOnIOThread() {
32  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
33  UtilityProcessHost* host =
34      UtilityProcessHost::Create(this, base::MessageLoopProxy::current().get());
35  host->Send(new ChromeUtilityMsg_ParseJSON(unsafe_json_));
36}
37
38void SafeJsonParser::OnJSONParseSucceeded(const base::ListValue& wrapper) {
39  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
40  const base::Value* value = NULL;
41  CHECK(wrapper.Get(0, &value));
42
43  parsed_json_.reset(value->DeepCopy());
44  ReportResults();
45}
46
47void SafeJsonParser::OnJSONParseFailed(const std::string& error_message) {
48  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
49  error_ = error_message;
50  ReportResults();
51}
52
53void SafeJsonParser::ReportResults() {
54  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
55
56  BrowserThread::PostTask(
57      BrowserThread::UI,
58      FROM_HERE,
59      base::Bind(&SafeJsonParser::ReportResultOnUIThread, this));
60}
61
62void SafeJsonParser::ReportResultOnUIThread() {
63  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
64  if (error_.empty() && parsed_json_) {
65    if (!success_callback_.is_null())
66      success_callback_.Run(parsed_json_.Pass());
67  } else {
68    if (!error_callback_.is_null())
69      error_callback_.Run(error_);
70  }
71}
72
73bool SafeJsonParser::OnMessageReceived(const IPC::Message& message) {
74  bool handled = true;
75  IPC_BEGIN_MESSAGE_MAP(SafeJsonParser, message)
76    IPC_MESSAGE_HANDLER(ChromeUtilityHostMsg_ParseJSON_Succeeded,
77                        OnJSONParseSucceeded)
78    IPC_MESSAGE_HANDLER(ChromeUtilityHostMsg_ParseJSON_Failed,
79                        OnJSONParseFailed)
80    IPC_MESSAGE_UNHANDLED(handled = false)
81  IPC_END_MESSAGE_MAP()
82  return handled;
83}
84