blob: 40b6fe1db9c25c318095cbf308a14cb3dee3fb71 [file] [log] [blame]
[email protected]a76226d2012-04-11 07:58:291// Copyright (c) 2012 The Chromium Authors. All rights reserved.
[email protected]2ee1e3a2011-10-04 15:04:042// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
[email protected]27131e72011-10-06 03:34:565#include "chrome/renderer/extensions/chrome_v8_context_set.h"
[email protected]2ee1e3a2011-10-04 15:04:046
7#include "base/logging.h"
[email protected]68275102013-07-17 23:54:208#include "base/message_loop/message_loop.h"
[email protected]2ee1e3a2011-10-04 15:04:049#include "base/tracked_objects.h"
[email protected]526476902011-10-06 20:34:0610#include "base/values.h"
[email protected]2a80aee2011-10-07 16:06:0311#include "chrome/common/url_constants.h"
[email protected]27131e72011-10-06 03:34:5612#include "chrome/renderer/extensions/chrome_v8_context.h"
[email protected]526476902011-10-06 20:34:0613#include "content/public/renderer/render_thread.h"
[email protected]a2ef54c2011-10-10 16:20:3114#include "content/public/renderer/render_view.h"
[email protected]885c0e92012-11-13 20:27:4215#include "extensions/common/constants.h"
[email protected]e4452d32013-11-15 23:07:4116#include "extensions/common/extension.h"
[email protected]e48cf4f2013-05-30 12:40:1217#include "third_party/WebKit/public/platform/WebURL.h"
18#include "third_party/WebKit/public/platform/WebURLRequest.h"
[email protected]2255a9332013-06-17 05:12:3119#include "third_party/WebKit/public/web/WebDocument.h"
20#include "third_party/WebKit/public/web/WebFrame.h"
21#include "third_party/WebKit/public/web/WebView.h"
[email protected]885c0e92012-11-13 20:27:4222#include "v8/include/v8.h"
[email protected]2ee1e3a2011-10-04 15:04:0423
[email protected]526476902011-10-06 20:34:0624using content::RenderThread;
[email protected]8d86f13d2011-10-04 17:01:1925
[email protected]8fe74bf2012-08-07 21:08:4226namespace extensions {
27
[email protected]27131e72011-10-06 03:34:5628ChromeV8ContextSet::ChromeV8ContextSet() {
[email protected]2ee1e3a2011-10-04 15:04:0429}
[email protected]27131e72011-10-06 03:34:5630ChromeV8ContextSet::~ChromeV8ContextSet() {
[email protected]2ee1e3a2011-10-04 15:04:0431}
32
[email protected]27131e72011-10-06 03:34:5633int ChromeV8ContextSet::size() const {
[email protected]2ee1e3a2011-10-04 15:04:0434 return static_cast<int>(contexts_.size());
35}
36
[email protected]27131e72011-10-06 03:34:5637void ChromeV8ContextSet::Add(ChromeV8Context* context) {
[email protected]bd82ccea2013-02-20 09:56:2038 if (DCHECK_IS_ON()) {
39 // It's OK to insert the same context twice, but we should only ever have
40 // one ChromeV8Context per v8::Context.
41 for (ContextSet::iterator iter = contexts_.begin(); iter != contexts_.end();
42 ++iter) {
43 ChromeV8Context* candidate = *iter;
44 if (candidate != context)
45 DCHECK(candidate->v8_context() != context->v8_context());
46 }
[email protected]2ee1e3a2011-10-04 15:04:0447 }
[email protected]2ee1e3a2011-10-04 15:04:0448 contexts_.insert(context);
49}
50
[email protected]27131e72011-10-06 03:34:5651void ChromeV8ContextSet::Remove(ChromeV8Context* context) {
[email protected]2ee1e3a2011-10-04 15:04:0452 if (contexts_.erase(context)) {
[email protected]4f1633f2013-03-09 14:26:2453 context->Invalidate();
[email protected]bb024fe2013-05-10 21:33:2654 base::MessageLoop::current()->DeleteSoon(FROM_HERE, context);
[email protected]2ee1e3a2011-10-04 15:04:0455 }
56}
57
[email protected]8c9311c2013-01-16 03:28:4758ChromeV8ContextSet::ContextSet ChromeV8ContextSet::GetAll() const {
[email protected]2ee1e3a2011-10-04 15:04:0459 return contexts_;
60}
61
[email protected]27131e72011-10-06 03:34:5662ChromeV8Context* ChromeV8ContextSet::GetCurrent() const {
[email protected]ad6aa8f92013-06-22 15:34:1663 return v8::Context::InContext() ?
64 GetByV8Context(v8::Context::GetCurrent()) : NULL;
65}
66
67ChromeV8Context* ChromeV8ContextSet::GetCalling() const {
68 v8::Local<v8::Context> calling = v8::Context::GetCalling();
69 return calling.IsEmpty() ? NULL : GetByV8Context(calling);
[email protected]2ee1e3a2011-10-04 15:04:0470}
71
[email protected]27131e72011-10-06 03:34:5672ChromeV8Context* ChromeV8ContextSet::GetByV8Context(
[email protected]2ee1e3a2011-10-04 15:04:0473 v8::Handle<v8::Context> v8_context) const {
74 for (ContextSet::const_iterator iter = contexts_.begin();
75 iter != contexts_.end(); ++iter) {
76 if ((*iter)->v8_context() == v8_context)
77 return *iter;
78 }
79
80 return NULL;
81}
82
[email protected]68e63ea12013-06-05 05:00:5483void ChromeV8ContextSet::ForEach(
[email protected]2ee1e3a2011-10-04 15:04:0484 const std::string& extension_id,
[email protected]68e63ea12013-06-05 05:00:5485 content::RenderView* render_view,
86 const base::Callback<void(ChromeV8Context*)>& callback) const {
[email protected]2ee1e3a2011-10-04 15:04:0487 // We copy the context list, because calling into javascript may modify it
88 // out from under us.
89 ContextSet contexts = GetAll();
90
[email protected]2ee1e3a2011-10-04 15:04:0491 for (ContextSet::iterator it = contexts.begin(); it != contexts.end();
92 ++it) {
[email protected]dd218902013-06-06 03:04:2593 ChromeV8Context* context = *it;
94
95 // For the same reason as above, contexts may become invalid while we run.
96 if (!context->is_valid())
97 continue;
98
[email protected]a76226d2012-04-11 07:58:2999 if (!extension_id.empty()) {
[email protected]dd218902013-06-06 03:04:25100 const Extension* extension = context->extension();
[email protected]a76226d2012-04-11 07:58:29101 if (!extension || (extension_id != extension->id()))
102 continue;
103 }
[email protected]2ee1e3a2011-10-04 15:04:04104
[email protected]dd218902013-06-06 03:04:25105 content::RenderView* context_render_view = context->GetRenderView();
[email protected]2ee1e3a2011-10-04 15:04:04106 if (!context_render_view)
107 continue;
108
109 if (render_view && render_view != context_render_view)
110 continue;
111
[email protected]dd218902013-06-06 03:04:25112 callback.Run(context);
[email protected]2ee1e3a2011-10-04 15:04:04113 }
114}
[email protected]8fe74bf2012-08-07 21:08:42115
[email protected]280055f2013-04-23 00:50:47116ChromeV8ContextSet::ContextSet ChromeV8ContextSet::OnExtensionUnloaded(
117 const std::string& extension_id) {
[email protected]8c9311c2013-01-16 03:28:47118 ContextSet contexts = GetAll();
[email protected]280055f2013-04-23 00:50:47119 ContextSet removed;
[email protected]8c9311c2013-01-16 03:28:47120
121 // Clean up contexts belonging to the unloaded extension. This is done so
122 // that content scripts (which remain injected into the page) don't continue
123 // receiving events and sending messages.
124 for (ContextSet::iterator it = contexts.begin(); it != contexts.end();
125 ++it) {
126 if ((*it)->extension() && (*it)->extension()->id() == extension_id) {
127 (*it)->DispatchOnUnloadEvent();
[email protected]280055f2013-04-23 00:50:47128 removed.insert(*it);
[email protected]8c9311c2013-01-16 03:28:47129 Remove(*it);
130 }
131 }
[email protected]280055f2013-04-23 00:50:47132
133 return removed;
[email protected]8c9311c2013-01-16 03:28:47134}
135
[email protected]8fe74bf2012-08-07 21:08:42136} // namespace extensions