Commit c28d4b75 authored by wjywbs@gmail.com's avatar wjywbs@gmail.com

Add generateAppForLink function in chrome.management

This function takes a url and a title as input, generates and
returns a bookmark app.

R=benwells@chromium.org,kalman@chromium.org,calamity@chromium.org
BUG=370350

Review URL: https://codereview.chromium.org/266353006

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@274549 0039d316-1c4b-4281-b951-d872f2087c98
parent 56ee0ed2
...@@ -25,6 +25,7 @@ ...@@ -25,6 +25,7 @@
#include "chrome/browser/extensions/extension_ui_util.h" #include "chrome/browser/extensions/extension_ui_util.h"
#include "chrome/browser/extensions/extension_uninstall_dialog.h" #include "chrome/browser/extensions/extension_uninstall_dialog.h"
#include "chrome/browser/extensions/launch_util.h" #include "chrome/browser/extensions/launch_util.h"
#include "chrome/browser/favicon/favicon_service_factory.h"
#include "chrome/browser/profiles/profile.h" #include "chrome/browser/profiles/profile.h"
#include "chrome/browser/ui/browser_dialogs.h" #include "chrome/browser/ui/browser_dialogs.h"
#include "chrome/browser/ui/browser_finder.h" #include "chrome/browser/ui/browser_finder.h"
...@@ -56,6 +57,7 @@ ...@@ -56,6 +57,7 @@
#include "extensions/common/permissions/permission_set.h" #include "extensions/common/permissions/permission_set.h"
#include "extensions/common/permissions/permissions_data.h" #include "extensions/common/permissions/permissions_data.h"
#include "extensions/common/url_pattern.h" #include "extensions/common/url_pattern.h"
#include "ui/gfx/favicon_size.h"
#if !defined(OS_ANDROID) #if !defined(OS_ANDROID)
#include "chrome/browser/ui/webui/ntp/core_app_launcher_handler.h" #include "chrome/browser/ui/webui/ntp/core_app_launcher_handler.h"
...@@ -852,6 +854,91 @@ bool ManagementSetLaunchTypeFunction::RunSync() { ...@@ -852,6 +854,91 @@ bool ManagementSetLaunchTypeFunction::RunSync() {
return true; return true;
} }
ManagementGenerateAppForLinkFunction::ManagementGenerateAppForLinkFunction() {
}
ManagementGenerateAppForLinkFunction::~ManagementGenerateAppForLinkFunction() {
}
void ManagementGenerateAppForLinkFunction::FinishCreateBookmarkApp(
const extensions::Extension* extension,
const WebApplicationInfo& web_app_info) {
if (extension) {
scoped_ptr<management::ExtensionInfo> info =
CreateExtensionInfo(*extension, ExtensionSystem::Get(GetProfile()));
results_ = management::GenerateAppForLink::Results::Create(*info);
SendResponse(true);
Release();
} else {
error_ = keys::kGenerateAppForLinkInstallError;
SendResponse(false);
Release();
}
}
void ManagementGenerateAppForLinkFunction::OnFaviconForApp(
const favicon_base::FaviconImageResult& image_result) {
WebApplicationInfo web_app;
web_app.title = base::UTF8ToUTF16(title_);
web_app.app_url = launch_url_;
if (!image_result.image.IsEmpty()) {
WebApplicationInfo::IconInfo icon;
icon.data = image_result.image.AsBitmap();
icon.width = icon.data.width();
icon.height = icon.data.height();
web_app.icons.push_back(icon);
}
bookmark_app_helper_.reset(new BookmarkAppHelper(service(), web_app, NULL));
bookmark_app_helper_->Create(base::Bind(
&ManagementGenerateAppForLinkFunction::FinishCreateBookmarkApp, this));
}
bool ManagementGenerateAppForLinkFunction::RunAsync() {
if (!user_gesture()) {
error_ = keys::kGestureNeededForGenerateAppForLinkError;
return false;
}
scoped_ptr<management::GenerateAppForLink::Params> params(
management::GenerateAppForLink::Params::Create(*args_));
EXTENSION_FUNCTION_VALIDATE(params.get());
GURL launch_url(params->url);
if (!launch_url.is_valid() || !launch_url.SchemeIsHTTPOrHTTPS()) {
error_ = ErrorUtils::FormatErrorMessage(keys::kInvalidURLError,
params->url);
return false;
}
if (params->title.empty()) {
error_ = keys::kEmptyTitleError;
return false;
}
FaviconService* favicon_service =
FaviconServiceFactory::GetForProfile(GetProfile(),
Profile::EXPLICIT_ACCESS);
DCHECK(favicon_service);
title_ = params->title;
launch_url_ = launch_url;
favicon_service->GetFaviconImageForURL(
FaviconService::FaviconForURLParams(
launch_url, favicon_base::FAVICON, gfx::kFaviconSize),
base::Bind(&ManagementGenerateAppForLinkFunction::OnFaviconForApp, this),
&cancelable_task_tracker_);
// Matched with a Release() in OnExtensionLoaded().
AddRef();
// Response is sent async in OnExtensionLoaded().
return true;
}
ManagementEventRouter::ManagementEventRouter(Profile* profile) ManagementEventRouter::ManagementEventRouter(Profile* profile)
: profile_(profile) { : profile_(profile) {
int types[] = {chrome::NOTIFICATION_EXTENSION_INSTALLED_DEPRECATED, int types[] = {chrome::NOTIFICATION_EXTENSION_INSTALLED_DEPRECATED,
......
...@@ -6,9 +6,13 @@ ...@@ -6,9 +6,13 @@
#define CHROME_BROWSER_EXTENSIONS_API_MANAGEMENT_MANAGEMENT_API_H_ #define CHROME_BROWSER_EXTENSIONS_API_MANAGEMENT_MANAGEMENT_API_H_
#include "base/compiler_specific.h" #include "base/compiler_specific.h"
#include "base/task/cancelable_task_tracker.h"
#include "chrome/browser/extensions/bookmark_app_helper.h"
#include "chrome/browser/extensions/chrome_extension_function.h" #include "chrome/browser/extensions/chrome_extension_function.h"
#include "chrome/browser/extensions/extension_install_prompt.h" #include "chrome/browser/extensions/extension_install_prompt.h"
#include "chrome/browser/extensions/extension_uninstall_dialog.h" #include "chrome/browser/extensions/extension_uninstall_dialog.h"
#include "chrome/common/web_application_info.h"
#include "components/favicon_base/favicon_types.h"
#include "components/keyed_service/core/keyed_service.h" #include "components/keyed_service/core/keyed_service.h"
#include "content/public/browser/notification_observer.h" #include "content/public/browser/notification_observer.h"
#include "content/public/browser/notification_registrar.h" #include "content/public/browser/notification_registrar.h"
...@@ -200,6 +204,32 @@ class ManagementSetLaunchTypeFunction : public ManagementFunction { ...@@ -200,6 +204,32 @@ class ManagementSetLaunchTypeFunction : public ManagementFunction {
virtual bool RunSync() OVERRIDE; virtual bool RunSync() OVERRIDE;
}; };
class ManagementGenerateAppForLinkFunction : public AsyncManagementFunction {
public:
DECLARE_EXTENSION_FUNCTION("management.generateAppForLink",
MANAGEMENT_GENERATEAPPFORLINK);
ManagementGenerateAppForLinkFunction();
protected:
virtual ~ManagementGenerateAppForLinkFunction();
virtual bool RunAsync() OVERRIDE;
private:
void OnFaviconForApp(const favicon_base::FaviconImageResult& image_result);
void FinishCreateBookmarkApp(const extensions::Extension* extension,
const WebApplicationInfo& web_app_info);
std::string title_;
GURL launch_url_;
scoped_ptr<BookmarkAppHelper> bookmark_app_helper_;
// Used for favicon loading tasks.
base::CancelableTaskTracker cancelable_task_tracker_;
};
class ManagementEventRouter : public content::NotificationObserver { class ManagementEventRouter : public content::NotificationObserver {
public: public:
explicit ManagementEventRouter(Profile* profile); explicit ManagementEventRouter(Profile* profile);
......
...@@ -37,5 +37,11 @@ const char kGestureNeededForSetLaunchTypeError[] = ...@@ -37,5 +37,11 @@ const char kGestureNeededForSetLaunchTypeError[] =
"chrome.management.setLaunchType requires a user gesture."; "chrome.management.setLaunchType requires a user gesture.";
const char kLaunchTypeNotAvailableError[] = const char kLaunchTypeNotAvailableError[] =
"The launch type is not available for this app."; "The launch type is not available for this app.";
const char kGestureNeededForGenerateAppForLinkError[] =
"chrome.management.generateAppForLink requires a user gesture.";
const char kInvalidURLError[] = "The URL \"*\" is invalid.";
const char kEmptyTitleError[] = "The title can not be empty.";
const char kGenerateAppForLinkInstallError[] =
"Failed to install the generated app.";
} // namespace extension_management_api_constants } // namespace extension_management_api_constants
...@@ -29,6 +29,10 @@ extern const char kCreateOnlyPackagedAppShortcutMac[]; ...@@ -29,6 +29,10 @@ extern const char kCreateOnlyPackagedAppShortcutMac[];
extern const char kCreateShortcutCanceledError[]; extern const char kCreateShortcutCanceledError[];
extern const char kGestureNeededForSetLaunchTypeError[]; extern const char kGestureNeededForSetLaunchTypeError[];
extern const char kLaunchTypeNotAvailableError[]; extern const char kLaunchTypeNotAvailableError[];
extern const char kGestureNeededForGenerateAppForLinkError[];
extern const char kInvalidURLError[];
extern const char kEmptyTitleError[];
extern const char kGenerateAppForLinkInstallError[];
} // namespace extension_management_api_constants } // namespace extension_management_api_constants
......
...@@ -149,6 +149,20 @@ IN_PROC_BROWSER_TEST_F(ExtensionManagementApiTest, ...@@ -149,6 +149,20 @@ IN_PROC_BROWSER_TEST_F(ExtensionManagementApiTest,
"createAppShortcutNotInStable.html")); "createAppShortcutNotInStable.html"));
} }
IN_PROC_BROWSER_TEST_F(ExtensionManagementApiTest, GenerateAppForLink) {
LoadExtensions();
ASSERT_TRUE(RunExtensionSubtest("management/test",
"generateAppForLink.html"));
}
IN_PROC_BROWSER_TEST_F(ExtensionManagementApiTest,
GenerateAppForLinkNotInStable) {
extensions::ScopedCurrentChannel channel(
chrome::VersionInfo::CHANNEL_STABLE);
ASSERT_TRUE(RunExtensionSubtest("management/test",
"generateAppForLinkNotInStable.html"));
}
// Fails often on Windows dbg bots. http://crbug.com/177163 // Fails often on Windows dbg bots. http://crbug.com/177163
#if defined(OS_WIN) #if defined(OS_WIN)
#define MAYBE_ManagementPolicyAllowed DISABLED_ManagementPolicyAllowed #define MAYBE_ManagementPolicyAllowed DISABLED_ManagementPolicyAllowed
......
...@@ -183,6 +183,9 @@ BookmarkAppHelper::BookmarkAppHelper(ExtensionService* service, ...@@ -183,6 +183,9 @@ BookmarkAppHelper::BookmarkAppHelper(ExtensionService* service,
crx_installer_->set_error_on_unsupported_requirements(true); crx_installer_->set_error_on_unsupported_requirements(true);
if (!contents)
return;
// Add urls from the WebApplicationInfo. // Add urls from the WebApplicationInfo.
std::vector<GURL> web_app_info_icon_urls; std::vector<GURL> web_app_info_icon_urls;
for (std::vector<WebApplicationInfo::IconInfo>::const_iterator it = for (std::vector<WebApplicationInfo::IconInfo>::const_iterator it =
...@@ -204,7 +207,11 @@ BookmarkAppHelper::~BookmarkAppHelper() {} ...@@ -204,7 +207,11 @@ BookmarkAppHelper::~BookmarkAppHelper() {}
void BookmarkAppHelper::Create(const CreateBookmarkAppCallback& callback) { void BookmarkAppHelper::Create(const CreateBookmarkAppCallback& callback) {
callback_ = callback; callback_ = callback;
favicon_downloader_->Start();
if (favicon_downloader_.get())
favicon_downloader_->Start();
else
OnIconsDownloaded(true, std::map<GURL, std::vector<SkBitmap> >());
} }
void BookmarkAppHelper::OnIconsDownloaded( void BookmarkAppHelper::OnIconsDownloaded(
...@@ -239,6 +246,18 @@ void BookmarkAppHelper::OnIconsDownloaded( ...@@ -239,6 +246,18 @@ void BookmarkAppHelper::OnIconsDownloaded(
} }
} }
// Add all existing icons from WebApplicationInfo.
for (std::vector<WebApplicationInfo::IconInfo>::const_iterator it =
web_app_info_.icons.begin();
it != web_app_info_.icons.end();
++it) {
const SkBitmap& icon = it->data;
if (!icon.drawsNothing() && icon.width() == icon.height())
downloaded_icons.push_back(icon);
}
web_app_info_.icons.clear();
// If there are icons that don't match the accepted icon sizes, find the // If there are icons that don't match the accepted icon sizes, find the
// closest bigger icon to the accepted sizes and resize the icon to it. An // closest bigger icon to the accepted sizes and resize the icon to it. An
// icon will be resized and used for at most one size. // icon will be resized and used for at most one size.
......
...@@ -37,7 +37,8 @@ class BookmarkAppHelper : public content::NotificationObserver { ...@@ -37,7 +37,8 @@ class BookmarkAppHelper : public content::NotificationObserver {
// This helper class will create a bookmark app out of |web_app_info| and // This helper class will create a bookmark app out of |web_app_info| and
// install it to |service|. Icons will be downloaded from the URLs in // install it to |service|. Icons will be downloaded from the URLs in
// |web_app_info.icons| using |contents|. // |web_app_info.icons| using |contents| if |contents| is not NULL.
// All existing icons from WebApplicationInfo will also be used.
BookmarkAppHelper(ExtensionService* service, BookmarkAppHelper(ExtensionService* service,
WebApplicationInfo web_app_info, WebApplicationInfo web_app_info,
content::WebContents* contents); content::WebContents* contents);
......
...@@ -8,6 +8,9 @@ ...@@ -8,6 +8,9 @@
#include "chrome/browser/extensions/extension_service_unittest.h" #include "chrome/browser/extensions/extension_service_unittest.h"
#include "chrome/common/extensions/manifest_handlers/app_launch_info.h" #include "chrome/common/extensions/manifest_handlers/app_launch_info.h"
#include "chrome/test/base/testing_profile.h" #include "chrome/test/base/testing_profile.h"
#include "content/public/browser/render_process_host.h"
#include "content/public/browser/web_contents.h"
#include "content/public/test/web_contents_tester.h"
#include "extensions/browser/extension_registry.h" #include "extensions/browser/extension_registry.h"
#include "extensions/common/constants.h" #include "extensions/common/constants.h"
#include "extensions/common/extension_icon_set.h" #include "extensions/common/extension_icon_set.h"
...@@ -24,7 +27,9 @@ const char kAppTitle[] = "Test title"; ...@@ -24,7 +27,9 @@ const char kAppTitle[] = "Test title";
const char kAlternativeAppTitle[] = "Different test title"; const char kAlternativeAppTitle[] = "Different test title";
const char kAppDescription[] = "Test description"; const char kAppDescription[] = "Test description";
const int kIconSizeTiny = extension_misc::EXTENSION_ICON_BITTY;
const int kIconSizeSmall = extension_misc::EXTENSION_ICON_SMALL; const int kIconSizeSmall = extension_misc::EXTENSION_ICON_SMALL;
const int kIconSizeMedium = extension_misc::EXTENSION_ICON_MEDIUM;
const int kIconSizeLarge = extension_misc::EXTENSION_ICON_LARGE; const int kIconSizeLarge = extension_misc::EXTENSION_ICON_LARGE;
#endif #endif
...@@ -49,6 +54,19 @@ class BookmarkAppHelperExtensionServiceTest : public ExtensionServiceTestBase { ...@@ -49,6 +54,19 @@ class BookmarkAppHelperExtensionServiceTest : public ExtensionServiceTestBase {
EXPECT_EQ(0u, service_->extensions()->size()); EXPECT_EQ(0u, service_->extensions()->size());
} }
virtual void TearDown() OVERRIDE {
ExtensionServiceTestBase::TearDown();
for (content::RenderProcessHost::iterator i(
content::RenderProcessHost::AllHostsIterator());
!i.IsAtEnd();
i.Advance()) {
content::RenderProcessHost* host = i.GetCurrentValue();
if (Profile::FromBrowserContext(host->GetBrowserContext()) ==
profile_.get())
delete host;
}
}
private: private:
DISALLOW_COPY_AND_ASSIGN(BookmarkAppHelperExtensionServiceTest); DISALLOW_COPY_AND_ASSIGN(BookmarkAppHelperExtensionServiceTest);
}; };
...@@ -136,7 +154,9 @@ TEST_F(BookmarkAppHelperExtensionServiceTest, CreateBookmarkApp) { ...@@ -136,7 +154,9 @@ TEST_F(BookmarkAppHelperExtensionServiceTest, CreateBookmarkApp) {
web_app_info.title = base::UTF8ToUTF16(kAppTitle); web_app_info.title = base::UTF8ToUTF16(kAppTitle);
web_app_info.description = base::UTF8ToUTF16(kAppDescription); web_app_info.description = base::UTF8ToUTF16(kAppDescription);
TestBookmarkAppHelper helper(service_, web_app_info, NULL); scoped_ptr<content::WebContents> contents(
content::WebContentsTester::CreateTestWebContents(profile_.get(), NULL));
TestBookmarkAppHelper helper(service_, web_app_info, contents.get());
helper.Create(base::Bind(&TestBookmarkAppHelper::CreationComplete, helper.Create(base::Bind(&TestBookmarkAppHelper::CreationComplete,
base::Unretained(&helper))); base::Unretained(&helper)));
...@@ -160,6 +180,47 @@ TEST_F(BookmarkAppHelperExtensionServiceTest, CreateBookmarkApp) { ...@@ -160,6 +180,47 @@ TEST_F(BookmarkAppHelperExtensionServiceTest, CreateBookmarkApp) {
extension, kIconSizeSmall, ExtensionIconSet::MATCH_EXACTLY).empty()); extension, kIconSizeSmall, ExtensionIconSet::MATCH_EXACTLY).empty());
} }
TEST_F(BookmarkAppHelperExtensionServiceTest, CreateBookmarkAppNoContents) {
WebApplicationInfo web_app_info;
web_app_info.app_url = GURL(kAppUrl);
web_app_info.title = base::UTF8ToUTF16(kAppTitle);
web_app_info.description = base::UTF8ToUTF16(kAppDescription);
web_app_info.icons.push_back(
CreateIconInfoWithBitmap(kIconSizeTiny, SK_ColorRED));
TestBookmarkAppHelper helper(service_, web_app_info, NULL);
helper.Create(base::Bind(&TestBookmarkAppHelper::CreationComplete,
base::Unretained(&helper)));
base::RunLoop().RunUntilIdle();
EXPECT_TRUE(helper.extension());
const Extension* extension =
service_->GetInstalledExtension(helper.extension()->id());
EXPECT_TRUE(extension);
EXPECT_EQ(1u, service_->extensions()->size());
EXPECT_TRUE(extension->from_bookmark());
EXPECT_EQ(kAppTitle, extension->name());
EXPECT_EQ(kAppDescription, extension->description());
EXPECT_EQ(GURL(kAppUrl), AppLaunchInfo::GetLaunchWebURL(extension));
EXPECT_FALSE(
IconsInfo::GetIconResource(
extension, kIconSizeTiny, ExtensionIconSet::MATCH_EXACTLY).empty());
EXPECT_FALSE(
IconsInfo::GetIconResource(
extension, kIconSizeSmall, ExtensionIconSet::MATCH_EXACTLY).empty());
EXPECT_FALSE(
IconsInfo::GetIconResource(extension,
kIconSizeSmall * 2,
ExtensionIconSet::MATCH_EXACTLY).empty());
EXPECT_FALSE(
IconsInfo::GetIconResource(
extension, kIconSizeMedium, ExtensionIconSet::MATCH_EXACTLY).empty());
EXPECT_FALSE(
IconsInfo::GetIconResource(extension,
kIconSizeMedium * 2,
ExtensionIconSet::MATCH_EXACTLY).empty());
}
TEST_F(BookmarkAppHelperExtensionServiceTest, CreateAndUpdateBookmarkApp) { TEST_F(BookmarkAppHelperExtensionServiceTest, CreateAndUpdateBookmarkApp) {
EXPECT_EQ(0u, registry_->enabled_extensions().size()); EXPECT_EQ(0u, registry_->enabled_extensions().size());
WebApplicationInfo web_app_info; WebApplicationInfo web_app_info;
......
...@@ -542,6 +542,11 @@ ...@@ -542,6 +542,11 @@
"channel": "dev", "channel": "dev",
"contexts": ["blessed_extension"] "contexts": ["blessed_extension"]
}, },
"management.generateAppForLink": {
"dependencies": ["permission:management"],
"channel": "dev",
"contexts": ["blessed_extension"]
},
// This is not a real API, only here for documentation purposes. // This is not a real API, only here for documentation purposes.
// See http://crbug.com/275944 for background. // See http://crbug.com/275944 for background.
"manifestTypes": { "manifestTypes": {
......
...@@ -355,6 +355,33 @@ ...@@ -355,6 +355,33 @@
"parameters": [] "parameters": []
} }
] ]
},
{
"name": "generateAppForLink",
"description": "Generate an app for a URL. Returns the generated bookmark app. Note: This function is only available to Chrome users on the dev channel.",
"parameters": [
{
"name": "url",
"type": "string",
"description": "The URL of a web page. The scheme of the URL can only be \"http\" or \"https\"."
},
{
"name": "title",
"type": "string",
"description": "The title of the generated app."
},
{
"name": "callback",
"type": "function",
"optional": true,
"parameters": [
{
"name": "result",
"$ref": "ExtensionInfo"
}
]
}
]
} }
], ],
"events": [ "events": [
......
<!--
* Copyright 2014 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.
-->
<script src="common.js"></script>
<script src="generateAppForLink.js"></script>
// Copyright 2014 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.
function testGenerateAppForLink(url, title, error, func) {
chrome.test.runWithUserGesture(function() {
if (error)
chrome.management.generateAppForLink(
url, title, callback(function(data) {}, error));
else
chrome.management.generateAppForLink(url, title, callback(func));
});
}
var tests = [
function generateAppForLinkWithoutUserGesture() {
chrome.management.generateAppForLink(
"http://google.com", "test", callback(function() {},
"chrome.management.generateAppForLink requires a user gesture."));
},
function generateAppForInvalidLink() {
testGenerateAppForLink("", "test", "The URL \"\" is invalid.");
testGenerateAppForLink("aaaa", "test", "The URL \"aaaa\" is invalid.");
testGenerateAppForLink("http1://google.com", "test",
"The URL \"http1://google.com\" is invalid.");
testGenerateAppForLink("chrome://about", "test",
"The URL \"chrome://about\" is invalid.");
testGenerateAppForLink("chrome-extension://test/test", "test",
"The URL \"chrome-extension://test/test\" is invalid.");
},
function generateAppWithEmptyTitle() {
testGenerateAppForLink("http://google.com", "",
"The title can not be empty.");
},
function generateAppForLinkWithShortURL() {
var url = "http://google.com", title = "testApp";
testGenerateAppForLink(
url, title, null, function(data) {
assertEq("http://google.com/", data.appLaunchUrl);
assertEq(title, data.name);
// There is no favicon in the test browser, so only 4 icons will
// be created.
assertEq(4, data.icons.length);
assertEq(32, data.icons[0].size);
assertEq(48, data.icons[1].size);
assertEq(64, data.icons[2].size);
assertEq(96, data.icons[3].size);
chrome.management.getAll(callback(function(items) {
assertTrue(getItemNamed(items, title) != null);
}));
});
},
function generateAppForLinkWithLongURL() {
var url = "http://google.com/page/page?aa=bb&cc=dd", title = "test App 2";
testGenerateAppForLink(
url, title, null, function(data) {
assertEq(url, data.appLaunchUrl);
assertEq(title, data.name);
assertEq(4, data.icons.length);
assertEq(32, data.icons[0].size);
assertEq(48, data.icons[1].size);
assertEq(64, data.icons[2].size);
assertEq(96, data.icons[3].size);
chrome.management.getAll(callback(function(items) {
assertTrue(getItemNamed(items, title) != null);
}));
});
}
];
chrome.test.runTests(tests);
<!--
* Copyright 2014 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.
-->
<script src="common.js"></script>
<script src="generateAppForLinkNotInStable.js"></script>
// Copyright 2014 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.
var tests = [
function generateAppForLinkNotInStable() {
assertEq(chrome.management.generateAppForLink, undefined);
succeed();
}
];
chrome.test.runTests(tests);
...@@ -843,6 +843,7 @@ enum HistogramValue { ...@@ -843,6 +843,7 @@ enum HistogramValue {
FILEBROWSERPRIVATE_OPENINSPECTOR, FILEBROWSERPRIVATE_OPENINSPECTOR,
STREAMSPRIVATE_ABORT, STREAMSPRIVATE_ABORT,
MANAGEMENT_SETLAUNCHTYPE, MANAGEMENT_SETLAUNCHTYPE,
MANAGEMENT_GENERATEAPPFORLINK,
// Last entry: Add new entries above and ensure to update // Last entry: Add new entries above and ensure to update
// tools/metrics/histograms/histograms/histograms.xml. // tools/metrics/histograms/histograms/histograms.xml.
ENUM_BOUNDARY ENUM_BOUNDARY
......
...@@ -35231,6 +35231,7 @@ Therefore, the affected-histogram name has to have at least one dot in it. ...@@ -35231,6 +35231,7 @@ Therefore, the affected-histogram name has to have at least one dot in it.
<int value="782" label="FILEBROWSERPRIVATE_OPENINSPECTOR"/> <int value="782" label="FILEBROWSERPRIVATE_OPENINSPECTOR"/>
<int value="783" label="STREAMSPRIVATE_ABORT"/> <int value="783" label="STREAMSPRIVATE_ABORT"/>
<int value="784" label="MANAGEMENT_SETLAUNCHTYPE"/> <int value="784" label="MANAGEMENT_SETLAUNCHTYPE"/>
<int value="785" label="MANAGEMENT_GENERATEAPPFORLINK"/>
</enum> </enum>
<enum name="ExtensionInstallCause" type="int"> <enum name="ExtensionInstallCause" type="int">
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment