diff options
author | aa@chromium.org <aa@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-07-01 01:20:59 +0000 |
---|---|---|
committer | aa@chromium.org <aa@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-07-01 01:20:59 +0000 |
commit | 4fdbc1492aa5003c6fdc0df7f95b3ae9046380e2 (patch) | |
tree | e806806102de20b0fab1c1d497d1332839b6a77f /chrome | |
parent | 17d40f00b7d7a078649fb142961f612c29553ec0 (diff) | |
download | chromium_src-4fdbc1492aa5003c6fdc0df7f95b3ae9046380e2.zip chromium_src-4fdbc1492aa5003c6fdc0df7f95b3ae9046380e2.tar.gz chromium_src-4fdbc1492aa5003c6fdc0df7f95b3ae9046380e2.tar.bz2 |
Add the concept of browse extent.
BUG=46636
Review URL: http://codereview.chromium.org/2862034
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@51327 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome')
24 files changed, 227 insertions, 26 deletions
diff --git a/chrome/browser/browser.cc b/chrome/browser/browser.cc index a4fc69d..97c0870 100644 --- a/chrome/browser/browser.cc +++ b/chrome/browser/browser.cc @@ -3606,6 +3606,11 @@ bool Browser::HandleCrossAppNavigation(TabContents* source, if (source_extension == destination_extension) return false; + // If there is a source extension and the new URL is part of its browse + // extent, also do nothing. + if (source_extension && source_extension->browse_extent().ContainsURL(url)) + return false; + if (destination_extension) { // Search for an existing app window for this app. for (BrowserList::const_iterator iter = BrowserList::begin(); diff --git a/chrome/browser/extensions/app_process_apitest.cc b/chrome/browser/extensions/app_process_apitest.cc index 99bfa9d..7cdc80b 100644 --- a/chrome/browser/extensions/app_process_apitest.cc +++ b/chrome/browser/extensions/app_process_apitest.cc @@ -107,4 +107,16 @@ IN_PROC_BROWSER_TEST_F(AppApiTest, AppProcess) { browser()->GetTabContentsAt(1)->render_view_host()->process()); EXPECT_EQ(host->render_process_host(), browser()->GetTabContentsAt(3)->render_view_host()->process()); + + // Navigate the non-app tab into the browse extent. It should not enter the + // app process. + // Navigate the app tab into the browse extent. It should stay in the app + // process. + const GURL& browse_url(base_url.Resolve("path4/empty.html")); + NavigateTabHelper(browser()->GetTabContentsAt(1), browse_url); + NavigateTabHelper(browser()->GetTabContentsAt(3), browse_url); + EXPECT_NE(host->render_process_host(), + browser()->GetTabContentsAt(1)->render_view_host()->process()); + EXPECT_EQ(host->render_process_host(), + browser()->GetTabContentsAt(3)->render_view_host()->process()); } diff --git a/chrome/browser/extensions/extensions_service.cc b/chrome/browser/extensions/extensions_service.cc index 6518b6f..81c56f3 100644 --- a/chrome/browser/extensions/extensions_service.cc +++ b/chrome/browser/extensions/extensions_service.cc @@ -455,7 +455,7 @@ void ExtensionsService::LoadComponentExtensions() { *static_cast<DictionaryValue*>(manifest.get()), true, // require key &error)) { - NOTREACHED(); + NOTREACHED() << error; return; } diff --git a/chrome/browser/renderer_host/browser_render_process_host.cc b/chrome/browser/renderer_host/browser_render_process_host.cc index 38b8b01..1afe34a 100644 --- a/chrome/browser/renderer_host/browser_render_process_host.cc +++ b/chrome/browser/renderer_host/browser_render_process_host.cc @@ -665,8 +665,11 @@ void BrowserRenderProcessHost::SendExtensionExtentsUpdate() { for (size_t i = 0; i < service->extensions()->size(); ++i) { Extension* extension = service->extensions()->at(i); if (!extension->web_extent().is_empty()) { - params.extension_apps.push_back( - make_pair(extension->id(), extension->web_extent())); + ViewMsg_ExtensionExtentInfo info; + info.extension_id = extension->id(); + info.web_extent = extension->web_extent(); + info.browse_extent = extension->browse_extent(); + params.extension_apps.push_back(info); } } diff --git a/chrome/browser/resources/calendar_app/manifest.json b/chrome/browser/resources/calendar_app/manifest.json index df388fa..8bcf843 100644 --- a/chrome/browser/resources/calendar_app/manifest.json +++ b/chrome/browser/resources/calendar_app/manifest.json @@ -13,6 +13,9 @@ "urls": [ "*://www.google.com/calendar/" ], + "browse_urls": [ + "https://www.google.com/accounts/" + ], "launch": { "container": "tab", "web_url": "https://www.google.com/calendar/" diff --git a/chrome/browser/resources/docs_app/manifest.json b/chrome/browser/resources/docs_app/manifest.json index 1df3c5c..10e965c 100644 --- a/chrome/browser/resources/docs_app/manifest.json +++ b/chrome/browser/resources/docs_app/manifest.json @@ -34,6 +34,9 @@ "*://spreadsheets8.google.com/", "*://spreadsheets9.google.com/" ], + "browse_urls": [ + "https://www.google.com/accounts/" + ], "launch": { "web_url": "https://docs.google.com/" } diff --git a/chrome/browser/resources/gmail_app/manifest.json b/chrome/browser/resources/gmail_app/manifest.json index 4a90be2..9dfcf98 100644 --- a/chrome/browser/resources/gmail_app/manifest.json +++ b/chrome/browser/resources/gmail_app/manifest.json @@ -15,6 +15,9 @@ "*://gmail.com/", "*://www.gmail.com/" ], + "browse_urls": [ + "https://www.google.com/accounts/" + ], "launch": { "web_url": "https://mail.google.com/mail/" } diff --git a/chrome/common/extensions/extension.cc b/chrome/common/extensions/extension.cc index a1b5255..a164ea4 100644 --- a/chrome/common/extensions/extension.cc +++ b/chrome/common/extensions/extension.cc @@ -532,14 +532,18 @@ bool Extension::LoadIsApp(const DictionaryValue* manifest, return true; } -bool Extension::LoadWebURLs(const DictionaryValue* manifest, - std::string* error) { +bool Extension::LoadExtent(const DictionaryValue* manifest, + const wchar_t* key, + ExtensionExtent* extent, + const char* list_error, + const char* value_error, + std::string* error) { Value* temp = NULL; - if (!manifest->Get(keys::kWebURLs, &temp)) + if (!manifest->Get(key, &temp)) return true; if (temp->GetType() != Value::TYPE_LIST) { - *error = errors::kInvalidWebURLs; + *error = list_error; return false; } @@ -547,28 +551,28 @@ bool Extension::LoadWebURLs(const DictionaryValue* manifest, for (size_t i = 0; i < pattern_list->GetSize(); ++i) { std::string pattern_string; if (!pattern_list->GetString(i, &pattern_string)) { - *error = ExtensionErrorUtils::FormatErrorMessage( - errors::kInvalidWebURL, UintToString(i)); + *error = ExtensionErrorUtils::FormatErrorMessage(value_error, + UintToString(i)); return false; } URLPattern pattern(kValidWebExtentSchemes); if (!pattern.Parse(pattern_string)) { - *error = ExtensionErrorUtils::FormatErrorMessage( - errors::kInvalidWebURL, UintToString(i)); + *error = ExtensionErrorUtils::FormatErrorMessage(value_error, + UintToString(i)); return false; } // We do not allow authors to put wildcards in their paths. Instead, we // imply one at the end. if (pattern.path().find('*') != std::string::npos) { - *error = ExtensionErrorUtils::FormatErrorMessage( - errors::kInvalidWebURL, UintToString(i)); + *error = ExtensionErrorUtils::FormatErrorMessage(value_error, + UintToString(i)); return false; } pattern.set_path(pattern.path() + '*'); - web_extent_.AddPattern(pattern); + extent->AddPattern(pattern); } return true; @@ -1466,7 +1470,11 @@ bool Extension::InitFromValue(const DictionaryValue& source, bool require_key, } if (!LoadIsApp(manifest_value_.get(), error) || - !LoadWebURLs(manifest_value_.get(), error) || + !LoadExtent(manifest_value_.get(), keys::kWebURLs, &web_extent_, + errors::kInvalidWebURLs, errors::kInvalidWebURL, error) || + !LoadExtent(manifest_value_.get(), keys::kBrowseURLs, &browse_extent_, + errors::kInvalidBrowseURLs, errors::kInvalidBrowseURL, + error) || !LoadLaunchURL(manifest_value_.get(), error) || !LoadLaunchContainer(manifest_value_.get(), error) || !LoadLaunchFullscreen(manifest_value_.get(), error)) { diff --git a/chrome/common/extensions/extension.h b/chrome/common/extensions/extension.h index 15aca06..5dc807f 100644 --- a/chrome/common/extensions/extension.h +++ b/chrome/common/extensions/extension.h @@ -342,6 +342,7 @@ class Extension { bool is_app() const { return is_app_; } const ExtensionExtent& web_extent() const { return web_extent_; } + const ExtensionExtent& browse_extent() const { return browse_extent_; } const std::string& launch_local_path() const { return launch_local_path_; } const std::string& launch_web_url() const { return launch_web_url_; } LaunchContainer launch_container() const { return launch_container_; } @@ -409,7 +410,9 @@ class Extension { // Helpers to load various chunks of the manifest. bool LoadIsApp(const DictionaryValue* manifest, std::string* error); - bool LoadWebURLs(const DictionaryValue* manifest, std::string* error); + bool LoadExtent(const DictionaryValue* manifest, const wchar_t* key, + ExtensionExtent* extent, const char* list_error, + const char* value_error, std::string* error); bool LoadLaunchContainer(const DictionaryValue* manifest, std::string* error); bool LoadLaunchFullscreen(const DictionaryValue* manifest, std::string* error); @@ -534,6 +537,11 @@ class Extension { // Defines the set of URLs in the extension's web content. ExtensionExtent web_extent_; + // Defines an extra set of URLs beyond web_extent_ which will stay in the app + // if browsed to from a page that is already in the app, but which will not + // launch the app if browse to from outside. + ExtensionExtent browse_extent_; + // The local path inside the extension to use with the launcher. std::string launch_local_path_; diff --git a/chrome/common/extensions/extension_constants.cc b/chrome/common/extensions/extension_constants.cc index e4f368a..724198a 100644 --- a/chrome/common/extensions/extension_constants.cc +++ b/chrome/common/extensions/extension_constants.cc @@ -9,6 +9,7 @@ namespace extension_manifest_keys { const wchar_t* kAllFrames = L"all_frames"; const wchar_t* kApp = L"app"; const wchar_t* kBackground = L"background_page"; +const wchar_t* kBrowseURLs = L"app.browse_urls"; const wchar_t* kBrowserAction = L"browser_action"; const wchar_t* kChromeURLOverrides = L"chrome_url_overrides"; const wchar_t* kContentScripts = L"content_scripts"; @@ -86,6 +87,10 @@ const char* kChromeVersionTooLow = "This extension requires * version * or greater."; const char* kInvalidAllFrames = "Invalid value for 'content_scripts[*].all_frames'."; +const char* kInvalidBrowseURL = + "Invalid value for 'app.browse_urls[*]'."; +const char* kInvalidBrowseURLs = + "Invalid value for 'app.browse_urls'."; const char* kInvalidBrowserAction = "Invalid value for 'browser_action'."; const char* kInvalidChromeURLOverrides = diff --git a/chrome/common/extensions/extension_constants.h b/chrome/common/extensions/extension_constants.h index a2a972b..cc2a017 100644 --- a/chrome/common/extensions/extension_constants.h +++ b/chrome/common/extensions/extension_constants.h @@ -11,6 +11,7 @@ namespace extension_manifest_keys { extern const wchar_t* kApp; extern const wchar_t* kBackground; extern const wchar_t* kBrowserAction; + extern const wchar_t* kBrowseURLs; extern const wchar_t* kMinimumChromeVersion; extern const wchar_t* kChromeURLOverrides; extern const wchar_t* kContentScripts; @@ -85,6 +86,8 @@ namespace extension_manifest_errors { extern const char* kChromeVersionTooLow; extern const char* kInvalidAllFrames; extern const char* kInvalidBackground; + extern const char* kInvalidBrowseURL; + extern const char* kInvalidBrowseURLs; extern const char* kInvalidBrowserAction; extern const char* kInvalidChromeURLOverrides; extern const char* kInvalidContentScript; diff --git a/chrome/common/extensions/extension_manifests_unittest.cc b/chrome/common/extensions/extension_manifests_unittest.cc index 86a6bb1..8e6402c 100644 --- a/chrome/common/extensions/extension_manifests_unittest.cc +++ b/chrome/common/extensions/extension_manifests_unittest.cc @@ -117,6 +117,30 @@ TEST_F(ManifestTest, AppWebUrls) { extension->web_extent().patterns()[0].GetAsString()); } +TEST_F(ManifestTest, AppBrowseUrls) { + LoadAndExpectError("browse_urls_wrong_type.json", + errors::kInvalidBrowseURLs); + LoadAndExpectError("browse_urls_invalid_1.json", + ExtensionErrorUtils::FormatErrorMessage( + errors::kInvalidBrowseURL, "0")); + LoadAndExpectError("browse_urls_invalid_2.json", + ExtensionErrorUtils::FormatErrorMessage( + errors::kInvalidBrowseURL, "0")); + LoadAndExpectError("browse_urls_invalid_3.json", + ExtensionErrorUtils::FormatErrorMessage( + errors::kInvalidBrowseURL, "0")); + + scoped_ptr<Extension> extension( + LoadAndExpectSuccess("browse_urls_default.json")); + EXPECT_EQ(0u, extension->browse_extent().patterns().size()); + + extension.reset( + LoadAndExpectSuccess("browse_urls_valid.json")); + ASSERT_EQ(1u, extension->browse_extent().patterns().size()); + EXPECT_EQ("https://www.google.com/accounts/*", + extension->browse_extent().patterns()[0].GetAsString()); +} + TEST_F(ManifestTest, AppLaunchContainer) { scoped_ptr<Extension> extension; diff --git a/chrome/common/render_messages.h b/chrome/common/render_messages.h index 3274a02..618b5e7 100644 --- a/chrome/common/render_messages.h +++ b/chrome/common/render_messages.h @@ -716,10 +716,15 @@ struct ViewHostMsg_RunFileChooser_Params { FilePath default_file_name; }; +struct ViewMsg_ExtensionExtentInfo { + std::string extension_id; + ExtensionExtent web_extent; + ExtensionExtent browse_extent; +}; + struct ViewMsg_ExtensionExtentsUpdated_Params { - // A list of (extension_id, web_extent) pairs that describe the installed - // extension apps and the URLs they cover. - std::vector< std::pair<std::string, ExtensionExtent> > extension_apps; + // Describes the installed extension apps and the URLs they cover. + std::vector<ViewMsg_ExtensionExtentInfo> extension_apps; }; // Values that may be OR'd together to form the 'flags' parameter of the @@ -2740,6 +2745,24 @@ struct ParamTraits<ExtensionExtent> { }; template <> +struct ParamTraits<ViewMsg_ExtensionExtentInfo> { + typedef ViewMsg_ExtensionExtentInfo param_type; + static void Write(Message* m, const param_type& p) { + WriteParam(m, p.extension_id); + WriteParam(m, p.web_extent); + WriteParam(m, p.browse_extent); + } + static bool Read(const Message* m, void** iter, param_type* p) { + return ReadParam(m, iter, &p->extension_id) && + ReadParam(m, iter, &p->web_extent) && + ReadParam(m, iter, &p->browse_extent); + } + static void Log(const param_type& p, std::wstring* l) { + LogParam(p.extension_id, l); + } +}; + +template <> struct ParamTraits<ViewMsg_ExtensionExtentsUpdated_Params> { typedef ViewMsg_ExtensionExtentsUpdated_Params param_type; static void Write(Message* m, const param_type& p) { diff --git a/chrome/renderer/render_thread.cc b/chrome/renderer/render_thread.cc index 87155c3b..d0d9eed 100644 --- a/chrome/renderer/render_thread.cc +++ b/chrome/renderer/render_thread.cc @@ -484,8 +484,10 @@ void RenderThread::OnExtensionExtentsUpdated( const ViewMsg_ExtensionExtentsUpdated_Params& params) { extension_extents_.resize(params.extension_apps.size()); for (size_t i = 0; i < params.extension_apps.size(); ++i) { - extension_extents_[i].extension_id = params.extension_apps[i].first; - extension_extents_[i].web_extent = params.extension_apps[i].second; + extension_extents_[i].extension_id = params.extension_apps[i].extension_id; + extension_extents_[i].web_extent = params.extension_apps[i].web_extent; + extension_extents_[i].browse_extent = + params.extension_apps[i].browse_extent; } } @@ -1040,7 +1042,7 @@ void RenderThread::OnGpuChannelEstablished( } } -std::string RenderThread::GetExtensionIdForURL(const GURL& url) { +std::string RenderThread::GetExtensionIdByURL(const GURL& url) { if (url.SchemeIs(chrome::kExtensionScheme)) return url.host(); @@ -1051,3 +1053,12 @@ std::string RenderThread::GetExtensionIdForURL(const GURL& url) { return std::string(); } + +std::string RenderThread::GetExtensionIdByBrowseExtent(const GURL& url) { + for (size_t i = 0; i < extension_extents_.size(); ++i) { + if (extension_extents_[i].browse_extent.ContainsURL(url)) + return extension_extents_[i].extension_id; + } + + return std::string(); +} diff --git a/chrome/renderer/render_thread.h b/chrome/renderer/render_thread.h index 5b8d024..03a865b 100644 --- a/chrome/renderer/render_thread.h +++ b/chrome/renderer/render_thread.h @@ -220,7 +220,9 @@ class RenderThread : public RenderThreadBase, // none. This includes web URLs that are part of an extension's web extent. // TODO(mpcomplete): this doesn't feel like it belongs here. Find a better // place. - std::string GetExtensionIdForURL(const GURL& url); + std::string GetExtensionIdByURL(const GURL& url); + + std::string GetExtensionIdByBrowseExtent(const GURL& url); private: // Contains extension-related data that the renderer needs to know about. @@ -229,6 +231,7 @@ class RenderThread : public RenderThreadBase, struct ExtensionInfo { std::string extension_id; ExtensionExtent web_extent; + ExtensionExtent browse_extent; }; virtual void OnControlMessageReceived(const IPC::Message& msg); diff --git a/chrome/renderer/render_view.cc b/chrome/renderer/render_view.cc index 59ec64a..d66d791 100644 --- a/chrome/renderer/render_view.cc +++ b/chrome/renderer/render_view.cc @@ -344,10 +344,17 @@ static bool CrossesExtensionExtents(WebFrame* frame, const GURL& new_url) { old_url = frame->opener()->url(); std::string old_extension = - RenderThread::current()->GetExtensionIdForURL(old_url); + RenderThread::current()->GetExtensionIdByURL(old_url); + if (!old_extension.empty()) { + if (RenderThread::current()->GetExtensionIdByBrowseExtent(new_url) == + old_extension) { + return false; + } + } + std::string new_extension = - RenderThread::current()->GetExtensionIdForURL(new_url); - return (old_extension != new_extension); + RenderThread::current()->GetExtensionIdByURL(new_url); + return old_extension != new_extension; } // Returns the ISO 639_1 language code of the specified |text|, or 'unknown' diff --git a/chrome/test/data/extensions/api_test/app_process/manifest.json b/chrome/test/data/extensions/api_test/app_process/manifest.json index eb41ee5..67b54e0 100644 --- a/chrome/test/data/extensions/api_test/app_process/manifest.json +++ b/chrome/test/data/extensions/api_test/app_process/manifest.json @@ -9,6 +9,9 @@ "http://localhost/files/extensions/api_test/app_process/path1", "http://localhost/files/extensions/api_test/app_process/path2" ], + "browse_urls": [ + "http://localhost/files/extensions/api_test/app_process/path4" + ], "launch": { "web_url": "http://localhost:1337/files/extensions/api_test/app_process/path1/foo.html" } diff --git a/chrome/test/data/extensions/api_test/app_process/path4/empty.html b/chrome/test/data/extensions/api_test/app_process/path4/empty.html new file mode 100644 index 0000000..fdc6289 --- /dev/null +++ b/chrome/test/data/extensions/api_test/app_process/path4/empty.html @@ -0,0 +1,2 @@ +<title>Unmodified</title> + diff --git a/chrome/test/data/extensions/manifest_tests/browse_urls_default.json b/chrome/test/data/extensions/manifest_tests/browse_urls_default.json new file mode 100644 index 0000000..b882e8b --- /dev/null +++ b/chrome/test/data/extensions/manifest_tests/browse_urls_default.json @@ -0,0 +1,13 @@ +{ + "name": "test", + "version": "1", + "app": { + "launch": { + "container": "window", + "web_url": "http://www.google.com/mail/" + } + }, + "permissions": [ + "notifications" + ] +} diff --git a/chrome/test/data/extensions/manifest_tests/browse_urls_invalid_1.json b/chrome/test/data/extensions/manifest_tests/browse_urls_invalid_1.json new file mode 100644 index 0000000..bb6bffdd --- /dev/null +++ b/chrome/test/data/extensions/manifest_tests/browse_urls_invalid_1.json @@ -0,0 +1,12 @@ +{ + "name": "test", + "version": "1", + "app": { + "browse_urls": [ + 42 + ], + "launch": { + "web_url": "http://www.google.com/foo.html" + } + } +} diff --git a/chrome/test/data/extensions/manifest_tests/browse_urls_invalid_2.json b/chrome/test/data/extensions/manifest_tests/browse_urls_invalid_2.json new file mode 100644 index 0000000..018cd44 --- /dev/null +++ b/chrome/test/data/extensions/manifest_tests/browse_urls_invalid_2.json @@ -0,0 +1,12 @@ +{ + "name": "test", + "version": "1", + "app": { + "browse_urls": [ + "monkey" + ], + "launch": { + "web_url": "http://www.google.com/foo.html" + } + } +} diff --git a/chrome/test/data/extensions/manifest_tests/browse_urls_invalid_3.json b/chrome/test/data/extensions/manifest_tests/browse_urls_invalid_3.json new file mode 100644 index 0000000..1ea8732 --- /dev/null +++ b/chrome/test/data/extensions/manifest_tests/browse_urls_invalid_3.json @@ -0,0 +1,12 @@ +{ + "name": "test", + "version": "1", + "app": { + "browse_urls": [ + "http://www.google.com/mon*key" + ], + "launch": { + "web_url": "http://www.google.com/foo.html" + } + } +} diff --git a/chrome/test/data/extensions/manifest_tests/browse_urls_valid.json b/chrome/test/data/extensions/manifest_tests/browse_urls_valid.json new file mode 100644 index 0000000..5a1579b --- /dev/null +++ b/chrome/test/data/extensions/manifest_tests/browse_urls_valid.json @@ -0,0 +1,16 @@ +{ + "name": "test", + "version": "1", + "app": { + "launch": { + "container": "window", + "web_url": "http://www.google.com/mail/" + }, + "browse_urls": [ + "https://www.google.com/accounts/" + ] + }, + "permissions": [ + "notifications" + ] +} diff --git a/chrome/test/data/extensions/manifest_tests/browse_urls_wrong_type.json b/chrome/test/data/extensions/manifest_tests/browse_urls_wrong_type.json new file mode 100644 index 0000000..223be9c --- /dev/null +++ b/chrome/test/data/extensions/manifest_tests/browse_urls_wrong_type.json @@ -0,0 +1,10 @@ +{ + "name": "test", + "version": "1", + "app": { + "browse_urls": 42, + "launch": { + "web_url": "http://www.google.com/foo.html" + } + } +} |