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.
5 #include "xwalk/application/extension/application_event_extension.h"
9 #include "base/stl_util.h"
10 #include "base/threading/thread_restrictions.h"
11 #include "content/public/browser/web_contents.h"
12 #include "grit/xwalk_application_resources.h"
13 #include "ipc/ipc_message.h"
14 #include "ui/base/resource/resource_bundle.h"
15 #include "xwalk/application/browser/application.h"
16 #include "xwalk/application/browser/application_event_manager.h"
17 #include "xwalk/application/browser/application_storage.h"
18 #include "xwalk/application/common/event_names.h"
19 #include "xwalk/runtime/browser/runtime.h"
22 namespace application {
24 ApplicationEventExtension::ApplicationEventExtension(
25 ApplicationEventManager* event_manager,
26 ApplicationStorage* app_storage,
28 : event_manager_(event_manager),
29 app_storage_(app_storage),
31 set_name("xwalk.app.events");
32 set_javascript_api(ResourceBundle::GetSharedInstance().GetRawDataResource(
33 IDR_XWALK_APPLICATION_EVENT_API).as_string());
36 XWalkExtensionInstance* ApplicationEventExtension::CreateInstance() {
37 int main_routing_id = MSG_ROUTING_NONE;
39 if (Runtime* runtime = application_->GetMainDocumentRuntime())
40 main_routing_id = runtime->web_contents()->GetRoutingID();
42 return new AppEventExtensionInstance(event_manager_, app_storage_,
43 application_, main_routing_id);
46 AppEventExtensionInstance::AppEventExtensionInstance(
47 ApplicationEventManager* event_manager,
48 ApplicationStorage* app_storage,
51 : EventObserver(event_manager),
52 app_storage_(app_storage),
54 main_routing_id_(main_routing_id),
56 handler_.Register("registerEvent",
57 base::Bind(&AppEventExtensionInstance::OnRegisterEvent,
58 base::Unretained(this)));
59 handler_.Register("unregisterEvent",
60 base::Bind(&AppEventExtensionInstance::OnUnregisterEvent,
61 base::Unretained(this)));
62 handler_.Register("dispatchEventFinish",
64 &AppEventExtensionInstance::OnDispatchEventFinish,
65 base::Unretained(this)));
66 // FIXME: give UI thread I/O permission temporarily. The application storage
67 // database should be accessed on DB thread.
68 base::ThreadRestrictions::SetIOAllowed(true);
71 AppEventExtensionInstance::~AppEventExtensionInstance() {
74 void AppEventExtensionInstance::HandleMessage(scoped_ptr<base::Value> msg) {
75 handler_.HandleMessage(msg.Pass());
78 void AppEventExtensionInstance::OnRegisterEvent(
79 scoped_ptr<XWalkExtensionFunctionInfo> info) {
80 std::string event_name;
82 if (info->arguments()->GetSize() != 2 ||
83 !info->arguments()->GetString(0, &event_name) ||
84 !info->arguments()->GetInteger(1, &routing_id))
87 if (!ContainsKey(registered_events_, event_name)) {
88 registered_events_.insert(
89 std::make_pair(event_name, info->post_result_cb()));
90 event_manager_->AttachObserver(application_->id(), event_name, this);
92 if (routing_id != main_routing_id_)
95 ApplicationData* app_data = application_->data();
99 // If the event is from main document, add it into system database.
100 // If Crosswalk application is launched from unpacked path without
101 // installation, the registered events information will be saved in
102 // ApplicationData, no copy of it in ApplicationStorage.
103 std::set<std::string> events = app_data->GetEvents();
104 if (ContainsKey(events, event_name))
106 events.insert(event_name);
107 app_data->SetEvents(events);
108 app_storage_->UpdateApplication(app_data);
112 void AppEventExtensionInstance::OnUnregisterEvent(
113 scoped_ptr<XWalkExtensionFunctionInfo> info) {
114 std::string event_name;
116 if (info->arguments()->GetSize() != 2 ||
117 !info->arguments()->GetString(0, &event_name) ||
118 !info->arguments()->GetInteger(1, &routing_id))
121 if (!ContainsKey(registered_events_, event_name))
124 registered_events_.erase(event_name);
125 event_manager_->DetachObserver(application_->id(), event_name, this);
127 // If the event is from main document, remove it from system database.
128 if (routing_id == main_routing_id_) {
129 ApplicationData* app_data = application_->data();
133 std::set<std::string> events = app_data->GetEvents();
134 if (!ContainsKey(events, event_name))
136 events.erase(event_name);
137 app_data->SetEvents(events);
138 app_storage_->UpdateApplication(app_data);
142 void AppEventExtensionInstance::OnDispatchEventFinish(
143 scoped_ptr<XWalkExtensionFunctionInfo> info) {
144 std::string event_name;
145 if (info->arguments()->GetSize() != 1 ||
146 !info->arguments()->GetString(0, &event_name))
149 scoped_ptr<base::ListValue> args(new base::ListValue());
150 args->AppendString(event_name);
151 scoped_refptr<Event> event = Event::CreateEvent(
152 kOnJavaScriptEventAck, args.Pass());
153 event_manager_->SendEvent(application_->id(), event);
156 void AppEventExtensionInstance::Observe(
157 const std::string& app_id, scoped_refptr<Event> event) {
158 DCHECK(application_->id() == app_id);
159 EventCallbackMap::iterator it = registered_events_.find(event->name());
160 if (it == registered_events_.end())
163 scoped_ptr<base::ListValue> args(new base::ListValue());
164 args->Append(event->args()->DeepCopy());
165 it->second.Run(args.Pass());
168 } // namespace application