summaryrefslogtreecommitdiffstats
path: root/chrome/renderer
diff options
context:
space:
mode:
authorjar@chromium.org <jar@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-06-19 02:51:42 +0000
committerjar@chromium.org <jar@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-06-19 02:51:42 +0000
commitd02982248bb68073e940deeec7e36f5c3aab9ee6 (patch)
treeed8f78c90e0a5c8a4af9d43d39ef0e84797939de /chrome/renderer
parent3332977cf064c71b0d25f83bc6e35d8856059d56 (diff)
downloadchromium_src-d02982248bb68073e940deeec7e36f5c3aab9ee6.zip
chromium_src-d02982248bb68073e940deeec7e36f5c3aab9ee6.tar.gz
chromium_src-d02982248bb68073e940deeec7e36f5c3aab9ee6.tar.bz2
Revert 18765 to try to repair perf regression
TBR=mpcomplete Review URL: http://codereview.chromium.org/131093 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@18784 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/renderer')
-rw-r--r--chrome/renderer/extensions/event_bindings.cc31
-rw-r--r--chrome/renderer/extensions/event_bindings.h8
-rw-r--r--chrome/renderer/extensions/extension_process_bindings.cc13
-rw-r--r--chrome/renderer/extensions/extension_process_bindings.h1
-rw-r--r--chrome/renderer/extensions/renderer_extension_bindings.cc13
-rw-r--r--chrome/renderer/render_view.cc28
-rw-r--r--chrome/renderer/render_view.h2
-rw-r--r--chrome/renderer/render_widget.h2
-rw-r--r--chrome/renderer/renderer_resources.grd2
-rw-r--r--chrome/renderer/resources/event_bindings.js31
-rw-r--r--chrome/renderer/resources/extension_process_bindings.js54
-rw-r--r--chrome/renderer/resources/greasemonkey_api.js4
-rw-r--r--chrome/renderer/resources/renderer_extension_bindings.js13
13 files changed, 58 insertions, 144 deletions
diff --git a/chrome/renderer/extensions/event_bindings.cc b/chrome/renderer/extensions/event_bindings.cc
index e412245..576beba 100644
--- a/chrome/renderer/extensions/event_bindings.cc
+++ b/chrome/renderer/extensions/event_bindings.cc
@@ -12,17 +12,16 @@
#include "chrome/renderer/js_only_v8_extensions.h"
#include "chrome/renderer/render_thread.h"
#include "grit/renderer_resources.h"
-#include "webkit/api/public/WebScriptSource.h"
-#include "webkit/glue/webframe.h"
-
-using WebKit::WebScriptSource;
-using WebKit::WebString;
namespace {
// Keep a local cache of RenderThread so that we can mock it out for unit tests.
static RenderThreadBase* render_thread = NULL;
+static RenderThreadBase* GetRenderThread() {
+ return render_thread ? render_thread : RenderThread::current();
+}
+
// Keep a list of contexts that have registered themselves with us. This lets
// us know where to dispatch events when we receive them.
typedef std::list< v8::Persistent<v8::Context> > ContextList;
@@ -92,7 +91,7 @@ class ExtensionImpl : public v8::Extension {
if (args[0]->IsString()) {
std::string event_name(*v8::String::AsciiValue(args[0]));
if (EventIncrementListenerCount(event_name) == 1) {
- EventBindings::GetRenderThread()->Send(
+ GetRenderThread()->Send(
new ViewHostMsg_ExtensionAddListener(event_name));
}
}
@@ -123,7 +122,7 @@ class ExtensionImpl : public v8::Extension {
if (args[0]->IsString()) {
std::string event_name(*v8::String::AsciiValue(args[0]));
if (EventDecrementListenerCount(event_name) == 0) {
- EventBindings::GetRenderThread()->Send(
+ GetRenderThread()->Send(
new ViewHostMsg_ExtensionRemoveListener(event_name));
}
}
@@ -165,24 +164,6 @@ void EventBindings::SetRenderThread(RenderThreadBase* thread) {
render_thread = thread;
}
-// static
-RenderThreadBase* EventBindings::GetRenderThread() {
- return render_thread ? render_thread : RenderThread::current();
-}
-
-// static
-void EventBindings::HandleDocumentReady(WebFrame* frame) {
- frame->ExecuteScript(WebScriptSource(WebString::fromUTF8(
- "chrome.dispatchOnLoad_();")));
-}
-
-// static
-void EventBindings::HandleDocumentClose(WebFrame* frame) {
- frame->ExecuteScript(WebScriptSource(WebString::fromUTF8(
- "chrome.dispatchOnUnload_();")));
-}
-
-// static
void EventBindings::CallFunction(const std::string& function_name,
int argc, v8::Handle<v8::Value>* argv) {
for (ContextList::iterator it = GetRegisteredContexts().begin();
diff --git a/chrome/renderer/extensions/event_bindings.h b/chrome/renderer/extensions/event_bindings.h
index 9e31d76..0ca59c0 100644
--- a/chrome/renderer/extensions/event_bindings.h
+++ b/chrome/renderer/extensions/event_bindings.h
@@ -10,7 +10,6 @@
#include <string>
class RenderThreadBase;
-class WebFrame;
// This class deals with the javascript bindings related to Event objects.
class EventBindings {
@@ -20,13 +19,6 @@ class EventBindings {
// Allow RenderThread to be mocked out.
static void SetRenderThread(RenderThreadBase* thread);
- static RenderThreadBase* GetRenderThread();
-
- // Notify script that the document object is ready. We don't use the DOM
- // unload event because that causes Chrome's "sudden termination" to be
- // disabled for this renderer, meaning we'll slow down shutdown.
- static void HandleDocumentReady(WebFrame* frame);
- static void HandleDocumentClose(WebFrame* frame);
// Calls the given function in each registered context which is listening
// for events. The function can be an object property, ie:
diff --git a/chrome/renderer/extensions/extension_process_bindings.cc b/chrome/renderer/extensions/extension_process_bindings.cc
index 907f4c4..1ce7ea2 100644
--- a/chrome/renderer/extensions/extension_process_bindings.cc
+++ b/chrome/renderer/extensions/extension_process_bindings.cc
@@ -14,8 +14,12 @@
#include "chrome/renderer/js_only_v8_extensions.h"
#include "chrome/renderer/render_view.h"
#include "grit/renderer_resources.h"
+#include "webkit/api/public/WebScriptSource.h"
#include "webkit/glue/webframe.h"
+using WebKit::WebScriptSource;
+using WebKit::WebString;
+
namespace {
const char kExtensionName[] = "chrome/ExtensionProcessBindings";
@@ -101,9 +105,7 @@ class ExtensionImpl : public v8::Extension {
RenderView* renderview = GetRenderViewForCurrentContext();
DCHECK(renderview);
GURL url = renderview->webview()->GetMainFrame()->GetURL();
- // Don't check the URL scheme in unit tests.
- if (RenderThread::current())
- DCHECK(url.scheme() == chrome::kExtensionScheme);
+ DCHECK(url.scheme() == chrome::kExtensionScheme);
v8::Persistent<v8::Context> current_context =
v8::Persistent<v8::Context>::New(v8::Context::GetCurrent());
@@ -216,6 +218,11 @@ void ExtensionProcessBindings::SetFunctionNames(
ExtensionImpl::SetFunctionNames(names);
}
+void ExtensionProcessBindings::RegisterExtensionContext(WebFrame* frame) {
+ frame->ExecuteScript(WebScriptSource(WebString::fromUTF8(
+ "chrome.self.register_();")));
+}
+
void ExtensionProcessBindings::HandleResponse(int request_id, bool success,
const std::string& response,
const std::string& error) {
diff --git a/chrome/renderer/extensions/extension_process_bindings.h b/chrome/renderer/extensions/extension_process_bindings.h
index fc62a73..9639090 100644
--- a/chrome/renderer/extensions/extension_process_bindings.h
+++ b/chrome/renderer/extensions/extension_process_bindings.h
@@ -18,6 +18,7 @@ class ExtensionProcessBindings {
public:
static void SetFunctionNames(const std::vector<std::string>& names);
static v8::Extension* Get();
+ static void RegisterExtensionContext(WebFrame* frame);
static void HandleResponse(int request_id, bool success,
const std::string& response,
const std::string& error);
diff --git a/chrome/renderer/extensions/renderer_extension_bindings.cc b/chrome/renderer/extensions/renderer_extension_bindings.cc
index b250ff5..0931c8c 100644
--- a/chrome/renderer/extensions/renderer_extension_bindings.cc
+++ b/chrome/renderer/extensions/renderer_extension_bindings.cc
@@ -43,8 +43,6 @@ class ExtensionImpl : public v8::Extension {
return v8::FunctionTemplate::New(OpenChannelToExtension);
} else if (name->Equals(v8::String::New("PostMessage"))) {
return v8::FunctionTemplate::New(PostMessage);
- } else if (name->Equals(v8::String::New("CloseChannel"))) {
- return v8::FunctionTemplate::New(CloseChannel);
}
return v8::Handle<v8::FunctionTemplate>();
}
@@ -82,17 +80,6 @@ class ExtensionImpl : public v8::Extension {
}
return v8::Undefined();
}
-
- // Sends a message along the given channel.
- static v8::Handle<v8::Value> CloseChannel(const v8::Arguments& args) {
- if (args.Length() >= 1 && args[0]->IsInt32()) {
- int port_id = args[0]->Int32Value();
- // Send via the RenderThread because the RenderView might be closing.
- EventBindings::GetRenderThread()->Send(
- new ViewHostMsg_ExtensionCloseChannel(port_id));
- }
- return v8::Undefined();
- }
};
// Convert a ListValue to a vector of V8 values.
diff --git a/chrome/renderer/render_view.cc b/chrome/renderer/render_view.cc
index 33b50d6..6151878 100644
--- a/chrome/renderer/render_view.cc
+++ b/chrome/renderer/render_view.cc
@@ -35,7 +35,6 @@
#include "chrome/renderer/debug_message_handler.h"
#include "chrome/renderer/devtools_agent.h"
#include "chrome/renderer/devtools_client.h"
-#include "chrome/renderer/extensions/event_bindings.h"
#include "chrome/renderer/extensions/extension_process_bindings.h"
#include "chrome/renderer/localized_error.h"
#include "chrome/renderer/media/audio_renderer_impl.h"
@@ -326,22 +325,6 @@ void RenderView::Init(gfx::NativeViewId parent_hwnd,
render_thread_->AddFilter(audio_message_filter_);
}
-// Recursively calls WillCloseFrame on every frame in the hierarchy.
-static void WillCloseFrameTree(RenderView* renderview, WebFrame* frame) {
- renderview->WillCloseFrame(renderview->webview(), frame);
-
- for (WebFrame* child = frame->GetFirstChild(); child;
- child = child->GetNextSibling()) {
- WillCloseFrameTree(renderview, child);
- }
-}
-
-void RenderView::Close() {
- if (webview() && webview()->GetMainFrame())
- WillCloseFrameTree(this, webview()->GetMainFrame());
- RenderWidget::Close();
-}
-
void RenderView::OnMessageReceived(const IPC::Message& message) {
WebFrame* main_frame = webview() ? webview()->GetMainFrame() : NULL;
renderer_logging::ScopedActiveRenderingURLSetter url_setter(
@@ -1412,18 +1395,17 @@ void RenderView::DocumentElementAvailable(WebFrame* frame) {
if (frame->GetURL().SchemeIs(chrome::kExtensionScheme))
frame->GrantUniversalAccess();
- // Tell bindings that the DOM is ready.
- EventBindings::HandleDocumentReady(frame);
+ // Tell extensions to self-register their js contexts.
+ // TODO(rafaelw): This is kind of gross. We need a way to call through
+ // the glue layer to retrieve the current v8::Context.
+ if (frame->GetURL().SchemeIs(chrome::kExtensionScheme))
+ ExtensionProcessBindings::RegisterExtensionContext(frame);
if (RenderThread::current()) // Will be NULL during unit tests.
RenderThread::current()->user_script_slave()->InjectScripts(
frame, UserScript::DOCUMENT_START);
}
-void RenderView::WillCloseFrame(WebView* webview, WebFrame* frame) {
- EventBindings::HandleDocumentClose(frame);
-}
-
WindowOpenDisposition RenderView::DispositionForNavigationAction(
WebView* webview,
WebFrame* frame,
diff --git a/chrome/renderer/render_view.h b/chrome/renderer/render_view.h
index 7e593e8..5e9d75b 100644
--- a/chrome/renderer/render_view.h
+++ b/chrome/renderer/render_view.h
@@ -225,7 +225,6 @@ class RenderView : public RenderWidget,
virtual void WindowObjectCleared(WebFrame* webframe);
virtual void DocumentElementAvailable(WebFrame* webframe);
- virtual void WillCloseFrame(WebView* webview, WebFrame* frame);
virtual WindowOpenDisposition DispositionForNavigationAction(
WebView* webview,
@@ -407,7 +406,6 @@ class RenderView : public RenderWidget,
const WebPreferences& webkit_prefs,
SharedRenderViewCounter* counter,
int32 routing_id);
- virtual void Close();
void UpdateURL(WebFrame* frame);
void UpdateTitle(WebFrame* frame, const std::wstring& title);
diff --git a/chrome/renderer/render_widget.h b/chrome/renderer/render_widget.h
index 780671a..440a7e2 100644
--- a/chrome/renderer/render_widget.h
+++ b/chrome/renderer/render_widget.h
@@ -96,7 +96,7 @@ class RenderWidget : public IPC::Channel::Listener,
void GenerateFullRepaint();
// Close the underlying WebWidget.
- virtual void Close();
+ void Close();
protected:
// Friend RefCounted so that the dtor can be non-public. Using this class
diff --git a/chrome/renderer/renderer_resources.grd b/chrome/renderer/renderer_resources.grd
index cda253b..c59e98c 100644
--- a/chrome/renderer/renderer_resources.grd
+++ b/chrome/renderer/renderer_resources.grd
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- This comment is only here because changes to resources are not picked up
-without changes to the corresponding grd file. -->
+without changes to the corresponding grd file. -->
<grit latest_public_release="0" current_release="1">
<outputs>
<output filename="grit/renderer_resources.h" type="rc_header">
diff --git a/chrome/renderer/resources/event_bindings.js b/chrome/renderer/resources/event_bindings.js
index 54dd108..f11ec78 100644
--- a/chrome/renderer/resources/event_bindings.js
+++ b/chrome/renderer/resources/event_bindings.js
@@ -1,5 +1,5 @@
-// Copyright (c) 2009 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
+// Copyright (c) 2009 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.
// -----------------------------------------------------------------------------
@@ -29,9 +29,6 @@ var chrome = chrome || {};
// A map of event names to the event object that is registered to that name.
chrome.Event.attached_ = {};
- // An array of all attached event objects, used for detaching on unload.
- chrome.Event.allAttached_ = [];
-
// Dispatches a named event with the given JSON array, which is deserialized
// before dispatch. The JSON array is the list of arguments that will be
// sent with the event callback.
@@ -108,7 +105,8 @@ var chrome = chrome || {};
// name.
chrome.Event.prototype.attach_ = function() {
AttachEvent(this.eventName_);
- chrome.Event.allAttached_[chrome.Event.allAttached_.length] = this;
+ this.unloadHandler_ = this.detach_.bind(this);
+ window.addEventListener('unload', this.unloadHandler_, false);
if (!this.eventName_)
return;
@@ -122,9 +120,7 @@ var chrome = chrome || {};
// Detaches this event object from its name.
chrome.Event.prototype.detach_ = function() {
- var i = chrome.Event.allAttached_.indexOf(this);
- if (i >= 0)
- delete chrome.Event.allAttached_[i];
+ window.removeEventListener('unload', this.unloadHandler_, false);
DetachEvent(this.eventName_);
if (!this.eventName_)
return;
@@ -136,21 +132,4 @@ var chrome = chrome || {};
delete chrome.Event.attached_[this.eventName_];
};
-
- // Load events. Note that onUnload_ might not always fire, since Chrome will
- // terminate renderers on shutdown.
- chrome.onLoad_ = new chrome.Event();
- chrome.onUnload_ = new chrome.Event();
-
- // This is called by native code when the DOM is ready.
- chrome.dispatchOnLoad_ = function() {
- chrome.onLoad_.dispatch();
- delete chrome.dispatchOnLoad_;
- }
-
- chrome.dispatchOnUnload_ = function() {
- chrome.onUnload_.dispatch();
- for (var i in chrome.Event.allAttached_)
- chrome.Event.allAttached_[i].detach_();
- }
})();
diff --git a/chrome/renderer/resources/extension_process_bindings.js b/chrome/renderer/resources/extension_process_bindings.js
index 93d9f50..ea6481c 100644
--- a/chrome/renderer/resources/extension_process_bindings.js
+++ b/chrome/renderer/resources/extension_process_bindings.js
@@ -51,7 +51,7 @@ var chrome;
validator.validate(args[i], schemas[i]);
if (validator.errors.length == 0)
continue;
-
+
var message = "Invalid value for argument " + i + ". ";
for (var i = 0, err; err = validator.errors[i]; i++) {
if (err.path) {
@@ -83,7 +83,7 @@ var chrome;
console.error("Error during " + name + ": " + error);
return;
}
-
+
if (callbacks[requestId]) {
if (response) {
callbacks[requestId](JSON.parse(response));
@@ -125,7 +125,7 @@ var chrome;
chrome.types.pInt,
chrome.types.fun
];
-
+
chrome.windows.getCurrent = function(callback) {
validate(arguments, arguments.callee.params);
sendRequest(GetCurrentWindow, null, callback);
@@ -134,7 +134,7 @@ var chrome;
chrome.windows.getCurrent.params = [
chrome.types.fun
];
-
+
chrome.windows.getLastFocused = function(callback) {
validate(arguments, arguments.callee.params);
sendRequest(GetLastFocusedWindow, null, callback);
@@ -153,7 +153,7 @@ var chrome;
chrome.types.optBool,
chrome.types.fun
];
-
+
chrome.windows.create = function(createData, callback) {
validate(arguments, arguments.callee.params);
sendRequest(CreateWindow, createData, callback);
@@ -200,7 +200,7 @@ var chrome;
chrome.types.pInt,
chrome.types.optFun
];
-
+
// sends (windowId).
// *WILL* be followed by tab-attached AND then tab-selection-changed.
chrome.windows.onCreated = new chrome.Event("window-created");
@@ -210,7 +210,7 @@ var chrome;
// tab-selection-changed -- one for each tab that was contained in the window
// that closed
chrome.windows.onRemoved = new chrome.Event("window-removed");
-
+
// sends (windowId).
chrome.windows.onFocusChanged =
new chrome.Event("window-focus-changed");
@@ -229,7 +229,7 @@ var chrome;
chrome.types.pInt,
chrome.types.fun
];
-
+
chrome.tabs.getSelected = function(windowId, callback) {
validate(arguments, arguments.callee.params);
sendRequest(GetSelectedTab, windowId, callback);
@@ -250,7 +250,7 @@ var chrome;
chrome.types.fun
];
- chrome.tabs.create = function(tab, callback) {
+ chrome.tabs.create = function(tab, callback) {
validate(arguments, arguments.callee.params);
sendRequest(CreateTab, tab, callback);
};
@@ -301,7 +301,7 @@ var chrome;
},
chrome.types.optFun
];
-
+
chrome.tabs.remove = function(tabId, callback) {
validate(arguments, arguments.callee.params);
sendRequest(RemoveTab, tabId, callback);
@@ -316,26 +316,26 @@ var chrome;
// Will *NOT* be followed by tab-attached - it is implied.
// *MAY* be followed by tab-selection-changed.
chrome.tabs.onCreated = new chrome.Event("tab-created");
-
+
// Sends (tabId, {ChangedProps}).
chrome.tabs.onUpdated = new chrome.Event("tab-updated");
// Sends (tabId, {windowId, fromIndex, toIndex}).
// Tabs can only "move" within a window.
chrome.tabs.onMoved = new chrome.Event("tab-moved");
-
+
// Sends (tabId, {windowId}).
- chrome.tabs.onSelectionChanged =
+ chrome.tabs.onSelectionChanged =
new chrome.Event("tab-selection-changed");
-
+
// Sends (tabId, {newWindowId, newPosition}).
// *MAY* be followed by tab-selection-changed.
chrome.tabs.onAttached = new chrome.Event("tab-attached");
-
+
// Sends (tabId, {oldWindowId, oldPosition}).
// *WILL* be followed by tab-selection-changed.
chrome.tabs.onDetached = new chrome.Event("tab-detached");
-
+
// Sends (tabId).
// *WILL* be followed by tab-selection-changed.
// Will *NOT* be followed or preceded by tab-detached.
@@ -351,7 +351,7 @@ var chrome;
sendRequest(EnablePageAction, [pageActionId, action]);
}
- chrome.pageActions.enableForTab.params = [
+ chrome.pageActions.enableForTab.params = [
chrome.types.str,
{
type: "object",
@@ -380,7 +380,7 @@ var chrome;
chrome.types.singleOrListOf(chrome.types.pInt),
chrome.types.fun
];
-
+
chrome.bookmarks.getChildren = function(id, callback) {
validate(arguments, arguments.callee.params);
sendRequest(GetBookmarkChildren, id, callback);
@@ -390,12 +390,12 @@ var chrome;
chrome.types.pInt,
chrome.types.fun
];
-
+
chrome.bookmarks.getTree = function(callback) {
validate(arguments, arguments.callee.params);
sendRequest(GetBookmarkTree, null, callback);
};
-
+
// TODO(erikkay): allow it to take an optional id as a starting point
// BUG=13727
chrome.bookmarks.getTree.params = [
@@ -497,7 +497,7 @@ var chrome;
// Sends (id, {parentId, index, oldParentId, oldIndex})
chrome.bookmarks.onMoved = new chrome.Event("bookmark-moved");
-
+
// Sends (id, [childrenIds])
chrome.bookmarks.onChildrenReordered =
new chrome.Event("bookmark-children-reordered");
@@ -508,14 +508,14 @@ var chrome;
// Self.
chrome.self = chrome.self || {};
chrome.self.onConnect = new chrome.Event("channel-connect");
-
+
// Register
- chrome.onLoad_.addListener(function() {
+ chrome.self.register_ = function() {
var extensionId = RegisterExtension();
- chrome.onUnload_.addListener(function() {
- UnregisterExtension(extensionId);
- });
- });
+ window.addEventListener('unload', function() {
+ UnregisterExtension(extensionId); }, false);
+ delete chrome.self.register_;
+ }
chrome.self.getViews = function() {
return GetViews();
diff --git a/chrome/renderer/resources/greasemonkey_api.js b/chrome/renderer/resources/greasemonkey_api.js
index 0ad24f0..3ce1d38 100644
--- a/chrome/renderer/resources/greasemonkey_api.js
+++ b/chrome/renderer/resources/greasemonkey_api.js
@@ -1,5 +1,5 @@
-// Copyright (c) 2009 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
+// Copyright (c) 2009 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.
// -----------------------------------------------------------------------------
diff --git a/chrome/renderer/resources/renderer_extension_bindings.js b/chrome/renderer/resources/renderer_extension_bindings.js
index f6222d7..31b97ed 100644
--- a/chrome/renderer/resources/renderer_extension_bindings.js
+++ b/chrome/renderer/resources/renderer_extension_bindings.js
@@ -10,7 +10,6 @@
var chrome = chrome || {};
(function () {
native function OpenChannelToExtension(id);
- native function CloseChannel(portId);
native function PostMessage(portId, msg);
// Port object. Represents a connection to another script context through
@@ -67,12 +66,6 @@ var chrome = chrome || {};
PostMessage(this.portId_, JSON.stringify(msg));
};
- // Disconnects the port from the other end.
- chrome.Port.prototype.disconnect = function() {
- delete chrome.Port.ports_[this.portId_];
- CloseChannel(this.portId_);
- }
-
// Extension object.
chrome.Extension = function(id) {
this.id_ = id;
@@ -92,10 +85,4 @@ var chrome = chrome || {};
chrome.Extension.prototype.getURL = function(path) {
return "chrome-extension://" + this.id_ + "/" + path;
};
-
- chrome.onUnload_.addListener(function() {
- for (var i in chrome.Port.ports_) {
- chrome.Port.ports_[i].disconnect();
- }
- });
})();