| Index: extensions/browser/extension_api_frame_id_map.h
|
| diff --git a/extensions/browser/extension_api_frame_id_map.h b/extensions/browser/extension_api_frame_id_map.h
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..c3af8b3da24a9db946b1df8cd90af3200d683525
|
| --- /dev/null
|
| +++ b/extensions/browser/extension_api_frame_id_map.h
|
| @@ -0,0 +1,168 @@
|
| +// Copyright 2015 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.
|
| +
|
| +#ifndef EXTENSIONS_BROWSER_EXTENSION_API_FRAME_ID_MAP_H_
|
| +#define EXTENSIONS_BROWSER_EXTENSION_API_FRAME_ID_MAP_H_
|
| +
|
| +#include <list>
|
| +#include <map>
|
| +
|
| +#include "base/callback.h"
|
| +#include "base/lazy_instance.h"
|
| +#include "base/macros.h"
|
| +#include "base/synchronization/lock.h"
|
| +
|
| +namespace content {
|
| +class RenderFrameHost;
|
| +class WebContents;
|
| +} // namespace content
|
| +
|
| +namespace extensions {
|
| +
|
| +// Extension frame IDs are exposed through the chrome.* APIs and have the
|
| +// following characteristics:
|
| +// - The top-level frame has ID 0.
|
| +// - Any child frame has a positive ID.
|
| +// - A non-existant frame has ID -1.
|
| +// - They are only guaranteed to be unique within a tab.
|
| +// - The ID does not change during the frame's lifetime and is not re-used after
|
| +// the frame is removed. The frame may change its current RenderFrameHost over
|
| +// time, so multiple RenderFrameHosts may map to the same extension frame ID.
|
| +
|
| +// This class provides a mapping from a (render_process_id, frame_routing_id)
|
| +// pair that maps a RenderFrameHost to an extension frame ID.
|
| +// Unless stated otherwise, the methods can only be called on the UI thread.
|
| +//
|
| +// The non-static methods of this class use an internal cache. This cache is
|
| +// used to minimize IO->UI->IO round-trips of GetFrameIdOnIO. If the cost of
|
| +// attaching FrameTreeNode IDs to requests is negligible (crbug.com/524228),
|
| +// then we can remove all key caching and remove the cache from this class.
|
| +// TODO(robwu): Keep an eye on crbug.com/524228 and act upon the outcome.
|
| +class ExtensionApiFrameIdMap {
|
| + public:
|
| + using FrameIdCallback =
|
| + base::Callback<void(int extension_api_frame_id,
|
| + int extension_api_parent_frame_id)>;
|
| +
|
| + // An invalid extension API frame ID.
|
| + static const int kInvalidFrameId;
|
| +
|
| + static ExtensionApiFrameIdMap* Get();
|
| +
|
| + // Get the extension API frame ID for |rfh|.
|
| + static int GetFrameId(content::RenderFrameHost* rfh);
|
| +
|
| + // Get the extension API frame ID for the parent of |rfh|.
|
| + static int GetParentFrameId(content::RenderFrameHost* rfh);
|
| +
|
| + // Find the current RenderFrameHost for a given WebContents and extension
|
| + // frame ID.
|
| + // Returns nullptr if not found.
|
| + static content::RenderFrameHost* GetRenderFrameHostById(
|
| + content::WebContents* web_contents,
|
| + int frame_id);
|
| +
|
| + // Runs |callback| with the result that is equivalent to calling GetFrameId()
|
| + // on the UI thread. Thread hopping is minimized if possible. Callbacks for
|
| + // the same |render_process_id| and |frame_routing_id| are guaranteed to be
|
| + // run in order. The order of other callbacks is undefined.
|
| + void GetFrameIdOnIO(int render_process_id,
|
| + int frame_routing_id,
|
| + const FrameIdCallback& callback);
|
| +
|
| + // Looks up the frame ID and stores it in the map. This method should be
|
| + // called as early as possible, e.g. in a
|
| + // WebContentsObserver::RenderFrameCreated notification.
|
| + void CacheFrameId(content::RenderFrameHost* rfh);
|
| +
|
| + // Removes the frame ID mapping for a given frame. This method can be called
|
| + // at any time, but it is typically called when a frame is destroyed.
|
| + // If this method is not called, the cached mapping for the frame is retained
|
| + // forever.
|
| + void RemoveFrameId(content::RenderFrameHost* rfh);
|
| +
|
| + protected:
|
| + friend struct base::DefaultLazyInstanceTraits<ExtensionApiFrameIdMap>;
|
| +
|
| + // A set of identifiers that uniquely identifies a RenderFrame.
|
| + struct RenderFrameIdKey {
|
| + RenderFrameIdKey();
|
| + RenderFrameIdKey(int render_process_id, int frame_routing_id);
|
| +
|
| + // The process ID of the renderer that contains the RenderFrame.
|
| + int render_process_id;
|
| +
|
| + // The routing ID of the RenderFrame.
|
| + int frame_routing_id;
|
| +
|
| + bool operator<(const RenderFrameIdKey& other) const;
|
| + bool operator==(const RenderFrameIdKey& other) const;
|
| + };
|
| +
|
| + // The cached pair of frame IDs of the frame. Every RenderFrameIdKey
|
| + // maps to a CachedFrameIdPair.
|
| + struct CachedFrameIdPair {
|
| + CachedFrameIdPair();
|
| + CachedFrameIdPair(int frame_id, int parent_frame_id);
|
| +
|
| + // The extension API frame ID of the frame.
|
| + int frame_id;
|
| +
|
| + // The extension API frame ID of the parent of the frame.
|
| + int parent_frame_id;
|
| + };
|
| +
|
| + struct FrameIdCallbacks {
|
| + FrameIdCallbacks();
|
| + ~FrameIdCallbacks();
|
| +
|
| + // This is a std::list so that iterators are not invalidated when the list
|
| + // is modified during an iteration.
|
| + std::list<FrameIdCallback> callbacks;
|
| +
|
| + // To avoid re-entrant processing of callbacks.
|
| + bool is_iterating;
|
| + };
|
| +
|
| + using FrameIdMap = std::map<RenderFrameIdKey, CachedFrameIdPair>;
|
| + using FrameIdCallbacksMap = std::map<RenderFrameIdKey, FrameIdCallbacks>;
|
| +
|
| + ExtensionApiFrameIdMap();
|
| + ~ExtensionApiFrameIdMap();
|
| +
|
| + // Determines the value to be stored in |frame_id_map_| for a given key. This
|
| + // method is only called when |key| is not in |frame_id_map_|.
|
| + // virtual for testing.
|
| + virtual CachedFrameIdPair KeyToValue(const RenderFrameIdKey& key) const;
|
| +
|
| + CachedFrameIdPair LookupFrameIdOnUI(const RenderFrameIdKey& key);
|
| +
|
| + // Called as soon as the frame ID is found for the given |key|, and runs all
|
| + // queued callbacks with |cached_frame_id_pair|.
|
| + void ReceivedFrameIdOnIO(const RenderFrameIdKey& key,
|
| + const CachedFrameIdPair& cached_frame_id_pair);
|
| +
|
| + // Implementation of CacheFrameId(RenderFrameHost), separated for testing.
|
| + void CacheFrameId(const RenderFrameIdKey& key);
|
| +
|
| + // Implementation of RemoveFrameId(RenderFrameHost), separated for testing.
|
| + void RemoveFrameId(const RenderFrameIdKey& key);
|
| +
|
| + // Queued callbacks for use on the IO thread.
|
| + FrameIdCallbacksMap callbacks_map_;
|
| +
|
| + // This map is only modified on the UI thread and is used to minimize the
|
| + // number of thread hops on the IO thread.
|
| + FrameIdMap frame_id_map_;
|
| +
|
| + // This lock protects |frame_id_map_| from being concurrently written on the
|
| + // UI thread and read on the IO thread.
|
| + base::Lock frame_id_map_lock_;
|
| +
|
| + DISALLOW_COPY_AND_ASSIGN(ExtensionApiFrameIdMap);
|
| +};
|
| +
|
| +} // namespace extensions
|
| +
|
| +#endif // EXTENSIONS_BROWSER_EXTENSION_API_FRAME_ID_MAP_H_
|
|
|