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.
5 // Implements the Chrome Extensions WebNavigation API.
7 #include "chrome/browser/extensions/api/web_navigation/web_navigation_api.h"
9 #include "base/lazy_instance.h"
10 #include "chrome/browser/chrome_notification_types.h"
11 #include "chrome/browser/extensions/api/web_navigation/web_navigation_api_constants.h"
12 #include "chrome/browser/extensions/api/web_navigation/web_navigation_api_helpers.h"
13 #include "chrome/browser/extensions/extension_tab_util.h"
14 #include "chrome/browser/profiles/profile.h"
15 #include "chrome/browser/tab_contents/retargeting_details.h"
16 #include "chrome/browser/ui/browser.h"
17 #include "chrome/browser/ui/browser_iterator.h"
18 #include "chrome/browser/ui/browser_list.h"
19 #include "chrome/common/extensions/api/web_navigation.h"
20 #include "content/public/browser/navigation_details.h"
21 #include "content/public/browser/notification_service.h"
22 #include "content/public/browser/notification_types.h"
23 #include "content/public/browser/render_process_host.h"
24 #include "content/public/browser/render_view_host.h"
25 #include "content/public/browser/resource_request_details.h"
26 #include "content/public/browser/web_contents.h"
27 #include "content/public/common/url_constants.h"
28 #include "extensions/browser/event_router.h"
29 #include "extensions/browser/view_type_utils.h"
30 #include "net/base/net_errors.h"
32 namespace GetFrame
= extensions::api::web_navigation::GetFrame
;
33 namespace GetAllFrames
= extensions::api::web_navigation::GetAllFrames
;
35 DEFINE_WEB_CONTENTS_USER_DATA_KEY(extensions::WebNavigationTabObserver
);
37 namespace extensions
{
39 #if !defined(OS_ANDROID)
41 namespace helpers
= web_navigation_api_helpers
;
42 namespace keys
= web_navigation_api_constants
;
43 namespace web_navigation
= api::web_navigation
;
47 typedef std::map
<content::WebContents
*, WebNavigationTabObserver
*>
49 static base::LazyInstance
<TabObserverMap
> g_tab_observer
=
50 LAZY_INSTANCE_INITIALIZER
;
54 // WebNavigtionEventRouter -------------------------------------------
56 WebNavigationEventRouter::PendingWebContents::PendingWebContents()
57 : source_web_contents(NULL
),
59 source_frame_is_main_frame(false),
60 target_web_contents(NULL
),
64 WebNavigationEventRouter::PendingWebContents::PendingWebContents(
65 content::WebContents
* source_web_contents
,
66 int64 source_frame_id
,
67 bool source_frame_is_main_frame
,
68 content::WebContents
* target_web_contents
,
69 const GURL
& target_url
)
70 : source_web_contents(source_web_contents
),
71 source_frame_id(source_frame_id
),
72 source_frame_is_main_frame(source_frame_is_main_frame
),
73 target_web_contents(target_web_contents
),
74 target_url(target_url
) {
77 WebNavigationEventRouter::PendingWebContents::~PendingWebContents() {}
79 WebNavigationEventRouter::WebNavigationEventRouter(Profile
* profile
)
81 CHECK(registrar_
.IsEmpty());
83 chrome::NOTIFICATION_RETARGETING
,
84 content::NotificationService::AllSources());
86 chrome::NOTIFICATION_TAB_ADDED
,
87 content::NotificationService::AllSources());
89 content::NOTIFICATION_WEB_CONTENTS_DESTROYED
,
90 content::NotificationService::AllSources());
92 BrowserList::AddObserver(this);
93 for (chrome::BrowserIterator it
; !it
.done(); it
.Next())
97 WebNavigationEventRouter::~WebNavigationEventRouter() {
98 for (chrome::BrowserIterator it
; !it
.done(); it
.Next())
99 OnBrowserRemoved(*it
);
100 BrowserList::RemoveObserver(this);
103 void WebNavigationEventRouter::OnBrowserAdded(Browser
* browser
) {
104 if (!profile_
->IsSameProfile(browser
->profile()))
106 browser
->tab_strip_model()->AddObserver(this);
109 void WebNavigationEventRouter::OnBrowserRemoved(Browser
* browser
) {
110 if (!profile_
->IsSameProfile(browser
->profile()))
112 browser
->tab_strip_model()->RemoveObserver(this);
115 void WebNavigationEventRouter::TabReplacedAt(
116 TabStripModel
* tab_strip_model
,
117 content::WebContents
* old_contents
,
118 content::WebContents
* new_contents
,
120 WebNavigationTabObserver
* tab_observer
=
121 WebNavigationTabObserver::Get(old_contents
);
123 // If you hit this DCHECK(), please add reproduction steps to
124 // http://crbug.com/109464.
125 DCHECK(GetViewType(old_contents
) != VIEW_TYPE_TAB_CONTENTS
);
128 const FrameNavigationState
& frame_navigation_state
=
129 tab_observer
->frame_navigation_state();
131 if (!frame_navigation_state
.IsValidUrl(old_contents
->GetURL()) ||
132 !frame_navigation_state
.IsValidUrl(new_contents
->GetURL()))
135 helpers::DispatchOnTabReplaced(old_contents
, profile_
, new_contents
);
138 void WebNavigationEventRouter::Observe(
140 const content::NotificationSource
& source
,
141 const content::NotificationDetails
& details
) {
143 case chrome::NOTIFICATION_RETARGETING
: {
144 Profile
* profile
= content::Source
<Profile
>(source
).ptr();
145 if (profile
->GetOriginalProfile() == profile_
) {
147 content::Details
<const RetargetingDetails
>(details
).ptr());
152 case chrome::NOTIFICATION_TAB_ADDED
:
153 TabAdded(content::Details
<content::WebContents
>(details
).ptr());
156 case content::NOTIFICATION_WEB_CONTENTS_DESTROYED
:
157 TabDestroyed(content::Source
<content::WebContents
>(source
).ptr());
165 void WebNavigationEventRouter::Retargeting(const RetargetingDetails
* details
) {
166 if (details
->source_render_frame_id
== 0)
168 WebNavigationTabObserver
* tab_observer
=
169 WebNavigationTabObserver::Get(details
->source_web_contents
);
171 // If you hit this DCHECK(), please add reproduction steps to
172 // http://crbug.com/109464.
173 DCHECK(GetViewType(details
->source_web_contents
) != VIEW_TYPE_TAB_CONTENTS
);
176 const FrameNavigationState
& frame_navigation_state
=
177 tab_observer
->frame_navigation_state();
179 FrameNavigationState::FrameID
frame_id(
180 details
->source_render_frame_id
,
181 details
->source_web_contents
->GetRenderViewHost());
182 if (!frame_navigation_state
.CanSendEvents(frame_id
))
185 // If the WebContents isn't yet inserted into a tab strip, we need to delay
186 // the extension event until the WebContents is fully initialized.
187 if (details
->not_yet_in_tabstrip
) {
188 pending_web_contents_
[details
->target_web_contents
] =
190 details
->source_web_contents
,
191 details
->source_render_frame_id
,
192 frame_navigation_state
.IsMainFrame(frame_id
),
193 details
->target_web_contents
,
194 details
->target_url
);
196 helpers::DispatchOnCreatedNavigationTarget(
197 details
->source_web_contents
,
198 details
->target_web_contents
->GetBrowserContext(),
199 details
->source_render_frame_id
,
200 frame_navigation_state
.IsMainFrame(frame_id
),
201 details
->target_web_contents
,
202 details
->target_url
);
206 void WebNavigationEventRouter::TabAdded(content::WebContents
* tab
) {
207 std::map
<content::WebContents
*, PendingWebContents
>::iterator iter
=
208 pending_web_contents_
.find(tab
);
209 if (iter
== pending_web_contents_
.end())
212 WebNavigationTabObserver
* tab_observer
=
213 WebNavigationTabObserver::Get(iter
->second
.source_web_contents
);
218 const FrameNavigationState
& frame_navigation_state
=
219 tab_observer
->frame_navigation_state();
221 FrameNavigationState::FrameID
frame_id(
222 iter
->second
.source_frame_id
,
223 iter
->second
.source_web_contents
->GetRenderViewHost());
224 if (frame_navigation_state
.CanSendEvents(frame_id
)) {
225 helpers::DispatchOnCreatedNavigationTarget(
226 iter
->second
.source_web_contents
,
227 iter
->second
.target_web_contents
->GetBrowserContext(),
228 iter
->second
.source_frame_id
,
229 iter
->second
.source_frame_is_main_frame
,
230 iter
->second
.target_web_contents
,
231 iter
->second
.target_url
);
233 pending_web_contents_
.erase(iter
);
236 void WebNavigationEventRouter::TabDestroyed(content::WebContents
* tab
) {
237 pending_web_contents_
.erase(tab
);
238 for (std::map
<content::WebContents
*, PendingWebContents
>::iterator i
=
239 pending_web_contents_
.begin(); i
!= pending_web_contents_
.end(); ) {
240 if (i
->second
.source_web_contents
== tab
)
241 pending_web_contents_
.erase(i
++);
247 // WebNavigationTabObserver ------------------------------------------
249 WebNavigationTabObserver::WebNavigationTabObserver(
250 content::WebContents
* web_contents
)
251 : WebContentsObserver(web_contents
),
252 render_view_host_(NULL
),
253 pending_render_view_host_(NULL
) {
254 g_tab_observer
.Get().insert(TabObserverMap::value_type(web_contents
, this));
256 content::NOTIFICATION_RENDER_VIEW_HOST_WILL_CLOSE_RENDER_VIEW
,
257 content::NotificationService::AllSources());
260 WebNavigationTabObserver::~WebNavigationTabObserver() {}
263 WebNavigationTabObserver
* WebNavigationTabObserver::Get(
264 content::WebContents
* web_contents
) {
265 TabObserverMap::iterator i
= g_tab_observer
.Get().find(web_contents
);
266 return i
== g_tab_observer
.Get().end() ? NULL
: i
->second
;
269 content::RenderViewHost
* WebNavigationTabObserver::GetRenderViewHostInProcess(
270 int process_id
) const {
271 if (render_view_host_
&&
272 render_view_host_
->GetProcess()->GetID() == process_id
) {
273 return render_view_host_
;
275 if (pending_render_view_host_
&&
276 pending_render_view_host_
->GetProcess()->GetID() == process_id
) {
277 return pending_render_view_host_
;
282 void WebNavigationTabObserver::Observe(
284 const content::NotificationSource
& source
,
285 const content::NotificationDetails
& details
) {
287 case content::NOTIFICATION_RENDER_VIEW_HOST_WILL_CLOSE_RENDER_VIEW
: {
288 // The RenderView is technically not yet deleted, but the RenderViewHost
289 // already starts to filter out some IPCs. In order to not get confused,
290 // we consider the RenderView dead already now.
291 RenderViewDeleted(content::Source
<content::RenderViewHost
>(source
).ptr());
300 void WebNavigationTabObserver::RenderViewDeleted(
301 content::RenderViewHost
* render_view_host
) {
302 if (render_view_host
== render_view_host_
) {
303 render_view_host_
= NULL
;
304 if (pending_render_view_host_
) {
305 render_view_host_
= pending_render_view_host_
;
306 pending_render_view_host_
= NULL
;
308 } else if (render_view_host
== pending_render_view_host_
) {
309 pending_render_view_host_
= NULL
;
314 web_contents(), render_view_host
, FrameNavigationState::FrameID());
317 void WebNavigationTabObserver::AboutToNavigateRenderView(
318 content::RenderViewHost
* render_view_host
) {
319 if (!render_view_host_
) {
320 render_view_host_
= render_view_host
;
321 } else if (render_view_host
!= render_view_host_
) {
322 if (pending_render_view_host_
) {
323 SendErrorEvents(web_contents(),
324 pending_render_view_host_
,
325 FrameNavigationState::FrameID());
327 pending_render_view_host_
= render_view_host
;
331 void WebNavigationTabObserver::DidStartProvisionalLoadForFrame(
333 int64 parent_frame_num
,
335 const GURL
& validated_url
,
337 bool is_iframe_srcdoc
,
338 content::RenderViewHost
* render_view_host
) {
339 DVLOG(2) << "DidStartProvisionalLoad("
340 << "render_view_host=" << render_view_host
341 << ", frame_num=" << frame_num
342 << ", url=" << validated_url
<< ")";
343 if (!render_view_host_
)
344 render_view_host_
= render_view_host
;
345 if (render_view_host
!= render_view_host_
&&
346 render_view_host
!= pending_render_view_host_
)
349 FrameNavigationState::FrameID
frame_id(frame_num
, render_view_host
);
350 FrameNavigationState::FrameID
parent_frame_id(
351 parent_frame_num
, render_view_host
);
353 navigation_state_
.TrackFrame(frame_id
,
360 if (!navigation_state_
.CanSendEvents(frame_id
))
363 helpers::DispatchOnBeforeNavigate(
365 render_view_host
->GetProcess()->GetID(),
369 navigation_state_
.IsMainFrame(parent_frame_id
),
370 navigation_state_
.GetUrl(frame_id
));
373 void WebNavigationTabObserver::DidCommitProvisionalLoadForFrame(
375 const base::string16
& frame_unique_name
,
378 content::PageTransition transition_type
,
379 content::RenderViewHost
* render_view_host
) {
380 DVLOG(2) << "DidCommitProvisionalLoad("
381 << "render_view_host=" << render_view_host
382 << ", frame_num=" << frame_num
383 << ", url=" << url
<< ")";
384 if (render_view_host
!= render_view_host_
&&
385 render_view_host
!= pending_render_view_host_
)
387 FrameNavigationState::FrameID
frame_id(frame_num
, render_view_host
);
389 bool is_reference_fragment_navigation
=
390 IsReferenceFragmentNavigation(frame_id
, url
);
391 bool is_history_state_modification
=
392 navigation_state_
.GetNavigationCommitted(frame_id
);
394 if (is_main_frame
&& render_view_host_
== render_view_host
) {
395 // Changing the reference fragment or the history state using
396 // history.pushState or history.replaceState does not cancel on-going
397 // iframe navigations.
398 if (!is_reference_fragment_navigation
&& !is_history_state_modification
)
399 SendErrorEvents(web_contents(), render_view_host_
, frame_id
);
400 if (pending_render_view_host_
) {
401 SendErrorEvents(web_contents(),
402 pending_render_view_host_
,
403 FrameNavigationState::FrameID());
404 pending_render_view_host_
= NULL
;
406 } else if (pending_render_view_host_
== render_view_host
) {
408 web_contents(), render_view_host_
, FrameNavigationState::FrameID());
409 render_view_host_
= pending_render_view_host_
;
410 pending_render_view_host_
= NULL
;
413 // Update the URL as it might have changed.
414 navigation_state_
.UpdateFrame(frame_id
, url
);
415 navigation_state_
.SetNavigationCommitted(frame_id
);
417 if (!navigation_state_
.CanSendEvents(frame_id
))
420 if (is_reference_fragment_navigation
) {
421 helpers::DispatchOnCommitted(
422 web_navigation::OnReferenceFragmentUpdated::kEventName
,
426 navigation_state_
.GetUrl(frame_id
),
428 } else if (is_history_state_modification
) {
429 helpers::DispatchOnCommitted(
430 web_navigation::OnHistoryStateUpdated::kEventName
,
434 navigation_state_
.GetUrl(frame_id
),
437 if (navigation_state_
.GetIsServerRedirected(frame_id
)) {
438 transition_type
= static_cast<content::PageTransition
>(
439 transition_type
| content::PAGE_TRANSITION_SERVER_REDIRECT
);
441 helpers::DispatchOnCommitted(
442 web_navigation::OnCommitted::kEventName
,
446 navigation_state_
.GetUrl(frame_id
),
451 void WebNavigationTabObserver::DidFailProvisionalLoad(
453 const base::string16
& frame_unique_id
,
455 const GURL
& validated_url
,
457 const base::string16
& error_description
,
458 content::RenderViewHost
* render_view_host
) {
459 DVLOG(2) << "DidFailProvisionalLoad("
460 << "render_view_host=" << render_view_host
461 << ", frame_num=" << frame_num
462 << ", url=" << validated_url
<< ")";
463 if (render_view_host
!= render_view_host_
&&
464 render_view_host
!= pending_render_view_host_
)
466 bool stop_tracking_frames
= false;
467 if (render_view_host
== pending_render_view_host_
) {
468 pending_render_view_host_
= NULL
;
469 stop_tracking_frames
= true;
472 FrameNavigationState::FrameID
frame_id(frame_num
, render_view_host
);
473 if (navigation_state_
.CanSendEvents(frame_id
)) {
474 helpers::DispatchOnErrorOccurred(
476 render_view_host
->GetProcess()->GetID(),
477 navigation_state_
.GetUrl(frame_id
),
482 navigation_state_
.SetErrorOccurredInFrame(frame_id
);
483 if (stop_tracking_frames
) {
484 navigation_state_
.StopTrackingFramesInRVH(render_view_host
,
485 FrameNavigationState::FrameID());
489 void WebNavigationTabObserver::DocumentLoadedInFrame(
491 content::RenderViewHost
* render_view_host
) {
492 DVLOG(2) << "DocumentLoadedInFrame("
493 << "render_view_host=" << render_view_host
494 << ", frame_num=" << frame_num
<< ")";
495 if (render_view_host
!= render_view_host_
)
497 FrameNavigationState::FrameID
frame_id(frame_num
, render_view_host
);
498 if (!navigation_state_
.CanSendEvents(frame_id
))
500 navigation_state_
.SetParsingFinished(frame_id
);
501 helpers::DispatchOnDOMContentLoaded(web_contents(),
502 navigation_state_
.GetUrl(frame_id
),
503 navigation_state_
.IsMainFrame(frame_id
),
506 if (!navigation_state_
.GetNavigationCompleted(frame_id
))
509 // The load might already have finished by the time we finished parsing. For
510 // compatibility reasons, we artifically delay the load completed signal until
511 // after parsing was completed.
512 helpers::DispatchOnCompleted(web_contents(),
513 navigation_state_
.GetUrl(frame_id
),
514 navigation_state_
.IsMainFrame(frame_id
),
518 void WebNavigationTabObserver::DidFinishLoad(
520 const GURL
& validated_url
,
522 content::RenderViewHost
* render_view_host
) {
523 DVLOG(2) << "DidFinishLoad("
524 << "render_view_host=" << render_view_host
525 << ", frame_num=" << frame_num
526 << ", url=" << validated_url
<< ")";
527 if (render_view_host
!= render_view_host_
)
529 FrameNavigationState::FrameID
frame_id(frame_num
, render_view_host
);
530 // When showing replacement content, we might get load signals for frames
531 // that weren't reguarly loaded.
532 if (!navigation_state_
.IsValidFrame(frame_id
))
534 navigation_state_
.SetNavigationCompleted(frame_id
);
535 if (!navigation_state_
.CanSendEvents(frame_id
))
538 navigation_state_
.GetUrl(frame_id
) == validated_url
||
539 (navigation_state_
.GetUrl(frame_id
) == GURL(content::kAboutSrcDocURL
) &&
540 validated_url
== GURL(content::kAboutBlankURL
)))
541 << "validated URL is " << validated_url
<< " but we expected "
542 << navigation_state_
.GetUrl(frame_id
);
543 DCHECK_EQ(navigation_state_
.IsMainFrame(frame_id
), is_main_frame
);
545 // The load might already have finished by the time we finished parsing. For
546 // compatibility reasons, we artifically delay the load completed signal until
547 // after parsing was completed.
548 if (!navigation_state_
.GetParsingFinished(frame_id
))
550 helpers::DispatchOnCompleted(web_contents(),
551 navigation_state_
.GetUrl(frame_id
),
556 void WebNavigationTabObserver::DidFailLoad(
558 const GURL
& validated_url
,
561 const base::string16
& error_description
,
562 content::RenderViewHost
* render_view_host
) {
563 DVLOG(2) << "DidFailLoad("
564 << "render_view_host=" << render_view_host
565 << ", frame_num=" << frame_num
566 << ", url=" << validated_url
<< ")";
567 if (render_view_host
!= render_view_host_
)
569 FrameNavigationState::FrameID
frame_id(frame_num
, render_view_host
);
570 // When showing replacement content, we might get load signals for frames
571 // that weren't reguarly loaded.
572 if (!navigation_state_
.IsValidFrame(frame_id
))
574 if (navigation_state_
.CanSendEvents(frame_id
)) {
575 helpers::DispatchOnErrorOccurred(
577 render_view_host
->GetProcess()->GetID(),
578 navigation_state_
.GetUrl(frame_id
),
583 navigation_state_
.SetErrorOccurredInFrame(frame_id
);
586 void WebNavigationTabObserver::DidGetRedirectForResourceRequest(
587 content::RenderViewHost
* render_view_host
,
588 const content::ResourceRedirectDetails
& details
) {
589 if (details
.resource_type
!= ResourceType::MAIN_FRAME
&&
590 details
.resource_type
!= ResourceType::SUB_FRAME
) {
593 FrameNavigationState::FrameID
frame_id(details
.render_frame_id
,
595 navigation_state_
.SetIsServerRedirected(frame_id
);
598 void WebNavigationTabObserver::DidOpenRequestedURL(
599 content::WebContents
* new_contents
,
601 const content::Referrer
& referrer
,
602 WindowOpenDisposition disposition
,
603 content::PageTransition transition
,
604 int64 source_frame_num
) {
605 FrameNavigationState::FrameID
frame_id(source_frame_num
, render_view_host_
);
606 if (!navigation_state_
.CanSendEvents(frame_id
))
609 // We only send the onCreatedNavigationTarget if we end up creating a new
611 if (disposition
!= SINGLETON_TAB
&&
612 disposition
!= NEW_FOREGROUND_TAB
&&
613 disposition
!= NEW_BACKGROUND_TAB
&&
614 disposition
!= NEW_POPUP
&&
615 disposition
!= NEW_WINDOW
&&
616 disposition
!= OFF_THE_RECORD
)
619 helpers::DispatchOnCreatedNavigationTarget(
621 new_contents
->GetBrowserContext(),
623 navigation_state_
.IsMainFrame(frame_id
),
628 void WebNavigationTabObserver::FrameDetached(
629 content::RenderViewHost
* render_view_host
,
631 if (render_view_host
!= render_view_host_
&&
632 render_view_host
!= pending_render_view_host_
) {
635 FrameNavigationState::FrameID
frame_id(frame_num
, render_view_host
);
636 if (navigation_state_
.CanSendEvents(frame_id
) &&
637 !navigation_state_
.GetNavigationCompleted(frame_id
)) {
638 helpers::DispatchOnErrorOccurred(
640 render_view_host
->GetProcess()->GetID(),
641 navigation_state_
.GetUrl(frame_id
),
643 navigation_state_
.IsMainFrame(frame_id
),
646 navigation_state_
.FrameDetached(frame_id
);
649 void WebNavigationTabObserver::WebContentsDestroyed(content::WebContents
* tab
) {
650 g_tab_observer
.Get().erase(tab
);
651 registrar_
.RemoveAll();
652 SendErrorEvents(tab
, NULL
, FrameNavigationState::FrameID());
655 void WebNavigationTabObserver::SendErrorEvents(
656 content::WebContents
* web_contents
,
657 content::RenderViewHost
* render_view_host
,
658 FrameNavigationState::FrameID id_to_skip
) {
659 for (FrameNavigationState::const_iterator frame
= navigation_state_
.begin();
660 frame
!= navigation_state_
.end(); ++frame
) {
661 if (!navigation_state_
.GetNavigationCompleted(*frame
) &&
662 navigation_state_
.CanSendEvents(*frame
) &&
663 *frame
!= id_to_skip
&&
664 (!render_view_host
|| frame
->render_view_host
== render_view_host
)) {
665 navigation_state_
.SetErrorOccurredInFrame(*frame
);
666 helpers::DispatchOnErrorOccurred(
668 frame
->render_view_host
->GetProcess()->GetID(),
669 navigation_state_
.GetUrl(*frame
),
671 navigation_state_
.IsMainFrame(*frame
),
675 if (render_view_host
)
676 navigation_state_
.StopTrackingFramesInRVH(render_view_host
, id_to_skip
);
679 // See also NavigationController::IsURLInPageNavigation.
680 bool WebNavigationTabObserver::IsReferenceFragmentNavigation(
681 FrameNavigationState::FrameID frame_id
,
683 GURL existing_url
= navigation_state_
.GetUrl(frame_id
);
684 if (existing_url
== url
)
687 url::Replacements
<char> replacements
;
688 replacements
.ClearRef();
689 return existing_url
.ReplaceComponents(replacements
) ==
690 url
.ReplaceComponents(replacements
);
693 bool WebNavigationGetFrameFunction::RunSync() {
694 scoped_ptr
<GetFrame::Params
> params(GetFrame::Params::Create(*args_
));
695 EXTENSION_FUNCTION_VALIDATE(params
.get());
696 int tab_id
= params
->details
.tab_id
;
697 int frame_id
= params
->details
.frame_id
;
698 int process_id
= params
->details
.process_id
;
700 SetResult(base::Value::CreateNullValue());
702 content::WebContents
* web_contents
;
703 if (!ExtensionTabUtil::GetTabById(tab_id
,
714 WebNavigationTabObserver
* observer
=
715 WebNavigationTabObserver::Get(web_contents
);
718 const FrameNavigationState
& frame_navigation_state
=
719 observer
->frame_navigation_state();
722 frame_id
= frame_navigation_state
.GetMainFrameID().frame_num
;
724 content::RenderViewHost
* render_view_host
=
725 observer
->GetRenderViewHostInProcess(process_id
);
726 if (!render_view_host
)
729 FrameNavigationState::FrameID
internal_frame_id(frame_id
, render_view_host
);
730 if (!frame_navigation_state
.IsValidFrame(internal_frame_id
))
733 GURL frame_url
= frame_navigation_state
.GetUrl(internal_frame_id
);
734 if (!frame_navigation_state
.IsValidUrl(frame_url
))
737 GetFrame::Results::Details frame_details
;
738 frame_details
.url
= frame_url
.spec();
739 frame_details
.error_occurred
=
740 frame_navigation_state
.GetErrorOccurredInFrame(internal_frame_id
);
741 FrameNavigationState::FrameID parent_frame_id
=
742 frame_navigation_state
.GetParentFrameID(internal_frame_id
);
743 frame_details
.parent_frame_id
= helpers::GetFrameId(
744 frame_navigation_state
.IsMainFrame(parent_frame_id
),
745 parent_frame_id
.frame_num
);
746 results_
= GetFrame::Results::Create(frame_details
);
750 bool WebNavigationGetAllFramesFunction::RunSync() {
751 scoped_ptr
<GetAllFrames::Params
> params(GetAllFrames::Params::Create(*args_
));
752 EXTENSION_FUNCTION_VALIDATE(params
.get());
753 int tab_id
= params
->details
.tab_id
;
755 SetResult(base::Value::CreateNullValue());
757 content::WebContents
* web_contents
;
758 if (!ExtensionTabUtil::GetTabById(tab_id
,
769 WebNavigationTabObserver
* observer
=
770 WebNavigationTabObserver::Get(web_contents
);
773 const FrameNavigationState
& navigation_state
=
774 observer
->frame_navigation_state();
776 std::vector
<linked_ptr
<GetAllFrames::Results::DetailsType
> > result_list
;
777 for (FrameNavigationState::const_iterator it
= navigation_state
.begin();
778 it
!= navigation_state
.end(); ++it
) {
779 FrameNavigationState::FrameID frame_id
= *it
;
780 FrameNavigationState::FrameID parent_frame_id
=
781 navigation_state
.GetParentFrameID(frame_id
);
782 GURL frame_url
= navigation_state
.GetUrl(frame_id
);
783 if (!navigation_state
.IsValidUrl(frame_url
))
785 linked_ptr
<GetAllFrames::Results::DetailsType
> frame(
786 new GetAllFrames::Results::DetailsType());
787 frame
->url
= frame_url
.spec();
788 frame
->frame_id
= helpers::GetFrameId(
789 navigation_state
.IsMainFrame(frame_id
), frame_id
.frame_num
);
790 frame
->parent_frame_id
= helpers::GetFrameId(
791 navigation_state
.IsMainFrame(parent_frame_id
),
792 parent_frame_id
.frame_num
);
793 frame
->process_id
= frame_id
.render_view_host
->GetProcess()->GetID();
794 frame
->error_occurred
= navigation_state
.GetErrorOccurredInFrame(frame_id
);
795 result_list
.push_back(frame
);
797 results_
= GetAllFrames::Results::Create(result_list
);
801 WebNavigationAPI::WebNavigationAPI(content::BrowserContext
* context
)
802 : browser_context_(context
) {
803 EventRouter
* event_router
= EventRouter::Get(browser_context_
);
804 event_router
->RegisterObserver(this,
805 web_navigation::OnBeforeNavigate::kEventName
);
806 event_router
->RegisterObserver(this, web_navigation::OnCommitted::kEventName
);
807 event_router
->RegisterObserver(this, web_navigation::OnCompleted::kEventName
);
808 event_router
->RegisterObserver(
809 this, web_navigation::OnCreatedNavigationTarget::kEventName
);
810 event_router
->RegisterObserver(
811 this, web_navigation::OnDOMContentLoaded::kEventName
);
812 event_router
->RegisterObserver(
813 this, web_navigation::OnHistoryStateUpdated::kEventName
);
814 event_router
->RegisterObserver(this,
815 web_navigation::OnErrorOccurred::kEventName
);
816 event_router
->RegisterObserver(
817 this, web_navigation::OnReferenceFragmentUpdated::kEventName
);
818 event_router
->RegisterObserver(this,
819 web_navigation::OnTabReplaced::kEventName
);
822 WebNavigationAPI::~WebNavigationAPI() {
825 void WebNavigationAPI::Shutdown() {
826 EventRouter::Get(browser_context_
)->UnregisterObserver(this);
829 static base::LazyInstance
<BrowserContextKeyedAPIFactory
<WebNavigationAPI
> >
830 g_factory
= LAZY_INSTANCE_INITIALIZER
;
833 BrowserContextKeyedAPIFactory
<WebNavigationAPI
>*
834 WebNavigationAPI::GetFactoryInstance() {
835 return g_factory
.Pointer();
838 void WebNavigationAPI::OnListenerAdded(const EventListenerInfo
& details
) {
839 web_navigation_event_router_
.reset(new WebNavigationEventRouter(
840 Profile::FromBrowserContext(browser_context_
)));
841 EventRouter::Get(browser_context_
)->UnregisterObserver(this);
846 } // namespace extensions