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_frame_host.h"
24 #include "content/public/browser/render_process_host.h"
25 #include "content/public/browser/render_view_host.h"
26 #include "content/public/browser/resource_request_details.h"
27 #include "content/public/browser/web_contents.h"
28 #include "content/public/common/url_constants.h"
29 #include "extensions/browser/event_router.h"
30 #include "extensions/browser/view_type_utils.h"
31 #include "net/base/net_errors.h"
33 using content::ResourceType;
35 namespace GetFrame = extensions::api::web_navigation::GetFrame;
36 namespace GetAllFrames = extensions::api::web_navigation::GetAllFrames;
38 DEFINE_WEB_CONTENTS_USER_DATA_KEY(extensions::WebNavigationTabObserver);
40 namespace extensions {
42 namespace helpers = web_navigation_api_helpers;
43 namespace keys = web_navigation_api_constants;
44 namespace web_navigation = api::web_navigation;
48 typedef std::map<content::WebContents*, WebNavigationTabObserver*>
50 static base::LazyInstance<TabObserverMap> g_tab_observer =
51 LAZY_INSTANCE_INITIALIZER;
55 // WebNavigtionEventRouter -------------------------------------------
57 WebNavigationEventRouter::PendingWebContents::PendingWebContents()
58 : source_web_contents(NULL),
59 source_frame_host(NULL),
60 target_web_contents(NULL),
64 WebNavigationEventRouter::PendingWebContents::PendingWebContents(
65 content::WebContents* source_web_contents,
66 content::RenderFrameHost* source_frame_host,
67 content::WebContents* target_web_contents,
68 const GURL& target_url)
69 : source_web_contents(source_web_contents),
70 source_frame_host(source_frame_host),
71 target_web_contents(target_web_contents),
72 target_url(target_url) {
75 WebNavigationEventRouter::PendingWebContents::~PendingWebContents() {}
77 WebNavigationEventRouter::WebNavigationEventRouter(Profile* profile)
79 CHECK(registrar_.IsEmpty());
81 chrome::NOTIFICATION_RETARGETING,
82 content::NotificationService::AllSources());
84 chrome::NOTIFICATION_TAB_ADDED,
85 content::NotificationService::AllSources());
87 content::NOTIFICATION_WEB_CONTENTS_DESTROYED,
88 content::NotificationService::AllSources());
90 BrowserList::AddObserver(this);
91 for (chrome::BrowserIterator it; !it.done(); it.Next())
95 WebNavigationEventRouter::~WebNavigationEventRouter() {
96 for (chrome::BrowserIterator it; !it.done(); it.Next())
97 OnBrowserRemoved(*it);
98 BrowserList::RemoveObserver(this);
101 void WebNavigationEventRouter::OnBrowserAdded(Browser* browser) {
102 if (!profile_->IsSameProfile(browser->profile()))
104 browser->tab_strip_model()->AddObserver(this);
107 void WebNavigationEventRouter::OnBrowserRemoved(Browser* browser) {
108 if (!profile_->IsSameProfile(browser->profile()))
110 browser->tab_strip_model()->RemoveObserver(this);
113 void WebNavigationEventRouter::TabReplacedAt(
114 TabStripModel* tab_strip_model,
115 content::WebContents* old_contents,
116 content::WebContents* new_contents,
118 WebNavigationTabObserver* tab_observer =
119 WebNavigationTabObserver::Get(old_contents);
121 // If you hit this DCHECK(), please add reproduction steps to
122 // http://crbug.com/109464.
123 DCHECK(GetViewType(old_contents) != VIEW_TYPE_TAB_CONTENTS);
126 const FrameNavigationState& frame_navigation_state =
127 tab_observer->frame_navigation_state();
129 if (!frame_navigation_state.IsValidUrl(old_contents->GetURL()) ||
130 !frame_navigation_state.IsValidUrl(new_contents->GetURL()))
133 helpers::DispatchOnTabReplaced(old_contents, profile_, new_contents);
136 void WebNavigationEventRouter::Observe(
138 const content::NotificationSource& source,
139 const content::NotificationDetails& details) {
141 case chrome::NOTIFICATION_RETARGETING: {
142 Profile* profile = content::Source<Profile>(source).ptr();
143 if (profile->GetOriginalProfile() == profile_) {
145 content::Details<const RetargetingDetails>(details).ptr());
150 case chrome::NOTIFICATION_TAB_ADDED:
151 TabAdded(content::Details<content::WebContents>(details).ptr());
154 case content::NOTIFICATION_WEB_CONTENTS_DESTROYED:
155 TabDestroyed(content::Source<content::WebContents>(source).ptr());
163 void WebNavigationEventRouter::Retargeting(const RetargetingDetails* details) {
164 if (details->source_render_frame_id == 0)
166 WebNavigationTabObserver* tab_observer =
167 WebNavigationTabObserver::Get(details->source_web_contents);
169 // If you hit this DCHECK(), please add reproduction steps to
170 // http://crbug.com/109464.
171 DCHECK(GetViewType(details->source_web_contents) != VIEW_TYPE_TAB_CONTENTS);
174 const FrameNavigationState& frame_navigation_state =
175 tab_observer->frame_navigation_state();
177 content::RenderFrameHost* frame_host = content::RenderFrameHost::FromID(
178 details->source_web_contents->GetRenderProcessHost()->GetID(),
179 details->source_render_frame_id);
180 if (!frame_navigation_state.CanSendEvents(frame_host))
183 // If the WebContents isn't yet inserted into a tab strip, we need to delay
184 // the extension event until the WebContents is fully initialized.
185 if (details->not_yet_in_tabstrip) {
186 pending_web_contents_[details->target_web_contents] =
187 PendingWebContents(details->source_web_contents,
189 details->target_web_contents,
190 details->target_url);
192 helpers::DispatchOnCreatedNavigationTarget(
193 details->source_web_contents,
194 details->target_web_contents->GetBrowserContext(),
196 details->target_web_contents,
197 details->target_url);
201 void WebNavigationEventRouter::TabAdded(content::WebContents* tab) {
202 std::map<content::WebContents*, PendingWebContents>::iterator iter =
203 pending_web_contents_.find(tab);
204 if (iter == pending_web_contents_.end())
207 WebNavigationTabObserver* tab_observer =
208 WebNavigationTabObserver::Get(iter->second.source_web_contents);
213 const FrameNavigationState& frame_navigation_state =
214 tab_observer->frame_navigation_state();
216 if (frame_navigation_state.CanSendEvents(iter->second.source_frame_host)) {
217 helpers::DispatchOnCreatedNavigationTarget(
218 iter->second.source_web_contents,
219 iter->second.target_web_contents->GetBrowserContext(),
220 iter->second.source_frame_host,
221 iter->second.target_web_contents,
222 iter->second.target_url);
224 pending_web_contents_.erase(iter);
227 void WebNavigationEventRouter::TabDestroyed(content::WebContents* tab) {
228 pending_web_contents_.erase(tab);
229 for (std::map<content::WebContents*, PendingWebContents>::iterator i =
230 pending_web_contents_.begin(); i != pending_web_contents_.end(); ) {
231 if (i->second.source_web_contents == tab)
232 pending_web_contents_.erase(i++);
238 // WebNavigationTabObserver ------------------------------------------
240 WebNavigationTabObserver::WebNavigationTabObserver(
241 content::WebContents* web_contents)
242 : WebContentsObserver(web_contents),
243 render_view_host_(NULL),
244 pending_render_view_host_(NULL) {
245 g_tab_observer.Get().insert(TabObserverMap::value_type(web_contents, this));
247 content::NOTIFICATION_RENDER_VIEW_HOST_WILL_CLOSE_RENDER_VIEW,
248 content::NotificationService::AllSources());
251 WebNavigationTabObserver::~WebNavigationTabObserver() {}
254 WebNavigationTabObserver* WebNavigationTabObserver::Get(
255 content::WebContents* web_contents) {
256 TabObserverMap::iterator i = g_tab_observer.Get().find(web_contents);
257 return i == g_tab_observer.Get().end() ? NULL : i->second;
260 content::RenderViewHost* WebNavigationTabObserver::GetRenderViewHostInProcess(
261 int process_id) const {
262 if (render_view_host_ &&
263 render_view_host_->GetProcess()->GetID() == process_id) {
264 return render_view_host_;
266 if (pending_render_view_host_ &&
267 pending_render_view_host_->GetProcess()->GetID() == process_id) {
268 return pending_render_view_host_;
273 void WebNavigationTabObserver::Observe(
275 const content::NotificationSource& source,
276 const content::NotificationDetails& details) {
278 case content::NOTIFICATION_RENDER_VIEW_HOST_WILL_CLOSE_RENDER_VIEW: {
279 // The RenderView is technically not yet deleted, but the RenderViewHost
280 // already starts to filter out some IPCs. In order to not get confused,
281 // we consider the RenderView dead already now.
282 RenderViewDeleted(content::Source<content::RenderViewHost>(source).ptr());
291 void WebNavigationTabObserver::RenderFrameDeleted(
292 content::RenderFrameHost* render_frame_host) {
293 content::RenderViewHost* render_view_host =
294 render_frame_host->GetRenderViewHost();
295 if (render_view_host != render_view_host_ &&
296 render_view_host != pending_render_view_host_) {
299 if (navigation_state_.CanSendEvents(render_frame_host) &&
300 !navigation_state_.GetNavigationCompleted(render_frame_host)) {
301 helpers::DispatchOnErrorOccurred(
304 navigation_state_.GetUrl(render_frame_host),
307 navigation_state_.FrameDetached(render_frame_host);
310 void WebNavigationTabObserver::RenderViewDeleted(
311 content::RenderViewHost* render_view_host) {
312 if (render_view_host == render_view_host_) {
313 render_view_host_ = NULL;
314 if (pending_render_view_host_) {
315 render_view_host_ = pending_render_view_host_;
316 pending_render_view_host_ = NULL;
318 } else if (render_view_host == pending_render_view_host_) {
319 pending_render_view_host_ = NULL;
323 SendErrorEvents(web_contents(), render_view_host, NULL);
326 void WebNavigationTabObserver::AboutToNavigateRenderView(
327 content::RenderViewHost* render_view_host) {
328 if (!render_view_host_) {
329 render_view_host_ = render_view_host;
330 } else if (render_view_host != render_view_host_) {
331 if (pending_render_view_host_) {
332 SendErrorEvents(web_contents(), pending_render_view_host_, NULL);
334 pending_render_view_host_ = render_view_host;
338 void WebNavigationTabObserver::DidStartProvisionalLoadForFrame(
339 content::RenderFrameHost* render_frame_host,
340 const GURL& validated_url,
342 bool is_iframe_srcdoc) {
343 content::RenderViewHost* render_view_host =
344 render_frame_host->GetRenderViewHost();
345 DVLOG(2) << "DidStartProvisionalLoad("
346 << "render_view_host=" << render_view_host
347 << ", frame_num=" << render_frame_host->GetRoutingID()
348 << ", url=" << validated_url << ")";
349 if (!render_view_host_)
350 render_view_host_ = render_view_host;
351 if (render_view_host != render_view_host_ &&
352 render_view_host != pending_render_view_host_)
355 navigation_state_.TrackFrame(
356 render_frame_host, validated_url, is_error_page, is_iframe_srcdoc);
358 if (!navigation_state_.CanSendEvents(render_frame_host))
361 helpers::DispatchOnBeforeNavigate(
364 navigation_state_.GetUrl(render_frame_host));
367 void WebNavigationTabObserver::DidCommitProvisionalLoadForFrame(
368 content::RenderFrameHost* render_frame_host,
370 ui::PageTransition transition_type) {
371 content::RenderViewHost* render_view_host =
372 render_frame_host->GetRenderViewHost();
373 DVLOG(2) << "DidCommitProvisionalLoad("
374 << "render_view_host=" << render_view_host
375 << ", frame_num=" << render_frame_host->GetRoutingID()
376 << ", url=" << url << ")";
377 if (render_view_host != render_view_host_ &&
378 render_view_host != pending_render_view_host_)
381 bool is_reference_fragment_navigation =
382 IsReferenceFragmentNavigation(render_frame_host, url);
383 bool is_history_state_modification =
384 navigation_state_.GetNavigationCommitted(render_frame_host);
386 if (!render_frame_host->GetParent() &&
387 render_view_host_ == render_view_host) {
388 // Changing the reference fragment or the history state using
389 // history.pushState or history.replaceState does not cancel on-going
390 // iframe navigations.
391 if (!is_reference_fragment_navigation && !is_history_state_modification)
392 SendErrorEvents(web_contents(), render_view_host_, render_frame_host);
393 if (pending_render_view_host_) {
394 SendErrorEvents(web_contents(), pending_render_view_host_, NULL);
395 pending_render_view_host_ = NULL;
397 } else if (pending_render_view_host_ == render_view_host) {
398 SendErrorEvents(web_contents(), render_view_host_, NULL);
399 render_view_host_ = pending_render_view_host_;
400 pending_render_view_host_ = NULL;
403 // Update the URL as it might have changed.
404 navigation_state_.UpdateFrame(render_frame_host, url);
405 navigation_state_.SetNavigationCommitted(render_frame_host);
407 if (!navigation_state_.CanSendEvents(render_frame_host))
410 if (is_reference_fragment_navigation) {
411 helpers::DispatchOnCommitted(
412 web_navigation::OnReferenceFragmentUpdated::kEventName,
415 navigation_state_.GetUrl(render_frame_host),
417 } else if (is_history_state_modification) {
418 helpers::DispatchOnCommitted(
419 web_navigation::OnHistoryStateUpdated::kEventName,
422 navigation_state_.GetUrl(render_frame_host),
425 if (navigation_state_.GetIsServerRedirected(render_frame_host)) {
426 transition_type = ui::PageTransitionFromInt(
427 transition_type | ui::PAGE_TRANSITION_SERVER_REDIRECT);
429 helpers::DispatchOnCommitted(web_navigation::OnCommitted::kEventName,
432 navigation_state_.GetUrl(render_frame_host),
437 void WebNavigationTabObserver::DidFailProvisionalLoad(
438 content::RenderFrameHost* render_frame_host,
439 const GURL& validated_url,
441 const base::string16& error_description) {
442 content::RenderViewHost* render_view_host =
443 render_frame_host->GetRenderViewHost();
444 DVLOG(2) << "DidFailProvisionalLoad("
445 << "render_view_host=" << render_view_host
446 << ", frame_num=" << render_frame_host->GetRoutingID()
447 << ", url=" << validated_url << ")";
448 if (render_view_host != render_view_host_ &&
449 render_view_host != pending_render_view_host_)
451 bool stop_tracking_frames = false;
452 if (render_view_host == pending_render_view_host_) {
453 pending_render_view_host_ = NULL;
454 stop_tracking_frames = true;
457 if (navigation_state_.CanSendEvents(render_frame_host)) {
458 helpers::DispatchOnErrorOccurred(
461 navigation_state_.GetUrl(render_frame_host),
464 navigation_state_.SetErrorOccurredInFrame(render_frame_host);
465 if (stop_tracking_frames) {
466 navigation_state_.StopTrackingFramesInRVH(render_view_host, NULL);
470 void WebNavigationTabObserver::DocumentLoadedInFrame(
471 content::RenderFrameHost* render_frame_host) {
472 content::RenderViewHost* render_view_host =
473 render_frame_host->GetRenderViewHost();
474 DVLOG(2) << "DocumentLoadedInFrame("
475 << "render_view_host=" << render_view_host
476 << ", frame_num=" << render_frame_host->GetRoutingID() << ")";
477 if (render_view_host != render_view_host_)
479 if (!navigation_state_.CanSendEvents(render_frame_host))
481 navigation_state_.SetParsingFinished(render_frame_host);
482 helpers::DispatchOnDOMContentLoaded(
485 navigation_state_.GetUrl(render_frame_host));
487 if (!navigation_state_.GetNavigationCompleted(render_frame_host))
490 // The load might already have finished by the time we finished parsing. For
491 // compatibility reasons, we artifically delay the load completed signal until
492 // after parsing was completed.
493 helpers::DispatchOnCompleted(web_contents(),
495 navigation_state_.GetUrl(render_frame_host));
498 void WebNavigationTabObserver::DidFinishLoad(
499 content::RenderFrameHost* render_frame_host,
500 const GURL& validated_url) {
501 content::RenderViewHost* render_view_host =
502 render_frame_host->GetRenderViewHost();
503 DVLOG(2) << "DidFinishLoad("
504 << "render_view_host=" << render_view_host
505 << ", frame_num=" << render_frame_host->GetRoutingID()
506 << ", url=" << validated_url << ")";
507 if (render_view_host != render_view_host_)
509 // When showing replacement content, we might get load signals for frames
510 // that weren't reguarly loaded.
511 if (!navigation_state_.IsValidFrame(render_frame_host))
513 navigation_state_.SetNavigationCompleted(render_frame_host);
514 if (!navigation_state_.CanSendEvents(render_frame_host))
516 DCHECK(navigation_state_.GetUrl(render_frame_host) == validated_url ||
517 (navigation_state_.GetUrl(render_frame_host) ==
518 GURL(content::kAboutSrcDocURL) &&
519 validated_url == GURL(url::kAboutBlankURL)))
520 << "validated URL is " << validated_url << " but we expected "
521 << navigation_state_.GetUrl(render_frame_host);
523 // The load might already have finished by the time we finished parsing. For
524 // compatibility reasons, we artifically delay the load completed signal until
525 // after parsing was completed.
526 if (!navigation_state_.GetParsingFinished(render_frame_host))
528 helpers::DispatchOnCompleted(web_contents(),
530 navigation_state_.GetUrl(render_frame_host));
533 void WebNavigationTabObserver::DidFailLoad(
534 content::RenderFrameHost* render_frame_host,
535 const GURL& validated_url,
537 const base::string16& error_description) {
538 content::RenderViewHost* render_view_host =
539 render_frame_host->GetRenderViewHost();
540 DVLOG(2) << "DidFailLoad("
541 << "render_view_host=" << render_view_host
542 << ", frame_num=" << render_frame_host->GetRoutingID()
543 << ", url=" << validated_url << ")";
544 if (render_view_host != render_view_host_)
546 // When showing replacement content, we might get load signals for frames
547 // that weren't reguarly loaded.
548 if (!navigation_state_.IsValidFrame(render_frame_host))
550 if (navigation_state_.CanSendEvents(render_frame_host)) {
551 helpers::DispatchOnErrorOccurred(
554 navigation_state_.GetUrl(render_frame_host),
557 navigation_state_.SetErrorOccurredInFrame(render_frame_host);
560 void WebNavigationTabObserver::DidGetRedirectForResourceRequest(
561 content::RenderViewHost* render_view_host,
562 const content::ResourceRedirectDetails& details) {
563 if (details.resource_type != content::RESOURCE_TYPE_MAIN_FRAME &&
564 details.resource_type != content::RESOURCE_TYPE_SUB_FRAME) {
567 content::RenderFrameHost* render_frame_host =
568 content::RenderFrameHost::FromID(render_view_host->GetProcess()->GetID(),
569 details.render_frame_id);
570 navigation_state_.SetIsServerRedirected(render_frame_host);
573 void WebNavigationTabObserver::DidOpenRequestedURL(
574 content::WebContents* new_contents,
576 const content::Referrer& referrer,
577 WindowOpenDisposition disposition,
578 ui::PageTransition transition,
579 int64 source_frame_num) {
580 content::RenderFrameHost* render_frame_host =
581 content::RenderFrameHost::FromID(render_view_host_->GetProcess()->GetID(),
583 if (!navigation_state_.CanSendEvents(render_frame_host))
586 // We only send the onCreatedNavigationTarget if we end up creating a new
588 if (disposition != SINGLETON_TAB &&
589 disposition != NEW_FOREGROUND_TAB &&
590 disposition != NEW_BACKGROUND_TAB &&
591 disposition != NEW_POPUP &&
592 disposition != NEW_WINDOW &&
593 disposition != OFF_THE_RECORD)
596 helpers::DispatchOnCreatedNavigationTarget(web_contents(),
597 new_contents->GetBrowserContext(),
603 void WebNavigationTabObserver::WebContentsDestroyed() {
604 g_tab_observer.Get().erase(web_contents());
605 registrar_.RemoveAll();
606 SendErrorEvents(web_contents(), NULL, NULL);
609 void WebNavigationTabObserver::SendErrorEvents(
610 content::WebContents* web_contents,
611 content::RenderViewHost* render_view_host,
612 content::RenderFrameHost* frame_host_to_skip) {
613 for (FrameNavigationState::const_iterator it = navigation_state_.begin();
614 it != navigation_state_.end();
616 if (!navigation_state_.GetNavigationCompleted(*it) &&
617 navigation_state_.CanSendEvents(*it) && *it != frame_host_to_skip &&
618 (!render_view_host || (*it)->GetRenderViewHost() == render_view_host)) {
619 navigation_state_.SetErrorOccurredInFrame(*it);
620 helpers::DispatchOnErrorOccurred(
621 web_contents, *it, navigation_state_.GetUrl(*it), net::ERR_ABORTED);
624 if (render_view_host)
625 navigation_state_.StopTrackingFramesInRVH(render_view_host,
629 // See also NavigationController::IsURLInPageNavigation.
630 bool WebNavigationTabObserver::IsReferenceFragmentNavigation(
631 content::RenderFrameHost* render_frame_host,
633 GURL existing_url = navigation_state_.GetUrl(render_frame_host);
634 if (existing_url == url)
637 url::Replacements<char> replacements;
638 replacements.ClearRef();
639 return existing_url.ReplaceComponents(replacements) ==
640 url.ReplaceComponents(replacements);
643 bool WebNavigationGetFrameFunction::RunSync() {
644 scoped_ptr<GetFrame::Params> params(GetFrame::Params::Create(*args_));
645 EXTENSION_FUNCTION_VALIDATE(params.get());
646 int tab_id = params->details.tab_id;
647 int frame_id = params->details.frame_id;
648 int process_id = params->details.process_id;
650 SetResult(base::Value::CreateNullValue());
652 content::WebContents* web_contents;
653 if (!ExtensionTabUtil::GetTabById(tab_id,
664 WebNavigationTabObserver* observer =
665 WebNavigationTabObserver::Get(web_contents);
668 const FrameNavigationState& frame_navigation_state =
669 observer->frame_navigation_state();
671 content::RenderFrameHost* render_frame_host =
672 frame_id == 0 ? frame_navigation_state.GetLastCommittedMainFrameHost()
673 : content::RenderFrameHost::FromID(process_id, frame_id);
674 if (!frame_navigation_state.IsValidFrame(render_frame_host))
677 GURL frame_url = frame_navigation_state.GetUrl(render_frame_host);
678 if (!frame_navigation_state.IsValidUrl(frame_url))
681 GetFrame::Results::Details frame_details;
682 frame_details.url = frame_url.spec();
683 frame_details.error_occurred =
684 frame_navigation_state.GetErrorOccurredInFrame(render_frame_host);
685 frame_details.parent_frame_id =
686 helpers::GetFrameId(render_frame_host->GetParent());
687 results_ = GetFrame::Results::Create(frame_details);
691 bool WebNavigationGetAllFramesFunction::RunSync() {
692 scoped_ptr<GetAllFrames::Params> params(GetAllFrames::Params::Create(*args_));
693 EXTENSION_FUNCTION_VALIDATE(params.get());
694 int tab_id = params->details.tab_id;
696 SetResult(base::Value::CreateNullValue());
698 content::WebContents* web_contents;
699 if (!ExtensionTabUtil::GetTabById(tab_id,
710 WebNavigationTabObserver* observer =
711 WebNavigationTabObserver::Get(web_contents);
714 const FrameNavigationState& navigation_state =
715 observer->frame_navigation_state();
717 std::vector<linked_ptr<GetAllFrames::Results::DetailsType> > result_list;
718 for (FrameNavigationState::const_iterator it = navigation_state.begin();
719 it != navigation_state.end(); ++it) {
720 GURL frame_url = navigation_state.GetUrl(*it);
721 if (!navigation_state.IsValidUrl(frame_url))
723 linked_ptr<GetAllFrames::Results::DetailsType> frame(
724 new GetAllFrames::Results::DetailsType());
725 frame->url = frame_url.spec();
726 frame->frame_id = helpers::GetFrameId(*it);
727 frame->parent_frame_id = helpers::GetFrameId((*it)->GetParent());
728 frame->process_id = (*it)->GetRenderViewHost()->GetProcess()->GetID();
729 frame->error_occurred = navigation_state.GetErrorOccurredInFrame(*it);
730 result_list.push_back(frame);
732 results_ = GetAllFrames::Results::Create(result_list);
736 WebNavigationAPI::WebNavigationAPI(content::BrowserContext* context)
737 : browser_context_(context) {
738 EventRouter* event_router = EventRouter::Get(browser_context_);
739 event_router->RegisterObserver(this,
740 web_navigation::OnBeforeNavigate::kEventName);
741 event_router->RegisterObserver(this, web_navigation::OnCommitted::kEventName);
742 event_router->RegisterObserver(this, web_navigation::OnCompleted::kEventName);
743 event_router->RegisterObserver(
744 this, web_navigation::OnCreatedNavigationTarget::kEventName);
745 event_router->RegisterObserver(
746 this, web_navigation::OnDOMContentLoaded::kEventName);
747 event_router->RegisterObserver(
748 this, web_navigation::OnHistoryStateUpdated::kEventName);
749 event_router->RegisterObserver(this,
750 web_navigation::OnErrorOccurred::kEventName);
751 event_router->RegisterObserver(
752 this, web_navigation::OnReferenceFragmentUpdated::kEventName);
753 event_router->RegisterObserver(this,
754 web_navigation::OnTabReplaced::kEventName);
757 WebNavigationAPI::~WebNavigationAPI() {
760 void WebNavigationAPI::Shutdown() {
761 EventRouter::Get(browser_context_)->UnregisterObserver(this);
764 static base::LazyInstance<BrowserContextKeyedAPIFactory<WebNavigationAPI> >
765 g_factory = LAZY_INSTANCE_INITIALIZER;
768 BrowserContextKeyedAPIFactory<WebNavigationAPI>*
769 WebNavigationAPI::GetFactoryInstance() {
770 return g_factory.Pointer();
773 void WebNavigationAPI::OnListenerAdded(const EventListenerInfo& details) {
774 web_navigation_event_router_.reset(new WebNavigationEventRouter(
775 Profile::FromBrowserContext(browser_context_)));
776 EventRouter::Get(browser_context_)->UnregisterObserver(this);
779 } // namespace extensions