55# If you try to keep PyBrowser() objects inside c_vector you will get segmentation
66# faults, as they will be garbage collected.
77
8- cdef list g_pyBrowsers = []
9-
10- # TODO: remove:
11- # Debug("DisplayHandler_OnTitleChange(): cdef pyBrowser: %s" % pyBrowser)
8+ cdef dict g_pyBrowsers = {}
129
1310cdef PyBrowser GetPyBrowser(CefRefPtr[CefBrowser] cefBrowser):
1411
@@ -17,39 +14,40 @@ cdef PyBrowser GetPyBrowser(CefRefPtr[CefBrowser] cefBrowser):
1714 if < void * > cefBrowser == NULL or not cefBrowser.get():
1815 Debug(" GetPyBrowser(): returning None" )
1916 return None
20-
17+
2118 cdef PyBrowser pyBrowser
22- cdef CefWindowHandle windowHandle1
23- cdef CefWindowHandle windowHandle2
19+ cdef int browserId
2420
25- for pyBrowser in g_pyBrowsers:
26- if pyBrowser.cefBrowser.get():
27- if pyBrowser.cefBrowser.get().GetIdentifier() == cefBrowser.get().GetIdentifier():
28- return pyBrowser
29- else :
30- Debug(" GetPyBrowser(): removing an empty reference from g_pyBrowsers" )
31- # TODO.
21+ browserId = cefBrowser.get().GetIdentifier()
22+ if browserId in g_pyBrowsers:
23+ return g_pyBrowsers[browserId]
3224
33- Debug(" GetPyBrowser(): creating new PyBrowser" )
25+ for id , pyBrowser in g_pyBrowsers.items():
26+ if not pyBrowser.cefBrowser.get():
27+ Debug(" GetPyBrowser(): removing an empty CefBrowser reference, browserId=%s " % id )
28+ del g_pyBrowsers[id ]
29+
30+ Debug(" GetPyBrowser(): creating new PyBrowser, browserId=%s " % browserId)
3431 pyBrowser = PyBrowser()
3532 pyBrowser.cefBrowser = cefBrowser
36- g_pyBrowsers.append( pyBrowser)
33+ g_pyBrowsers[browserId] = pyBrowser
3734 return pyBrowser
3835
3936cpdef PyBrowser GetBrowserByWindowHandle(int windowHandle):
4037
4138 cdef PyBrowser pyBrowser
42- for pyBrowser in g_pyBrowsers:
43- if (pyBrowser.GetWindowHandle() == windowHandle or
39+ for browserId in g_pyBrowsers:
40+ pyBrowser = g_pyBrowsers[browserId]
41+ if (pyBrowser.GetWindowHandle() == windowHandle or
4442 pyBrowser.GetUserData(" __outerWindowHandle" ) == windowHandle):
4543 return pyBrowser
4644 return None
4745
4846IF CEF_VERSION == 3 :
49-
47+
5048 cdef CefRefPtr[CefBrowserHost] GetCefBrowserHost(
5149 CefRefPtr[CefBrowser] cefBrowser) except * :
52-
50+
5351 cdef CefRefPtr[CefBrowserHost] cefBrowserHost = cefBrowser.get().GetHost()
5452 if < void * > cefBrowserHost != NULL and cefBrowserHost.get():
5553 return cefBrowserHost
@@ -65,7 +63,7 @@ cdef class PyBrowser:
6563 IF CEF_VERSION == 1 :
6664 cdef public JavascriptBindings javascriptBindings
6765 cdef public dict userData
68-
66+
6967 # Properties used by ToggleFullscreen().
7068 cdef public int isFullscreen
7169 cdef public int maximized
@@ -82,57 +80,57 @@ cdef class PyBrowser:
8280 IF CEF_VERSION == 3 :
8381
8482 cdef CefRefPtr[CefBrowserHost] GetCefBrowserHost(self ) except * :
85-
83+
8684 cdef CefRefPtr[CefBrowserHost] cefBrowserHost = self .GetCefBrowser().get().GetHost()
8785 if < void * > cefBrowserHost != NULL and cefBrowserHost.get():
8886 return cefBrowserHost
8987 raise Exception (" PyBrowser.GetCefBrowserHost() failed: this method "
9088 " can only be called in the browser process." )
91-
89+
9290 def __init__ (self ):
9391
9492 self .clientCallbacks = {}
9593 self .allowedClientCallbacks = []
9694 self .userData = {}
9795
98- cpdef object SetClientCallback(self , str name, object callback):
96+ cpdef py_void SetClientCallback(self , py_string name, object callback):
9997
10098 if not self .allowedClientCallbacks:
101-
99+
102100 # CefLoadHandler.
103101 self .allowedClientCallbacks += [" OnLoadEnd" , " OnLoadError" , " OnLoadStart" ]
104-
102+
105103 # CefKeyboardHandler.
106104 self .allowedClientCallbacks += [" OnKeyEvent" ]
107-
105+
108106 # CefV8ContextHandler.
109107 self .allowedClientCallbacks += [" OnUncaughtException" ]
110-
108+
111109 # CefRequestHandler.
112- self .allowedClientCallbacks += [" OnBeforeBrowse" , " OnBeforeResourceLoad" ,
113- " OnResourceRedirect" , " OnResourceResponse" , " OnProtocolExecution" ,
110+ self .allowedClientCallbacks += [" OnBeforeBrowse" , " OnBeforeResourceLoad" ,
111+ " OnResourceRedirect" , " OnResourceResponse" , " OnProtocolExecution" ,
114112 " GetDownloadHandler" , " GetAuthCredentials" , " GetCookieManager" ]
115-
113+
116114 # CefDisplayHandler.
117- self .allowedClientCallbacks += [" OnAddressChange" , " OnConsoleMessage" ,
118- " OnContentsSizeChange" , " OnNavStateChange" , " OnStatusMessage" ,
115+ self .allowedClientCallbacks += [" OnAddressChange" , " OnConsoleMessage" ,
116+ " OnContentsSizeChange" , " OnNavStateChange" , " OnStatusMessage" ,
119117 " OnTitleChange" , " OnTooltip" ]
120-
118+
121119 # LifespanHandler.
122120 self .allowedClientCallbacks += [" DoClose" , " OnAfterCreated" , " OnBeforeClose" ,
123121 " RunModal" ]
124122
125123 if name not in self .allowedClientCallbacks:
126124 raise Exception (" Browser.SetClientCallback() failed: unknown callback: %s " % name)
127-
125+
128126 self .clientCallbacks[name] = callback
129-
130- cpdef object SetClientHandler(self , object clientHandler):
131-
127+
128+ cpdef py_void SetClientHandler(self , object clientHandler):
129+
132130 if not hasattr (clientHandler, " __class__" ):
133131 raise Exception (" Browser.SetClientHandler() failed: __class__ attribute missing" )
134132 cdef dict methods = {}
135- cdef str key
133+ cdef py_string key
136134 cdef object method
137135 cdef tuple value
138136 for value in inspect.getmembers(clientHandler, predicate = inspect.ismethod):
@@ -141,7 +139,7 @@ cdef class PyBrowser:
141139 if key and key[0 ] != ' _' :
142140 self .SetClientCallback(key, method)
143141
144- cpdef object GetClientCallback(self , str name):
142+ cpdef object GetClientCallback(self , py_string name):
145143
146144 if name in self .clientCallbacks:
147145 return self .clientCallbacks[name]
@@ -152,7 +150,7 @@ cdef class PyBrowser:
152150
153151 IF CEF_VERSION == 1 :
154152
155- cpdef object SetJavascriptBindings(self , JavascriptBindings bindings):
153+ cpdef py_void SetJavascriptBindings(self , JavascriptBindings bindings):
156154
157155 self .javascriptBindings = bindings
158156
@@ -178,15 +176,15 @@ cdef class PyBrowser:
178176
179177 self .GetCefBrowser().get().ClearHistory()
180178
181- cpdef object CloseBrowser(self ):
179+ cpdef py_void CloseBrowser(self ):
182180
183181 # In cefclient/cefclient_win.cpp there is only ParentWindowWillClose() called.
184182 # CloseBrowser() is called only for popups.
185183
186184 if self .GetUserData(" __outerWindowHandle" ):
187185 IF CEF_VERSION == 1 :
188- Debug(" CefBrowser::ParentWindowWillClose()" )
189- self .GetCefBrowser().get().ParentWindowWillClose()
186+ Debug(" CefBrowser::ParentWindowWillClose()" )
187+ self .GetCefBrowser().get().ParentWindowWillClose()
190188 ELIF CEF_VERSION == 3 :
191189 Debug(" CefBrowserHost::ParentWindowWillClose()" )
192190 self .GetCefBrowserHost().get().ParentWindowWillClose()
@@ -200,11 +198,11 @@ cdef class PyBrowser:
200198
201199 IF CEF_VERSION == 1 :
202200
203- cpdef object CloseDevTools(self ):
204-
201+ cpdef py_void CloseDevTools(self ):
202+
205203 self .GetCefBrowser().get().CloseDevTools()
206204
207- cpdef object Find(self , int searchId, str searchText, py_bool forward,
205+ cpdef py_void Find(self , int searchId, py_string searchText, py_bool forward,
208206 py_bool matchCase, py_bool findNext):
209207
210208 cdef CefString cefSearchText
@@ -217,7 +215,7 @@ cdef class PyBrowser:
217215 assert IsCurrentThread(TID_UI), " Browser.GetFocusedFrame() may only be called on the UI thread"
218216 return GetPyFrame(self .GetCefBrowser().get().GetFocusedFrame())
219217
220- cpdef PyFrame GetFrame(self , str name):
218+ cpdef PyFrame GetFrame(self , py_string name):
221219
222220 assert IsCurrentThread(TID_UI), " Browser.GetFrame() may only be called on the UI thread"
223221 cdef CefString cefName
@@ -242,7 +240,7 @@ cdef class PyBrowser:
242240
243241 return GetPyFrame(self .GetCefBrowser().get().GetMainFrame())
244242
245- def GetOpenerWindowHandle (self ):
243+ cpdef int GetOpenerWindowHandle(self ) except * :
246244
247245 cdef HWND hwnd
248246 IF CEF_VERSION == 1 :
@@ -251,20 +249,20 @@ cdef class PyBrowser:
251249 hwnd = self .GetCefBrowserHost().get().GetOpenerWindowHandle()
252250 return < int > hwnd
253251
254- def GetOuterWindowHandle (self ):
252+ cpdef int GetOuterWindowHandle(self ) except * :
255253
256254 if self .GetUserData(" __outerWindowHandle" ):
257- return self .GetUserData(" __outerWindowHandle" )
255+ return int ( self .GetUserData(" __outerWindowHandle" ) )
258256 else :
259257 return self .GetWindowHandle()
260258
261- def GetUserData (self , key ):
259+ cpdef object GetUserData(self , object key):
262260
263261 if key in self .userData:
264262 return self .userData[key]
265263 return None
266264
267- def GetWindowHandle (self ):
265+ cpdef int GetWindowHandle(self ) except * :
268266
269267 cdef HWND hwnd
270268 IF CEF_VERSION == 1 :
@@ -273,7 +271,7 @@ cdef class PyBrowser:
273271 hwnd = self .GetCefBrowserHost().get().GetWindowHandle()
274272 return < int > hwnd
275273
276- def GetZoomLevel (self ):
274+ cpdef double GetZoomLevel(self ) except * :
277275
278276 IF CEF_VERSION == 1 :
279277 assert IsCurrentThread(TID_UI), " Browser.GetZoomLevel() may only be called on the UI thread"
@@ -284,97 +282,98 @@ cdef class PyBrowser:
284282 zoomLevel = self .GetCefBrowserHost().get().GetZoomLevel()
285283 return zoomLevel
286284
287- def GoBack (self ):
285+ cpdef py_void GoBack(self ):
288286
289287 self .GetCefBrowser().get().GoBack()
290288
291- def GoForward (self ):
289+ cpdef py_void GoForward(self ):
292290
293291 self .GetCefBrowser().get().GoForward()
294292
295- def HasDocument (self ):
293+ cpdef py_bool HasDocument(self ):
296294
297295 return self .GetCefBrowser().get().HasDocument()
298296
299297 IF CEF_VERSION == 1 :
300298
301- def HidePopup (self ):
299+ cpdef py_void HidePopup(self ):
302300
303301 self .GetCefBrowser().get().HidePopup()
304302
305- def IsFullscreen (self ):
303+ cpdef py_bool IsFullscreen(self ):
306304
307305 return bool (self .isFullscreen)
308306
309- def IsPopup (self ):
307+ cpdef py_bool IsPopup(self ):
310308
311309 return self .GetCefBrowser().get().IsPopup()
312310
313311 IF CEF_VERSION == 1 :
314312
315- def IsPopupVisible (self ):
313+ cpdef py_bool IsPopupVisible(self ):
316314
317315 assert IsCurrentThread(TID_UI), " Browser.IsPopupVisible() may only be called on the UI thread"
318316 return self .GetCefBrowser().get().IsPopupVisible()
319317
320- def IsWindowRenderingDisabled (self ):
318+ cpdef py_bool IsWindowRenderingDisabled(self ):
321319
322320 return self .GetCefBrowser().get().IsWindowRenderingDisabled()
323321
324- def Reload (self ):
322+ cpdef py_void Reload(self ):
325323
326324 self .GetCefBrowser().get().Reload()
327325
328- def ReloadIgnoreCache (self ):
326+ cpdef py_void ReloadIgnoreCache(self ):
329327
330328 self .GetCefBrowser().get().ReloadIgnoreCache()
331329
332- def SetFocus (self , enable ):
330+ cpdef py_void SetFocus(self , enable):
333331
334332 IF CEF_VERSION == 1 :
335333 self .GetCefBrowser().get().SetFocus(bool (enable))
336334 ELIF CEF_VERSION == 3 :
337335 self .GetCefBrowserHost().get().SetFocus(bool (enable))
338336
339- def SetUserData (self , key , value ):
337+ cpdef py_void SetUserData(self , object key, object value):
340338
341339 self .userData[key] = value
342340
343- def SetZoomLevel (self , zoomLevel ):
341+ cpdef py_void SetZoomLevel(self , double zoomLevel):
344342
345343 IF CEF_VERSION == 1 :
346- self .GetCefBrowser().get().SetZoomLevel(< double > float ( zoomLevel) )
344+ self .GetCefBrowser().get().SetZoomLevel(zoomLevel)
347345 ELIF CEF_VERSION == 3 :
348- self .GetCefBrowserHost().get().SetZoomLevel(< double > float ( zoomLevel) )
346+ self .GetCefBrowserHost().get().SetZoomLevel(zoomLevel)
349347
350348 IF CEF_VERSION == 1 :
351349
352- def ShowDevTools (self ):
350+ cpdef py_void ShowDevTools(self ):
353351
354352 self .GetCefBrowser().get().ShowDevTools()
355353
356- def StopLoad (self ):
354+ cpdef py_void StopLoad(self ):
357355
358356 self .GetCefBrowser().get().StopLoad()
359357
360358 IF CEF_VERSION == 1 :
361359
362- def StopFinding (self , clearSelection ):
360+ cpdef py_void StopFinding(self , py_bool clearSelection):
363361
364362 self .GetCefBrowser().get().StopFinding(bool (clearSelection))
365363
366- def ToggleFullscreen (self ):
364+ cpdef py_void ToggleFullscreen(self ):
367365
368366 IF UNAME_SYSNAME == " Windows" :
369367
368+ cdef int windowHandle
370369 if self .GetUserData(" __outerWindowHandle" ):
371370 windowHandle = self .GetUserData(" __outerWindowHandle" )
372371 else :
373372 windowHandle = self .GetWindowHandle()
374-
373+
375374 # Offscreen browser will have an empty window handle.
376375 assert windowHandle, " Browser.ToggleFullscreen() failed: no window handle found"
377-
376+
378377 cdef HWND hwnd = < HWND>< int > int (windowHandle)
379378 cdef RECT rect
380379 cdef HMONITOR monitor
@@ -384,7 +383,7 @@ cdef class PyBrowser:
384383 # Logic copied from chromium > fullscreen_handler.cc > FullscreenHandler::SetFullscreenImpl:
385384 # http://src.chromium.org/viewvc/chrome/trunk/src/ui/views/win/fullscreen_handler.cc
386385
387- for_metro = False
386+ cdef py_bool for_metro = False
388387
389388 if not self .isFullscreen:
390389 self .maximized = IsZoomed(hwnd)
@@ -394,7 +393,10 @@ cdef class PyBrowser:
394393 self .gwlExStyle = GetWindowLong(hwnd, GWL_EXSTYLE)
395394 GetWindowRect(hwnd, & rect)
396395 self .windowRect = (rect.left, rect.top, rect.right, rect.bottom)
397-
396+
397+ cdef int remove_style, remove_exstyle
398+ cdef int left, top, right, bottom
399+
398400 if not self .isFullscreen:
399401 remove_style = WS_CAPTION | WS_THICKFRAME
400402 remove_exstyle = WS_EX_DLGMODALFRAME | WS_EX_WINDOWEDGE | WS_EX_CLIENTEDGE | WS_EX_STATICEDGE
0 commit comments