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( |