Commit 7436542b authored by mazda@chromium.org's avatar mazda@chromium.org

Implement InputWindowDialog with WebUI for bookmark folder management.

WebUI version of InputWindowDialog is used by the chrome built with touchui=1 or use_aura=1.

BUG=97850
TEST=Manually tested with touchui=1 or use_aura=1


Review URL: http://codereview.chromium.org/8298019

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@107096 0039d316-1c4b-4281-b951-d872f2087c98
parent 8743f327
......@@ -50,11 +50,8 @@ BookmarkFolderEditorController::BookmarkFolderEditorController(
l10n_util::GetStringUTF16(IDS_BOOKMARK_EDITOR_NEW_FOLDER_NAME) :
node_->GetTitle();
#if !defined(USE_AURA)
// TODO(saintlou): We seem to be missing a pure Views implemntation.
dialog_ = InputWindowDialog::Create(wnd, title, label, contents, this);
dialog_->Show();
#endif
}
bool BookmarkFolderEditorController::IsValid(const string16& text) {
......
......@@ -47,6 +47,7 @@
<include name="IDR_EDIT_SEARCH_ENGINE_DIALOG_HTML" file="resources\edit_search_engine_dialog.html" type="BINDATA" />
<include name="IDR_EDIT_SEARCH_ENGINE_DIALOG_JS" file="resources\edit_search_engine_dialog.js" type="BINDATA" />
<include name="IDR_EDIT_SEARCH_ENGINE_DIALOG_CSS" file="resources\edit_search_engine_dialog.css" type="BINDATA" />
<include name="IDR_INPUT_WINDOW_DIALOG_HTML" file="resources\input_window_dialog.html" flattenhtml="true" type="BINDATA" />
<include name="IDR_TASK_MANAGER_HTML" file="resources\task_manager\main.html" flattenhtml="true" allowexternalscript="true" type="BINDATA" />
<include name="IDR_TASK_MANAGER_INCLUDES_JS" file="resources\task_manager\includes.js" type="BINDATA" />
<include name="IDR_TASK_MANAGER_JS" file="resources\task_manager\main.js" type="BINDATA" />
......
/* Copyright (c) 2011 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.
*/
html,
body {
background-color: #EEE;
height: 100%;
margin: 0;
overflow: hidden;
}
.vbox {
height: 100%;
width: 100%;
}
.input-area {
-webkit-box-align: center;
-webkit-box-pack: center;
display: -webkit-box;
height: 60%;
}
.buttons-area {
display: table;
float: right;
height: 100%;
margin-right: 8px;
width: auto;
}
.buttons-area > div {
display: table-cell;
padding: 3px;
vertical-align: top;
width: 50%;
}
button {
white-space: nowrap;
width: 100%;
}
<!DOCTYPE HTML>
<html i18n-values="dir:textdirection">
<head>
<meta charset="utf-8">
<title i18n-content="title"></title>
<link rel="stylesheet" href="chrome://resources/css/button.css">
<link rel="stylesheet" href="chrome://resources/css/chrome_shared.css">
<link rel="stylesheet" href="input_window_dialog.css">
<script src="chrome://input-window-dialog/strings.js"></script>
<script src="chrome://resources/js/cr.js"></script>
<script src="chrome://resources/js/cr/ui.js"></script>
<script src="chrome://resources/js/i18n_template.js"></script>
<script src="chrome://resources/js/util.js"></script>
<script src="input_window_dialog.js"></script>
</head>
<body>
<div class="vbox">
<div class="input-area">
<div>
<span id="name-label"></span>
<input id="name" type="text" autofocus>
</div>
</div>
<div class="buttons-area">
<div>
<button id="cancel" type="reset" i18n-content="cancel">Cancel</button>
</div>
<div>
<button id="ok" type="submit" i18n-content="ok">OK</button>
</div>
</div>
</div>
</body>
</html>
// Copyright (c) 2011 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.
cr.define('inputWindowDialog', function() {
'use strict';
/**
* Disables the controls while the dialog is busy.
*/
function disableControls() {
$('cancel').disabled = true;
$('ok').disabled = true;
}
/**
* Close the dialog and pass a result value to the dialog close handler.
* @param {boolean} result The value to pass to the dialog close handler.
*/
function closeWithResult(result) {
disableControls();
var value = [result];
if (result) {
value.push($('name').value);
}
var json = JSON.stringify(value);
chrome.send('DialogClose', [json]);
}
/**
* Inserts translated strings on loading.
*/
function initialize() {
i18nTemplate.process(document, templateData);
var args = JSON.parse(chrome.dialogArguments);
$('name-label').textContent = args.label;
$('name').value = args.contents;
$('cancel').onclick = function() {
closeWithResult(false);
}
$('ok').onclick = function() {
if (!$('ok').disabled) {
closeWithResult(true);
}
}
$('name').oninput = function() {
var name = $('name').value;
chrome.send('validate', [name]);
}
document.body.onkeydown = function(evt) {
if (evt.keyCode == 13) { // Enter key
$('ok').onclick();
} else if (evt.keyCode == 27) { // Escape key
$('cancel').onclick();
}
}
}
/**
* Called in response to validate request.
* @param {boolean} valid The result of validate request.
*/
function ackValidation(valid) {
$('ok').disabled = !valid;
}
return {
initialize: initialize,
ackValidation: ackValidation,
};
});
document.addEventListener('DOMContentLoaded', inputWindowDialog.initialize);
......@@ -2,47 +2,14 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chrome/browser/ui/input_window_dialog.h"
#include "chrome/browser/ui/input_window_dialog_gtk.h"
#include <gtk/gtk.h>
#include "base/memory/scoped_ptr.h"
#include "base/message_loop.h"
#include "base/utf_string_conversions.h"
#include "chrome/browser/ui/gtk/gtk_util.h"
#include "ui/base/gtk/gtk_signal.h"
class InputWindowDialogGtk : public InputWindowDialog {
public:
// Creates a dialog. Takes ownership of |delegate|.
InputWindowDialogGtk(GtkWindow* parent,
const std::string& window_title,
const std::string& label,
const std::string& contents,
Delegate* delegate);
virtual ~InputWindowDialogGtk();
virtual void Show();
virtual void Close();
private:
CHROMEG_CALLBACK_0(InputWindowDialogGtk, void, OnEntryChanged, GtkEditable*);
CHROMEGTK_CALLBACK_1(InputWindowDialogGtk, void, OnResponse, int);
CHROMEGTK_CALLBACK_1(InputWindowDialogGtk, gboolean,
OnWindowDeleteEvent, GdkEvent*);
CHROMEGTK_CALLBACK_0(InputWindowDialogGtk, void, OnWindowDestroy);
// The underlying gtk dialog window.
GtkWidget* dialog_;
// The GtkEntry in this form.
GtkWidget* input_;
// Our delegate. Consumes the window's output.
scoped_ptr<InputWindowDialog::Delegate> delegate_;
};
InputWindowDialogGtk::InputWindowDialogGtk(GtkWindow* parent,
const std::string& window_title,
const std::string& label,
......@@ -132,15 +99,3 @@ gboolean InputWindowDialogGtk::OnWindowDeleteEvent(GtkWidget* widget,
void InputWindowDialogGtk::OnWindowDestroy(GtkWidget* widget) {
MessageLoop::current()->DeleteSoon(FROM_HERE, this);
}
InputWindowDialog* InputWindowDialog::Create(gfx::NativeWindow parent,
const string16& window_title,
const string16& label,
const string16& contents,
Delegate* delegate) {
return new InputWindowDialogGtk(parent,
UTF16ToUTF8(window_title),
UTF16ToUTF8(label),
UTF16ToUTF8(contents),
delegate);
}
// Copyright (c) 2011 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_INPUT_WINDOW_DIALOG_GTK_H_
#define CHROME_BROWSER_UI_INPUT_WINDOW_DIALOG_GTK_H_
#pragma once
#include <gtk/gtk.h>
#include <string>
#include "base/basictypes.h"
#include "base/memory/scoped_ptr.h"
#include "chrome/browser/ui/input_window_dialog.h"
#include "ui/base/gtk/gtk_signal.h"
class InputWindowDialogGtk : public InputWindowDialog {
public:
// Creates a dialog. Takes ownership of |delegate|.
InputWindowDialogGtk(GtkWindow* parent,
const std::string& window_title,
const std::string& label,
const std::string& contents,
Delegate* delegate);
virtual ~InputWindowDialogGtk();
virtual void Show();
virtual void Close();
private:
CHROMEG_CALLBACK_0(InputWindowDialogGtk, void, OnEntryChanged, GtkEditable*);
CHROMEGTK_CALLBACK_1(InputWindowDialogGtk, void, OnResponse, int);
CHROMEGTK_CALLBACK_1(InputWindowDialogGtk, gboolean,
OnWindowDeleteEvent, GdkEvent*);
CHROMEGTK_CALLBACK_0(InputWindowDialogGtk, void, OnWindowDestroy);
// The underlying gtk dialog window.
GtkWidget* dialog_;
// The GtkEntry in this form.
GtkWidget* input_;
// Our delegate. Consumes the window's output.
scoped_ptr<InputWindowDialog::Delegate> delegate_;
DISALLOW_COPY_AND_ASSIGN(InputWindowDialogGtk);
};
#endif // CHROME_BROWSER_UI_INPUT_WINDOW_DIALOG_GTK_H_
// Copyright (c) 2011 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/input_window_dialog.h"
#include "base/utf_string_conversions.h"
#include "chrome/browser/ui/webui/chrome_web_ui.h"
#include "chrome/browser/ui/webui/input_window_dialog_webui.h"
#if !defined(USE_AURA)
#include "chrome/browser/ui/input_window_dialog_gtk.h"
#endif
InputWindowDialog* InputWindowDialog::Create(gfx::NativeWindow parent,
const string16& window_title,
const string16& label,
const string16& contents,
Delegate* delegate) {
#if defined(USE_AURA)
return new InputWindowDialogWebUI(window_title,
label,
contents,
delegate);
#else
if (ChromeWebUI::IsMoreWebUI()) {
return new InputWindowDialogWebUI(window_title,
label,
contents,
delegate);
} else {
return new InputWindowDialogGtk(parent,
UTF16ToUTF8(window_title),
UTF16ToUTF8(label),
UTF16ToUTF8(contents),
delegate);
}
#endif
}
......@@ -59,6 +59,7 @@ class ChromeURLContentSecurityPolicyExceptionSet
insert(chrome::kChromeUICreditsHost);
insert(chrome::kChromeUIDevToolsHost);
insert(chrome::kChromeUIDialogHost);
insert(chrome::kChromeUIInputWindowDialogHost);
insert(chrome::kChromeUINewTabHost);
#if defined(OS_CHROMEOS)
insert(chrome::kChromeUIEnterpriseEnrollmentHost);
......
......@@ -26,6 +26,7 @@
#include "chrome/browser/ui/webui/history_ui.h"
#include "chrome/browser/ui/webui/html_dialog_ui.h"
#include "chrome/browser/ui/webui/hung_renderer_dialog_ui.h"
#include "chrome/browser/ui/webui/input_window_dialog_ui.h"
#include "chrome/browser/ui/webui/media/media_internals_ui.h"
#include "chrome/browser/ui/webui/net_internals_ui.h"
#include "chrome/browser/ui/webui/ntp/new_tab_ui.h"
......@@ -160,6 +161,9 @@ static WebUIFactoryFunction GetWebUIFactoryFunction(Profile* profile,
if (url.host() == chrome::kChromeUIHungRendererDialogHost) {
return &NewWebUI<HungRendererDialogUI>;
}
if (url.host() == chrome::kChromeUIInputWindowDialogHost) {
return &NewWebUI<InputWindowDialogUI>;
}
if (url.host() == chrome::kChromeUICrashesHost)
return &NewWebUI<CrashesUI>;
if (url.host() == chrome::kChromeUIDevToolsHost)
......
// Copyright (c) 2011 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/input_window_dialog_ui.h"
#include "chrome/browser/ui/webui/chrome_web_ui_data_source.h"
#include "chrome/common/url_constants.h"
#include "content/browser/tab_contents/tab_contents.h"
#include "chrome/browser/profiles/profile.h"
#include "grit/browser_resources.h"
#include "grit/generated_resources.h"
InputWindowDialogUI::InputWindowDialogUI(TabContents* contents)
: HtmlDialogUI(contents) {
ChromeWebUIDataSource* source =
new ChromeWebUIDataSource(chrome::kChromeUIInputWindowDialogHost);
source->AddLocalizedString("ok", IDS_OK);
source->AddLocalizedString("cancel", IDS_CANCEL);
// Set the json path.
source->set_json_path("strings.js");
// Set default resource.
source->set_default_resource(IDR_INPUT_WINDOW_DIALOG_HTML);
Profile* profile = Profile::FromBrowserContext(contents->browser_context());
profile->GetChromeURLDataManager()->AddDataSource(source);
}
InputWindowDialogUI::~InputWindowDialogUI() {
}
// Copyright (c) 2011 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_INPUT_WINDOW_DIALOG_UI_H_
#define CHROME_BROWSER_UI_WEBUI_INPUT_WINDOW_DIALOG_UI_H_
#pragma once
#include "chrome/browser/ui/webui/html_dialog_ui.h"
class TabContents;
// The WebUI for chrome://input-window-dialog
class InputWindowDialogUI : public HtmlDialogUI {
public:
explicit InputWindowDialogUI(TabContents* contents);
virtual ~InputWindowDialogUI();
protected:
DISALLOW_COPY_AND_ASSIGN(InputWindowDialogUI);
};
#endif // CHROME_BROWSER_UI_WEBUI_INPUT_WINDOW_DIALOG_UI_H_
// Copyright (c) 2011 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/input_window_dialog_webui.h"
#include "base/bind.h"
#include "base/bind_helpers.h"
#include "base/json/json_reader.h"
#include "base/json/json_writer.h"
#include "base/utf_string_conversions.h"
#include "base/values.h"
#include "chrome/browser/ui/browser.h"
#include "chrome/browser/ui/browser_list.h"
#include "chrome/browser/ui/browser_dialogs.h"
#include "chrome/browser/ui/webui/html_dialog_ui.h"
#include "chrome/common/url_constants.h"
#include "content/browser/tab_contents/tab_contents.h"
namespace {
const int kInputWindowDialogWidth = 240;
const int kInputWindowDialogHeight = 120;
}
////////////////////////////////////////////////////////////////////////////////
// InputWindowWebUIDailog private methods
InputWindowDialogWebUI::InputWindowDialogWebUI(
const string16& window_title,
const string16& label,
const string16& contents,
InputWindowDialog::Delegate* delegate)
: handler_(new InputWindowDialogHandler(delegate)),
window_title_(window_title),
label_(label),
contents_(contents),
closed_(true),
delegate_(delegate) {
}
InputWindowDialogWebUI::~InputWindowDialogWebUI() {
}
void InputWindowDialogWebUI::Show() {
Browser* browser = BrowserList::GetLastActive();
DCHECK(browser);
browser->BrowserShowHtmlDialog(this, NULL);
closed_ = false;
}
void InputWindowDialogWebUI::Close() {
if (!closed_) {
DCHECK(handler_);
handler_->CloseDialog();
}
}
bool InputWindowDialogWebUI::IsDialogModal() const {
return true;
}
string16 InputWindowDialogWebUI::GetDialogTitle() const {
return window_title_;
}
GURL InputWindowDialogWebUI::GetDialogContentURL() const {
return GURL(chrome::kChromeUIInputWindowDialogURL);
}
void InputWindowDialogWebUI::GetWebUIMessageHandlers(
std::vector<WebUIMessageHandler*>* handlers) const {
handlers->push_back(handler_);
}
void InputWindowDialogWebUI::GetDialogSize(gfx::Size* size) const {
size->SetSize(kInputWindowDialogWidth, kInputWindowDialogHeight);
}
std::string InputWindowDialogWebUI::GetDialogArgs() const {
DictionaryValue value;
value.SetString("label", label_);
value.SetString("contents", contents_);
std::string json;
base::JSONWriter::Write(&value, false, &json);
return json;
}
void InputWindowDialogWebUI::OnDialogClosed(const std::string& json_retval) {
scoped_ptr<Value> root(base::JSONReader::Read(json_retval, false));
bool response = false;
ListValue* list = NULL;
bool accepted = false;
// If the dialog closes because of a button click then the json is a list
// containing a bool value. When OK button is clicked, a string in the text
// field is added to the list.
if (root.get() && root->GetAsList(&list) && list &&
list->GetBoolean(0, &response) && response) {
DCHECK_EQ(2U, list->GetSize());
string16 text;
if (list->GetString(1, &text)) {
delegate_->InputAccepted(text);
accepted = true;
}
}
if (!accepted) {
delegate_->InputCanceled();
}
closed_ = true;
}
void InputWindowDialogWebUI::OnCloseContents(TabContents* source,
bool* out_close_dialog) {
}
bool InputWindowDialogWebUI::ShouldShowDialogTitle() const {
return true;
}
////////////////////////////////////////////////////////////////////////////////
// InputWindowDialogHandler methods
InputWindowDialogHandler::InputWindowDialogHandler(
InputWindowDialog::Delegate* delegate)
: delegate_(delegate) {
}
void InputWindowDialogHandler::CloseDialog() {
DCHECK(web_ui_);
static_cast<HtmlDialogUI*>(web_ui_)->CloseDialog(NULL);
}
void InputWindowDialogHandler::RegisterMessages() {
web_ui_->RegisterMessageCallback("validate",
base::Bind(&InputWindowDialogHandler::Validate,
base::Unretained(this)));
}
void InputWindowDialogHandler::Validate(const base::ListValue* args) {
DCHECK_EQ(1U, args->GetSize());
bool valid = false;
string16 text;
if (args->GetString(0, &text)) {
valid = delegate_->IsValid(text);
}
scoped_ptr<Value> result(Value::CreateBooleanValue(valid));
web_ui_->CallJavascriptFunction("inputWindowDialog.ackValidation",
*result);
}
// Copyright (c) 2011 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_INPUT_WINDOW_DIALOG_WEBUI_H_
#define CHROME_BROWSER_UI_WEBUI_INPUT_WINDOW_DIALOG_WEBUI_H_
#pragma once
#include <string>
#include <vector>
#include "base/string16.h"
#include "chrome/browser/ui/input_window_dialog.h"
#include "chrome/browser/ui/webui/html_dialog_ui.h"
namespace base {
class ListValue;
} // namespace base
class InputWindowDialogHandler;
// A class that implements InputWindowDialog methods with WebUI.
class InputWindowDialogWebUI : public InputWindowDialog,
private HtmlDialogUIDelegate {
public:
InputWindowDialogWebUI(const string16& window_title,
const string16& label,
const string16& contents,
InputWindowDialog::Delegate* delegate);
virtual ~InputWindowDialogWebUI();
// InputWindowDialog methods
virtual void Show() OVERRIDE;
virtual void Close() OVERRIDE;
private:
// HtmlDialogUIDelegate methods
virtual bool IsDialogModal() const OVERRIDE;
virtual string16 GetDialogTitle() const OVERRIDE;
virtual GURL GetDialogContentURL() const OVERRIDE;
virtual void GetWebUIMessageHandlers(
std::vector<WebUIMessageHandler*>* handlers) const OVERRIDE;
virtual void GetDialogSize(gfx::Size* size) const OVERRIDE;
virtual std::string GetDialogArgs() const OVERRIDE;
virtual void OnDialogClosed(const std::string& json_retval) OVERRIDE;
virtual void OnCloseContents(TabContents* source,
bool* out_close_dialog) OVERRIDE;
virtual bool ShouldShowDialogTitle() const OVERRIDE;
// The dialog handler.
InputWindowDialogHandler* handler_;
string16 window_title_;
string16 label_;
string16 contents_;
bool closed_;
InputWindowDialog::Delegate* delegate_;
DISALLOW_COPY_AND_ASSIGN(InputWindowDialogWebUI);
};
// Dialog handler that handles calls from the JS WebUI code to validate the
// string value in the text field.
class InputWindowDialogHandler : public WebUIMessageHandler {
public:
explicit InputWindowDialogHandler(InputWindowDialog::Delegate* delegate);
void CloseDialog();
// Overridden from WebUIMessageHandler
virtual void RegisterMessages();
private:
void Validate(const base::ListValue* args);
InputWindowDialog::Delegate* delegate_;
DISALLOW_COPY_AND_ASSIGN(InputWindowDialogHandler);
};
#endif // CHROME_BROWSER_UI_WEBUI_INPUT_WINDOW_DIALOG_WEBUI_H_
......@@ -3093,7 +3093,9 @@
'browser/ui/gtk/web_intent_picker_gtk.cc',
'browser/ui/gtk/web_intent_picker_gtk.h',
'browser/ui/input_window_dialog.h',
'browser/ui/input_window_dialog_linux.cc',
'browser/ui/input_window_dialog_gtk.cc',
'browser/ui/input_window_dialog_gtk.h',
'browser/ui/input_window_dialog_win.cc',
'browser/ui/intents/web_intent_picker.h',
'browser/ui/intents/web_intent_picker_controller.cc',
......@@ -3694,6 +3696,10 @@
'browser/ui/webui/history2_ui.h',
'browser/ui/webui/history_ui.cc',
'browser/ui/webui/history_ui.h',
'browser/ui/webui/input_window_dialog_ui.cc',
'browser/ui/webui/input_window_dialog_ui.h',
'browser/ui/webui/input_window_dialog_webui.cc',
'browser/ui/webui/input_window_dialog_webui.h',
'browser/ui/webui/html_dialog_tab_contents_delegate.cc',
'browser/ui/webui/html_dialog_tab_contents_delegate.h',
'browser/ui/webui/html_dialog_ui.cc',
......
......@@ -50,6 +50,7 @@ const char kChromeUIHangURL[] = "chrome://hang/";
const char kChromeUIHistory2URL[] = "chrome://history2/";
const char kChromeUIHistoryURL[] = "chrome://history/";
const char kChromeUIHungRendererDialogURL[] = "chrome://hung-renderer/";
const char kChromeUIInputWindowDialogURL[] = "chrome://input-window-dialog/";
const char kChromeUIIPCURL[] = "chrome://ipc/";
const char kChromeUIKeyboardURL[] = "chrome://keyboard/";
const char kChromeUIKillURL[] = "chrome://kill/";
......@@ -146,6 +147,7 @@ const char kChromeUIHistogramsHost[] = "histograms";
const char kChromeUIHistory2Host[] = "history2";
const char kChromeUIHistoryHost[] = "history";
const char kChromeUIHungRendererDialogHost[] = "hung-renderer";
const char kChromeUIInputWindowDialogHost[] = "input-window-dialog";
const char kChromeUIIPCHost[] = "ipc";
const char kChromeUIKeyboardHost[] = "keyboard";
const char kChromeUIKillHost[] = "kill";
......
......@@ -45,6 +45,7 @@ extern const char kChromeUIHangURL[];
extern const char kChromeUIHistory2URL[];
extern const char kChromeUIHistoryURL[];
extern const char kChromeUIHungRendererDialogURL[];
extern const char kChromeUIInputWindowDialogURL[];
extern const char kChromeUIIPCURL[];
extern const char kChromeUIKeyboardURL[];
extern const char kChromeUIKillURL[];
......@@ -137,6 +138,7 @@ extern const char kChromeUIHistogramsHost[];
extern const char kChromeUIHistory2Host[];
extern const char kChromeUIHistoryHost[];
extern const char kChromeUIHungRendererDialogHost[];
extern const char kChromeUIInputWindowDialogHost[];
extern const char kChromeUIIPCHost[];
extern const char kChromeUIKeyboardHost[];
extern const char kChromeUIKillHost[];
......
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