| OLD | NEW |
| (Empty) |
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. | |
| 2 // Use of this source code is governed by a BSD-style license that can be | |
| 3 // found in the LICENSE file. | |
| 4 | |
| 5 #include "base/bind.h" | |
| 6 #include "base/macros.h" | |
| 7 #include "examples/window_manager/debug_panel_host.mojom.h" | |
| 8 #include "examples/window_manager/window_manager.mojom.h" | |
| 9 #include "mojo/application/application_runner_chromium.h" | |
| 10 #include "mojo/common/binding_set.h" | |
| 11 #include "mojo/converters/geometry/geometry_type_converters.h" | |
| 12 #include "mojo/converters/input_events/input_events_type_converters.h" | |
| 13 #include "mojo/public/c/system/main.h" | |
| 14 #include "mojo/public/cpp/application/application_connection.h" | |
| 15 #include "mojo/public/cpp/application/application_delegate.h" | |
| 16 #include "mojo/public/cpp/application/application_impl.h" | |
| 17 #include "mojo/public/cpp/application/service_provider_impl.h" | |
| 18 #include "mojo/public/cpp/bindings/strong_binding.h" | |
| 19 #include "mojo/services/input_events/interfaces/input_events.mojom.h" | |
| 20 #include "mojo/services/navigation/interfaces/navigation.mojom.h" | |
| 21 #include "mojo/services/view_manager/cpp/view.h" | |
| 22 #include "mojo/services/view_manager/cpp/view_manager.h" | |
| 23 #include "mojo/services/view_manager/cpp/view_manager_delegate.h" | |
| 24 #include "mojo/services/view_manager/cpp/view_observer.h" | |
| 25 #include "services/window_manager/basic_focus_rules.h" | |
| 26 #include "services/window_manager/view_target.h" | |
| 27 #include "services/window_manager/window_manager_app.h" | |
| 28 #include "services/window_manager/window_manager_delegate.h" | |
| 29 #include "services/window_manager/window_manager_root.h" | |
| 30 #include "ui/events/event.h" | |
| 31 #include "ui/events/event_constants.h" | |
| 32 #include "url/gurl.h" | |
| 33 | |
| 34 #if defined CreateWindow | |
| 35 #undef CreateWindow | |
| 36 #endif | |
| 37 | |
| 38 namespace mojo { | |
| 39 namespace examples { | |
| 40 | |
| 41 class WindowManagerController; | |
| 42 | |
| 43 namespace { | |
| 44 | |
| 45 const int kBorderInset = 25; | |
| 46 const int kControlPanelWidth = 200; | |
| 47 const int kTextfieldHeight = 39; | |
| 48 | |
| 49 } // namespace | |
| 50 | |
| 51 class WindowManagerConnection : public ::examples::IWindowManager { | |
| 52 public: | |
| 53 WindowManagerConnection(WindowManagerController* window_manager, | |
| 54 InterfaceRequest<::examples::IWindowManager> request) | |
| 55 : window_manager_(window_manager), binding_(this, request.Pass()) {} | |
| 56 ~WindowManagerConnection() override {} | |
| 57 | |
| 58 private: | |
| 59 // Overridden from ::examples::IWindowManager: | |
| 60 void CloseWindow(Id view_id) override; | |
| 61 | |
| 62 WindowManagerController* window_manager_; | |
| 63 StrongBinding<::examples::IWindowManager> binding_; | |
| 64 | |
| 65 DISALLOW_COPY_AND_ASSIGN(WindowManagerConnection); | |
| 66 }; | |
| 67 | |
| 68 class NavigatorHostImpl : public NavigatorHost { | |
| 69 public: | |
| 70 NavigatorHostImpl(WindowManagerController* window_manager, Id view_id) | |
| 71 : window_manager_(window_manager), | |
| 72 view_id_(view_id), | |
| 73 current_index_(-1) {} | |
| 74 ~NavigatorHostImpl() override {} | |
| 75 | |
| 76 void Bind(InterfaceRequest<NavigatorHost> request) { | |
| 77 bindings_.AddBinding(this, request.Pass()); | |
| 78 } | |
| 79 | |
| 80 void RecordNavigation(const std::string& url); | |
| 81 | |
| 82 private: | |
| 83 void DidNavigateLocally(const mojo::String& url) override; | |
| 84 void RequestNavigate(Target target, URLRequestPtr request) override; | |
| 85 void RequestNavigateHistory(int32_t delta) override; | |
| 86 | |
| 87 WindowManagerController* window_manager_; | |
| 88 Id view_id_; | |
| 89 std::vector<std::string> history_; | |
| 90 int32_t current_index_; | |
| 91 | |
| 92 BindingSet<NavigatorHost> bindings_; | |
| 93 | |
| 94 DISALLOW_COPY_AND_ASSIGN(NavigatorHostImpl); | |
| 95 }; | |
| 96 | |
| 97 class RootLayoutManager : public ViewObserver { | |
| 98 public: | |
| 99 RootLayoutManager(ViewManager* view_manager, | |
| 100 View* root, | |
| 101 Id content_view_id, | |
| 102 Id launcher_ui_view_id, | |
| 103 Id control_panel_view_id) | |
| 104 : root_(root), | |
| 105 view_manager_(view_manager), | |
| 106 content_view_id_(content_view_id), | |
| 107 launcher_ui_view_id_(launcher_ui_view_id), | |
| 108 control_panel_view_id_(control_panel_view_id) {} | |
| 109 ~RootLayoutManager() override { | |
| 110 if (root_) | |
| 111 root_->RemoveObserver(this); | |
| 112 } | |
| 113 | |
| 114 private: | |
| 115 // Overridden from ViewObserver: | |
| 116 void OnViewBoundsChanged(View* view, | |
| 117 const Rect& old_bounds, | |
| 118 const Rect& new_bounds) override { | |
| 119 DCHECK_EQ(view, root_); | |
| 120 | |
| 121 View* content_view = view_manager_->GetViewById(content_view_id_); | |
| 122 content_view->SetBounds(new_bounds); | |
| 123 | |
| 124 int delta_width = new_bounds.width - old_bounds.width; | |
| 125 int delta_height = new_bounds.height - old_bounds.height; | |
| 126 | |
| 127 View* launcher_ui_view = view_manager_->GetViewById(launcher_ui_view_id_); | |
| 128 Rect launcher_ui_bounds(launcher_ui_view->bounds()); | |
| 129 launcher_ui_bounds.width += delta_width; | |
| 130 launcher_ui_view->SetBounds(launcher_ui_bounds); | |
| 131 | |
| 132 View* control_panel_view = | |
| 133 view_manager_->GetViewById(control_panel_view_id_); | |
| 134 Rect control_panel_bounds(control_panel_view->bounds()); | |
| 135 control_panel_bounds.x += delta_width; | |
| 136 control_panel_view->SetBounds(control_panel_bounds); | |
| 137 | |
| 138 const View::Children& content_views = content_view->children(); | |
| 139 View::Children::const_iterator iter = content_views.begin(); | |
| 140 for (; iter != content_views.end(); ++iter) { | |
| 141 View* view = *iter; | |
| 142 if (view->id() == control_panel_view->id() || | |
| 143 view->id() == launcher_ui_view->id()) | |
| 144 continue; | |
| 145 Rect view_bounds(view->bounds()); | |
| 146 view_bounds.width += delta_width; | |
| 147 view_bounds.height += delta_height; | |
| 148 view->SetBounds(view_bounds); | |
| 149 } | |
| 150 } | |
| 151 void OnViewDestroyed(View* view) override { | |
| 152 DCHECK_EQ(view, root_); | |
| 153 root_->RemoveObserver(this); | |
| 154 root_ = NULL; | |
| 155 } | |
| 156 | |
| 157 View* root_; | |
| 158 ViewManager* view_manager_; | |
| 159 const Id content_view_id_; | |
| 160 const Id launcher_ui_view_id_; | |
| 161 const Id control_panel_view_id_; | |
| 162 | |
| 163 DISALLOW_COPY_AND_ASSIGN(RootLayoutManager); | |
| 164 }; | |
| 165 | |
| 166 class Window : public InterfaceFactory<NavigatorHost> { | |
| 167 public: | |
| 168 Window(WindowManagerController* window_manager, View* view) | |
| 169 : window_manager_(window_manager), | |
| 170 view_(view), | |
| 171 navigator_host_(window_manager_, view_->id()) { | |
| 172 exposed_services_impl_.AddService<NavigatorHost>(this); | |
| 173 } | |
| 174 | |
| 175 ~Window() override {} | |
| 176 | |
| 177 View* view() const { return view_; } | |
| 178 | |
| 179 NavigatorHost* navigator_host() { return &navigator_host_; } | |
| 180 | |
| 181 void Embed(const std::string& url) { | |
| 182 // TODO: Support embedding multiple times? | |
| 183 ServiceProviderPtr exposed_services; | |
| 184 exposed_services_impl_.Bind(GetProxy(&exposed_services)); | |
| 185 view_->Embed(url, nullptr, exposed_services.Pass()); | |
| 186 navigator_host_.RecordNavigation(url); | |
| 187 } | |
| 188 | |
| 189 private: | |
| 190 // InterfaceFactory<NavigatorHost> | |
| 191 void Create(ApplicationConnection* connection, | |
| 192 InterfaceRequest<NavigatorHost> request) override { | |
| 193 navigator_host_.Bind(request.Pass()); | |
| 194 } | |
| 195 | |
| 196 WindowManagerController* window_manager_; | |
| 197 View* view_; | |
| 198 ServiceProviderImpl exposed_services_impl_; | |
| 199 NavigatorHostImpl navigator_host_; | |
| 200 }; | |
| 201 | |
| 202 class WindowManagerController | |
| 203 : public examples::DebugPanelHost, | |
| 204 public window_manager::WindowManagerController, | |
| 205 public ui::EventHandler, | |
| 206 public ui::AcceleratorTarget, | |
| 207 public mojo::InterfaceFactory<examples::DebugPanelHost>, | |
| 208 public InterfaceFactory<::examples::IWindowManager> { | |
| 209 public: | |
| 210 WindowManagerController(Shell* shell, | |
| 211 ApplicationImpl* app, | |
| 212 ApplicationConnection* connection, | |
| 213 window_manager::WindowManagerRoot* wm_root) | |
| 214 : shell_(shell), | |
| 215 launcher_ui_(NULL), | |
| 216 view_manager_(NULL), | |
| 217 window_manager_root_(wm_root), | |
| 218 navigation_target_(Target::DEFAULT), | |
| 219 app_(app), | |
| 220 binding_(this) { | |
| 221 connection->AddService<::examples::IWindowManager>(this); | |
| 222 } | |
| 223 | |
| 224 ~WindowManagerController() override { | |
| 225 // host() may be destroyed by the time we get here. | |
| 226 // TODO: figure out a way to always cleanly remove handler. | |
| 227 | |
| 228 // TODO(erg): In the aura version, we removed ourselves from the | |
| 229 // PreTargetHandler list here. We may need to do something analogous when | |
| 230 // we get event handling without aura working. | |
| 231 } | |
| 232 | |
| 233 void CloseWindow(Id view_id) { | |
| 234 WindowVector::iterator iter = GetWindowByViewId(view_id); | |
| 235 DCHECK(iter != windows_.end()); | |
| 236 Window* window = *iter; | |
| 237 windows_.erase(iter); | |
| 238 window->view()->Destroy(); | |
| 239 } | |
| 240 | |
| 241 void DidNavigateLocally(uint32 source_view_id, const mojo::String& url) { | |
| 242 LOG(ERROR) << "DidNavigateLocally: source_view_id: " << source_view_id | |
| 243 << " url: " << url.To<std::string>(); | |
| 244 } | |
| 245 | |
| 246 void RequestNavigate(uint32 source_view_id, | |
| 247 Target target, | |
| 248 const mojo::String& url) { | |
| 249 OnLaunch(source_view_id, target, url); | |
| 250 } | |
| 251 | |
| 252 // Overridden from mojo::DebugPanelHost: | |
| 253 void CloseTopWindow() override { | |
| 254 if (!windows_.empty()) | |
| 255 CloseWindow(windows_.back()->view()->id()); | |
| 256 } | |
| 257 | |
| 258 void NavigateTo(const String& url) override { | |
| 259 OnLaunch(control_panel_id_, Target::NEW_NODE, url); | |
| 260 } | |
| 261 | |
| 262 void SetNavigationTarget(Target t) override { navigation_target_ = t; } | |
| 263 | |
| 264 // mojo::InterfaceFactory<examples::DebugPanelHost> implementation. | |
| 265 void Create( | |
| 266 mojo::ApplicationConnection* connection, | |
| 267 mojo::InterfaceRequest<examples::DebugPanelHost> request) override { | |
| 268 binding_.Bind(request.Pass()); | |
| 269 } | |
| 270 | |
| 271 // mojo::InterfaceFactory<::examples::IWindowManager> implementation. | |
| 272 void Create( | |
| 273 mojo::ApplicationConnection* connection, | |
| 274 mojo::InterfaceRequest<::examples::IWindowManager> request) override { | |
| 275 new WindowManagerConnection(this, request.Pass()); | |
| 276 } | |
| 277 | |
| 278 private: | |
| 279 typedef std::vector<Window*> WindowVector; | |
| 280 | |
| 281 // Overridden from ViewManagerDelegate: | |
| 282 void OnEmbed(View* root, | |
| 283 InterfaceRequest<ServiceProvider> services, | |
| 284 ServiceProviderPtr exposed_services) override { | |
| 285 DCHECK(!view_manager_); | |
| 286 view_manager_ = root->view_manager(); | |
| 287 | |
| 288 View* view = view_manager_->CreateView(); | |
| 289 root->AddChild(view); | |
| 290 Rect rect; | |
| 291 rect.width = root->bounds().width; | |
| 292 rect.height = root->bounds().height; | |
| 293 view->SetBounds(rect); | |
| 294 view->SetVisible(true); | |
| 295 content_view_id_ = view->id(); | |
| 296 | |
| 297 Id launcher_ui_id = CreateLauncherUI(); | |
| 298 control_panel_id_ = CreateControlPanel(view); | |
| 299 | |
| 300 root_layout_manager_.reset( | |
| 301 new RootLayoutManager(view_manager_, root, content_view_id_, | |
| 302 launcher_ui_id, control_panel_id_)); | |
| 303 root->AddObserver(root_layout_manager_.get()); | |
| 304 | |
| 305 // TODO(erg): In the aura version, we explicitly added ourselves as a | |
| 306 // PreTargetHandler to the window() here. We probably have to do something | |
| 307 // analogous here. | |
| 308 | |
| 309 window_manager_root_->InitFocus( | |
| 310 make_scoped_ptr(new window_manager::BasicFocusRules(root))); | |
| 311 window_manager_root_->accelerator_manager()->Register( | |
| 312 ui::Accelerator(ui::VKEY_BROWSER_BACK, 0), | |
| 313 ui::AcceleratorManager::kNormalPriority, this); | |
| 314 } | |
| 315 void OnViewManagerDisconnected(ViewManager* view_manager) override { | |
| 316 DCHECK_EQ(view_manager_, view_manager); | |
| 317 view_manager_ = NULL; | |
| 318 base::MessageLoop::current()->Quit(); | |
| 319 } | |
| 320 | |
| 321 // Overridden from WindowManagerDelegate: | |
| 322 void Embed(const String& url, | |
| 323 InterfaceRequest<ServiceProvider> services, | |
| 324 ServiceProviderPtr exposed_services) override { | |
| 325 const Id kInvalidSourceViewId = 0; | |
| 326 OnLaunch(kInvalidSourceViewId, Target::DEFAULT, url); | |
| 327 } | |
| 328 | |
| 329 // Overridden from ui::EventHandler: | |
| 330 void OnEvent(ui::Event* event) override { | |
| 331 View* view = | |
| 332 static_cast<window_manager::ViewTarget*>(event->target())->view(); | |
| 333 if (event->type() == ui::ET_MOUSE_PRESSED) | |
| 334 view->SetFocus(); | |
| 335 } | |
| 336 | |
| 337 // Overriden from ui::AcceleratorTarget: | |
| 338 bool AcceleratorPressed(const ui::Accelerator& accelerator, | |
| 339 mojo::View* view) override { | |
| 340 if (accelerator.key_code() != ui::VKEY_BROWSER_BACK) | |
| 341 return false; | |
| 342 | |
| 343 WindowVector::iterator iter = GetWindowByViewId(view->id()); | |
| 344 DCHECK(iter != windows_.end()); | |
| 345 Window* window = *iter; | |
| 346 window->navigator_host()->RequestNavigateHistory(-1); | |
| 347 return true; | |
| 348 } | |
| 349 | |
| 350 // Overriden from ui::AcceleratorTarget: | |
| 351 bool CanHandleAccelerators() const override { return true; } | |
| 352 | |
| 353 void OnLaunch(uint32 source_view_id, | |
| 354 Target requested_target, | |
| 355 const mojo::String& url) { | |
| 356 Target target = navigation_target_; | |
| 357 if (target == Target::DEFAULT) { | |
| 358 if (requested_target != Target::DEFAULT) { | |
| 359 target = requested_target; | |
| 360 } else { | |
| 361 // TODO(aa): Should be Target::NEW_NODE if source origin and dest origin | |
| 362 // are different? | |
| 363 target = Target::SOURCE_NODE; | |
| 364 } | |
| 365 } | |
| 366 | |
| 367 Window* dest_view = NULL; | |
| 368 if (target == Target::SOURCE_NODE) { | |
| 369 WindowVector::iterator source_view = GetWindowByViewId(source_view_id); | |
| 370 bool app_initiated = source_view != windows_.end(); | |
| 371 if (app_initiated) | |
| 372 dest_view = *source_view; | |
| 373 else if (!windows_.empty()) | |
| 374 dest_view = windows_.back(); | |
| 375 } | |
| 376 | |
| 377 if (!dest_view) { | |
| 378 dest_view = CreateWindow(); | |
| 379 windows_.push_back(dest_view); | |
| 380 } | |
| 381 | |
| 382 dest_view->Embed(url); | |
| 383 } | |
| 384 | |
| 385 // TODO(beng): proper layout manager!! | |
| 386 Id CreateLauncherUI() { | |
| 387 View* view = view_manager_->GetViewById(content_view_id_); | |
| 388 Rect bounds = view->bounds(); | |
| 389 bounds.x += kBorderInset; | |
| 390 bounds.y += kBorderInset; | |
| 391 bounds.width -= 2 * kBorderInset; | |
| 392 bounds.height = kTextfieldHeight; | |
| 393 launcher_ui_ = CreateWindow(bounds); | |
| 394 launcher_ui_->Embed("mojo:browser"); | |
| 395 return launcher_ui_->view()->id(); | |
| 396 } | |
| 397 | |
| 398 Window* CreateWindow() { | |
| 399 View* view = view_manager_->GetViewById(content_view_id_); | |
| 400 Rect bounds; | |
| 401 bounds.x = kBorderInset; | |
| 402 bounds.y = 2 * kBorderInset + kTextfieldHeight; | |
| 403 bounds.width = view->bounds().width - 3 * kBorderInset - kControlPanelWidth; | |
| 404 bounds.height = | |
| 405 view->bounds().height - (3 * kBorderInset + kTextfieldHeight); | |
| 406 if (!windows_.empty()) { | |
| 407 bounds.x = windows_.back()->view()->bounds().x + 35; | |
| 408 bounds.y = windows_.back()->view()->bounds().y + 35; | |
| 409 } | |
| 410 return CreateWindow(bounds); | |
| 411 } | |
| 412 | |
| 413 Window* CreateWindow(const Rect& bounds) { | |
| 414 View* content = view_manager_->GetViewById(content_view_id_); | |
| 415 View* view = view_manager_->CreateView(); | |
| 416 content->AddChild(view); | |
| 417 view->SetBounds(bounds); | |
| 418 view->SetVisible(true); | |
| 419 view->SetFocus(); | |
| 420 return new Window(this, view); | |
| 421 } | |
| 422 | |
| 423 Id CreateControlPanel(View* root) { | |
| 424 View* view = view_manager_->CreateView(); | |
| 425 root->AddChild(view); | |
| 426 | |
| 427 Rect bounds; | |
| 428 bounds.x = root->bounds().width - kControlPanelWidth - kBorderInset; | |
| 429 bounds.y = kBorderInset * 2 + kTextfieldHeight; | |
| 430 bounds.width = kControlPanelWidth; | |
| 431 bounds.height = root->bounds().height - kBorderInset * 3 - kTextfieldHeight; | |
| 432 view->SetBounds(bounds); | |
| 433 view->SetVisible(true); | |
| 434 | |
| 435 ServiceProviderPtr exposed_services; | |
| 436 control_panel_exposed_services_impl_.Bind(GetProxy(&exposed_services)); | |
| 437 control_panel_exposed_services_impl_.AddService<::examples::IWindowManager>( | |
| 438 this); | |
| 439 | |
| 440 GURL frame_url = url_.Resolve("/examples/window_manager/debug_panel.sky"); | |
| 441 view->Embed(frame_url.spec(), nullptr, exposed_services.Pass()); | |
| 442 | |
| 443 return view->id(); | |
| 444 } | |
| 445 | |
| 446 WindowVector::iterator GetWindowByViewId(Id view_id) { | |
| 447 for (std::vector<Window*>::iterator iter = windows_.begin(); | |
| 448 iter != windows_.end(); ++iter) { | |
| 449 if ((*iter)->view()->id() == view_id) { | |
| 450 return iter; | |
| 451 } | |
| 452 } | |
| 453 return windows_.end(); | |
| 454 } | |
| 455 | |
| 456 Shell* shell_; | |
| 457 | |
| 458 Window* launcher_ui_; | |
| 459 WindowVector windows_; | |
| 460 ViewManager* view_manager_; | |
| 461 scoped_ptr<RootLayoutManager> root_layout_manager_; | |
| 462 ServiceProviderImpl control_panel_exposed_services_impl_; | |
| 463 | |
| 464 window_manager::WindowManagerRoot* window_manager_root_; | |
| 465 | |
| 466 // Id of the view most content is added to. | |
| 467 Id content_view_id_; | |
| 468 | |
| 469 // Id of the debug panel. | |
| 470 Id control_panel_id_; | |
| 471 | |
| 472 GURL url_; | |
| 473 Target navigation_target_; | |
| 474 | |
| 475 ApplicationImpl* app_; | |
| 476 | |
| 477 mojo::Binding<examples::DebugPanelHost> binding_; | |
| 478 | |
| 479 DISALLOW_COPY_AND_ASSIGN(WindowManagerController); | |
| 480 }; | |
| 481 | |
| 482 class WindowManager : public ApplicationDelegate, | |
| 483 public window_manager::WindowManagerControllerFactory { | |
| 484 public: | |
| 485 WindowManager() | |
| 486 : window_manager_app_(new window_manager::WindowManagerApp(this)) {} | |
| 487 | |
| 488 scoped_ptr<window_manager::WindowManagerController> | |
| 489 CreateWindowManagerController( | |
| 490 ApplicationConnection* connection, | |
| 491 window_manager::WindowManagerRoot* wm_root) override { | |
| 492 return scoped_ptr<WindowManagerController>( | |
| 493 new WindowManagerController(shell_, app_, connection, wm_root)); | |
| 494 } | |
| 495 | |
| 496 private: | |
| 497 // Overridden from ApplicationDelegate: | |
| 498 void Initialize(ApplicationImpl* app) override { | |
| 499 window_manager_app_.reset(new window_manager::WindowManagerApp(this)); | |
| 500 shell_ = app->shell(); | |
| 501 app_ = app; | |
| 502 // FIXME: Mojo applications don't know their URLs yet: | |
| 503 // https://docs.google.com/a/chromium.org/document/d/1AQ2y6ekzvbdaMF5WrUQmne
yXJnke-MnYYL4Gz1AKDos | |
| 504 url_ = GURL(app->args()[1]); | |
| 505 window_manager_app_->Initialize(app); | |
| 506 } | |
| 507 | |
| 508 bool ConfigureIncomingConnection(ApplicationConnection* connection) override { | |
| 509 window_manager_app_->ConfigureIncomingConnection(connection); | |
| 510 return true; | |
| 511 } | |
| 512 | |
| 513 ApplicationImpl* app_; | |
| 514 Shell* shell_; | |
| 515 GURL url_; | |
| 516 | |
| 517 scoped_ptr<window_manager::WindowManagerApp> window_manager_app_; | |
| 518 DISALLOW_COPY_AND_ASSIGN(WindowManager); | |
| 519 }; | |
| 520 | |
| 521 void WindowManagerConnection::CloseWindow(Id view_id) { | |
| 522 window_manager_->CloseWindow(view_id); | |
| 523 } | |
| 524 | |
| 525 void NavigatorHostImpl::DidNavigateLocally(const mojo::String& url) { | |
| 526 window_manager_->DidNavigateLocally(view_id_, url); | |
| 527 RecordNavigation(url); | |
| 528 } | |
| 529 | |
| 530 void NavigatorHostImpl::RequestNavigate(Target target, URLRequestPtr request) { | |
| 531 window_manager_->RequestNavigate(view_id_, target, request->url); | |
| 532 } | |
| 533 | |
| 534 void NavigatorHostImpl::RequestNavigateHistory(int32_t delta) { | |
| 535 if (history_.empty()) | |
| 536 return; | |
| 537 current_index_ = | |
| 538 std::max(0, std::min(current_index_ + delta, | |
| 539 static_cast<int32_t>(history_.size()) - 1)); | |
| 540 window_manager_->RequestNavigate(view_id_, Target::SOURCE_NODE, | |
| 541 history_[current_index_]); | |
| 542 } | |
| 543 | |
| 544 void NavigatorHostImpl::RecordNavigation(const std::string& url) { | |
| 545 if (current_index_ >= 0 && history_[current_index_] == url) { | |
| 546 // This is a navigation to the current entry, ignore. | |
| 547 return; | |
| 548 } | |
| 549 history_.erase(history_.begin() + (current_index_ + 1), history_.end()); | |
| 550 history_.push_back(url); | |
| 551 ++current_index_; | |
| 552 } | |
| 553 | |
| 554 } // namespace examples | |
| 555 } // namespace mojo | |
| 556 | |
| 557 MojoResult MojoMain(MojoHandle application_request) { | |
| 558 mojo::ApplicationRunnerChromium runner(new mojo::examples::WindowManager); | |
| 559 return runner.Run(application_request); | |
| 560 } | |
| OLD | NEW |