Chromium Code Reviews| Index: chrome/browser/extensions/extension_webnavigation_api.cc |
| diff --git a/chrome/browser/extensions/extension_webnavigation_api.cc b/chrome/browser/extensions/extension_webnavigation_api.cc |
| index 159fdb7995d9b0dab899d8e77a4e2f68d7063914..b816f96b5659bd9d3f9db881fdb27a9c141a3fe2 100644 |
| --- a/chrome/browser/extensions/extension_webnavigation_api.cc |
| +++ b/chrome/browser/extensions/extension_webnavigation_api.cc |
| @@ -17,6 +17,7 @@ |
| #include "chrome/browser/tab_contents/provisional_load_details.h" |
| #include "chrome/common/notification_type.h" |
| #include "chrome/common/notification_service.h" |
| +#include "chrome/common/url_constants.h" |
| #include "net/base/net_errors.h" |
| namespace keys = extension_webnavigation_api_constants; |
| @@ -36,6 +37,59 @@ double MilliSecondsFromTime(const base::Time& time) { |
| } // namespace |
| +FrameNavigationState::FrameNavigationState() { |
| + registrar_.Add(this, |
| + NotificationType::TAB_CONTENTS_DESTROYED, |
| + NotificationService::AllSources()); |
| +} |
| + |
| +FrameNavigationState::~FrameNavigationState() { |
| +} |
| + |
| +bool FrameNavigationState::CanSendEvents(long long frame_id) const { |
| + FrameIdToErrorStateMap::const_iterator frame_state = |
| + frame_state_map_.find(frame_id); |
| + return frame_state != frame_state_map_.end() && |
| + !frame_state->second; |
| +} |
| + |
| +void FrameNavigationState::TrackFrame(long long frame_id, |
| + const GURL& url, |
| + bool is_main_frame, |
| + const TabContents* tab_contents) { |
| + if (is_main_frame) |
| + RemoveTabContentsState(tab_contents); |
| + tab_contents_map_.insert( |
| + TabContentsToFrameIdMap::value_type(tab_contents, frame_id)); |
| + frame_state_map_[frame_id] = |
| + (url.spec() == chrome::kChromeUnreachableWebDataURL); |
| +} |
| + |
| +void FrameNavigationState::ErrorOccurredInFrame(long long frame_id) { |
| + DCHECK(frame_state_map_.find(frame_id) != frame_state_map_.end()); |
| + frame_state_map_[frame_id] = true; |
| +} |
| + |
| +void FrameNavigationState::Observe( |
| + NotificationType type, |
| + const NotificationSource& source, |
| + const NotificationDetails& details) { |
| + RemoveTabContentsState(Source<TabContents>(source).ptr()); |
| +} |
| + |
| +void FrameNavigationState::RemoveTabContentsState( |
| + const TabContents* tab_contents) { |
| + typedef TabContentsToFrameIdMap::iterator FrameIdIterator; |
| + std::pair<FrameIdIterator, FrameIdIterator> frame_ids = |
| + tab_contents_map_.equal_range(tab_contents); |
| + for (FrameIdIterator frame_id = frame_ids.first; frame_id != frame_ids.second; |
| + frame_id++) { |
|
yzshen
2010/10/27 17:43:38
[optional] Better to use ++frame_id.
|
| + frame_state_map_.erase(frame_id->second); |
| + } |
| + tab_contents_map_.erase(tab_contents); |
| +} |
| + |
| + |
| // static |
| ExtensionWebNavigationEventRouter* |
| ExtensionWebNavigationEventRouter::GetInstance() { |
| @@ -84,6 +138,10 @@ void ExtensionWebNavigationEventRouter::Observe( |
| void ExtensionWebNavigationEventRouter::FrameProvisionalLoadStart( |
| NavigationController* controller, |
| ProvisionalLoadDetails* details) { |
| + navigation_state_.TrackFrame(details->frame_id(), |
| + details->url(), |
| + details->main_frame(), |
| + controller->tab_contents()); |
| ListValue args; |
| DictionaryValue* dict = new DictionaryValue(); |
| dict->SetInteger(keys::kTabIdKey, |
| @@ -97,7 +155,8 @@ void ExtensionWebNavigationEventRouter::FrameProvisionalLoadStart( |
| std::string json_args; |
| base::JSONWriter::Write(&args, false, &json_args); |
| - DispatchEvent(controller->profile(), keys::kOnBeforeNavigate, json_args); |
| + if (navigation_state_.CanSendEvents(details->frame_id())) |
| + DispatchEvent(controller->profile(), keys::kOnBeforeNavigate, json_args); |
| } |
| void ExtensionWebNavigationEventRouter::FrameProvisionalLoadCommitted( |
| @@ -121,7 +180,8 @@ void ExtensionWebNavigationEventRouter::FrameProvisionalLoadCommitted( |
| std::string json_args; |
| base::JSONWriter::Write(&args, false, &json_args); |
| - DispatchEvent(controller->profile(), keys::kOnCommitted, json_args); |
| + if (navigation_state_.CanSendEvents(details->frame_id())) |
| + DispatchEvent(controller->profile(), keys::kOnCommitted, json_args); |
| } |
| void ExtensionWebNavigationEventRouter::FailProvisionalLoadWithError( |
| @@ -141,7 +201,10 @@ void ExtensionWebNavigationEventRouter::FailProvisionalLoadWithError( |
| std::string json_args; |
| base::JSONWriter::Write(&args, false, &json_args); |
| - DispatchEvent(controller->profile(), keys::kOnErrorOccurred, json_args); |
| + if (navigation_state_.CanSendEvents(details->frame_id())) { |
| + navigation_state_.ErrorOccurredInFrame(details->frame_id()); |
| + DispatchEvent(controller->profile(), keys::kOnErrorOccurred, json_args); |
| + } |
| } |
| void ExtensionWebNavigationEventRouter::DispatchEvent( |