Upstream version 7.36.149.0
[platform/framework/web/crosswalk.git] / src / chrome / browser / extensions / api / web_navigation / web_navigation_api_helpers.cc
1 // Copyright (c) 2012 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 // Implements the Chrome Extensions WebNavigation API.
6
7 #include "chrome/browser/extensions/api/web_navigation/web_navigation_api_helpers.h"
8
9 #include "base/json/json_writer.h"
10 #include "base/strings/string_number_conversions.h"
11 #include "base/time/time.h"
12 #include "base/values.h"
13 #include "chrome/browser/extensions/api/web_navigation/web_navigation_api_constants.h"
14 #include "chrome/browser/extensions/extension_tab_util.h"
15 #include "chrome/browser/profiles/profile.h"
16 #include "chrome/common/extensions/api/web_navigation.h"
17 #include "content/public/browser/render_process_host.h"
18 #include "content/public/browser/render_view_host.h"
19 #include "content/public/browser/web_contents.h"
20 #include "content/public/common/page_transition_types.h"
21 #include "extensions/browser/event_router.h"
22 #include "extensions/common/event_filtering_info.h"
23 #include "net/base/net_errors.h"
24
25 namespace extensions {
26
27 namespace keys = web_navigation_api_constants;
28 namespace web_navigation = api::web_navigation;
29
30 namespace web_navigation_api_helpers {
31
32 namespace {
33
34 // Returns |time| as milliseconds since the epoch.
35 double MilliSecondsFromTime(const base::Time& time) {
36   return 1000 * time.ToDoubleT();
37 }
38
39 // Dispatches events to the extension message service.
40 void DispatchEvent(content::BrowserContext* browser_context,
41                    const std::string& event_name,
42                    scoped_ptr<base::ListValue> args,
43                    const GURL& url) {
44   EventFilteringInfo info;
45   info.SetURL(url);
46
47   Profile* profile = Profile::FromBrowserContext(browser_context);
48   EventRouter* event_router = EventRouter::Get(profile);
49   if (profile && event_router) {
50     scoped_ptr<Event> event(new Event(event_name, args.Pass()));
51     event->restrict_to_browser_context = profile;
52     event->filter_info = info;
53     event_router->BroadcastEvent(event.Pass());
54   }
55 }
56
57 }  // namespace
58
59 int GetFrameId(bool is_main_frame, int64 frame_id) {
60   return is_main_frame ? 0 : static_cast<int>(frame_id);
61 }
62
63 // Constructs and dispatches an onBeforeNavigate event.
64 void DispatchOnBeforeNavigate(content::WebContents* web_contents,
65                               int render_process_id,
66                               int64 frame_id,
67                               bool is_main_frame,
68                               int64 parent_frame_id,
69                               bool parent_is_main_frame,
70                               const GURL& validated_url) {
71   scoped_ptr<base::ListValue> args(new base::ListValue());
72   base::DictionaryValue* dict = new base::DictionaryValue();
73   dict->SetInteger(keys::kTabIdKey, ExtensionTabUtil::GetTabId(web_contents));
74   dict->SetString(keys::kUrlKey, validated_url.spec());
75   dict->SetInteger(keys::kProcessIdKey, render_process_id);
76   dict->SetInteger(keys::kFrameIdKey, GetFrameId(is_main_frame, frame_id));
77   dict->SetInteger(keys::kParentFrameIdKey,
78                    GetFrameId(parent_is_main_frame, parent_frame_id));
79   dict->SetDouble(keys::kTimeStampKey, MilliSecondsFromTime(base::Time::Now()));
80   args->Append(dict);
81
82   DispatchEvent(web_contents->GetBrowserContext(),
83                 web_navigation::OnBeforeNavigate::kEventName,
84                 args.Pass(),
85                 validated_url);
86 }
87
88 // Constructs and dispatches an onCommitted or onReferenceFragmentUpdated
89 // event.
90 void DispatchOnCommitted(const std::string& event_name,
91                          content::WebContents* web_contents,
92                          int64 frame_id,
93                          bool is_main_frame,
94                          const GURL& url,
95                          content::PageTransition transition_type) {
96   scoped_ptr<base::ListValue> args(new base::ListValue());
97   base::DictionaryValue* dict = new base::DictionaryValue();
98   dict->SetInteger(keys::kTabIdKey, ExtensionTabUtil::GetTabId(web_contents));
99   dict->SetString(keys::kUrlKey, url.spec());
100   dict->SetInteger(keys::kProcessIdKey,
101                    web_contents->GetRenderViewHost()->GetProcess()->GetID());
102   dict->SetInteger(keys::kFrameIdKey, GetFrameId(is_main_frame, frame_id));
103   std::string transition_type_string =
104       content::PageTransitionGetCoreTransitionString(transition_type);
105   // For webNavigation API backward compatibility, keep "start_page" even after
106   // renamed to "auto_toplevel".
107   if (PageTransitionStripQualifier(transition_type) ==
108           content::PAGE_TRANSITION_AUTO_TOPLEVEL)
109     transition_type_string = "start_page";
110   dict->SetString(keys::kTransitionTypeKey, transition_type_string);
111   base::ListValue* qualifiers = new base::ListValue();
112   if (transition_type & content::PAGE_TRANSITION_CLIENT_REDIRECT)
113     qualifiers->Append(new base::StringValue("client_redirect"));
114   if (transition_type & content::PAGE_TRANSITION_SERVER_REDIRECT)
115     qualifiers->Append(new base::StringValue("server_redirect"));
116   if (transition_type & content::PAGE_TRANSITION_FORWARD_BACK)
117     qualifiers->Append(new base::StringValue("forward_back"));
118   if (transition_type & content::PAGE_TRANSITION_FROM_ADDRESS_BAR)
119     qualifiers->Append(new base::StringValue("from_address_bar"));
120   dict->Set(keys::kTransitionQualifiersKey, qualifiers);
121   dict->SetDouble(keys::kTimeStampKey, MilliSecondsFromTime(base::Time::Now()));
122   args->Append(dict);
123
124   DispatchEvent(web_contents->GetBrowserContext(), event_name, args.Pass(),
125                 url);
126 }
127
128 // Constructs and dispatches an onDOMContentLoaded event.
129 void DispatchOnDOMContentLoaded(content::WebContents* web_contents,
130                                 const GURL& url,
131                                 bool is_main_frame,
132                                 int64 frame_id) {
133   scoped_ptr<base::ListValue> args(new base::ListValue());
134   base::DictionaryValue* dict = new base::DictionaryValue();
135   dict->SetInteger(keys::kTabIdKey,
136                    ExtensionTabUtil::GetTabId(web_contents));
137   dict->SetString(keys::kUrlKey, url.spec());
138   dict->SetInteger(keys::kProcessIdKey,
139                    web_contents->GetRenderViewHost()->GetProcess()->GetID());
140   dict->SetInteger(keys::kFrameIdKey, GetFrameId(is_main_frame, frame_id));
141   dict->SetDouble(keys::kTimeStampKey, MilliSecondsFromTime(base::Time::Now()));
142   args->Append(dict);
143
144   DispatchEvent(web_contents->GetBrowserContext(),
145                 web_navigation::OnDOMContentLoaded::kEventName,
146                 args.Pass(),
147                 url);
148 }
149
150 // Constructs and dispatches an onCompleted event.
151 void DispatchOnCompleted(content::WebContents* web_contents,
152                          const GURL& url,
153                          bool is_main_frame,
154                          int64 frame_id) {
155   scoped_ptr<base::ListValue> args(new base::ListValue());
156   base::DictionaryValue* dict = new base::DictionaryValue();
157   dict->SetInteger(keys::kTabIdKey,
158                    ExtensionTabUtil::GetTabId(web_contents));
159   dict->SetString(keys::kUrlKey, url.spec());
160   dict->SetInteger(keys::kProcessIdKey,
161                    web_contents->GetRenderViewHost()->GetProcess()->GetID());
162   dict->SetInteger(keys::kFrameIdKey, GetFrameId(is_main_frame, frame_id));
163   dict->SetDouble(keys::kTimeStampKey, MilliSecondsFromTime(base::Time::Now()));
164   args->Append(dict);
165
166   DispatchEvent(web_contents->GetBrowserContext(),
167                 web_navigation::OnCompleted::kEventName,
168                 args.Pass(), url);
169 }
170
171 // Constructs and dispatches an onCreatedNavigationTarget event.
172 void DispatchOnCreatedNavigationTarget(
173     content::WebContents* web_contents,
174     content::BrowserContext* browser_context,
175     int64 source_frame_id,
176     bool source_frame_is_main_frame,
177     content::WebContents* target_web_contents,
178     const GURL& target_url) {
179   // Check that the tab is already inserted into a tab strip model. This code
180   // path is exercised by ExtensionApiTest.WebNavigationRequestOpenTab.
181   DCHECK(ExtensionTabUtil::GetTabById(
182       ExtensionTabUtil::GetTabId(target_web_contents),
183       Profile::FromBrowserContext(target_web_contents->GetBrowserContext()),
184       false, NULL, NULL, NULL, NULL));
185
186   scoped_ptr<base::ListValue> args(new base::ListValue());
187   base::DictionaryValue* dict = new base::DictionaryValue();
188   dict->SetInteger(keys::kSourceTabIdKey,
189                    ExtensionTabUtil::GetTabId(web_contents));
190   dict->SetInteger(keys::kSourceProcessIdKey,
191                    web_contents->GetRenderViewHost()->GetProcess()->GetID());
192   dict->SetInteger(keys::kSourceFrameIdKey,
193       GetFrameId(source_frame_is_main_frame, source_frame_id));
194   dict->SetString(keys::kUrlKey, target_url.possibly_invalid_spec());
195   dict->SetInteger(keys::kTabIdKey,
196                    ExtensionTabUtil::GetTabId(target_web_contents));
197   dict->SetDouble(keys::kTimeStampKey, MilliSecondsFromTime(base::Time::Now()));
198   args->Append(dict);
199
200   DispatchEvent(browser_context,
201                 web_navigation::OnCreatedNavigationTarget::kEventName,
202                 args.Pass(),
203                 target_url);
204 }
205
206 // Constructs and dispatches an onErrorOccurred event.
207 void DispatchOnErrorOccurred(content::WebContents* web_contents,
208                              int render_process_id,
209                              const GURL& url,
210                              int64 frame_id,
211                              bool is_main_frame,
212                              int error_code) {
213   scoped_ptr<base::ListValue> args(new base::ListValue());
214   base::DictionaryValue* dict = new base::DictionaryValue();
215   dict->SetInteger(keys::kTabIdKey, ExtensionTabUtil::GetTabId(web_contents));
216   dict->SetString(keys::kUrlKey, url.spec());
217   dict->SetInteger(keys::kProcessIdKey, render_process_id);
218   dict->SetInteger(keys::kFrameIdKey, GetFrameId(is_main_frame, frame_id));
219   dict->SetString(keys::kErrorKey, net::ErrorToString(error_code));
220   dict->SetDouble(keys::kTimeStampKey,
221       MilliSecondsFromTime(base::Time::Now()));
222   args->Append(dict);
223
224   DispatchEvent(web_contents->GetBrowserContext(),
225                 web_navigation::OnErrorOccurred::kEventName,
226                 args.Pass(), url);
227 }
228
229 // Constructs and dispatches an onTabReplaced event.
230 void DispatchOnTabReplaced(
231     content::WebContents* old_web_contents,
232     content::BrowserContext* browser_context,
233     content::WebContents* new_web_contents) {
234   scoped_ptr<base::ListValue> args(new base::ListValue());
235   base::DictionaryValue* dict = new base::DictionaryValue();
236   dict->SetInteger(keys::kReplacedTabIdKey,
237                    ExtensionTabUtil::GetTabId(old_web_contents));
238   dict->SetInteger(
239       keys::kTabIdKey,
240       ExtensionTabUtil::GetTabId(new_web_contents));
241   dict->SetDouble(keys::kTimeStampKey, MilliSecondsFromTime(base::Time::Now()));
242   args->Append(dict);
243
244   DispatchEvent(browser_context,
245                 web_navigation::OnTabReplaced::kEventName,
246                 args.Pass(),
247                 GURL());
248 }
249
250 }  // namespace web_navigation_api_helpers
251
252 }  // namespace extensions