// Copyright (c) 2011 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// Defines the Chrome Extensions WebNavigation API functions for observing and
// intercepting navigation events, as specified in
// chrome/common/extensions/api/extension_api.json.
#ifndef CHROME_BROWSER_EXTENSIONS_EXTENSION_WEBNAVIGATION_API_H_
#define CHROME_BROWSER_EXTENSIONS_EXTENSION_WEBNAVIGATION_API_H_
#pragma once
#include <map>
#include "base/memory/singleton.h"
#include "chrome/browser/extensions/extension_function.h"
#include "content/browser/tab_contents/tab_contents_observer.h"
#include "content/common/notification_observer.h"
#include "content/common/notification_registrar.h"
#include "googleurl/src/gurl.h"
class TabContents;
struct ViewHostMsg_CreateWindow_Params;
// Tracks the navigation state of all frames currently known to the
// webNavigation API. It is mainly used to track in which frames an error
// occurred so no further events for this frame are being sent.
class FrameNavigationState {
public:
FrameNavigationState();
~FrameNavigationState();
// True if navigation events for the given frame can be sent.
bool CanSendEvents(int64 frame_id) const;
// Starts to track a frame given by its |frame_id| showing the URL |url| in
// a |tab_contents|.
void TrackFrame(int64 frame_id,
const GURL& url,
bool is_main_frame,
bool is_error_page,
const TabContents* tab_contents);
// Returns the URL corresponding to a tracked frame given by its |frame_id|.
GURL GetUrl(int64 frame_id) const;
// True if the frame given by its |frame_id| is the main frame of its tab.
bool IsMainFrame(int64 frame_id) const;
// Marks a frame as in an error state.
void ErrorOccurredInFrame(int64 frame_id);
// Removes state associated with this tab contents and all of its frames.
void RemoveTabContentsState(const TabContents* tab_contents);
#ifdef UNIT_TEST
static void set_allow_extension_scheme(bool allow_extension_scheme) {
allow_extension_scheme_ = allow_extension_scheme;
}
#endif
private:
typedef std::multimap<const TabContents*, int64> TabContentsToFrameIdMap;
struct FrameState {
bool error_occurred; // True if an error has occurred in this frame.
bool is_main_frame; // True if this is a main frame.
GURL url; // URL of this frame.
};
typedef std::map<int64, FrameState> FrameIdToStateMap;
// Tracks which frames belong to a given tab contents object.
TabContentsToFrameIdMap tab_contents_map_;
// Tracks the state of known frames.
FrameIdToStateMap frame_state_map_;
// If true, also allow events from chrome-extension:// URLs.
static bool allow_extension_scheme_;
DISALLOW_COPY_AND_ASSIGN(FrameNavigationState);
};
// Tab contents observer that forwards navigation events to the event router.
class ExtensionWebNavigationTabObserver : public TabContentsObserver {
public:
explicit ExtensionWebNavigationTabObserver(TabContents* tab_contents);
virtual ~ExtensionWebNavigationTabObserver();
// TabContentsObserver implementation.
virtual void DidStartProvisionalLoadForFrame(int64 frame_id,
bool is_main_frame,
const GURL& validated_url,
bool is_error_page) OVERRIDE;
virtual void DidCommitProvisionalLoadForFrame(
int64 frame_id,
bool is_main_frame,
const GURL& url,
PageTransition::Type transition_type) OVERRIDE;
virtual void DidFailProvisionalLoad(int64 frame_id,
bool is_main_frame,
const GURL& validated_url,
int error_code) OVERRIDE;
virtual void DocumentLoadedInFrame(int64 frame_id) OVERRIDE;
virtual void DidFinishLoad(int64 frame_id) OVERRIDE;
virtual void TabContentsDestroyed(TabContents* tab) OVERRIDE;
virtual void DidOpenURL(const GURL& url,
const GURL& referrer,
WindowOpenDisposition disposition,
PageTransition::Type transition);
private:
// True if the transition and target url correspond to a reference fragment
// navigation.
bool IsReferenceFragmentNavigation(int64 frame_id, const GURL& url);
// Simulates a complete series of events for reference fragment navigations.
void NavigatedReferenceFragment(int64 frame_id,
bool is_main_frame,
const GURL& url,
PageTransition::Type transition_type);
// Tracks the state of the frames we are sending events for.
FrameNavigationState navigation_state_;
DISALLOW_COPY_AND_ASSIGN(ExtensionWebNavigationTabObserver);
};
// Observes navigation notifications and routes them as events to the extension
// system.
class ExtensionWebNavigationEventRouter : public NotificationObserver {
public:
// Returns the singleton instance of the event router.
static ExtensionWebNavigationEventRouter* GetInstance();
// Invoked by the extensions service once the extension system is fully set
// up and can start dispatching events to extensions.
void Init();
private:
friend struct DefaultSingletonTraits<ExtensionWebNavigationEventRouter>;
ExtensionWebNavigationEventRouter();
virtual ~ExtensionWebNavigationEventRouter();
// NotificationObserver implementation.
virtual void Observe(NotificationType type,
const NotificationSource& source,
const NotificationDetails& details);
// Handler for the CREATING_NEW_WINDOW event. The method takes the details of
// such an event and constructs a suitable JSON formatted extension event from
// it.
void CreatingNewWindow(TabContents* tab_content,
const ViewHostMsg_CreateWindow_Params* details);
// Used for tracking registrations to navigation notifications.
NotificationRegistrar registrar_;
DISALLOW_COPY_AND_ASSIGN(ExtensionWebNavigationEventRouter);
};
#endif // CHROME_BROWSER_EXTENSIONS_EXTENSION_WEBNAVIGATION_API_H_