Upstream version 5.34.97.0
[platform/framework/web/crosswalk.git] / src / xwalk / extensions / browser / xwalk_extension_function_handler.cc
1 // Copyright (c) 2013 Intel Corporation. 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 "xwalk/extensions/browser/xwalk_extension_function_handler.h"
6
7 #include "base/location.h"
8 #include "xwalk/extensions/common/xwalk_external_instance.h"
9
10 namespace xwalk {
11 namespace extensions {
12
13 XWalkExtensionFunctionInfo::XWalkExtensionFunctionInfo(
14     const std::string& name,
15     scoped_ptr<base::ListValue> arguments,
16     const PostResultCallback& post_result_cb)
17   : name_(name),
18     arguments_(arguments.Pass()),
19     post_result_cb_(post_result_cb) {}
20
21 XWalkExtensionFunctionInfo::~XWalkExtensionFunctionInfo() {}
22
23 XWalkExtensionFunctionHandler::XWalkExtensionFunctionHandler(
24     XWalkExtensionInstance* instance)
25   : instance_(instance),
26     weak_factory_(this) {}
27
28 XWalkExtensionFunctionHandler::~XWalkExtensionFunctionHandler() {}
29
30 void XWalkExtensionFunctionHandler::HandleMessage(scoped_ptr<base::Value> msg) {
31   base::ListValue* args;
32   if (!msg->GetAsList(&args) || args->GetSize() < 2) {
33     // FIXME(tmpsantos): This warning could be better if the Context had a
34     // pointer to the Extension. We could tell what extension sent the
35     // invalid message.
36     LOG(WARNING) << "Invalid number of arguments.";
37     return;
38   }
39
40   // The first parameter stands for the function signature.
41   std::string function_name;
42   if (!args->GetString(0, &function_name)) {
43     LOG(WARNING) << "The function name is not a string.";
44     return;
45   }
46
47   // The second parameter stands for callback id, the remaining
48   // ones are the function arguments.
49   std::string callback_id;
50   if (!args->GetString(1, &callback_id)) {
51     LOG(WARNING) << "The callback id is not a string.";
52     return;
53   }
54
55   // We reuse args to pass the extra arguments to the handler, so remove
56   // function_name and callback_id from it.
57   args->Remove(0, NULL);
58   args->Remove(0, NULL);
59
60   scoped_ptr<XWalkExtensionFunctionInfo> info(
61       new XWalkExtensionFunctionInfo(
62           function_name,
63           make_scoped_ptr(static_cast<base::ListValue*>(msg.release())),
64           base::Bind(&XWalkExtensionFunctionHandler::DispatchResult,
65                      weak_factory_.GetWeakPtr(),
66                      base::MessageLoopProxy::current(),
67                      callback_id)));
68
69   if (!HandleFunction(info.Pass())) {
70     DLOG(WARNING) << "Function not registered: " << function_name;
71     return;
72   }
73 }
74
75 bool XWalkExtensionFunctionHandler::HandleFunction(
76     scoped_ptr<XWalkExtensionFunctionInfo> info) {
77   FunctionHandlerMap::iterator iter = handlers_.find(info->name());
78   if (iter == handlers_.end())
79     return false;
80
81   iter->second.Run(info.Pass());
82
83   return true;
84 }
85
86 // static
87 void XWalkExtensionFunctionHandler::DispatchResult(
88     const base::WeakPtr<XWalkExtensionFunctionHandler>& handler,
89     scoped_refptr<base::MessageLoopProxy> client_task_runner,
90     const std::string& callback_id,
91     scoped_ptr<base::ListValue> result) {
92   DCHECK(result);
93
94   if (client_task_runner != base::MessageLoopProxy::current()) {
95     client_task_runner->PostTask(FROM_HERE,
96         base::Bind(&XWalkExtensionFunctionHandler::DispatchResult,
97                    handler,
98                    client_task_runner,
99                    callback_id,
100                    base::Passed(&result)));
101     return;
102   }
103
104   if (callback_id.empty()) {
105     DLOG(WARNING) << "Sending a reply with an empty callback id has no"
106         "practical effect. This code can be optimized by not creating "
107         "and not posting the result.";
108     return;
109   }
110
111   // Prepend the callback id to the list, so the handlers
112   // on the JavaScript side know which callback should be evoked.
113   result->Insert(0, new base::StringValue(callback_id));
114
115   if (handler)
116     handler->PostMessageToInstance(result.PassAs<base::Value>());
117 }
118
119 void XWalkExtensionFunctionHandler::PostMessageToInstance(
120     scoped_ptr<base::Value> msg) {
121   instance_->PostMessageToJS(msg.Pass());
122 }
123
124 }  // namespace extensions
125 }  // namespace xwalk