diff options
author | erg@chromium.org <erg@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-07-29 17:42:02 +0000 |
---|---|---|
committer | erg@chromium.org <erg@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-07-29 17:42:02 +0000 |
commit | dead21caa8e88e85efcd90f033a92629b0df08b3 (patch) | |
tree | cf899e2b6cd445ffc4343a03422d6fc7dda19e25 | |
parent | 02a63db901e14b550815e592016c27fa395cb7b6 (diff) | |
download | chromium_src-dead21caa8e88e85efcd90f033a92629b0df08b3.zip chromium_src-dead21caa8e88e85efcd90f033a92629b0df08b3.tar.gz chromium_src-dead21caa8e88e85efcd90f033a92629b0df08b3.tar.bz2 |
mojo: Port chrome://identity-internals to mojo Web UI.
BUG=391095
NOPRESUBMIT=true
R=fgorski@chromium.org, jam@chromium.org, jschuh@chromium.org, sky@chromium.org
Review URL: https://codereview.chromium.org/365513002
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@286247 0039d316-1c4b-4281-b951-d872f2087c98
30 files changed, 576 insertions, 407 deletions
diff --git a/chrome/browser/BUILD.gn b/chrome/browser/BUILD.gn index 43dbfbc..fd180b1 100644 --- a/chrome/browser/BUILD.gn +++ b/chrome/browser/BUILD.gn @@ -620,12 +620,15 @@ grit("resources") { ] omnibox_mojom_file = "$root_gen_dir/chrome/browser/ui/webui/omnibox/omnibox.mojom.js" + identity_internals_mojom_file = "$root_gen_dir/chrome/browser/ui/webui/identity_internals/identity_internals.mojom.js" grit_flags = [ "-E", "about_credits_file=" + rebase_path(about_credits_file, root_build_dir), "-E", "additional_modules_list_file=" + rebase_path(additional_modules_list_file, root_build_dir), + "-E", "identity_internals_mojom_file=" + + rebase_path(identity_internals_mojom_file, root_build_dir), "-E", "omnibox_mojom_file=" + rebase_path(omnibox_mojom_file, root_build_dir), ] @@ -633,6 +636,7 @@ grit("resources") { deps = [ ":about_credits", ":chrome_internal_resources_gen", + "//chrome/browser/ui/webui/identity_internals:mojo_bindings", "//chrome/browser/ui/webui/omnibox:mojo_bindings", ] } diff --git a/chrome/browser/browser_resources.grd b/chrome/browser/browser_resources.grd index 8be80db..db5c26d 100644 --- a/chrome/browser/browser_resources.grd +++ b/chrome/browser/browser_resources.grd @@ -386,6 +386,7 @@ <include name="IDR_IDENTITY_INTERNALS_HTML" file="resources\identity_internals.html" type="BINDATA" /> <include name="IDR_IDENTITY_INTERNALS_CSS" file="resources\identity_internals.css" type="BINDATA" /> <include name="IDR_IDENTITY_INTERNALS_JS" file="resources\identity_internals.js" type="BINDATA" /> + <include name="IDR_IDENTITY_INTERNALS_MOJO_JS" file="${identity_internals_mojom_file}" use_base_dir="false" type="BINDATA"/> </if> <if expr="chromeos"> <include name="IDR_NETWORK_UI_HTML" file="resources\chromeos\network_ui\network_ui.html" type="BINDATA" /> diff --git a/chrome/browser/resources/identity_internals.js b/chrome/browser/resources/identity_internals.js index 7e7a01f..ea296b7 100644 --- a/chrome/browser/resources/identity_internals.js +++ b/chrome/browser/resources/identity_internals.js @@ -2,9 +2,15 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -cr.define('identity_internals', function() { +define('main', [ + 'mojo/public/js/bindings/connection', + 'chrome/browser/ui/webui/identity_internals/identity_internals.mojom', +], function(connector, browser) { 'use strict'; + var connection; + var page; + /** * Creates an identity token item. * @param {!Object} tokenInfo Object containing token information. @@ -24,20 +30,20 @@ cr.define('identity_internals', function() { /** @override */ decorate: function() { this.textContent = ''; - this.id = this.data_.accessToken; + this.id = this.data_.access_token; var table = this.ownerDocument.createElement('table'); var tbody = this.ownerDocument.createElement('tbody'); tbody.appendChild(this.createEntry_( - 'accessToken', this.data_.accessToken, 'access-token')); + 'accessToken', this.data_.access_token, 'access-token')); tbody.appendChild(this.createEntry_( - 'extensionName', this.data_.extensionName, 'extension-name')); + 'extensionName', this.data_.extension_name, 'extension-name')); tbody.appendChild(this.createEntry_( - 'extensionId', this.data_.extensionId, 'extension-id')); + 'extensionId', this.data_.extension_id, 'extension-id')); tbody.appendChild(this.createEntry_( - 'tokenStatus', this.data_.status, 'token-status')); + 'tokenStatus', this.data_.token_status, 'token-status')); tbody.appendChild(this.createEntry_( - 'expirationTime', this.data_.expirationTime, 'expiration-time')); + 'expirationTime', this.data_.expiration_time, 'expiration-time')); tbody.appendChild(this.createEntryForScopes_()); table.appendChild(tbody); var tfoot = this.ownerDocument.createElement('tfoot'); @@ -113,8 +119,13 @@ cr.define('identity_internals', function() { var revokeButton = this.ownerDocument.createElement('button'); revokeButton.classList.add('revoke-button'); revokeButton.addEventListener('click', function() { - chrome.send('identityInternalsRevokeToken', - [this.data_.extensionId, this.data_.accessToken]); + var accessToken = this.data_.access_token; + page.browser_.revokeToken(this.data_.extension_id, + accessToken).then(function() { + tokenList_.removeTokenNode_(accessToken); + if (window.revokeTokenTest) + window.revokeTokenTest(); + }); }.bind(this)); revokeButton.textContent = loadTimeData.getString('revoke'); return revokeButton; @@ -156,7 +167,7 @@ cr.define('identity_internals', function() { removeTokenNode_: function(accessToken) { var tokenIndex; for (var index = 0; index < this.data_.length; index++) { - if (this.data_[index].accessToken == accessToken) { + if (this.data_[index].access_token == accessToken) { tokenIndex = index; break; } @@ -175,42 +186,28 @@ cr.define('identity_internals', function() { var tokenList_; - /** - * Initializes the UI by asking the contoller for list of identity tokens. - */ - function initialize() { - chrome.send('identityInternalsGetTokens'); + function InternalsPageImpl(browser) { + this.browser_ = browser; + page = this; + tokenList_ = $('token-list'); tokenList_.data_ = []; tokenList_.__proto__ = TokenList.prototype; tokenList_.decorate(); - } - /** - * Callback function accepting a list of tokens to be displayed. - * @param {!Token[]} tokens A list of tokens to be displayed - */ - function returnTokens(tokens) { - tokenList_.data_ = tokens; - tokenList_.showTokenNodes_(); + page.browser_.getTokens().then(function(results) { + tokenList_.data_ = results.tokens; + tokenList_.showTokenNodes_(); + }); } - /** - * Callback function that removes a token from UI once it has been revoked. - * @param {!Array.<string>} accessTokens Array with a single element, which is - * an access token to be removed. - */ - function tokenRevokeDone(accessTokens) { - assert(accessTokens.length > 0); - tokenList_.removeTokenNode_(accessTokens[0]); - } + InternalsPageImpl.prototype = + Object.create(browser.InternalsPageStub.prototype); - // Return an object with all of the exports. - return { - initialize: initialize, - returnTokens: returnTokens, - tokenRevokeDone: tokenRevokeDone, + return function(handle) { + connection = new connector.Connection( + handle, + InternalsPageImpl, + browser.IdentityInternalsHandlerMojoProxy); }; }); - -document.addEventListener('DOMContentLoaded', identity_internals.initialize); diff --git a/chrome/browser/ui/webui/chrome_web_ui_controller_factory.cc b/chrome/browser/ui/webui/chrome_web_ui_controller_factory.cc index ee64a13..cbe8486 100644 --- a/chrome/browser/ui/webui/chrome_web_ui_controller_factory.cc +++ b/chrome/browser/ui/webui/chrome_web_ui_controller_factory.cc @@ -32,7 +32,7 @@ #include "chrome/browser/ui/webui/gcm_internals_ui.h" #include "chrome/browser/ui/webui/help/help_ui.h" #include "chrome/browser/ui/webui/history_ui.h" -#include "chrome/browser/ui/webui/identity_internals_ui.h" +#include "chrome/browser/ui/webui/identity_internals/identity_internals_ui.h" #include "chrome/browser/ui/webui/inspect_ui.h" #include "chrome/browser/ui/webui/instant_ui.h" #include "chrome/browser/ui/webui/invalidations_ui.h" diff --git a/chrome/browser/ui/webui/identity_internals/BUILD.gn b/chrome/browser/ui/webui/identity_internals/BUILD.gn new file mode 100644 index 0000000..0e47e6d --- /dev/null +++ b/chrome/browser/ui/webui/identity_internals/BUILD.gn @@ -0,0 +1,12 @@ +# 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. + +import("//mojo/public/tools/bindings/mojom.gni") + +# GYP version: chrome/chrome_web_ui_mojo_bindings.gyp:webui_mojo_bindings +mojom("mojo_bindings") { + sources = [ + "identity_internals.mojom", + ] +} diff --git a/chrome/browser/ui/webui/identity_internals/identity_internals.mojom b/chrome/browser/ui/webui/identity_internals/identity_internals.mojom new file mode 100644 index 0000000..34624ec --- /dev/null +++ b/chrome/browser/ui/webui/identity_internals/identity_internals.mojom @@ -0,0 +1,27 @@ +// 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. + +// Data structure passed from the browser process to the webui page with all +// data about an individual identity token. +struct IdentityTokenMojo { + string access_token; + string extension_name; + string extension_id; + string token_status; + string expiration_time; + string[] scopes; +}; + +[Client=InternalsPage] +interface IdentityInternalsHandlerMojo { + GetTokens() => (IdentityTokenMojo[] tokens); + RevokeToken(string extension_id, string access_token) => (); +}; + +// Empty interface to represent the page. +// +// TODO(erg): Once the javascript bindings no longer require the page to have +// an interface, remove this. +interface InternalsPage { +}; diff --git a/chrome/browser/ui/webui/identity_internals/identity_internals_token_revoker.cc b/chrome/browser/ui/webui/identity_internals/identity_internals_token_revoker.cc new file mode 100644 index 0000000..f40401d6 --- /dev/null +++ b/chrome/browser/ui/webui/identity_internals/identity_internals_token_revoker.cc @@ -0,0 +1,31 @@ +// 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. + +#include "chrome/browser/ui/webui/identity_internals/identity_internals_token_revoker.h" + +#include "chrome/browser/profiles/profile.h" +#include "chrome/browser/ui/webui/identity_internals/identity_internals_ui_handler.h" +#include "google_apis/gaia/gaia_constants.h" + +IdentityInternalsTokenRevoker::IdentityInternalsTokenRevoker( + const std::string& extension_id, + const std::string& access_token, + const mojo::Callback<void()>& callback, + Profile* profile, + IdentityInternalsUIHandler* consumer) + : fetcher_(this, GaiaConstants::kChromeSource, + profile->GetRequestContext()), + extension_id_(extension_id), + access_token_(access_token), + callback_(callback), + consumer_(consumer) { + DCHECK(consumer_); + fetcher_.StartRevokeOAuth2Token(access_token); +} + +IdentityInternalsTokenRevoker::~IdentityInternalsTokenRevoker() {} + +void IdentityInternalsTokenRevoker::OnOAuth2RevokeTokenCompleted() { + consumer_->OnTokenRevokerDone(this); +} diff --git a/chrome/browser/ui/webui/identity_internals/identity_internals_token_revoker.h b/chrome/browser/ui/webui/identity_internals/identity_internals_token_revoker.h new file mode 100644 index 0000000..58c957c --- /dev/null +++ b/chrome/browser/ui/webui/identity_internals/identity_internals_token_revoker.h @@ -0,0 +1,63 @@ +// 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. + +#ifndef CHROME_BROWSER_UI_WEBUI_IDENTITY_INTERNALS_IDENTITY_INTERNALS_TOKEN_REVOKER_H_ +#define CHROME_BROWSER_UI_WEBUI_IDENTITY_INTERNALS_IDENTITY_INTERNALS_TOKEN_REVOKER_H_ + +#include <string> + +#include "base/basictypes.h" +#include "base/compiler_specific.h" +#include "google_apis/gaia/gaia_auth_fetcher.h" +#include "mojo/public/cpp/bindings/callback.h" + +class IdentityInternalsUIHandler; +class Profile; + +// Handles the revoking of an access token and helps performing the clean up +// after it is revoked by holding information about the access token and related +// extension ID. +class IdentityInternalsTokenRevoker : public GaiaAuthConsumer { + public: + // Revokes |access_token| from extension with |extension_id|. + // |profile| is required for its request context. |consumer| will be + // notified when revocation succeeds via |OnTokenRevokerDone()|. + IdentityInternalsTokenRevoker(const std::string& extension_id, + const std::string& access_token, + const mojo::Callback<void()>& callback, + Profile* profile, + IdentityInternalsUIHandler* consumer); + virtual ~IdentityInternalsTokenRevoker(); + + // Returns the access token being revoked. + const std::string& access_token() const { return access_token_; } + + // Returns the ID of the extension the access token is related to. + const std::string& extension_id() const { return extension_id_; } + + const mojo::Callback<void()>& callback() const { return callback_; } + + // GaiaAuthConsumer implementation. + virtual void OnOAuth2RevokeTokenCompleted() OVERRIDE; + + private: + // An object used to start a token revoke request. + GaiaAuthFetcher fetcher_; + + // An ID of an extension the access token is related to. + const std::string extension_id_; + + // The access token to revoke. + const std::string access_token_; + + // Callback for when we complete. + const mojo::Callback<void()> callback_; + + // An object that needs to be notified once the access token is revoked. + IdentityInternalsUIHandler* consumer_; // weak. + + DISALLOW_COPY_AND_ASSIGN(IdentityInternalsTokenRevoker); +}; + +#endif // CHROME_BROWSER_UI_WEBUI_IDENTITY_INTERNALS_IDENTITY_INTERNALS_TOKEN_REVOKER_H_ diff --git a/chrome/browser/ui/webui/identity_internals/identity_internals_ui.cc b/chrome/browser/ui/webui/identity_internals/identity_internals_ui.cc new file mode 100644 index 0000000..23b310a --- /dev/null +++ b/chrome/browser/ui/webui/identity_internals/identity_internals_ui.cc @@ -0,0 +1,67 @@ +// Copyright 2013 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. + +#include "chrome/browser/ui/webui/identity_internals/identity_internals_ui.h" + +#include <string> + +#include "chrome/browser/profiles/profile.h" +#include "chrome/browser/ui/webui/identity_internals/identity_internals_ui_handler.h" +#include "chrome/common/url_constants.h" +#include "content/public/browser/web_ui.h" +#include "content/public/browser/web_ui_controller.h" +#include "content/public/browser/web_ui_data_source.h" +#include "grit/browser_resources.h" +#include "grit/generated_resources.h" +#include "ui/base/l10n/l10n_util.h" + + +IdentityInternalsUI::IdentityInternalsUI(content::WebUI* web_ui) + : MojoWebUIController(web_ui) { + // chrome://identity-internals source. + content::WebUIDataSource* html_source = + content::WebUIDataSource::Create(chrome::kChromeUIIdentityInternalsHost); + html_source->SetUseJsonJSFormatV2(); + + // Localized strings + html_source->AddLocalizedString("tokenCacheHeader", + IDS_IDENTITY_INTERNALS_TOKEN_CACHE_TEXT); + html_source->AddLocalizedString("accessToken", + IDS_IDENTITY_INTERNALS_ACCESS_TOKEN); + html_source->AddLocalizedString("extensionName", + IDS_IDENTITY_INTERNALS_EXTENSION_NAME); + html_source->AddLocalizedString("extensionId", + IDS_IDENTITY_INTERNALS_EXTENSION_ID); + html_source->AddLocalizedString("tokenStatus", + IDS_IDENTITY_INTERNALS_TOKEN_STATUS); + html_source->AddLocalizedString("expirationTime", + IDS_IDENTITY_INTERNALS_EXPIRATION_TIME); + html_source->AddLocalizedString("scopes", + IDS_IDENTITY_INTERNALS_SCOPES); + html_source->AddLocalizedString("revoke", + IDS_IDENTITY_INTERNALS_REVOKE); + html_source->SetJsonPath("strings.js"); + + // Required resources + html_source->AddResourcePath("identity_internals.css", + IDR_IDENTITY_INTERNALS_CSS); + html_source->AddResourcePath("identity_internals.js", + IDR_IDENTITY_INTERNALS_JS); + html_source->SetDefaultResource(IDR_IDENTITY_INTERNALS_HTML); + + content::WebUIDataSource::Add(Profile::FromWebUI(web_ui), html_source); + + AddMojoResourcePath( + "chrome/browser/ui/webui/identity_internals/identity_internals.mojom", + IDR_IDENTITY_INTERNALS_MOJO_JS); +} + +IdentityInternalsUI::~IdentityInternalsUI() {} + +scoped_ptr<MojoWebUIHandler> IdentityInternalsUI::CreateUIHandler( + mojo::ScopedMessagePipeHandle handle_to_page) { + return scoped_ptr<MojoWebUIHandler>(mojo::BindToPipe( + new IdentityInternalsUIHandler(Profile::FromWebUI(web_ui())), + handle_to_page.Pass())); +} diff --git a/chrome/browser/ui/webui/identity_internals/identity_internals_ui.h b/chrome/browser/ui/webui/identity_internals/identity_internals_ui.h new file mode 100644 index 0000000..0fbe98a --- /dev/null +++ b/chrome/browser/ui/webui/identity_internals/identity_internals_ui.h @@ -0,0 +1,27 @@ +// Copyright 2013 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 CHROME_BROWSER_UI_WEBUI_IDENTITY_INTERNALS_IDENTITY_INTERNALS_UI_H_ +#define CHROME_BROWSER_UI_WEBUI_IDENTITY_INTERNALS_IDENTITY_INTERNALS_UI_H_ + +#include "base/basictypes.h" +#include "chrome/browser/ui/webui/mojo_web_ui_controller.h" + +class IdentityInternalsUITest; + +// The WebUI for chrome://identity-internals +class IdentityInternalsUI : public MojoWebUIController { + public: + explicit IdentityInternalsUI(content::WebUI* web_ui); + virtual ~IdentityInternalsUI(); + + private: + // MojoWebUIController overrides: + virtual scoped_ptr<MojoWebUIHandler> CreateUIHandler( + mojo::ScopedMessagePipeHandle handle_to_page) OVERRIDE; + + DISALLOW_COPY_AND_ASSIGN(IdentityInternalsUI); +}; + +#endif // CHROME_BROWSER_UI_WEBUI_IDENTITY_INTERNALS_IDENTITY_INTERNALS_UI_H_ diff --git a/chrome/browser/ui/webui/identity_internals_ui_browsertest.cc b/chrome/browser/ui/webui/identity_internals/identity_internals_ui_browsertest.cc index 82f47b9..577a1d9 100644 --- a/chrome/browser/ui/webui/identity_internals_ui_browsertest.cc +++ b/chrome/browser/ui/webui/identity_internals/identity_internals_ui_browsertest.cc @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "chrome/browser/ui/webui/identity_internals_ui_browsertest.h" +#include "chrome/browser/ui/webui/identity_internals/identity_internals_ui_browsertest.h" #include "base/strings/string_number_conversions.h" #include "base/time/time.h" @@ -15,6 +15,7 @@ namespace { const char kChromeWebStoreId[] = "ahfgeienlihckogmohjhadlkjgocpleb"; const int kOneHour = 3600; + } // namespace IdentityInternalsUIBrowserTest::IdentityInternalsUIBrowserTest() {} diff --git a/chrome/browser/ui/webui/identity_internals_ui_browsertest.h b/chrome/browser/ui/webui/identity_internals/identity_internals_ui_browsertest.h index d2abf18..e093fc0 100644 --- a/chrome/browser/ui/webui/identity_internals_ui_browsertest.h +++ b/chrome/browser/ui/webui/identity_internals/identity_internals_ui_browsertest.h @@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef CHROME_BROWSER_UI_WEBUI_IDENTITY_INTERNALS_UI_BROWSERTEST_H_ -#define CHROME_BROWSER_UI_WEBUI_IDENTITY_INTERNALS_UI_BROWSERTEST_H_ +#ifndef CHROME_BROWSER_UI_WEBUI_IDENTITY_INTERNALS_IDENTITY_INTERNALS_UI_BROWSERTEST_H_ +#define CHROME_BROWSER_UI_WEBUI_IDENTITY_INTERNALS_IDENTITY_INTERNALS_UI_BROWSERTEST_H_ #include <string> #include <vector> @@ -29,4 +29,4 @@ class IdentityInternalsUIBrowserTest : public WebUIBrowserTest { DISALLOW_COPY_AND_ASSIGN(IdentityInternalsUIBrowserTest); }; -#endif // CHROME_BROWSER_UI_WEBUI_IDENTITY_INTERNALS_UI_BROWSERTEST_H_ +#endif // CHROME_BROWSER_UI_WEBUI_IDENTITY_INTERNALS_IDENTITY_INTERNALS_UI_BROWSERTEST_H_ diff --git a/chrome/browser/ui/webui/identity_internals_ui_browsertest.js b/chrome/browser/ui/webui/identity_internals/identity_internals_ui_browsertest.js index f71a760..4fba259 100644 --- a/chrome/browser/ui/webui/identity_internals_ui_browsertest.js +++ b/chrome/browser/ui/webui/identity_internals/identity_internals_ui_browsertest.js @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -GEN('#include "chrome/browser/ui/webui/identity_internals_ui_browsertest.h"'); +GEN('#include "chrome/browser/ui/webui/identity_internals/identity_internals_ui_browsertest.h"'); /** * Test C++ fixture for downloads WebUI testing. @@ -24,7 +24,7 @@ BaseIdentityInternalsWebUITest.prototype = { /** * Browse to the downloads page & call our preLoad(). */ - browsePreload: 'chrome://identity-internals', + browsePreloadAndWaitForMain: 'chrome://identity-internals', /** @override */ typedefCppFixture: 'IdentityInternalsUIBrowserTest', @@ -245,11 +245,8 @@ IdentityInternalsWebUITestAsync.prototype = { TEST_F('IdentityInternalsWebUITestAsync', 'revokeToken', function() { var tokenListBefore = this.getTokens(); expectEquals(2, tokenListBefore.length); - var tokenRevokeDone = identity_internals.tokenRevokeDone; - identity_internals.tokenRevokeDone = this.continueTest( + window.revokeTokenTest = this.continueTest( WhenTestDone.ALWAYS, function(accessTokens) { - tokenRevokeDone.call(identity_internals, accessTokens); - identity_internals.tokenRevokeDone = tokenRevokeDone; var tokenListAfter = this.getTokens(); expectEquals(1, tokenListAfter.length); expectEquals(this.getAccessToken(tokenListBefore[0]), @@ -257,4 +254,3 @@ TEST_F('IdentityInternalsWebUITestAsync', 'revokeToken', function() { }.bind(this)); this.getRevokeButton(tokenListBefore[1]).click(); }); - diff --git a/chrome/browser/ui/webui/identity_internals/identity_internals_ui_handler.cc b/chrome/browser/ui/webui/identity_internals/identity_internals_ui_handler.cc new file mode 100644 index 0000000..8a486d5 --- /dev/null +++ b/chrome/browser/ui/webui/identity_internals/identity_internals_ui_handler.cc @@ -0,0 +1,120 @@ +// 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. + +#include "chrome/browser/ui/webui/identity_internals/identity_internals_ui_handler.h" + +#include "base/i18n/time_formatting.h" +#include "base/strings/utf_string_conversions.h" +#include "chrome/browser/extensions/extension_service.h" +#include "chrome/browser/profiles/profile.h" +#include "chrome/browser/ui/webui/identity_internals/identity_internals_token_revoker.h" +#include "extensions/browser/extension_system.h" +#include "grit/browser_resources.h" +#include "grit/generated_resources.h" +#include "ui/base/l10n/l10n_util.h" + +IdentityInternalsUIHandler::IdentityInternalsUIHandler(Profile* profile) + : profile_(profile) {} + +IdentityInternalsUIHandler::~IdentityInternalsUIHandler() {} + +void IdentityInternalsUIHandler::OnTokenRevokerDone( + IdentityInternalsTokenRevoker* token_revoker) { + // Remove token from the cache. + extensions::IdentityAPI::GetFactoryInstance() + ->Get(profile_) + ->EraseCachedToken(token_revoker->extension_id(), + token_revoker->access_token()); + + // Update view about the token being removed. + token_revoker->callback().Run(); + + // Erase the revoker. + ScopedVector<IdentityInternalsTokenRevoker>::iterator iter = + std::find(token_revokers_.begin(), token_revokers_.end(), token_revoker); + DCHECK(iter != token_revokers_.end()); + token_revokers_.erase(iter); +} + +void IdentityInternalsUIHandler::GetTokens( + const mojo::Callback<void(mojo::Array<IdentityTokenMojoPtr>)>& callback) { + extensions::IdentityAPI::CachedTokens tokens = + extensions::IdentityAPI::GetFactoryInstance() + ->Get(profile_)->GetAllCachedTokens(); + callback.Run(ConvertCachedTokens(tokens).Pass()); +} + +void IdentityInternalsUIHandler::RevokeToken( + const mojo::String& extension_id, + const mojo::String& access_token, + const mojo::Callback<void()>& callback) { + token_revokers_.push_back(new IdentityInternalsTokenRevoker( + extension_id, access_token, callback, profile_, this)); +} + +mojo::Array<IdentityTokenMojoPtr> +IdentityInternalsUIHandler::ConvertCachedTokens( + const extensions::IdentityAPI::CachedTokens& tokens) { + mojo::Array<IdentityTokenMojoPtr> array(tokens.size()); + size_t index = 0; + for (extensions::IdentityAPI::CachedTokens::const_iterator + it = tokens.begin(); it != tokens.end(); ++it, index++) { + IdentityTokenMojoPtr item(IdentityTokenMojo::New()); + item->access_token = it->second.token(); + item->extension_name = GetExtensionName(it->first); + item->extension_id = it->first.extension_id; + item->token_status = GetStatus(it->second); + item->expiration_time = GetExpirationTime(it->second); + item->scopes = GetScopes(it->first).Pass(); + + array[index] = item.Pass(); + } + + return array.Pass(); +} + +const std::string IdentityInternalsUIHandler::GetExtensionName( + const extensions::ExtensionTokenKey& token_cache_key) { + ExtensionService* extension_service = extensions::ExtensionSystem::Get( + profile_)->extension_service(); + const extensions::Extension* extension = + extension_service->extensions()->GetByID(token_cache_key.extension_id); + if (!extension) + return std::string(); + return extension->name(); +} + +mojo::Array<mojo::String> IdentityInternalsUIHandler::GetScopes( + const extensions::ExtensionTokenKey& token_cache_key) { + mojo::Array<mojo::String> array(token_cache_key.scopes.size()); + size_t index = 0; + for (std::set<std::string>::const_iterator + it = token_cache_key.scopes.begin(); + it != token_cache_key.scopes.end(); ++it, index++) { + array[index] = mojo::String(*it); + } + return array.Pass(); +} + +const std::string IdentityInternalsUIHandler::GetStatus( + const extensions::IdentityTokenCacheValue& token_cache_value) { + switch (token_cache_value.status()) { + case extensions::IdentityTokenCacheValue::CACHE_STATUS_ADVICE: + // Fallthrough to NOT FOUND case, as ADVICE is short lived. + case extensions::IdentityTokenCacheValue::CACHE_STATUS_NOTFOUND: + return l10n_util::GetStringUTF8( + IDS_IDENTITY_INTERNALS_TOKEN_NOT_FOUND); + case extensions::IdentityTokenCacheValue::CACHE_STATUS_TOKEN: + return l10n_util::GetStringUTF8( + IDS_IDENTITY_INTERNALS_TOKEN_PRESENT); + } + NOTREACHED(); + return std::string(); +} + +const std::string IdentityInternalsUIHandler::GetExpirationTime( + const extensions::IdentityTokenCacheValue& token_cache_value) { + return base::UTF16ToUTF8(base::TimeFormatFriendlyDateAndTime( + token_cache_value.expiration_time())); +} diff --git a/chrome/browser/ui/webui/identity_internals/identity_internals_ui_handler.h b/chrome/browser/ui/webui/identity_internals/identity_internals_ui_handler.h new file mode 100644 index 0000000..400e521 --- /dev/null +++ b/chrome/browser/ui/webui/identity_internals/identity_internals_ui_handler.h @@ -0,0 +1,71 @@ +// 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. + +#ifndef CHROME_BROWSER_UI_WEBUI_IDENTITY_INTERNALS_IDENTITY_INTERNALS_UI_HANDLER_H_ +#define CHROME_BROWSER_UI_WEBUI_IDENTITY_INTERNALS_IDENTITY_INTERNALS_UI_HANDLER_H_ + +#include "base/basictypes.h" +#include "base/compiler_specific.h" +#include "chrome/browser/extensions/api/identity/identity_api.h" +#include "chrome/browser/ui/webui/identity_internals/identity_internals.mojom.h" +#include "chrome/browser/ui/webui/mojo_web_ui_handler.h" + +class Profile; +class IdentityInternalsTokenRevoker; + +// Class acting as a controller of the chrome://identity-internals WebUI. +class IdentityInternalsUIHandler + : public mojo::InterfaceImpl<IdentityInternalsHandlerMojo>, + public MojoWebUIHandler { + public: + explicit IdentityInternalsUIHandler(Profile* profile); + virtual ~IdentityInternalsUIHandler(); + + // Ensures that a proper clean up happens after a token is revoked. That + // includes deleting the |token_revoker|, removing the token from Identity API + // cache and updating the UI that the token is gone. + void OnTokenRevokerDone(IdentityInternalsTokenRevoker* token_revoker); + + // Overridden from IdentityInternalsHandlerMojo: + virtual void GetTokens( + const mojo::Callback<void(mojo::Array<IdentityTokenMojoPtr>)>& callback) + OVERRIDE; + virtual void RevokeToken(const mojo::String& extension_id, + const mojo::String& access_token, + const mojo::Callback<void()>& callback) OVERRIDE; + + private: + // We use an explicit conversion function instead of TypeConverter because + // creating an IdentityTokenMojo relies on having the Profile* as state. + mojo::Array<IdentityTokenMojoPtr> ConvertCachedTokens( + const extensions::IdentityAPI::CachedTokens& tokens); + + // Gets the name of an extension referred to by |token_cache_key| as a string. + const std::string GetExtensionName( + const extensions::ExtensionTokenKey& token_cache_key); + + // Gets a list of scopes specified in |token_cache_key| and returns a pointer + // to a ListValue containing the scopes. The caller gets ownership of the + // returned object. + mojo::Array<mojo::String> GetScopes( + const extensions::ExtensionTokenKey& token_cache_key); + + // Gets a localized status of the access token in |token_cache_value|. + const std::string GetStatus( + const extensions::IdentityTokenCacheValue& token_cache_value); + + // Gets a string representation of an expiration time of the access token in + // |token_cache_value|. + const std::string GetExpirationTime( + const extensions::IdentityTokenCacheValue& token_cache_value); + + Profile* profile_; + + // A vector of token revokers that are currently revoking tokens. + ScopedVector<IdentityInternalsTokenRevoker> token_revokers_; + + DISALLOW_COPY_AND_ASSIGN(IdentityInternalsUIHandler); +}; + +#endif // CHROME_BROWSER_UI_WEBUI_IDENTITY_INTERNALS_IDENTITY_INTERNALS_UI_HANDLER_H_ diff --git a/chrome/browser/ui/webui/identity_internals_ui.cc b/chrome/browser/ui/webui/identity_internals_ui.cc deleted file mode 100644 index 16607b1..0000000 --- a/chrome/browser/ui/webui/identity_internals_ui.cc +++ /dev/null @@ -1,314 +0,0 @@ -// Copyright 2013 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. - -#include "chrome/browser/ui/webui/identity_internals_ui.h" - -#include <set> -#include <string> - -#include "base/bind.h" -#include "base/i18n/time_formatting.h" -#include "base/strings/utf_string_conversions.h" -#include "base/values.h" -#include "chrome/browser/extensions/api/identity/identity_api.h" -#include "chrome/browser/extensions/extension_service.h" -#include "chrome/browser/profiles/profile.h" -#include "chrome/common/url_constants.h" -#include "content/public/browser/web_ui.h" -#include "content/public/browser/web_ui_controller.h" -#include "content/public/browser/web_ui_data_source.h" -#include "content/public/browser/web_ui_message_handler.h" -#include "extensions/browser/extension_system.h" -#include "google_apis/gaia/gaia_auth_fetcher.h" -#include "google_apis/gaia/gaia_constants.h" -#include "grit/browser_resources.h" -#include "grit/generated_resources.h" -#include "ui/base/l10n/l10n_util.h" - -namespace { - -// Properties of the Javascript object representing a token. -const char kExtensionId[] = "extensionId"; -const char kExtensionName[] = "extensionName"; -const char kScopes[] = "scopes"; -const char kStatus[] = "status"; -const char kTokenExpirationTime[] = "expirationTime"; -const char kAccessToken[] = "accessToken"; - -// RevokeToken message parameter offsets. -const int kRevokeTokenExtensionOffset = 0; -const int kRevokeTokenTokenOffset = 1; - -class IdentityInternalsTokenRevoker; - -// Class acting as a controller of the chrome://identity-internals WebUI. -class IdentityInternalsUIMessageHandler : public content::WebUIMessageHandler { - public: - IdentityInternalsUIMessageHandler(); - virtual ~IdentityInternalsUIMessageHandler(); - - // Ensures that a proper clean up happens after a token is revoked. That - // includes deleting the |token_revoker|, removing the token from Identity API - // cache and updating the UI that the token is gone. - void OnTokenRevokerDone(IdentityInternalsTokenRevoker* token_revoker); - - // WebUIMessageHandler implementation. - virtual void RegisterMessages() OVERRIDE; - - private: - // Gets the name of an extension referred to by |token_cache_key| as a string. - const std::string GetExtensionName( - const extensions::ExtensionTokenKey& token_cache_key); - - // Gets a list of scopes specified in |token_cache_key| and returns a pointer - // to a ListValue containing the scopes. The caller gets ownership of the - // returned object. - base::ListValue* GetScopes( - const extensions::ExtensionTokenKey& token_cache_key); - - // Gets a localized status of the access token in |token_cache_value|. - const base::string16 GetStatus( - const extensions::IdentityTokenCacheValue& token_cache_value); - - // Gets a string representation of an expiration time of the access token in - // |token_cache_value|. - const std::string GetExpirationTime( - const extensions::IdentityTokenCacheValue& token_cache_value); - - // Converts a pair of |token_cache_key| and |token_cache_value| to a - // DictionaryValue object with corresponding information in a localized and - // readable form and returns a pointer to created object. Caller gets the - // ownership of the returned object. - base::DictionaryValue* GetInfoForToken( - const extensions::ExtensionTokenKey& token_cache_key, - const extensions::IdentityTokenCacheValue& token_cache_value); - - // Gets all of the tokens stored in IdentityAPI token cache and returns them - // to the caller using Javascript callback function - // |identity_internals.returnTokens()|. - void GetInfoForAllTokens(const base::ListValue* args); - - // Initiates revoking of the token, based on the extension ID and token - // passed as entries in the |args| list. Updates the caller of completion - // using Javascript callback function |identity_internals.tokenRevokeDone()|. - void RevokeToken(const base::ListValue* args); - - // A vector of token revokers that are currently revoking tokens. - ScopedVector<IdentityInternalsTokenRevoker> token_revokers_; -}; - -// Handles the revoking of an access token and helps performing the clean up -// after it is revoked by holding information about the access token and related -// extension ID. -class IdentityInternalsTokenRevoker : public GaiaAuthConsumer { - public: - // Revokes |access_token| from extension with |extension_id|. - // |profile| is required for its request context. |consumer| will be - // notified when revocation succeeds via |OnTokenRevokerDone()|. - IdentityInternalsTokenRevoker(const std::string& extension_id, - const std::string& access_token, - Profile* profile, - IdentityInternalsUIMessageHandler* consumer); - virtual ~IdentityInternalsTokenRevoker(); - - // Returns the access token being revoked. - const std::string& access_token() const { return access_token_; } - - // Returns the ID of the extension the access token is related to. - const std::string& extension_id() const { return extension_id_; } - - // GaiaAuthConsumer implementation. - virtual void OnOAuth2RevokeTokenCompleted() OVERRIDE; - - private: - // An object used to start a token revoke request. - GaiaAuthFetcher fetcher_; - // An ID of an extension the access token is related to. - const std::string extension_id_; - // The access token to revoke. - const std::string access_token_; - // An object that needs to be notified once the access token is revoked. - IdentityInternalsUIMessageHandler* consumer_; // weak. - - DISALLOW_COPY_AND_ASSIGN(IdentityInternalsTokenRevoker); -}; - -IdentityInternalsUIMessageHandler::IdentityInternalsUIMessageHandler() {} - -IdentityInternalsUIMessageHandler::~IdentityInternalsUIMessageHandler() {} - -void IdentityInternalsUIMessageHandler::OnTokenRevokerDone( - IdentityInternalsTokenRevoker* token_revoker) { - // Remove token from the cache. - extensions::IdentityAPI::GetFactoryInstance() - ->Get(Profile::FromWebUI(web_ui())) - ->EraseCachedToken(token_revoker->extension_id(), - token_revoker->access_token()); - - // Update view about the token being removed. - base::ListValue result; - result.AppendString(token_revoker->access_token()); - web_ui()->CallJavascriptFunction("identity_internals.tokenRevokeDone", - result); - - // Erase the revoker. - ScopedVector<IdentityInternalsTokenRevoker>::iterator iter = - std::find(token_revokers_.begin(), token_revokers_.end(), token_revoker); - DCHECK(iter != token_revokers_.end()); - token_revokers_.erase(iter); -} - -const std::string IdentityInternalsUIMessageHandler::GetExtensionName( - const extensions::ExtensionTokenKey& token_cache_key) { - ExtensionService* extension_service = extensions::ExtensionSystem::Get( - Profile::FromWebUI(web_ui()))->extension_service(); - const extensions::Extension* extension = - extension_service->extensions()->GetByID(token_cache_key.extension_id); - if (!extension) - return std::string(); - return extension->name(); -} - -base::ListValue* IdentityInternalsUIMessageHandler::GetScopes( - const extensions::ExtensionTokenKey& token_cache_key) { - base::ListValue* scopes_value = new base::ListValue(); - for (std::set<std::string>::const_iterator - iter = token_cache_key.scopes.begin(); - iter != token_cache_key.scopes.end(); ++iter) { - scopes_value->AppendString(*iter); - } - return scopes_value; -} - -const base::string16 IdentityInternalsUIMessageHandler::GetStatus( - const extensions::IdentityTokenCacheValue& token_cache_value) { - switch (token_cache_value.status()) { - case extensions::IdentityTokenCacheValue::CACHE_STATUS_ADVICE: - // Fallthrough to NOT FOUND case, as ADVICE is short lived. - case extensions::IdentityTokenCacheValue::CACHE_STATUS_NOTFOUND: - return l10n_util::GetStringUTF16( - IDS_IDENTITY_INTERNALS_TOKEN_NOT_FOUND); - case extensions::IdentityTokenCacheValue::CACHE_STATUS_TOKEN: - return l10n_util::GetStringUTF16( - IDS_IDENTITY_INTERNALS_TOKEN_PRESENT); - } - NOTREACHED(); - return base::string16(); -} - -const std::string IdentityInternalsUIMessageHandler::GetExpirationTime( - const extensions::IdentityTokenCacheValue& token_cache_value) { - return base::UTF16ToUTF8(base::TimeFormatFriendlyDateAndTime( - token_cache_value.expiration_time())); -} - -base::DictionaryValue* IdentityInternalsUIMessageHandler::GetInfoForToken( - const extensions::ExtensionTokenKey& token_cache_key, - const extensions::IdentityTokenCacheValue& token_cache_value) { - base::DictionaryValue* token_data = new base::DictionaryValue(); - token_data->SetString(kExtensionId, token_cache_key.extension_id); - token_data->SetString(kExtensionName, GetExtensionName(token_cache_key)); - token_data->Set(kScopes, GetScopes(token_cache_key)); - token_data->SetString(kStatus, GetStatus(token_cache_value)); - token_data->SetString(kAccessToken, token_cache_value.token()); - token_data->SetString(kTokenExpirationTime, - GetExpirationTime(token_cache_value)); - return token_data; -} - -void IdentityInternalsUIMessageHandler::GetInfoForAllTokens( - const base::ListValue* args) { - base::ListValue results; - extensions::IdentityAPI::CachedTokens tokens = - extensions::IdentityAPI::GetFactoryInstance() - ->Get(Profile::FromWebUI(web_ui())) - ->GetAllCachedTokens(); - for (extensions::IdentityAPI::CachedTokens::const_iterator - iter = tokens.begin(); iter != tokens.end(); ++iter) { - results.Append(GetInfoForToken(iter->first, iter->second)); - } - - web_ui()->CallJavascriptFunction("identity_internals.returnTokens", results); -} - -void IdentityInternalsUIMessageHandler::RegisterMessages() { - web_ui()->RegisterMessageCallback("identityInternalsGetTokens", - base::Bind(&IdentityInternalsUIMessageHandler::GetInfoForAllTokens, - base::Unretained(this))); - web_ui()->RegisterMessageCallback("identityInternalsRevokeToken", - base::Bind(&IdentityInternalsUIMessageHandler::RevokeToken, - base::Unretained(this))); -} - -void IdentityInternalsUIMessageHandler::RevokeToken( - const base::ListValue* args) { - std::string extension_id; - std::string access_token; - args->GetString(kRevokeTokenExtensionOffset, &extension_id); - args->GetString(kRevokeTokenTokenOffset, &access_token); - token_revokers_.push_back(new IdentityInternalsTokenRevoker( - extension_id, access_token, Profile::FromWebUI(web_ui()), this)); -} - -IdentityInternalsTokenRevoker::IdentityInternalsTokenRevoker( - const std::string& extension_id, - const std::string& access_token, - Profile* profile, - IdentityInternalsUIMessageHandler* consumer) - : fetcher_(this, GaiaConstants::kChromeSource, - profile->GetRequestContext()), - extension_id_(extension_id), - access_token_(access_token), - consumer_(consumer) { - DCHECK(consumer_); - fetcher_.StartRevokeOAuth2Token(access_token); -} - -IdentityInternalsTokenRevoker::~IdentityInternalsTokenRevoker() {} - -void IdentityInternalsTokenRevoker::OnOAuth2RevokeTokenCompleted() { - consumer_->OnTokenRevokerDone(this); -} - -} // namespace - -IdentityInternalsUI::IdentityInternalsUI(content::WebUI* web_ui) - : content::WebUIController(web_ui) { - // chrome://identity-internals source. - content::WebUIDataSource* html_source = - content::WebUIDataSource::Create(chrome::kChromeUIIdentityInternalsHost); - html_source->SetUseJsonJSFormatV2(); - - // Localized strings - html_source->AddLocalizedString("tokenCacheHeader", - IDS_IDENTITY_INTERNALS_TOKEN_CACHE_TEXT); - html_source->AddLocalizedString("accessToken", - IDS_IDENTITY_INTERNALS_ACCESS_TOKEN); - html_source->AddLocalizedString("extensionName", - IDS_IDENTITY_INTERNALS_EXTENSION_NAME); - html_source->AddLocalizedString("extensionId", - IDS_IDENTITY_INTERNALS_EXTENSION_ID); - html_source->AddLocalizedString("tokenStatus", - IDS_IDENTITY_INTERNALS_TOKEN_STATUS); - html_source->AddLocalizedString("expirationTime", - IDS_IDENTITY_INTERNALS_EXPIRATION_TIME); - html_source->AddLocalizedString("scopes", - IDS_IDENTITY_INTERNALS_SCOPES); - html_source->AddLocalizedString("revoke", - IDS_IDENTITY_INTERNALS_REVOKE); - html_source->SetJsonPath("strings.js"); - - // Required resources - html_source->AddResourcePath("identity_internals.css", - IDR_IDENTITY_INTERNALS_CSS); - html_source->AddResourcePath("identity_internals.js", - IDR_IDENTITY_INTERNALS_JS); - html_source->SetDefaultResource(IDR_IDENTITY_INTERNALS_HTML); - - content::WebUIDataSource::Add(Profile::FromWebUI(web_ui), html_source); - - web_ui->AddMessageHandler(new IdentityInternalsUIMessageHandler()); -} - -IdentityInternalsUI::~IdentityInternalsUI() {} diff --git a/chrome/browser/ui/webui/identity_internals_ui.h b/chrome/browser/ui/webui/identity_internals_ui.h deleted file mode 100644 index 929b610..0000000 --- a/chrome/browser/ui/webui/identity_internals_ui.h +++ /dev/null @@ -1,23 +0,0 @@ -// Copyright 2013 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 CHROME_BROWSER_UI_WEBUI_IDENTITY_INTERNALS_UI_H_ -#define CHROME_BROWSER_UI_WEBUI_IDENTITY_INTERNALS_UI_H_ - -#include "content/public/browser/web_ui_controller.h" - -class IdentityInternalsUITest; - -// The WebUI for chrome://identity-internals -class IdentityInternalsUI - : public content::WebUIController { - public: - explicit IdentityInternalsUI(content::WebUI* web_ui); - virtual ~IdentityInternalsUI(); - - private: - DISALLOW_COPY_AND_ASSIGN(IdentityInternalsUI); -}; - -#endif // CHROME_BROWSER_UI_WEBUI_IDENTITY_INTERNALS_UI_H_ diff --git a/chrome/chrome_browser_ui.gypi b/chrome/chrome_browser_ui.gypi index a194db4..e48340b 100644 --- a/chrome/chrome_browser_ui.gypi +++ b/chrome/chrome_browser_ui.gypi @@ -1613,8 +1613,12 @@ 'browser/ui/webui/help/version_updater_mac.h', 'browser/ui/webui/help/version_updater_mac.mm', 'browser/ui/webui/help/version_updater_win.cc', - 'browser/ui/webui/identity_internals_ui.cc', - 'browser/ui/webui/identity_internals_ui.h', + 'browser/ui/webui/identity_internals/identity_internals_ui.cc', + 'browser/ui/webui/identity_internals/identity_internals_ui.h', + 'browser/ui/webui/identity_internals/identity_internals_ui_handler.cc', + 'browser/ui/webui/identity_internals/identity_internals_ui_handler.h', + 'browser/ui/webui/identity_internals/identity_internals_token_revoker.cc', + 'browser/ui/webui/identity_internals/identity_internals_token_revoker.h', 'browser/ui/webui/inspect_ui.cc', 'browser/ui/webui/inspect_ui.h', 'browser/ui/webui/ntp/app_launcher_handler.cc', @@ -2595,6 +2599,7 @@ ['OS != "ios"', { 'sources': [ '<@(chrome_browser_ui_non_ios_sources)', + '<(SHARED_INTERMEDIATE_DIR)/chrome/browser/ui/webui/identity_internals/identity_internals.mojom.cc', '<(SHARED_INTERMEDIATE_DIR)/chrome/browser/ui/webui/omnibox/omnibox.mojom.cc', ], 'dependencies': [ diff --git a/chrome/chrome_resources.gyp b/chrome/chrome_resources.gyp index 5d715ad..4b5644f 100644 --- a/chrome/chrome_resources.gyp +++ b/chrome/chrome_resources.gyp @@ -3,9 +3,10 @@ # found in the LICENSE file. { 'variables': { - 'grit_out_dir': '<(SHARED_INTERMEDIATE_DIR)/chrome', 'about_credits_file': '<(SHARED_INTERMEDIATE_DIR)/about_credits.html', 'additional_modules_list_file': '<(SHARED_INTERMEDIATE_DIR)/chrome/browser/internal/additional_modules_list.txt', + 'grit_out_dir': '<(SHARED_INTERMEDIATE_DIR)/chrome', + 'identity_internals_mojom_file': '<(SHARED_INTERMEDIATE_DIR)/chrome/browser/ui/webui/identity_internals/identity_internals.mojom.js', 'omnibox_mojom_file': '<(SHARED_INTERMEDIATE_DIR)/chrome/browser/ui/webui/omnibox/omnibox.mojom.js', }, 'targets': [ @@ -198,6 +199,7 @@ 'grit_additional_defines': [ '-E', 'about_credits_file=<(about_credits_file)', '-E', 'additional_modules_list_file=<(additional_modules_list_file)', + '-E', 'identity_internals_mojom_file=<(identity_internals_mojom_file)', '-E', 'omnibox_mojom_file=<(omnibox_mojom_file)', ], }, diff --git a/chrome/chrome_tests.gypi b/chrome/chrome_tests.gypi index ad0a0fe..0991f0c5 100644 --- a/chrome/chrome_tests.gypi +++ b/chrome/chrome_tests.gypi @@ -1471,9 +1471,9 @@ 'browser/ui/webui/extensions/extension_settings_browsertest.h', 'browser/ui/webui/extensions/extension_settings_browsertest.js', 'browser/ui/webui/help/help_browsertest.js', - 'browser/ui/webui/identity_internals_ui_browsertest.cc', - 'browser/ui/webui/identity_internals_ui_browsertest.h', - 'browser/ui/webui/identity_internals_ui_browsertest.js', + 'browser/ui/webui/identity_internals/identity_internals_ui_browsertest.cc', + 'browser/ui/webui/identity_internals/identity_internals_ui_browsertest.h', + 'browser/ui/webui/identity_internals/identity_internals_ui_browsertest.js', 'browser/ui/webui/inspect_ui_browsertest.cc', 'browser/ui/webui/net_internals/net_internals_ui_browsertest.cc', 'browser/ui/webui/net_internals/net_internals_ui_browsertest.h', diff --git a/chrome/chrome_web_ui_mojo_bindings.gyp b/chrome/chrome_web_ui_mojo_bindings.gyp index 4419898..6c18b79 100644 --- a/chrome/chrome_web_ui_mojo_bindings.gyp +++ b/chrome/chrome_web_ui_mojo_bindings.gyp @@ -11,6 +11,7 @@ # generated cpp files be listed explicitly in browser_ui. 'type': 'none', 'sources': [ + 'browser/ui/webui/identity_internals/identity_internals.mojom', 'browser/ui/webui/omnibox/omnibox.mojom', ], 'includes': [ '../mojo/public/tools/bindings/mojom_bindings_generator.gypi' ], diff --git a/chrome/test/base/js2gtest.js b/chrome/test/base/js2gtest.js index c20b934..83c4c48 100644 --- a/chrome/test/base/js2gtest.js +++ b/chrome/test/base/js2gtest.js @@ -324,6 +324,8 @@ function GEN_INCLUDE(includes) { function TEST_F(testFixture, testFunction, testBody) { maybeGenHeader(testFixture); var browsePreload = this[testFixture].prototype.browsePreload; + var browsePreloadAndWaitForMain = + this[testFixture].prototype.browsePreloadAndWaitForMain; var browsePrintPreload = this[testFixture].prototype.browsePrintPreload; var testGenPreamble = this[testFixture].prototype.testGenPreamble; var testGenPostamble = this[testFixture].prototype.testGenPostamble; @@ -359,6 +361,10 @@ function TEST_F(testFixture, testFunction, testBody) { testGenPreamble(testFixture, testFunction); if (browsePreload) print(' BrowsePreload(GURL("' + browsePreload + '"));'); + if (browsePreloadAndWaitForMain) { + print(' BrowsePreloadAndWaitForMain(GURL("' + browsePreloadAndWaitForMain + + '"));'); + } if (browsePrintPreload) { print(' BrowsePrintPreload(GURL(WebUITestDataPathToURL(\n' + ' FILE_PATH_LITERAL("' + browsePrintPreload + '"))));'); diff --git a/chrome/test/base/web_ui_browser_test.cc b/chrome/test/base/web_ui_browser_test.cc index cf9a2aa..c82c1d0 100644 --- a/chrome/test/base/web_ui_browser_test.cc +++ b/chrome/test/base/web_ui_browser_test.cc @@ -9,6 +9,7 @@ #include "base/lazy_instance.h" #include "base/memory/ref_counted_memory.h" +#include "base/message_loop/message_loop.h" #include "base/path_service.h" #include "base/strings/string_util.h" #include "base/values.h" @@ -82,6 +83,35 @@ class WebUIJsInjectionReadyObserver : public content::WebContentsObserver { std::string preload_test_name_; }; +class WebUIMainObserver : public content::WebContentsObserver { + public: + explicit WebUIMainObserver(content::WebContents* web_contents) + : content::WebContentsObserver(web_contents), + message_loop_runner_(new content::MessageLoopRunner), + has_fired_(false) { + } + + void Wait() { + if (has_fired_) + return; + + message_loop_runner_->Run(); + } + + virtual void DidRunWebUIMojoMain() OVERRIDE { + has_fired_ = true; + message_loop_runner_->Quit(); + } + + private: + // The MessageLoopRunner used to spin the message loop. + scoped_refptr<content::MessageLoopRunner> message_loop_runner_; + + bool has_fired_; + + DISALLOW_COPY_AND_ASSIGN(WebUIMainObserver); +}; + } // namespace WebUIBrowserTest::~WebUIBrowserTest() { @@ -220,6 +250,14 @@ void WebUIBrowserTest::BrowsePreload(const GURL& browse_to) { navigation_observer.Wait(); } +void WebUIBrowserTest::BrowsePreloadAndWaitForMain(const GURL& browse_to) { + content::WebContents* web_contents = + browser()->tab_strip_model()->GetActiveWebContents(); + WebUIMainObserver webui_main_observer(web_contents); + BrowsePreload(browse_to); + webui_main_observer.Wait(); +} + #if defined(ENABLE_FULL_PRINTING) // This custom ContentBrowserClient is used to get notified when a WebContents diff --git a/chrome/test/base/web_ui_browser_test.h b/chrome/test/base/web_ui_browser_test.h index 3220442..a4cb28b 100644 --- a/chrome/test/base/web_ui_browser_test.h +++ b/chrome/test/base/web_ui_browser_test.h @@ -95,6 +95,11 @@ class WebUIBrowserTest : public JavaScriptBrowserTest { // handler mocking. void BrowsePreload(const GURL& browse_to); + // Called by javascript-generated test bodies. In addition to doing + // everything in BrowsePreload(), it also waits until the + // DidRunWebUIMojoMain() event fires. + void BrowsePreloadAndWaitForMain(const GURL& browse_to); + // Called by javascript-generated test bodies to browse to a page and preload // the javascript for the given |preload_test_fixture| and // |preload_test_name|. chrome.send will be overridden to allow javascript diff --git a/content/browser/web_contents/web_contents_impl.cc b/content/browser/web_contents/web_contents_impl.cc index 5e8942b..6dd5bb1 100644 --- a/content/browser/web_contents/web_contents_impl.cc +++ b/content/browser/web_contents/web_contents_impl.cc @@ -570,6 +570,7 @@ bool WebContentsImpl::OnMessageReceived(RenderViewHost* render_view_host, OnMediaPausedNotification) IPC_MESSAGE_HANDLER(FrameHostMsg_DidFirstVisuallyNonEmptyPaint, OnFirstVisuallyNonEmptyPaint) + IPC_MESSAGE_HANDLER(FrameHostMsg_WebUIMojoMainRan, OnWebUIMojoMainRan) IPC_MESSAGE_HANDLER(ViewHostMsg_DidLoadResourceFromMemoryCache, OnDidLoadResourceFromMemoryCache) IPC_MESSAGE_HANDLER(ViewHostMsg_DidDisplayInsecureContent, @@ -3059,6 +3060,12 @@ void WebContentsImpl::OnFirstVisuallyNonEmptyPaint() { DidFirstVisuallyNonEmptyPaint()); } +void WebContentsImpl::OnWebUIMojoMainRan() { + FOR_EACH_OBSERVER(WebContentsObserver, + observers_, + DidRunWebUIMojoMain()); +} + void WebContentsImpl::DidChangeVisibleSSLState() { if (delegate_) delegate_->VisibleSSLStateChanged(this); diff --git a/content/browser/web_contents/web_contents_impl.h b/content/browser/web_contents/web_contents_impl.h index 765ac46..528ffa7 100644 --- a/content/browser/web_contents/web_contents_impl.h +++ b/content/browser/web_contents/web_contents_impl.h @@ -796,6 +796,7 @@ class CONTENT_EXPORT WebContentsImpl const std::vector<gfx::Size>& original_bitmap_sizes); void OnUpdateFaviconURL(const std::vector<FaviconURL>& candidates); void OnFirstVisuallyNonEmptyPaint(); + void OnWebUIMojoMainRan(); void OnMediaPlayingNotification(int64 player_cookie, bool has_video, bool has_audio); diff --git a/content/common/frame_messages.h b/content/common/frame_messages.h index 6e53ded..ca117a87 100644 --- a/content/common/frame_messages.h +++ b/content/common/frame_messages.h @@ -688,3 +688,7 @@ IPC_MESSAGE_ROUTED1(FrameHostMsg_BeginNavigation, // Sent once a paint happens after the first non empty layout. In other words // after the frame has painted something. IPC_MESSAGE_ROUTED0(FrameHostMsg_DidFirstVisuallyNonEmptyPaint) + +// Sent when a WebUI page that uses Mojo has executed its 'main' module. Our +// javascript based testing framework must wait until this has happened. +IPC_MESSAGE_ROUTED0(FrameHostMsg_WebUIMojoMainRan) diff --git a/content/public/browser/web_contents_observer.h b/content/public/browser/web_contents_observer.h index f264392..5ea5ef6 100644 --- a/content/public/browser/web_contents_observer.h +++ b/content/public/browser/web_contents_observer.h @@ -325,6 +325,10 @@ class CONTENT_EXPORT WebContentsObserver : public IPC::Listener, // Invoked when theme color is changed to |theme_color|. virtual void DidChangeThemeColor(SkColor theme_color) {} + // Invoked when the gin bindings have run the main module on mojoized WebUI + // pages. Only invoked on the main frame. + virtual void DidRunWebUIMojoMain() {} + // Invoked if an IPC message is coming from a specific RenderFrameHost. virtual bool OnMessageReceived(const IPC::Message& message, RenderFrameHost* render_frame_host); diff --git a/content/renderer/web_ui_mojo_context_state.cc b/content/renderer/web_ui_mojo_context_state.cc index f1ff5f4..56a46df 100644 --- a/content/renderer/web_ui_mojo_context_state.cc +++ b/content/renderer/web_ui_mojo_context_state.cc @@ -6,6 +6,8 @@ #include "base/bind.h" #include "base/stl_util.h" +#include "content/common/frame_messages.h" +#include "content/public/renderer/render_frame.h" #include "content/public/renderer/resource_fetcher.h" #include "content/renderer/web_ui_runner.h" #include "gin/converter.h" @@ -35,17 +37,6 @@ namespace { // TODO(sky): move this into some common place. const char kModulePrefix[] = "chrome://mojo/"; -void RunMain(base::WeakPtr<gin::Runner> runner, - mojo::ScopedMessagePipeHandle* handle, - v8::Handle<v8::Value> module) { - v8::Isolate* isolate = runner->GetContextHolder()->isolate(); - v8::Handle<v8::Function> start; - CHECK(gin::ConvertFromV8(isolate, module, &start)); - v8::Handle<v8::Value> args[] = { - gin::ConvertToV8(isolate, mojo::Handle(handle->release().value())) }; - runner->Call(start, runner->global(), 1, args); -} - } // namespace // WebUIMojo ------------------------------------------------------------------- @@ -78,7 +69,23 @@ void WebUIMojoContextState::SetHandle(mojo::ScopedMessagePipeHandle handle) { gin::ModuleRegistry::From(context_holder->context())->LoadModule( context_holder->isolate(), "main", - base::Bind(RunMain, runner_->GetWeakPtr(), base::Owned(passed_handle))); + base::Bind(&WebUIMojoContextState::RunMain, + AsWeakPtr(), + base::Owned(passed_handle))); +} + +void WebUIMojoContextState::RunMain(mojo::ScopedMessagePipeHandle* handle, + v8::Handle<v8::Value> module) { + v8::Isolate* isolate = runner_->GetContextHolder()->isolate(); + v8::Handle<v8::Function> start; + CHECK(gin::ConvertFromV8(isolate, module, &start)); + v8::Handle<v8::Value> args[] = { + gin::ConvertToV8(isolate, mojo::Handle(handle->release().value())) }; + runner_->Call(start, runner_->global(), 1, args); + + RenderFrame* render_frame = RenderFrame::FromWebFrame(frame_); + render_frame->Send(new FrameHostMsg_WebUIMojoMainRan( + render_frame->GetRoutingID())); } void WebUIMojoContextState::FetchModules(const std::vector<std::string>& ids) { diff --git a/content/renderer/web_ui_mojo_context_state.h b/content/renderer/web_ui_mojo_context_state.h index e4eb0a4..beaa665 100644 --- a/content/renderer/web_ui_mojo_context_state.h +++ b/content/renderer/web_ui_mojo_context_state.h @@ -10,6 +10,7 @@ #include "base/memory/scoped_ptr.h" #include "base/memory/scoped_vector.h" +#include "base/memory/weak_ptr.h" #include "gin/modules/module_registry_observer.h" #include "mojo/public/cpp/system/core.h" #include "v8/include/v8.h" @@ -21,6 +22,7 @@ class WebURLResponse; namespace gin { class ContextHolder; +class Runner; struct PendingModule; } @@ -32,7 +34,9 @@ class WebUIRunner; // WebUIMojoContextState manages the modules needed for mojo bindings. It does // this by way of gin. Non-builtin modules are downloaded by way of // ResourceFetchers. -class WebUIMojoContextState : public gin::ModuleRegistryObserver { +class WebUIMojoContextState + : public gin::ModuleRegistryObserver, + public base::SupportsWeakPtr<WebUIMojoContextState> { public: WebUIMojoContextState(blink::WebFrame* frame, v8::Handle<v8::Context> context); @@ -47,6 +51,11 @@ class WebUIMojoContextState : public gin::ModuleRegistryObserver { private: class Loader; + // The implementation of the 'main' module. Calls the closure passed in and + // then notifies our RenderView that we've run the main closure. + void RunMain(mojo::ScopedMessagePipeHandle* handle, + v8::Handle<v8::Value> module); + // Invokes FetchModule() for any modules that have not already been // downloaded. void FetchModules(const std::vector<std::string>& ids); |