diff options
author | stuartmorgan <stuartmorgan@chromium.org> | 2015-05-26 21:13:34 -0700 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2015-05-27 04:15:14 +0000 |
commit | a5df0663172d93a056cb74a034867c3f1e3b4a9b (patch) | |
tree | 1ac5bbb8fb572265dead41dd783015c5e8e8ede4 /ios | |
parent | 2eb910dffeee1b1ea0ffaff5eae81ea496155046 (diff) | |
download | chromium_src-a5df0663172d93a056cb74a034867c3f1e3b4a9b.zip chromium_src-a5df0663172d93a056cb74a034867c3f1e3b4a9b.tar.gz chromium_src-a5df0663172d93a056cb74a034867c3f1e3b4a9b.tar.bz2 |
Upstream the iOS web_shell and supporting code
This upstreams the iOS app/ and shell/ directories.
- app/ is equivalent to the content/ versions, and is heavily based on
that code.
- shell/ is the web_shell target, which is an incredibly stripped-down
browser build on ios/web, in the spirit of content_shell.
Currently web_shell is extremely minimal, but allows basic browsing to
test ios/web/.
BUG=464810
Review URL: https://codereview.chromium.org/1149323004
Cr-Commit-Position: refs/heads/master@{#331526}
Diffstat (limited to 'ios')
31 files changed, 2072 insertions, 0 deletions
diff --git a/ios/ios.gyp b/ios/ios.gyp index 84b5e95..4caf955 100644 --- a/ios/ios.gyp +++ b/ios/ios.gyp @@ -20,6 +20,7 @@ 'provider/ios_provider_web.gyp:*', 'testing/ios_testing.gyp:*', 'web/ios_web.gyp:*', + 'web/ios_web_shell.gyp:*', 'web/ios_web_unittests.gyp:*', ], }, diff --git a/ios/web/app/web_main.mm b/ios/web/app/web_main.mm new file mode 100644 index 0000000..5e5aa2b --- /dev/null +++ b/ios/web/app/web_main.mm @@ -0,0 +1,19 @@ +// 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 "ios/web/app/web_main_runner.h" +#include "ios/web/public/app/web_main.h" + +namespace web { + +WebMain::WebMain(const WebMainParams& params) { + web_main_runner_.reset(WebMainRunner::Create()); + web_main_runner_->Initialize(params); +} + +WebMain::~WebMain() { + web_main_runner_->ShutDown(); +} + +} // namespace web diff --git a/ios/web/app/web_main_loop.h b/ios/web/app/web_main_loop.h new file mode 100644 index 0000000..8fd9178 --- /dev/null +++ b/ios/web/app/web_main_loop.h @@ -0,0 +1,99 @@ +// 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 IOS_WEB_APP_WEB_MAIN_LOOP_H_ +#define IOS_WEB_APP_WEB_MAIN_LOOP_H_ + +#include "base/basictypes.h" +#include "base/memory/ref_counted.h" +#include "base/memory/scoped_ptr.h" + +namespace base { +class CommandLine; +class FilePath; +class MessageLoop; +class PowerMonitor; +class SystemMonitor; +} // namespace base + +namespace net { +class NetworkChangeNotifier; +} // namespace net + +namespace web { +class CookieNotificationBridge; +class WebMainParts; +class WebThreadImpl; + +// Implements the main web loop stages called from WebMainRunner. +// See comments in web_main_parts.h for additional info. +class WebMainLoop { + public: + explicit WebMainLoop(); + virtual ~WebMainLoop(); + + void Init(); + + void EarlyInitialization(); + void MainMessageLoopStart(); + + // Creates and starts running the tasks needed to complete startup. + void CreateStartupTasks(); + + // Performs the shutdown sequence, starting with PostMainMessageLoopRun + // through stopping threads to PostDestroyThreads. + void ShutdownThreadsAndCleanUp(); + + int GetResultCode() const { return result_code_; } + + private: + void InitializeMainThread(); + + // Called just before creating the threads + int PreCreateThreads(); + + // Creates all secondary threads. + int CreateThreads(); + + // Called right after the web threads have been started. + int WebThreadsStarted(); + + // Called just before attaching to the main message loop. + int PreMainMessageLoopRun(); + + // Members initialized on construction --------------------------------------- + int result_code_; + // True if the non-UI threads were created. + bool created_threads_; + + // Members initialized in |MainMessageLoopStart()| --------------------------- + scoped_ptr<base::MessageLoop> main_message_loop_; + scoped_ptr<base::SystemMonitor> system_monitor_; + scoped_ptr<base::PowerMonitor> power_monitor_; + scoped_ptr<net::NetworkChangeNotifier> network_change_notifier_; + + // Destroy parts_ before main_message_loop_ (required) and before other + // classes constructed in web (but after main_thread_). + scoped_ptr<WebMainParts> parts_; + + // Members initialized in |InitializeMainThread()| --------------------------- + // This must get destroyed before other threads that are created in parts_. + scoped_ptr<WebThreadImpl> main_thread_; + + // Members initialized in |RunMainMessageLoopParts()| ------------------------ + scoped_ptr<WebThreadImpl> db_thread_; + scoped_ptr<WebThreadImpl> file_user_blocking_thread_; + scoped_ptr<WebThreadImpl> file_thread_; + scoped_ptr<WebThreadImpl> cache_thread_; + scoped_ptr<WebThreadImpl> io_thread_; + + // Members initialized in |WebThreadsStarted()| -------------------------- + scoped_ptr<CookieNotificationBridge> cookie_notification_bridge_; + + DISALLOW_COPY_AND_ASSIGN(WebMainLoop); +}; + +} // namespace web + +#endif // IOS_WEB_APP_WEB_MAIN_LOOP_H_ diff --git a/ios/web/app/web_main_loop.mm b/ios/web/app/web_main_loop.mm new file mode 100644 index 0000000..b3300d4 --- /dev/null +++ b/ios/web/app/web_main_loop.mm @@ -0,0 +1,278 @@ +// 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 "ios/web/app/web_main_loop.h" + +#include "base/bind.h" +#include "base/command_line.h" +#include "base/logging.h" +#include "base/message_loop/message_loop.h" +#include "base/metrics/histogram.h" +#include "base/path_service.h" +#include "base/power_monitor/power_monitor.h" +#include "base/power_monitor/power_monitor_device_source.h" +#include "base/process/process_metrics.h" +#include "base/system_monitor/system_monitor.h" +#include "base/threading/thread_restrictions.h" +#include "crypto/nss_util.h" +#include "ios/web/net/cookie_notification_bridge.h" +#include "ios/web/public/app/web_main_parts.h" +#include "ios/web/public/web_client.h" +#include "ios/web/web_thread_impl.h" +#include "net/base/network_change_notifier.h" + +namespace web { + +// The currently-running WebMainLoop. There can be one or zero. +// TODO(rohitrao): Desktop uses this to implement +// ImmediateShutdownAndExitProcess. If we don't need that functionality, we can +// remove this. +WebMainLoop* g_current_web_main_loop = nullptr; + +WebMainLoop::WebMainLoop() : result_code_(0), created_threads_(false) { + DCHECK(!g_current_web_main_loop); + g_current_web_main_loop = this; +} + +WebMainLoop::~WebMainLoop() { + DCHECK_EQ(this, g_current_web_main_loop); + g_current_web_main_loop = nullptr; +} + +void WebMainLoop::Init() { + parts_.reset(web::GetWebClient()->CreateWebMainParts()); +} + +void WebMainLoop::EarlyInitialization() { + if (parts_) { + parts_->PreEarlyInitialization(); + } + +#if !defined(USE_OPENSSL) + // We want to be sure to init NSPR on the main thread. + crypto::EnsureNSPRInit(); +#endif // !defined(USE_OPENSSL) + + if (parts_) { + parts_->PostEarlyInitialization(); + } +} + +void WebMainLoop::MainMessageLoopStart() { + if (parts_) { + parts_->PreMainMessageLoopStart(); + } + + // Create a MessageLoop if one does not already exist for the current thread. + if (!base::MessageLoop::current()) { + main_message_loop_.reset(new base::MessageLoopForUI); + } + // Note: In Chrome, Attach() is called in + // ChromeBrowserMainPartsIOS::PreMainMessageLoopStart(). + base::MessageLoopForUI::current()->Attach(); + + InitializeMainThread(); + +#if 0 + // TODO(droger): SystemMonitor is not working properly on iOS. + // See http://crbug.com/228014. + system_monitor_.reset(new base::SystemMonitor); +#endif + // TODO(rohitrao): Do we need PowerMonitor on iOS, or can we get rid of it? + scoped_ptr<base::PowerMonitorSource> power_monitor_source( + new base::PowerMonitorDeviceSource()); + power_monitor_.reset(new base::PowerMonitor(power_monitor_source.Pass())); + network_change_notifier_.reset(net::NetworkChangeNotifier::Create()); + + if (parts_) { + parts_->PostMainMessageLoopStart(); + } +} + +void WebMainLoop::CreateStartupTasks() { + int result = 0; + result = PreCreateThreads(); + if (result > 0) + return; + + result = CreateThreads(); + if (result > 0) + return; + + result = WebThreadsStarted(); + if (result > 0) + return; + + result = PreMainMessageLoopRun(); + if (result > 0) + return; +} + +int WebMainLoop::PreCreateThreads() { + if (parts_) { + result_code_ = parts_->PreCreateThreads(); + } + + return result_code_; +} + +int WebMainLoop::CreateThreads() { + base::Thread::Options default_options; + base::Thread::Options io_message_loop_options; + io_message_loop_options.message_loop_type = base::MessageLoop::TYPE_IO; + base::Thread::Options ui_message_loop_options; + ui_message_loop_options.message_loop_type = base::MessageLoop::TYPE_UI; + + // Start threads in the order they occur in the WebThread::ID + // enumeration, except for WebThread::UI which is the main + // thread. + // + // Must be size_t so we can increment it. + for (size_t thread_id = WebThread::UI + 1; thread_id < WebThread::ID_COUNT; + ++thread_id) { + scoped_ptr<WebThreadImpl>* thread_to_start = nullptr; + base::Thread::Options* options = &default_options; + + switch (thread_id) { + // TODO(rohitrao): We probably do not need all of these threads. Remove + // the ones that serve no purpose. http://crbug.com/365909 + case WebThread::DB: + thread_to_start = &db_thread_; + break; + case WebThread::FILE_USER_BLOCKING: + thread_to_start = &file_user_blocking_thread_; + break; + case WebThread::FILE: + thread_to_start = &file_thread_; + options = &io_message_loop_options; + break; + case WebThread::CACHE: + thread_to_start = &cache_thread_; + options = &io_message_loop_options; + break; + case WebThread::IO: + thread_to_start = &io_thread_; + options = &io_message_loop_options; + break; + case WebThread::UI: + case WebThread::ID_COUNT: + default: + NOTREACHED(); + break; + } + + WebThread::ID id = static_cast<WebThread::ID>(thread_id); + + if (thread_to_start) { + (*thread_to_start).reset(new WebThreadImpl(id)); + (*thread_to_start)->StartWithOptions(*options); + } else { + NOTREACHED(); + } + } + created_threads_ = true; + return result_code_; +} + +int WebMainLoop::PreMainMessageLoopRun() { + if (parts_) { + parts_->PreMainMessageLoopRun(); + } + + // If the UI thread blocks, the whole UI is unresponsive. + // Do not allow disk IO from the UI thread. + base::ThreadRestrictions::SetIOAllowed(false); + base::ThreadRestrictions::DisallowWaiting(); + return result_code_; +} + +void WebMainLoop::ShutdownThreadsAndCleanUp() { + if (!created_threads_) { + // Called early, nothing to do + return; + } + + // Teardown may start in PostMainMessageLoopRun, and during teardown we + // need to be able to perform IO. + base::ThreadRestrictions::SetIOAllowed(true); + WebThread::PostTask( + WebThread::IO, FROM_HERE, + base::Bind(base::IgnoreResult(&base::ThreadRestrictions::SetIOAllowed), + true)); + + if (parts_) { + parts_->PostMainMessageLoopRun(); + } + + // Must be size_t so we can subtract from it. + for (size_t thread_id = WebThread::ID_COUNT - 1; + thread_id >= (WebThread::UI + 1); --thread_id) { + // Find the thread object we want to stop. Looping over all valid + // WebThread IDs and DCHECKing on a missing case in the switch + // statement helps avoid a mismatch between this code and the + // WebThread::ID enumeration. + // + // The destruction order is the reverse order of occurrence in the + // WebThread::ID list. The rationale for the order is as + // follows (need to be filled in a bit): + // + // + // - The IO thread is the only user of the CACHE thread. + // + // - (Not sure why DB stops last.) + switch (thread_id) { + case WebThread::DB: + db_thread_.reset(); + break; + case WebThread::FILE_USER_BLOCKING: + file_user_blocking_thread_.reset(); + break; + case WebThread::FILE: + file_thread_.reset(); + break; + case WebThread::CACHE: + cache_thread_.reset(); + break; + case WebThread::IO: + io_thread_.reset(); + break; + case WebThread::UI: + case WebThread::ID_COUNT: + default: + NOTREACHED(); + break; + } + } + + // Close the blocking I/O pool after the other threads. Other threads such + // as the I/O thread may need to schedule work like closing files or flushing + // data during shutdown, so the blocking pool needs to be available. There + // may also be slow operations pending that will block shutdown, so closing + // it here (which will block until required operations are complete) gives + // more head start for those operations to finish. + WebThreadImpl::ShutdownThreadPool(); + + if (parts_) { + parts_->PostDestroyThreads(); + } +} + +void WebMainLoop::InitializeMainThread() { + const char* kThreadName = "CrWebMain"; + base::PlatformThread::SetName(kThreadName); + if (main_message_loop_) { + main_message_loop_->set_thread_name(kThreadName); + } + + // Register the main thread by instantiating it, but don't call any methods. + main_thread_.reset( + new WebThreadImpl(WebThread::UI, base::MessageLoop::current())); +} + +int WebMainLoop::WebThreadsStarted() { + cookie_notification_bridge_.reset(new CookieNotificationBridge); + return result_code_; +} + +} // namespace web diff --git a/ios/web/app/web_main_runner.h b/ios/web/app/web_main_runner.h new file mode 100644 index 0000000..c0c3c6f --- /dev/null +++ b/ios/web/app/web_main_runner.h @@ -0,0 +1,29 @@ +// 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 IOS_WEB_APP_WEB_MAIN_RUNNER_H_ +#define IOS_WEB_APP_WEB_MAIN_RUNNER_H_ + +#include "ios/web/public/app/web_main.h" + +namespace web { + +// This class is responsible for web initialization and shutdown. +class WebMainRunner { + public: + virtual ~WebMainRunner() {} + + // Create a new WebMainRunner object. + static WebMainRunner* Create(); + + // Initialize all necessary web state. + virtual int Initialize(const WebMainParams& params) = 0; + + // Shut down the web state. + virtual void ShutDown() = 0; +}; + +} // namespace web + +#endif // IOS_WEB_APP_WEB_MAIN_RUNNER_H_ diff --git a/ios/web/app/web_main_runner.mm b/ios/web/app/web_main_runner.mm new file mode 100644 index 0000000..ff50552 --- /dev/null +++ b/ios/web/app/web_main_runner.mm @@ -0,0 +1,133 @@ +// 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 "ios/web/app/web_main_runner.h" + +#include "base/at_exit.h" +#include "base/command_line.h" +#include "base/i18n/icu_util.h" +#include "base/logging.h" +#include "base/metrics/statistics_recorder.h" +#include "ios/web/app/web_main_loop.h" +#include "ios/web/public/web_client.h" +#include "ui/base/ui_base_paths.h" + +namespace web { + +class WebMainRunnerImpl : public WebMainRunner { + public: + WebMainRunnerImpl() + : is_initialized_(false), + is_shutdown_(false), + completed_basic_startup_(false), + delegate_(nullptr) {} + + ~WebMainRunnerImpl() override { + if (is_initialized_ && !is_shutdown_) { + ShutDown(); + } + } + + int Initialize(const WebMainParams& params) override { + //////////////////////////////////////////////////////////////////////// + // ContentMainRunnerImpl::Initialize() + // + is_initialized_ = true; + delegate_ = params.delegate; + + // TODO(rohitrao): Chrome for iOS initializes this in main(), because it's + // needed for breakpad. Are we really going to require that all embedders + // initialize an AtExitManager in main()? + exit_manager_.reset(new base::AtExitManager); + + // There is no way to pass commandline flags to process on iOS, so the + // CommandLine is always initialized empty. Embedders can add switches in + // |BasicStartupComplete|. + base::CommandLine::Init(0, nullptr); + if (delegate_) { + delegate_->BasicStartupComplete(); + } + completed_basic_startup_ = true; + + // TODO(rohitrao): Should we instead require that all embedders call + // SetWebClient()? + if (!GetWebClient()) + SetWebClient(&empty_web_client_); + +#if defined(USE_NSS) + crypto::EarlySetupForNSSInit(); +#endif + + // TODO(rohitrao): Desktop calls content::RegisterContentSchemes(true) here. + // Do we need similar scheme registration on iOS? + ui::RegisterPathProvider(); + + CHECK(base::i18n::InitializeICU()); + + //////////////////////////////////////////////////////////// + // BrowserMainRunnerImpl::Initialize() + base::StatisticsRecorder::Initialize(); + + main_loop_.reset(new WebMainLoop()); + main_loop_->Init(); + main_loop_->EarlyInitialization(); + main_loop_->MainMessageLoopStart(); + main_loop_->CreateStartupTasks(); + int result_code = main_loop_->GetResultCode(); + if (result_code > 0) + return result_code; + + // Return -1 to indicate no early termination. + return -1; + } + + void ShutDown() override { + //////////////////////////////////////////////////////////////////// + // BrowserMainRunner::Shutdown() + // + DCHECK(is_initialized_); + DCHECK(!is_shutdown_); + main_loop_->ShutdownThreadsAndCleanUp(); + main_loop_.reset(nullptr); + + //////////////////////////////////////////////////////////////////// + // ContentMainRunner::Shutdown() + // + if (completed_basic_startup_ && delegate_) { + delegate_->ProcessExiting(); + } + + exit_manager_.reset(nullptr); + delegate_ = nullptr; + is_shutdown_ = true; + } + + protected: + // True if we have started to initialize the runner. + bool is_initialized_; + + // True if the runner has been shut down. + bool is_shutdown_; + + // True if basic startup was completed. + bool completed_basic_startup_; + + // The delegate will outlive this object. + WebMainDelegate* delegate_; + + // Used if the embedder doesn't set one. + WebClient empty_web_client_; + + scoped_ptr<base::AtExitManager> exit_manager_; + scoped_ptr<WebMainLoop> main_loop_; + + DISALLOW_COPY_AND_ASSIGN(WebMainRunnerImpl); +}; + +// static +WebMainRunner* WebMainRunner::Create() { + return new WebMainRunnerImpl(); +} + +} // namespace web diff --git a/ios/web/ios_web.gyp b/ios/web/ios_web.gyp index 030d9ada..d5ab122 100644 --- a/ios/web/ios_web.gyp +++ b/ios/web/ios_web.gyp @@ -7,6 +7,35 @@ 'chromium_code': 1, }, 'targets': [ + { + 'target_name': 'ios_web_app', + 'type': 'static_library', + 'include_dirs': [ + '../..', + ], + 'dependencies': [ + 'ios_web', + 'ios_web_thread', + '../../base/base.gyp:base', + '../../base/base.gyp:base_i18n', + '../../crypto/crypto.gyp:crypto', + '../../net/net.gyp:net', + '../../ui/base/ui_base.gyp:ui_base', + '../../ui/gfx/gfx.gyp:gfx', + '../../ui/gfx/gfx.gyp:gfx_geometry', + ], + 'sources': [ + 'app/web_main.mm', + 'app/web_main_loop.h', + 'app/web_main_loop.mm', + 'app/web_main_runner.h', + 'app/web_main_runner.mm', + 'public/app/web_main.h', + 'public/app/web_main_delegate.h', + 'public/app/web_main_parts.h', + 'public/app/web_main_parts.mm', + ], + }, # Note: any embedder using ios_web will for now need to include either # ios_web_thread (any new embedder) or ios_web_content_thread_shim (Chrome). # This will become unnecessary once Chrome switches to using ios_web_thread, diff --git a/ios/web/ios_web_shell.gyp b/ios/web/ios_web_shell.gyp new file mode 100644 index 0000000..51de8889 --- /dev/null +++ b/ios/web/ios_web_shell.gyp @@ -0,0 +1,66 @@ +# 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. + +{ + 'variables': { + 'chromium_code': 1, + }, + 'targets': [ + { + 'target_name': 'ios_web_shell', + 'type': 'executable', + 'mac_bundle': 1, + 'include_dirs': [ + '../..', + ], + 'dependencies': [ + 'ios_web.gyp:ios_web', + 'ios_web.gyp:ios_web_app', + '../../base/base.gyp:base', + '../../net/net.gyp:net', + '../../ui/base/ui_base.gyp:ui_base', + ], + 'xcode_settings': { + 'INFOPLIST_FILE': 'shell/Info.plist', + 'OTHER_LDFLAGS': [ + '-Xlinker -objc_abi_version -Xlinker 2' + ] + }, + 'sources': [ + 'shell/app_delegate.h', + 'shell/app_delegate.mm', + 'shell/shell_browser_state.h', + 'shell/shell_browser_state.mm', + 'shell/shell_main_delegate.h', + 'shell/shell_main_delegate.mm', + 'shell/shell_network_delegate.cc', + 'shell/shell_network_delegate.h', + 'shell/shell_url_request_context_getter.cc', + 'shell/shell_url_request_context_getter.h', + 'shell/shell_web_client.h', + 'shell/shell_web_client.mm', + 'shell/shell_web_main_parts.h', + 'shell/shell_web_main_parts.mm', + 'shell/view_controller.h', + 'shell/view_controller.mm', + 'shell/web_exe_main.mm', + ], + 'mac_bundle_resources': [ + 'shell/Default.png', + 'shell/MainView.xib', + 'shell/textfield_background@2x.png', + 'shell/toolbar_back@2x.png', + 'shell/toolbar_forward@2x.png', + ], + 'link_settings': { + 'libraries': [ + '$(SDKROOT)/System/Library/Frameworks/CoreGraphics.framework', + '$(SDKROOT)/System/Library/Frameworks/CoreFoundation.framework', + '$(SDKROOT)/System/Library/Frameworks/Foundation.framework', + '$(SDKROOT)/System/Library/Frameworks/UIKit.framework', + ], + }, + }, + ], +} diff --git a/ios/web/public/app/web_main.h b/ios/web/public/app/web_main.h new file mode 100644 index 0000000..b5d651c --- /dev/null +++ b/ios/web/public/app/web_main.h @@ -0,0 +1,39 @@ +// 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 IOS_WEB_PUBLIC_APP_WEB_MAIN_H_ +#define IOS_WEB_PUBLIC_APP_WEB_MAIN_H_ + +#include "base/memory/scoped_ptr.h" +#include "ios/web/public/app/web_main_delegate.h" + +namespace web { +class WebMainRunner; + +// Contains parameters passed to WebMain. +struct WebMainParams { + explicit WebMainParams(WebMainDelegate* delegate) : delegate(delegate) {} + + WebMainDelegate* delegate; +}; + +// Encapsulates any setup and initialization that is needed by common +// web/ code. A single instance of this object should be created during app +// startup (or shortly after launch), and clients must ensure that this object +// is not destroyed while web/ code is still on the stack. +// +// Clients can add custom code to the startup flow by implementing the methods +// in WebMainDelegate and WebMainParts. +class WebMain { + public: + explicit WebMain(const WebMainParams& params); + ~WebMain(); + + private: + scoped_ptr<WebMainRunner> web_main_runner_; +}; + +} // namespace web + +#endif // IOS_WEB_PUBLIC_APP_WEB_MAIN_H_ diff --git a/ios/web/public/app/web_main_delegate.h b/ios/web/public/app/web_main_delegate.h new file mode 100644 index 0000000..f462384c --- /dev/null +++ b/ios/web/public/app/web_main_delegate.h @@ -0,0 +1,30 @@ +// 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 IOS_WEB_PUBLIC_APP_WEB_MAIN_DELEGATE_H_ +#define IOS_WEB_PUBLIC_APP_WEB_MAIN_DELEGATE_H_ + +namespace web { + +// Contains delegate hooks that allow a web/ embedder to customize the basic +// startup and shutdown flow. This delegate is called very early in startup and +// very late in shutdown, so only minimal code should be run in its +// implementation. WebMainParts will be a more appropriate place for most +// startup code. +class WebMainDelegate { + public: + virtual ~WebMainDelegate() {} + + // Tells the embedder that the absolute basic startup has been done, i.e. + // it's now safe to create singletons and check the command line. + virtual void BasicStartupComplete() {} + + // Called right before the process exits. + // TODO(rohitrao): This may not be used for anything. Remove if useless. + virtual void ProcessExiting() {} +}; + +} // namespace web + +#endif // IOS_WEB_PUBLIC_APP_WEB_MAIN_DELEGATE_H_ diff --git a/ios/web/public/app/web_main_parts.h b/ios/web/public/app/web_main_parts.h new file mode 100644 index 0000000..166e9b3 --- /dev/null +++ b/ios/web/public/app/web_main_parts.h @@ -0,0 +1,78 @@ +// 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 IOS_WEB_PUBLIC_APP_WEB_MAIN_PARTS_H_ +#define IOS_WEB_PUBLIC_APP_WEB_MAIN_PARTS_H_ + +#include "base/basictypes.h" + +namespace web { + +// This class contains different "stages" to be executed by |WebMain()|. +// Each stage is represented by a single WebMainParts method, called from +// the corresponding method in |WebMainLoop| (e.g., EarlyInitialization()) +// which does the following: +// - calls a method (e.g., "PreEarlyInitialization()") which implements +// platform / tookit specific code for that stage. +// - calls various methods for things common to all platforms (for that stage). +// - calls a method (e.g., "PostEarlyInitialization()") for platform-specific +// code to be called after the common code. +// +// Stages: +// - EarlyInitialization: things which should be done as soon as possible on +// program start (such as setting up signal handlers) and things to be done +// at some generic time before the start of the main message loop. +// - MainMessageLoopStart: things beginning with the start of the main message +// loop and ending with initialization of the main thread; things which +// should be done immediately before the start of the main message loop +// should go in |PreMainMessageLoopStart()|. +// - RunMainMessageLoopParts: things to be done before and after invoking the +// main message loop run method (e.g. MessageLoopForUI::current()->Run()). +// +// How to add stuff (to existing parts): +// - Figure out when your new code should be executed. What must happen +// before/after your code is executed? Are there performance reasons for +// running your code at a particular time? Document these things! +// - Unless your new code is just one or two lines, put it into a separate +// method with a well-defined purpose. (Likewise, if you're adding to an +// existing chunk which makes it longer than one or two lines, please move +// the code out into a separate method.) +// +class WebMainParts { + public: + WebMainParts() {} + virtual ~WebMainParts() {} + + virtual void PreEarlyInitialization() {} + + virtual void PostEarlyInitialization() {} + + virtual void PreMainMessageLoopStart() {} + + virtual void PostMainMessageLoopStart() {} + + // Called just before any child threads owned by the web + // framework are created. + // + // The main message loop has been started at this point (but has not + // been run), and the toolkit has been initialized. Returns the error code + // (or 0 if no error). + virtual int PreCreateThreads(); + + // This is called just before the main message loop is run. The + // various browser threads have all been created at this point + virtual void PreMainMessageLoopRun() {} + + // This happens after the main message loop has stopped, but before + // threads are stopped. + virtual void PostMainMessageLoopRun() {} + + // Called as the very last part of shutdown, after threads have been + // stopped and destroyed. + virtual void PostDestroyThreads() {} +}; + +} // namespace web + +#endif // IOS_WEB_PUBLIC_APP_WEB_MAIN_PARTS_H_ diff --git a/ios/web/public/app/web_main_parts.mm b/ios/web/public/app/web_main_parts.mm new file mode 100644 index 0000000..541cc36 --- /dev/null +++ b/ios/web/public/app/web_main_parts.mm @@ -0,0 +1,13 @@ +// 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 "ios/web/public/app/web_main_parts.h" + +namespace web { + +int WebMainParts::PreCreateThreads() { + return 0; +} + +} // namespace web diff --git a/ios/web/shell/Info.plist b/ios/web/shell/Info.plist new file mode 100644 index 0000000..5740b88 --- /dev/null +++ b/ios/web/shell/Info.plist @@ -0,0 +1,121 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> +<plist version="1.0"> +<dict> + <key>CFBundleDevelopmentRegion</key> + <string>en</string> + <key>CFBundleDisplayName</key> + <string>${PRODUCT_NAME}</string> + <key>CFBundleExecutable</key> + <string>${EXECUTABLE_NAME}</string> + <key>CFBundleIdentifier</key> + <string>org.chromium.${PRODUCT_NAME:rfc1034identifier}</string> + <key>CFBundleInfoDictionaryVersion</key> + <string>6.0</string> + <key>CFBundleName</key> + <string>${PRODUCT_NAME}</string> + <key>CFBundlePackageType</key> + <string>APPL</string> + <key>CFBundleShortVersionString</key> + <string>1.0</string> + <key>CFBundleSignature</key> + <string>????</string> + <key>CFBundleVersion</key> + <string>1.0</string> + <key>LSRequiresIPhoneOS</key> + <true/> + <key>UIRequiredDeviceCapabilities</key> + <array> + <string>armv7</string> + </array> + <key>UILaunchImages</key> + <array> + <dict> + <key>UILaunchImageMinimumOSVersion</key> + <string>7.0</string> + <key>UILaunchImageName</key> + <string>Default</string> + <key>UILaunchImageOrientation</key> + <string>Portrait</string> + <key>UILaunchImageSize</key> + <string>{320, 480}</string> + </dict> + <dict> + <key>UILaunchImageMinimumOSVersion</key> + <string>7.0</string> + <key>UILaunchImageName</key> + <string>Default</string> + <key>UILaunchImageOrientation</key> + <string>Portrait</string> + <key>UILaunchImageSize</key> + <string>{320, 568}</string> + </dict> + <dict> + <key>UILaunchImageMinimumOSVersion</key> + <string>8.0</string> + <key>UILaunchImageName</key> + <string>Default</string> + <key>UILaunchImageOrientation</key> + <string>Portrait</string> + <key>UILaunchImageSize</key> + <string>{375, 667}</string> + </dict> + <dict> + <key>UILaunchImageMinimumOSVersion</key> + <string>8.0</string> + <key>UILaunchImageName</key> + <string>Default</string> + <key>UILaunchImageOrientation</key> + <string>Portrait</string> + <key>UILaunchImageSize</key> + <string>{414, 736}</string> + </dict> + <dict> + <key>UILaunchImageMinimumOSVersion</key> + <string>8.0</string> + <key>UILaunchImageName</key> + <string>Default</string> + <key>UILaunchImageOrientation</key> + <string>Landscape</string> + <key>UILaunchImageSize</key> + <string>{414, 736}</string> + </dict> + </array> + <key>UILaunchImages~ipad</key> + <array> + <dict> + <key>UILaunchImageMinimumOSVersion</key> + <string>7.0</string> + <key>UILaunchImageName</key> + <string>Default</string> + <key>UILaunchImageOrientation</key> + <string>Portrait</string> + <key>UILaunchImageSize</key> + <string>{768, 1024}</string> + </dict> + <dict> + <key>UILaunchImageMinimumOSVersion</key> + <string>7.0</string> + <key>UILaunchImageName</key> + <string>Default</string> + <key>UILaunchImageOrientation</key> + <string>Landscape</string> + <key>UILaunchImageSize</key> + <string>{768, 1024}</string> + </dict> + </array> + <key>UISupportedInterfaceOrientations</key> + <array> + <string>UIInterfaceOrientationPortrait</string> + <string>UIInterfaceOrientationLandscapeLeft</string> + <string>UIInterfaceOrientationLandscapeRight</string> + </array> + <key>UISupportedInterfaceOrientations~ipad</key> + <array> + <string>UIInterfaceOrientationPortrait</string> + <string>UIInterfaceOrientationPortraitUpsideDown</string> + <string>UIInterfaceOrientationLandscapeLeft</string> + <string>UIInterfaceOrientationLandscapeRight</string> + </array> +</dict> +</plist> diff --git a/ios/web/shell/MainView.xib b/ios/web/shell/MainView.xib new file mode 100644 index 0000000..00cea73 --- /dev/null +++ b/ios/web/shell/MainView.xib @@ -0,0 +1,43 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="5053" systemVersion="13D65" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none"> + <dependencies> + <deployment version="1552" identifier="iOS"/> + <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="3733"/> + </dependencies> + <objects> + <placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner" customClass="ViewController"> + <connections> + <outlet property="containerView" destination="HS4-2y-YS7" id="KRU-Lk-zhW"/> + <outlet property="toolbarView" destination="Mtt-2S-TM5" id="Ngt-zy-T1l"/> + <outlet property="view" destination="iN0-l3-epB" id="0A6-5l-qvv"/> + </connections> + </placeholder> + <placeholder placeholderIdentifier="IBFirstResponder" id="-2" customClass="UIResponder"/> + <view contentMode="scaleToFill" id="iN0-l3-epB"> + <rect key="frame" x="0.0" y="0.0" width="320" height="568"/> + <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/> + <subviews> + <toolbar opaque="NO" clearsContextBeforeDrawing="NO" contentMode="scaleToFill" id="Mtt-2S-TM5"> + <rect key="frame" x="0.0" y="20" width="320" height="44"/> + <autoresizingMask key="autoresizingMask" widthSizable="YES" flexibleMaxY="YES"/> + <inset key="insetFor6xAndEarlier" minX="0.0" minY="20" maxX="0.0" maxY="-20"/> + <items/> + <color key="barTintColor" red="0.33725490196078434" green="0.46666666666666667" blue="0.9882352941176471" alpha="1" colorSpace="calibratedRGB"/> + <connections> + <outlet property="delegate" destination="-1" id="80Y-wy-gHw"/> + </connections> + </toolbar> + <view contentMode="scaleToFill" id="HS4-2y-YS7"> + <rect key="frame" x="0.0" y="64" width="320" height="504"/> + <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/> + <color key="backgroundColor" white="0.66666666666666663" alpha="1" colorSpace="calibratedWhite"/> + <inset key="insetFor6xAndEarlier" minX="0.0" minY="20" maxX="0.0" maxY="0.0"/> + </view> + </subviews> + <color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="calibratedWhite"/> + <simulatedStatusBarMetrics key="simulatedStatusBarMetrics"/> + <simulatedScreenMetrics key="simulatedDestinationMetrics" type="retina4"/> + <inset key="insetFor6xAndEarlier" minX="0.0" minY="0.0" maxX="0.0" maxY="-20"/> + </view> + </objects> +</document> diff --git a/ios/web/shell/app_delegate.h b/ios/web/shell/app_delegate.h new file mode 100644 index 0000000..fba25e8 --- /dev/null +++ b/ios/web/shell/app_delegate.h @@ -0,0 +1,16 @@ +// 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 IOS_WEB_SHELL_APP_DELEGATE_H_ +#define IOS_WEB_SHELL_APP_DELEGATE_H_ + +#import <UIKit/UIKit.h> + +@interface AppDelegate : UIResponder<UIApplicationDelegate> + +@property(nonatomic, retain) UIWindow* window; + +@end + +#endif // IOS_WEB_SHELL_APP_DELEGATE_H_ diff --git a/ios/web/shell/app_delegate.mm b/ios/web/shell/app_delegate.mm new file mode 100644 index 0000000..0bba03c --- /dev/null +++ b/ios/web/shell/app_delegate.mm @@ -0,0 +1,64 @@ +// 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 "ios/web/shell/app_delegate.h" + +#import "base/mac/scoped_nsobject.h" +#include "base/memory/scoped_ptr.h" +#include "ios/web/public/app/web_main.h" +#include "ios/web/public/web_client.h" +#include "ios/web/public/web_state/web_state.h" +#include "ios/web/shell/shell_browser_state.h" +#include "ios/web/shell/shell_main_delegate.h" +#include "ios/web/shell/shell_web_client.h" +#import "ios/web/shell/view_controller.h" + +@interface AppDelegate () { + scoped_ptr<web::ShellMainDelegate> _delegate; + scoped_ptr<web::WebMain> _webMain; +} +@end + +@implementation AppDelegate + +@synthesize window = _window; + +- (BOOL)application:(UIApplication*)application + didFinishLaunchingWithOptions:(NSDictionary*)launchOptions { + _window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]]; + self.window.backgroundColor = [UIColor whiteColor]; + + _delegate.reset(new web::ShellMainDelegate()); + web::WebMainParams params(_delegate.get()); + _webMain.reset(new web::WebMain(params)); + + web::ShellWebClient* client = + static_cast<web::ShellWebClient*>(web::GetWebClient()); + web::BrowserState* browserState = client->browser_state(); + + base::scoped_nsobject<ViewController> controller( + [[ViewController alloc] initWithBrowserState:browserState]); + self.window.rootViewController = controller; + [self.window makeKeyAndVisible]; + return YES; +} + +- (void)applicationWillResignActive:(UIApplication*)application { +} + +- (void)applicationDidEnterBackground:(UIApplication*)application { +} + +- (void)applicationWillEnterForeground:(UIApplication*)application { +} + +- (void)applicationDidBecomeActive:(UIApplication*)application { +} + +- (void)applicationWillTerminate:(UIApplication*)application { + _webMain.reset(); + _delegate.reset(); +} + +@end diff --git a/ios/web/shell/shell_browser_state.h b/ios/web/shell/shell_browser_state.h new file mode 100644 index 0000000..f08121d --- /dev/null +++ b/ios/web/shell/shell_browser_state.h @@ -0,0 +1,41 @@ +// 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 IOS_WEB_SHELL_SHELL_BROWSER_STATE_H_ +#define IOS_WEB_SHELL_SHELL_BROWSER_STATE_H_ + +#include "ios/web/public/browser_state.h" + +#include "base/files/file_path.h" +#include "base/macros.h" +#include "base/memory/ref_counted.h" +#include "base/memory/scoped_ptr.h" + +namespace web { + +class ShellBrowserContext; +class ShellURLRequestContextGetter; + +// Shell-specific implementation of BrowserState. Can only be called from the +// UI thread. +class ShellBrowserState : public BrowserState { + public: + ShellBrowserState(); + ~ShellBrowserState() override; + + // BrowserState implementation. + bool IsOffTheRecord() const override; + base::FilePath GetStatePath() const override; + net::URLRequestContextGetter* GetRequestContext() override; + + private: + base::FilePath path_; + scoped_refptr<ShellURLRequestContextGetter> request_context_getter_; + + DISALLOW_COPY_AND_ASSIGN(ShellBrowserState); +}; + +} // namespace web + +#endif // IOS_WEB_SHELL_SHELL_BROWSER_STATE_H_ diff --git a/ios/web/shell/shell_browser_state.mm b/ios/web/shell/shell_browser_state.mm new file mode 100644 index 0000000..4702b1b --- /dev/null +++ b/ios/web/shell/shell_browser_state.mm @@ -0,0 +1,43 @@ +// 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 "ios/web/shell/shell_browser_state.h" + +#include "base/base_paths.h" +#include "base/files/file_path.h" +#include "base/memory/scoped_ptr.h" +#include "base/message_loop/message_loop.h" +#include "base/path_service.h" +#include "base/threading/thread_restrictions.h" +#include "ios/web/public/web_thread.h" +#include "ios/web/shell/shell_url_request_context_getter.h" + +namespace web { + +ShellBrowserState::ShellBrowserState() : BrowserState() { + CHECK(PathService::Get(base::DIR_APP_DATA, &path_)); + + request_context_getter_ = new ShellURLRequestContextGetter( + GetStatePath(), + web::WebThread::GetMessageLoopProxyForThread(web::WebThread::IO), + web::WebThread::GetMessageLoopProxyForThread(web::WebThread::FILE), + web::WebThread::GetMessageLoopProxyForThread(web::WebThread::CACHE)); +} + +ShellBrowserState::~ShellBrowserState() { +} + +bool ShellBrowserState::IsOffTheRecord() const { + return false; +} + +base::FilePath ShellBrowserState::GetStatePath() const { + return path_; +} + +net::URLRequestContextGetter* ShellBrowserState::GetRequestContext() { + return request_context_getter_.get(); +} + +} // namespace web diff --git a/ios/web/shell/shell_main_delegate.h b/ios/web/shell/shell_main_delegate.h new file mode 100644 index 0000000..1bfd9bd --- /dev/null +++ b/ios/web/shell/shell_main_delegate.h @@ -0,0 +1,29 @@ +// 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 IOS_WEB_SHELL_SHELL_MAIN_DELEGATE_H_ +#define IOS_WEB_SHELL_SHELL_MAIN_DELEGATE_H_ + +#include "base/basictypes.h" +#include "base/compiler_specific.h" +#include "base/memory/scoped_ptr.h" +#include "ios/web/public/app/web_main_delegate.h" + +namespace web { +class ShellWebClient; + +class ShellMainDelegate : public WebMainDelegate { + public: + ShellMainDelegate(); + ~ShellMainDelegate() override; + + void BasicStartupComplete() override; + + private: + scoped_ptr<ShellWebClient> web_client_; +}; + +} // namespace web + +#endif // IOS_WEB_SHELL_SHELL_MAIN_DELEGATE_H_ diff --git a/ios/web/shell/shell_main_delegate.mm b/ios/web/shell/shell_main_delegate.mm new file mode 100644 index 0000000..97db23d --- /dev/null +++ b/ios/web/shell/shell_main_delegate.mm @@ -0,0 +1,22 @@ +// 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 "ios/web/shell/shell_main_delegate.h" + +#include "ios/web/shell/shell_web_client.h" + +namespace web { + +ShellMainDelegate::ShellMainDelegate() { +} + +ShellMainDelegate::~ShellMainDelegate() { +} + +void ShellMainDelegate::BasicStartupComplete() { + web_client_.reset(new ShellWebClient()); + web::SetWebClient(web_client_.get()); +} + +} // namespace web diff --git a/ios/web/shell/shell_network_delegate.cc b/ios/web/shell/shell_network_delegate.cc new file mode 100644 index 0000000..a973f4c --- /dev/null +++ b/ios/web/shell/shell_network_delegate.cc @@ -0,0 +1,95 @@ +// 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 "ios/web/shell/shell_network_delegate.h" + +#include "net/base/net_errors.h" + +namespace web { + +ShellNetworkDelegate::ShellNetworkDelegate() { +} + +ShellNetworkDelegate::~ShellNetworkDelegate() { +} + +int ShellNetworkDelegate::OnBeforeURLRequest( + net::URLRequest* request, + const net::CompletionCallback& callback, + GURL* new_url) { + return net::OK; +} + +int ShellNetworkDelegate::OnBeforeSendHeaders( + net::URLRequest* request, + const net::CompletionCallback& callback, + net::HttpRequestHeaders* headers) { + return net::OK; +} + +void ShellNetworkDelegate::OnSendHeaders( + net::URLRequest* request, + const net::HttpRequestHeaders& headers) { +} + +int ShellNetworkDelegate::OnHeadersReceived( + net::URLRequest* request, + const net::CompletionCallback& callback, + const net::HttpResponseHeaders* original_response_headers, + scoped_refptr<net::HttpResponseHeaders>* override_response_headers, + GURL* allowed_unsafe_redirect_url) { + return net::OK; +} + +void ShellNetworkDelegate::OnBeforeRedirect(net::URLRequest* request, + const GURL& new_location) { +} + +void ShellNetworkDelegate::OnResponseStarted(net::URLRequest* request) { +} + +void ShellNetworkDelegate::OnRawBytesRead(const net::URLRequest& request, + int bytes_read) { +} + +void ShellNetworkDelegate::OnCompleted(net::URLRequest* request, bool started) { +} + +void ShellNetworkDelegate::OnURLRequestDestroyed(net::URLRequest* request) { +} + +void ShellNetworkDelegate::OnPACScriptError(int line_number, + const base::string16& error) { +} + +ShellNetworkDelegate::AuthRequiredResponse ShellNetworkDelegate::OnAuthRequired( + net::URLRequest* request, + const net::AuthChallengeInfo& auth_info, + const AuthCallback& callback, + net::AuthCredentials* credentials) { + return AUTH_REQUIRED_RESPONSE_NO_ACTION; +} + +bool ShellNetworkDelegate::OnCanGetCookies(const net::URLRequest& request, + const net::CookieList& cookie_list) { + return true; +} + +bool ShellNetworkDelegate::OnCanSetCookie(const net::URLRequest& request, + const std::string& cookie_line, + net::CookieOptions* options) { + return true; +} + +bool ShellNetworkDelegate::OnCanAccessFile(const net::URLRequest& request, + const base::FilePath& path) const { + return true; +} + +bool ShellNetworkDelegate::OnCanThrottleRequest( + const net::URLRequest& request) const { + return false; +} + +} // namespace web diff --git a/ios/web/shell/shell_network_delegate.h b/ios/web/shell/shell_network_delegate.h new file mode 100644 index 0000000..70f0f21 --- /dev/null +++ b/ios/web/shell/shell_network_delegate.h @@ -0,0 +1,61 @@ +// 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 IOS_WEB_SHELL_SHELL_NETWORK_DELEGATE_H_ +#define IOS_WEB_SHELL_SHELL_NETWORK_DELEGATE_H_ + +#include "base/basictypes.h" +#include "base/compiler_specific.h" +#include "net/base/network_delegate_impl.h" + +namespace web { + +class ShellNetworkDelegate : public net::NetworkDelegateImpl { + public: + ShellNetworkDelegate(); + ~ShellNetworkDelegate() override; + + private: + // net::NetworkDelegate implementation. + int OnBeforeURLRequest(net::URLRequest* request, + const net::CompletionCallback& callback, + GURL* new_url) override; + int OnBeforeSendHeaders(net::URLRequest* request, + const net::CompletionCallback& callback, + net::HttpRequestHeaders* headers) override; + void OnSendHeaders(net::URLRequest* request, + const net::HttpRequestHeaders& headers) override; + int OnHeadersReceived( + net::URLRequest* request, + const net::CompletionCallback& callback, + const net::HttpResponseHeaders* original_response_headers, + scoped_refptr<net::HttpResponseHeaders>* override_response_headers, + GURL* allowed_unsafe_redirect_url) override; + void OnBeforeRedirect(net::URLRequest* request, + const GURL& new_location) override; + void OnResponseStarted(net::URLRequest* request) override; + void OnRawBytesRead(const net::URLRequest& request, int bytes_read) override; + void OnCompleted(net::URLRequest* request, bool started) override; + void OnURLRequestDestroyed(net::URLRequest* request) override; + void OnPACScriptError(int line_number, const base::string16& error) override; + AuthRequiredResponse OnAuthRequired( + net::URLRequest* request, + const net::AuthChallengeInfo& auth_info, + const AuthCallback& callback, + net::AuthCredentials* credentials) override; + bool OnCanGetCookies(const net::URLRequest& request, + const net::CookieList& cookie_list) override; + bool OnCanSetCookie(const net::URLRequest& request, + const std::string& cookie_line, + net::CookieOptions* options) override; + bool OnCanAccessFile(const net::URLRequest& request, + const base::FilePath& path) const override; + bool OnCanThrottleRequest(const net::URLRequest& request) const override; + + DISALLOW_COPY_AND_ASSIGN(ShellNetworkDelegate); +}; + +} // namespace web + +#endif // IOS_WEB_SHELL_SHELL_NETWORK_DELEGATE_H_ diff --git a/ios/web/shell/shell_url_request_context_getter.cc b/ios/web/shell/shell_url_request_context_getter.cc new file mode 100644 index 0000000..b091466 --- /dev/null +++ b/ios/web/shell/shell_url_request_context_getter.cc @@ -0,0 +1,159 @@ +// 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 "ios/web/shell/shell_url_request_context_getter.h" + +#include "base/base_paths.h" +#include "base/logging.h" +#include "base/memory/ref_counted.h" +#include "base/path_service.h" +#include "base/threading/worker_pool.h" +#include "ios/net/cookies/cookie_store_ios.h" +#include "ios/web/public/web_client.h" +#include "ios/web/public/web_thread.h" +#include "ios/web/shell/shell_network_delegate.h" +#include "net/base/cache_type.h" +#include "net/cert/cert_verifier.h" +#include "net/dns/host_resolver.h" +#include "net/extras/sqlite/sqlite_persistent_cookie_store.h" +#include "net/http/http_auth_handler_factory.h" +#include "net/http/http_cache.h" +#include "net/http/http_network_session.h" +#include "net/http/http_server_properties_impl.h" +#include "net/http/transport_security_persister.h" +#include "net/http/transport_security_state.h" +#include "net/proxy/proxy_config_service_ios.h" +#include "net/proxy/proxy_service.h" +#include "net/ssl/channel_id_service.h" +#include "net/ssl/default_channel_id_store.h" +#include "net/ssl/ssl_config_service_defaults.h" +#include "net/url_request/data_protocol_handler.h" +#include "net/url_request/static_http_user_agent_settings.h" +#include "net/url_request/url_request_context.h" +#include "net/url_request/url_request_context_storage.h" +#include "net/url_request/url_request_job_factory_impl.h" + +namespace web { + +ShellURLRequestContextGetter::ShellURLRequestContextGetter( + const base::FilePath& base_path, + const scoped_refptr<base::SingleThreadTaskRunner>& network_task_runner, + const scoped_refptr<base::SingleThreadTaskRunner>& file_task_runner, + const scoped_refptr<base::MessageLoopProxy>& cache_task_runner) + : base_path_(base_path), + file_task_runner_(file_task_runner), + network_task_runner_(network_task_runner), + cache_task_runner_(cache_task_runner), + proxy_config_service_(new net::ProxyConfigServiceIOS), + net_log_(new net::NetLog()) { +} + +ShellURLRequestContextGetter::~ShellURLRequestContextGetter() { +} + +net::URLRequestContext* ShellURLRequestContextGetter::GetURLRequestContext() { + DCHECK(network_task_runner_->BelongsToCurrentThread()); + + if (!url_request_context_) { + url_request_context_.reset(new net::URLRequestContext()); + url_request_context_->set_net_log(net_log_.get()); + DCHECK(!network_delegate_.get()); + network_delegate_.reset(new ShellNetworkDelegate); + url_request_context_->set_network_delegate(network_delegate_.get()); + + storage_.reset( + new net::URLRequestContextStorage(url_request_context_.get())); + + // Setup the cookie store. + base::FilePath cookie_path; + bool cookie_path_found = PathService::Get(base::DIR_APP_DATA, &cookie_path); + DCHECK(cookie_path_found); + cookie_path = cookie_path.Append("WebShell").Append("Cookies"); + scoped_refptr<net::CookieMonster::PersistentCookieStore> persistent_store = + new net::SQLitePersistentCookieStore( + cookie_path, network_task_runner_, + web::WebThread::GetBlockingPool()->GetSequencedTaskRunner( + web::WebThread::GetBlockingPool()->GetSequenceToken()), + true, nullptr); + scoped_refptr<net::CookieStoreIOS> cookie_store = + new net::CookieStoreIOS(persistent_store.get()); + storage_->set_cookie_store(cookie_store.get()); + net::CookieStoreIOS::SwitchSynchronizedStore(nullptr, cookie_store.get()); + + std::string user_agent = web::GetWebClient()->GetUserAgent(false); + storage_->set_http_user_agent_settings( + new net::StaticHttpUserAgentSettings("en-us,en", user_agent)); + storage_->set_proxy_service( + net::ProxyService::CreateUsingSystemProxyResolver( + proxy_config_service_.release(), 0, + url_request_context_->net_log())); + storage_->set_ssl_config_service(new net::SSLConfigServiceDefaults); + storage_->set_cert_verifier(net::CertVerifier::CreateDefault()); + + net::TransportSecurityState* transport_security_state = + new net::TransportSecurityState(); + storage_->set_transport_security_state(transport_security_state); + transport_security_persister_.reset(new net::TransportSecurityPersister( + transport_security_state, base_path_, file_task_runner_, false)); + storage_->set_channel_id_service(make_scoped_ptr( + new net::ChannelIDService(new net::DefaultChannelIDStore(nullptr), + base::WorkerPool::GetTaskRunner(true)))); + storage_->set_http_server_properties(scoped_ptr<net::HttpServerProperties>( + new net::HttpServerPropertiesImpl())); + + scoped_ptr<net::HostResolver> host_resolver( + net::HostResolver::CreateDefaultResolver( + url_request_context_->net_log())); + storage_->set_http_auth_handler_factory( + net::HttpAuthHandlerFactory::CreateDefault(host_resolver.get())); + storage_->set_host_resolver(host_resolver.Pass()); + + net::HttpNetworkSession::Params network_session_params; + network_session_params.cert_verifier = + url_request_context_->cert_verifier(); + network_session_params.transport_security_state = + url_request_context_->transport_security_state(); + network_session_params.channel_id_service = + url_request_context_->channel_id_service(); + network_session_params.net_log = url_request_context_->net_log(); + network_session_params.proxy_service = + url_request_context_->proxy_service(); + network_session_params.ssl_config_service = + url_request_context_->ssl_config_service(); + network_session_params.http_auth_handler_factory = + url_request_context_->http_auth_handler_factory(); + network_session_params.network_delegate = network_delegate_.get(); + network_session_params.http_server_properties = + url_request_context_->http_server_properties(); + network_session_params.host_resolver = + url_request_context_->host_resolver(); + + base::FilePath cache_path = base_path_.Append(FILE_PATH_LITERAL("Cache")); + net::HttpCache::DefaultBackend* main_backend = + new net::HttpCache::DefaultBackend(net::DISK_CACHE, + net::CACHE_BACKEND_DEFAULT, + cache_path, 0, cache_task_runner_); + + net::HttpCache* main_cache = + new net::HttpCache(network_session_params, main_backend); + storage_->set_http_transaction_factory(main_cache); + + scoped_ptr<net::URLRequestJobFactoryImpl> job_factory( + new net::URLRequestJobFactoryImpl()); + bool set_protocol = + job_factory->SetProtocolHandler("data", new net::DataProtocolHandler); + DCHECK(set_protocol); + + storage_->set_job_factory(job_factory.release()); + } + + return url_request_context_.get(); +} + +scoped_refptr<base::SingleThreadTaskRunner> +ShellURLRequestContextGetter::GetNetworkTaskRunner() const { + return network_task_runner_; +} + +} // namespace web diff --git a/ios/web/shell/shell_url_request_context_getter.h b/ios/web/shell/shell_url_request_context_getter.h new file mode 100644 index 0000000..2fdb971 --- /dev/null +++ b/ios/web/shell/shell_url_request_context_getter.h @@ -0,0 +1,62 @@ +// 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 IOS_WEB_SHELL_SHELL_URL_REQUEST_CONTEXT_GETTER_H_ +#define IOS_WEB_SHELL_SHELL_URL_REQUEST_CONTEXT_GETTER_H_ + +#include "base/compiler_specific.h" +#include "base/files/file_path.h" +#include "base/memory/ref_counted.h" +#include "base/memory/scoped_ptr.h" +#include "base/message_loop/message_loop_proxy.h" +#include "base/single_thread_task_runner.h" +#include "net/url_request/url_request_context_getter.h" + +namespace net { +class HostResolver; +class MappedHostResolver; +class NetworkDelegate; +class NetLog; +class ProxyConfigService; +class TransportSecurityPersister; +class URLRequestContext; +class URLRequestContextStorage; +} + +namespace web { + +class ShellURLRequestContextGetter : public net::URLRequestContextGetter { + public: + ShellURLRequestContextGetter( + const base::FilePath& base_path, + const scoped_refptr<base::SingleThreadTaskRunner>& network_task_runner, + const scoped_refptr<base::SingleThreadTaskRunner>& file_task_runner, + const scoped_refptr<base::MessageLoopProxy>& cache_task_runner); + + // net::URLRequestContextGetter implementation. + net::URLRequestContext* GetURLRequestContext() override; + scoped_refptr<base::SingleThreadTaskRunner> GetNetworkTaskRunner() + const override; + + protected: + ~ShellURLRequestContextGetter() override; + + private: + base::FilePath base_path_; + scoped_refptr<base::SingleThreadTaskRunner> file_task_runner_; + scoped_refptr<base::SingleThreadTaskRunner> network_task_runner_; + scoped_refptr<base::MessageLoopProxy> cache_task_runner_; + scoped_ptr<net::ProxyConfigService> proxy_config_service_; + scoped_ptr<net::NetworkDelegate> network_delegate_; + scoped_ptr<net::URLRequestContextStorage> storage_; + scoped_ptr<net::URLRequestContext> url_request_context_; + scoped_ptr<net::NetLog> net_log_; + scoped_ptr<net::TransportSecurityPersister> transport_security_persister_; + + DISALLOW_COPY_AND_ASSIGN(ShellURLRequestContextGetter); +}; + +} // namespace web + +#endif // IOS_WEB_SHELL_SHELL_URL_REQUEST_CONTEXT_GETTER_H_ diff --git a/ios/web/shell/shell_web_client.h b/ios/web/shell/shell_web_client.h new file mode 100644 index 0000000..298a5e4 --- /dev/null +++ b/ios/web/shell/shell_web_client.h @@ -0,0 +1,36 @@ +// 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 IOS_WEB_SHELL_SHELL_WEB_CLIENT_H_ +#define IOS_WEB_SHELL_SHELL_WEB_CLIENT_H_ + +#include "base/compiler_specific.h" +#include "base/memory/scoped_ptr.h" +#include "ios/web/public/web_client.h" + +namespace web { +class ShellBrowserState; +class ShellWebMainParts; + +class ShellWebClient : public WebClient { + public: + ShellWebClient(); + ~ShellWebClient() override; + + // WebClient implementation. + WebMainParts* CreateWebMainParts() override; + std::string GetProduct() const override; + std::string GetUserAgent(bool desktop_user_agent) const override; + + ShellBrowserState* browser_state() const; + + private: + scoped_ptr<ShellWebMainParts> web_main_parts_; + + DISALLOW_COPY_AND_ASSIGN(ShellWebClient); +}; + +} // namespace web + +#endif // IOS_WEB_SHELL_SHELL_WEB_CLIENT_H_ diff --git a/ios/web/shell/shell_web_client.mm b/ios/web/shell/shell_web_client.mm new file mode 100644 index 0000000..405aeca8 --- /dev/null +++ b/ios/web/shell/shell_web_client.mm @@ -0,0 +1,36 @@ +// 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 "ios/web/shell/shell_web_client.h" + +#include "ios/web/public/user_agent.h" +#include "ios/web/shell/shell_web_main_parts.h" + +namespace web { + +ShellWebClient::ShellWebClient() { +} + +ShellWebClient::~ShellWebClient() { +} + +WebMainParts* ShellWebClient::CreateWebMainParts() { + web_main_parts_.reset(new ShellWebMainParts); + return web_main_parts_.get(); +} + +ShellBrowserState* ShellWebClient::browser_state() const { + return web_main_parts_->browser_state(); +} + +std::string ShellWebClient::GetProduct() const { + return "CriOS/36.77.34.45"; +} + +std::string ShellWebClient::GetUserAgent(bool desktop_user_agent) const { + std::string product = GetProduct(); + return web::BuildUserAgentFromProduct(product); +} + +} // namespace web diff --git a/ios/web/shell/shell_web_main_parts.h b/ios/web/shell/shell_web_main_parts.h new file mode 100644 index 0000000..6b6f001 --- /dev/null +++ b/ios/web/shell/shell_web_main_parts.h @@ -0,0 +1,32 @@ +// 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 IOS_WEB_SHELL_SHELL_WEB_MAIN_PARTS_H_ +#define IOS_WEB_SHELL_SHELL_WEB_MAIN_PARTS_H_ + +#include "ios/web/public/app/web_main_parts.h" + +#include "base/memory/scoped_ptr.h" + +namespace web { +class ShellBrowserState; + +// Shell-specific implementation of WebMainParts. +class ShellWebMainParts : public WebMainParts { + public: + ShellWebMainParts(); + ~ShellWebMainParts() override; + + ShellBrowserState* browser_state() const { return browser_state_.get(); } + + // WebMainParts implementation. + void PreMainMessageLoopRun() override; + + private: + scoped_ptr<ShellBrowserState> browser_state_; +}; + +} // namespace web + +#endif // IOS_WEB_SHELL_SHELL_WEB_MAIN_PARTS_H_ diff --git a/ios/web/shell/shell_web_main_parts.mm b/ios/web/shell/shell_web_main_parts.mm new file mode 100644 index 0000000..1a1c7ee --- /dev/null +++ b/ios/web/shell/shell_web_main_parts.mm @@ -0,0 +1,21 @@ +// 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 "ios/web/shell/shell_web_main_parts.h" + +#include "ios/web/shell/shell_browser_state.h" + +namespace web { + +ShellWebMainParts::ShellWebMainParts() { +} + +ShellWebMainParts::~ShellWebMainParts() { +} + +void ShellWebMainParts::PreMainMessageLoopRun() { + browser_state_.reset(new ShellBrowserState); +} + +} // namespace web diff --git a/ios/web/shell/view_controller.h b/ios/web/shell/view_controller.h new file mode 100644 index 0000000..c6e11bb --- /dev/null +++ b/ios/web/shell/view_controller.h @@ -0,0 +1,29 @@ +// 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 IOS_WEB_SHELL_VIEW_CONTROLLER_H_ +#define IOS_WEB_SHELL_VIEW_CONTROLLER_H_ + +#import <UIKit/UIKit.h> + +#include "ios/web/public/web_state/crw_web_delegate.h" + +namespace web { +class BrowserState; +} + +// Implements the main UI for ios_web_shell, including a toolbar and web view. +@interface ViewController + : UIViewController<CRWWebDelegate, UITextFieldDelegate> + +@property(nonatomic, retain) IBOutlet UIView* containerView; +@property(nonatomic, retain) IBOutlet UIToolbar* toolbarView; + +// Initializes a new ViewController from |MainView.xib| using the given +// |browserState|. +- (instancetype)initWithBrowserState:(web::BrowserState*)browserState; + +@end + +#endif // IOS_WEB_SHELL_VIEW_CONTROLLER_H_ diff --git a/ios/web/shell/view_controller.mm b/ios/web/shell/view_controller.mm new file mode 100644 index 0000000..16e78fe --- /dev/null +++ b/ios/web/shell/view_controller.mm @@ -0,0 +1,334 @@ +// 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 "ios/web/shell/view_controller.h" + +#include "base/mac/objc_property_releaser.h" +#import "base/mac/scoped_nsobject.h" +#include "base/memory/scoped_ptr.h" +#include "base/strings/sys_string_conversions.h" +#include "ios/net/cookies/cookie_store_ios.h" +#import "ios/net/crn_http_protocol_handler.h" +#import "ios/web/navigation/crw_session_controller.h" +#include "ios/web/navigation/web_load_params.h" +#import "ios/web/net/crw_url_verifying_protocol_handler.h" +#include "ios/web/net/request_tracker_factory_impl.h" +#import "ios/web/net/web_http_protocol_handler_delegate.h" +#include "ios/web/public/referrer.h" +#import "ios/web/public/web_controller_factory.h" +#include "ios/web/public/web_state/web_state.h" +#include "ios/web/public/web_view_util.h" +#include "ios/web/shell/shell_browser_state.h" +#include "ios/web/web_state/ui/crw_web_controller.h" +#include "ios/web/web_state/web_state_impl.h" +#include "ui/base/page_transition_types.h" + +namespace { +// Returns true if WKWebView should be used instead of UIWebView. +// TODO(stuartmorgan): Decide on a better way to control this. +bool UseWKWebView() { +#if defined(FORCE_ENABLE_WKWEBVIEW) + return web::IsWKWebViewSupported(); +#else + return false; +#endif +} +} + +@interface ViewController () { + web::BrowserState* _browserState; + base::scoped_nsobject<CRWWebController> _webController; + scoped_ptr<web::RequestTrackerFactoryImpl> _requestTrackerFactory; + scoped_ptr<web::WebHTTPProtocolHandlerDelegate> _httpProtocolDelegate; + + base::mac::ObjCPropertyReleaser _propertyReleaser_ViewController; +} +@property(nonatomic, readwrite, retain) UITextField* field; +@end + +@implementation ViewController + +@synthesize field = _field; +@synthesize containerView = _containerView; +@synthesize toolbarView = _toolbarView; + +- (instancetype)initWithBrowserState:(web::BrowserState*)browserState { + self = [super initWithNibName:@"MainView" bundle:nil]; + if (self) { + _propertyReleaser_ViewController.Init(self, [ViewController class]); + _browserState = browserState; + } + return self; +} + +- (void)dealloc { + net::HTTPProtocolHandlerDelegate::SetInstance(nullptr); + net::RequestTracker::SetRequestTrackerFactory(nullptr); + [super dealloc]; +} + +- (void)viewDidLoad { + [super viewDidLoad]; + + // Set up the toolbar buttons. + UIButton* back = [UIButton buttonWithType:UIButtonTypeCustom]; + [back setImage:[UIImage imageNamed:@"toolbar_back"] + forState:UIControlStateNormal]; + [back setFrame:CGRectMake(0, 0, 44, 44)]; + [back setImageEdgeInsets:UIEdgeInsetsMake(5, 5, 4, 4)]; + [back setAutoresizingMask:UIViewAutoresizingFlexibleRightMargin]; + [back addTarget:self + action:@selector(back) + forControlEvents:UIControlEventTouchUpInside]; + + UIButton* forward = [UIButton buttonWithType:UIButtonTypeCustom]; + [forward setImage:[UIImage imageNamed:@"toolbar_forward"] + forState:UIControlStateNormal]; + [forward setFrame:CGRectMake(44, 0, 44, 44)]; + [forward setImageEdgeInsets:UIEdgeInsetsMake(5, 5, 4, 4)]; + [forward setAutoresizingMask:UIViewAutoresizingFlexibleRightMargin]; + [forward addTarget:self + action:@selector(forward) + forControlEvents:UIControlEventTouchUpInside]; + + base::scoped_nsobject<UITextField> field([[UITextField alloc] + initWithFrame:CGRectMake(88, 6, CGRectGetWidth([_toolbarView frame]) - 98, + 31)]); + [field setDelegate:self]; + [field setBackground:[[UIImage imageNamed:@"textfield_background"] + resizableImageWithCapInsets:UIEdgeInsetsMake( + 12, 12, 12, 12)]]; + [field setAutoresizingMask:UIViewAutoresizingFlexibleWidth]; + [field setKeyboardType:UIKeyboardTypeWebSearch]; + [field setAutocorrectionType:UITextAutocorrectionTypeNo]; + [field setClearButtonMode:UITextFieldViewModeWhileEditing]; + self.field = field; + + [_toolbarView addSubview:back]; + [_toolbarView addSubview:forward]; + [_toolbarView addSubview:field]; + + // Set up the network stack before creating the WebState. + [self setUpNetworkStack]; + + scoped_ptr<web::WebStateImpl> webState(new web::WebStateImpl(_browserState)); + webState->GetNavigationManagerImpl().InitializeSession(nil, nil, NO, 0); + web::WebViewType webViewType = + UseWKWebView() ? web::WK_WEB_VIEW_TYPE : web::UI_WEB_VIEW_TYPE; + _webController.reset(web::CreateWebController(webViewType, webState.Pass())); + [_webController setDelegate:self]; + [_webController setWebUsageEnabled:YES]; + + [[_webController view] setFrame:[_containerView bounds]]; + [_containerView addSubview:[_webController view]]; + + web::WebLoadParams params(GURL("https://dev.chromium.org/")); + params.transition_type = ui::PAGE_TRANSITION_TYPED; + [_webController loadWithParams:params]; +} + +- (void)setUpNetworkStack { + // Disable the default cache. + [NSURLCache setSharedURLCache:nil]; + + _httpProtocolDelegate.reset(new web::WebHTTPProtocolHandlerDelegate( + _browserState->GetRequestContext())); + net::HTTPProtocolHandlerDelegate::SetInstance(_httpProtocolDelegate.get()); + BOOL success = [NSURLProtocol registerClass:[CRNHTTPProtocolHandler class]]; + DCHECK(success); + // The CRWURLVerifyingProtocolHandler is used to verify URL in the + // CRWWebController. It must be registered after the HttpProtocolHandler + // because handlers are called in the reverse order of declaration. + success = + [NSURLProtocol registerClass:[CRWURLVerifyingProtocolHandler class]]; + DCHECK(success); + _requestTrackerFactory.reset( + new web::RequestTrackerFactoryImpl(std::string())); + net::RequestTracker::SetRequestTrackerFactory(_requestTrackerFactory.get()); + net::CookieStoreIOS::SetCookiePolicy(net::CookieStoreIOS::ALLOW); +} + +- (void)didReceiveMemoryWarning { + [super didReceiveMemoryWarning]; +} + +- (UIBarPosition)positionForBar:(id<UIBarPositioning>)bar { + if (bar == _toolbarView) { + return UIBarPositionTopAttached; + } + return UIBarPositionAny; +} + +- (void)back { + if ([_webController canGoBack]) { + [_webController goBack]; + } +} + +- (void)forward { + if ([_webController canGoForward]) { + [_webController goForward]; + } +} + +- (BOOL)textFieldShouldReturn:(UITextField*)field { + GURL url = GURL(base::SysNSStringToUTF8([field text])); + + // Do not try to load invalid URLs. + if (url.is_valid()) { + web::WebLoadParams params(url); + params.transition_type = ui::PAGE_TRANSITION_TYPED; + [_webController loadWithParams:params]; + } + + [field resignFirstResponder]; + [self updateToolbar]; + return YES; +} + +- (void)updateToolbar { + // Do not update the URL if the text field is currently being edited. + if ([_field isFirstResponder]) { + return; + } + + const GURL& url = [_webController webStateImpl]->GetVisibleURL(); + [_field setText:base::SysUTF8ToNSString(url.spec())]; +} + +// ----------------------------------------------------------------------- +#pragma mark Bikeshedding Implementation + +// Overridden to allow this view controller to receive motion events by being +// first responder when no other views are. +- (BOOL)canBecomeFirstResponder { + return YES; +} + +- (void)motionEnded:(UIEventSubtype)motion withEvent:(UIEvent*)event { + if (event.subtype == UIEventSubtypeMotionShake) { + [self updateToolbarColor]; + } +} + +- (void)updateToolbarColor { + // Cycle through the following set of colors: + NSArray* colors = @[ + // Vanilla Blue. + [UIColor colorWithRed:0.337 green:0.467 blue:0.988 alpha:1.0], + // Vanilla Red. + [UIColor colorWithRed:0.898 green:0.110 blue:0.137 alpha:1.0], + // Blue Grey. + [UIColor colorWithRed:0.376 green:0.490 blue:0.545 alpha:1.0], + // Brown. + [UIColor colorWithRed:0.475 green:0.333 blue:0.282 alpha:1.0], + // Purple. + [UIColor colorWithRed:0.612 green:0.153 blue:0.690 alpha:1.0], + // Teal. + [UIColor colorWithRed:0.000 green:0.737 blue:0.831 alpha:1.0], + // Deep Orange. + [UIColor colorWithRed:1.000 green:0.341 blue:0.133 alpha:1.0], + // Indigo. + [UIColor colorWithRed:0.247 green:0.318 blue:0.710 alpha:1.0], + // Vanilla Green. + [UIColor colorWithRed:0.145 green:0.608 blue:0.141 alpha:1.0], + // Pinkerton. + [UIColor colorWithRed:0.914 green:0.118 blue:0.388 alpha:1.0], + ]; + + NSUInteger currentIndex = [colors indexOfObject:_toolbarView.barTintColor]; + if (currentIndex == NSNotFound) { + currentIndex = 0; + } + NSUInteger newIndex = currentIndex + 1; + if (newIndex >= [colors count]) { + // TODO(rohitrao): Out of colors! Consider prompting the user to pick their + // own color here. Also consider allowing the user to choose the entire set + // of colors or allowing the user to choose color randomization. + newIndex = 0; + } + _toolbarView.barTintColor = [colors objectAtIndex:newIndex]; +} + +// ----------------------------------------------------------------------- +// WebDelegate implementation. + +- (void)webWillAddPendingURL:(const GURL&)url + transition:(ui::PageTransition)transition { +} +- (void)webDidAddPendingURL { + [self updateToolbar]; +} +- (void)webCancelStartLoadingRequest { +} +- (void)webDidStartLoadingURL:(const GURL&)currentUrl + shouldUpdateHistory:(BOOL)updateHistory { + [self updateToolbar]; +} +- (void)webDidFinishWithURL:(const GURL&)url loadSuccess:(BOOL)loadSuccess { + [self updateToolbar]; +} + +- (CRWWebController*)webPageOrderedOpen:(const GURL&)url + referrer:(const web::Referrer&)referrer + windowName:(NSString*)windowName + inBackground:(BOOL)inBackground { + return nil; +} + +- (CRWWebController*)webPageOrderedOpenBlankWithReferrer: + (const web::Referrer&)referrer + inBackground:(BOOL)inBackground { + return nil; +} + +- (void)webPageOrderedClose { +} +- (void)goDelta:(int)delta { +} +- (void)openURLWithParams:(const web::WebState::OpenURLParams&)params { +} +- (BOOL)openExternalURL:(const GURL&)url { + return NO; +} +- (void)presentSSLError:(const net::SSLInfo&)info + forSSLStatus:(const web::SSLStatus&)status + recoverable:(BOOL)recoverable + callback:(SSLErrorCallback)shouldContinue { +} +- (void)presentSpoofingError { +} +- (void)webLoadCancelled:(const GURL&)url { +} +- (void)webDidUpdateHistoryStateWithPageURL:(const GURL&)pageUrl { +} +- (void)webController:(CRWWebController*)webController + retrievePlaceholderOverlayImage:(void (^)(UIImage*))block { +} +- (void)webController:(CRWWebController*)webController + onFormResubmissionForRequest:(NSURLRequest*)request + continueBlock:(ProceduralBlock)continueBlock + cancelBlock:(ProceduralBlock)cancelBlock { +} +- (void)webWillReload { +} +- (void)webWillInitiateLoadWithParams:(web::WebLoadParams&)params { +} +- (void)webDidUpdateSessionForLoadWithParams:(const web::WebLoadParams&)params + wasInitialNavigation:(BOOL)initialNavigation { +} +- (void)webWillFinishHistoryNavigationFromEntry:(CRWSessionEntry*)fromEntry { +} +- (void)webWillGoDelta:(int)delta { +} +- (void)webDidPrepareForGoBack { +} +- (int)downloadImageAtUrl:(const GURL&)url + maxBitmapSize:(uint32_t)maxBitmapSize + callback: + (const web::WebState::ImageDownloadCallback&)callback { + return -1; +} + +@end diff --git a/ios/web/shell/web_exe_main.mm b/ios/web/shell/web_exe_main.mm new file mode 100644 index 0000000..0e7c58b --- /dev/null +++ b/ios/web/shell/web_exe_main.mm @@ -0,0 +1,14 @@ +// 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 <UIKit/UIKit.h> + +#import "ios/web/shell/app_delegate.h" + +int main(int argc, char* argv[]) { + @autoreleasepool { + return UIApplicationMain(argc, argv, nil, + NSStringFromClass([AppDelegate class])); + } +} |